インプットキャプチャ
入力ピンがジャンプすると、cnt の値が ccr に記録され、pwm 信号の測定などに使用できます。pwmi モードとして設定すると、周波数とデューティ サイクルを同時に測定することもできます。マスタースレーブトリガモードはハードウェアによる全自動測定を実現します。
アドバンストタイマー、汎用タイマーのみで使用できる機能です。
この機能はデジタル信号のみを測定できるため、信号の場合はコンパレータなどのレジュームアドを介してデジタル信号に変換する必要があります。
周期測定法は高速で 1 周期で測定できますが、ノイズによる誤差が大きくなる場合があります。
入力信号はフィルタリングされてバリが除去され、信号がより安定します; CH1 が IC1 と IC2 に分割されるなど、2 つの送信に分割され、スイッチングに便利で拡張が容易になります。デューティサイクルと周波数を同時に調整します。
三相モーターにはTRCおよびXOR回路が使用されます。
psc を設定し、立ち上がりエッジを設定して ccr 値を保存すると、2 つの立ち上がりエッジの間の時間を記録できます。次にcntをクリアします。
フィルタ ICF 設定: n 個の連続した同一イベントのみが記録されます。例えば、安定した高水準となっています。信号がジッターし続ける場合、録音できません。ノイズが大きい場合は、このパラメータを大きく設定できます。
フィルタリング後のエッジ検出、TIFPによる選択。
出力は分周に設定でき、CC1E が有効になります。TIFP はモードからの cnt クリアを自動的にトリガーします。
マスターモード: 他の周辺機器をトリガーするためのセルフタイマー出力信号。
スレーブ モード: 他の (または独自の) 周辺機器から信号を受信して、独自のタイマーの動作を制御します。
例えば今回使用する関数はモードからのリセットとcntのリセットです。
2つのタイマをカスケード接続し、プリスケーラ後の最初のタイマの出力を2番目のタイマに与えて、2つのプリスケーラがカウントできる周期を長くするなどの使用法もあります。
要約原則:
fc: クロックソース周波数/psc。
N: 最新の ccr 値。
fc/N は信号周波数を計算できます。
- なお、cntには65535などの上限があり、信号周波数が低すぎるとオーバーフローする可能性があるので、このときpscを少し大きくしてもよい。
- 1 2 タイマーは 1 2 のスレーブ モードのみを設定できます。3 4 タイマーを使用してリセット コマンドをトリガーしたい場合は、より多くのリソースを消費する割り込み機能を使用する必要があります。
上の図から周波数とデューティ サイクルを取得します。CCR1 は周期全体の長さ、CCR2 はハイレベルの周期の長さであり、これらを比較することでデューティ比を求めることができます。
コード: 周波数を測定するためにキャプチャ モードに入る
信号発生器がないので、前のレッスンの PWM 波形を使用して別のピンに出力し、他のピンの IC がその周波数を取得します。
異なる入力波形を試しているため、psc の値が変化します。したがって、psc を変更する関数を書くことが可能です。
初期化関数は OC と似ています。以下は複数のチャネルを同時に初期化できます。
初期値を代入します。
トリガーソースを選択します。
マスターモード出力のトリガソースを選択し、スレーブモードのモードを選択します。
ccr値を読み取ります。oc 状態では、ccr は書き込まれるだけであり、setCompare で書き込むことができます。ic の状態は読み取り専用なので、読み取るには次の 4 つの関数を使用します。
#include "stm32f10x.h"
void IC_Init(){
//1. 打开输入接收的RCC,GPIO
//2. 时基单元,启动计数器
//3. 设置输入捕获单元
//4. 选用触发源
//5. 设置触发后的reset操作
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_InternalClockConfig(TIM3);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period=65536-1;//满计时,尽量避免溢出
TIM_TimeBaseInitStructure.TIM_Prescaler=72-1;//输入信号频率:1MHz
TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_ICInitStructure.TIM_Channel=TIM_Channel_1;//PA6对应定时器3 ch1
TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICFilter=0xF;//滤波消除毛刺,越大效果越好,看需求
TIM_ICInitStructure.TIM_ICPrescaler =TIM_ICPSC_DIV1;//不分频,每次都触发
TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;//直连或者交叉通道
TIM_ICInit(TIM3, &TIM_ICInitStructure);
TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);//定时器1的从模式
TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);
TIM_Cmd(TIM3,ENABLE);
}
uint32_t IC_GetFreq(void){
//fc: 1MHz
return 1000000/(TIM_GetCapture1(TIM3)+1);//CH1的捕获
}
main で psc=720 に設定すると、入力周波数は 1MHz、1000000、ccr 値は 50 に設定されます。
PWM_SetPrescaler(720-1);//freq: 72M/100/720
TIM_SetCompare1(TIM2,50);//duty: 50/100
OC: PWM 設定 ccr=50、psc 7200、周期 100 (デューティ=ccr/(arr+1) のため、出力ピンの分周を変更する際に arr を変更するスキームが採用されている場合、デューティ サイクルもそれに応じて変更されます。計算は簡単ではありません。arr を修正して psc を変更する方が良いです。)、つまり、デューティ サイクルは 50/100 の半分です。したがって、1kHzの波形が出力されます。
IC: 100 0000/1000=1000. 2 つの隣接する立ち上がりエッジの間で 1k をカウントし、合計周波数 1M/1k を使用して入力波形を取得します。
get 関数がなぜ +1 なのかは被験者にはよくわかりませんが、先生によると、たまたまジャンプがあっただけで立ち上がりが記録されていないのではないかとのことです。
コード: 周波数と立ち上がりエッジを検出
基本的には変更はありませんが、IC 初期化関数の 1 つを 2 チャネル同時に初期化する関数に変更します。初期化のためにこの行を変更するだけで、ライブラリ関数が自動的に他のチャンネルを反対に調整します。たとえば、チャンネル 1 は立ち上がりエッジ トリガーに直接接続され、チャンネル 2 は立ち下がりエッジ トリガーにクロスコネクトされます。
TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);
デューティ サイクルを取得する別の関数を作成します。
uint32_t IC_GetDuty(void){
return (TIM_GetCapture2(TIM3)+1)*100/(TIM_GetCapture1(TIM3)+1);
}
setprescaler を周波数に変更し、setcompare をデューティに変更します。
- 入力信号周波数は 1MHz、最大カウンタは 65535 であるため、オーバーフローしない最低周波数は 1M/65535 ≒ 15Hz となります。
- 誤差が 1000 分の 1 である必要がある場合、周波数は 1M/1k=1k になります。