素人なので間違い等ありましたらご指摘ください。
目次
1. タイマのピン配置図
2.全体の枠組み
注: アドバンストタイマは、一般タイマのインプットキャプチャ機能、出力比較機能に加え、プログラマブルデッドゾーン相補出力機能、繰り返しカウンタ機能、ブレーキ(サーキットブレーク)機能を追加しています。本記事では出力比較機能のみを取り上げます。
アドバンストタイマのフレームワークを、タイムベースモジュール、比較レジスタ、デッドゾーンジェネレータ、出力制御の4つの部分に分けます。
2.1 タイムベースモジュール
アドバンスト タイマ クロック ソースは 4 つありますが、ここでは内部クロック ソースのみを紹介します。
タイムベースユニットのフレームは図のとおりです
これを 4 つの部分に分割します。 1. プリスケーラー PSC。1 ~ 65536 の周波数分割を実現できます。2. カウンタ CNT: アップカウント モード、ダウンカウント モード、アップ/ダウン (中央揃え) カウント モードの 3 つのカウント モード。3. 自動リロードレジスタ ARR および 4. リピートカウンタ RCR
ここで基本的なタイマーと異なるのは、3 つのカウント モードと繰り返しカウンターです。
平たく言えば、ループは 0 (または最大値) から始まり、上方向 (または下方向) にカウントされます。最大値 (または 0) に達すると、割り込みまたはイベントが発生します。繰り返しカウンターが使用される場合、特定の回数がカウントされ、その回数に応じて割り込み1またはイベントが発生します。カウントアップまたはカウントダウンはカウントモードによって異なります。
今回はPWM波を出力するため割り込みを使う必要はなく、カウント機能だけで十分です。
2.2 コンペアレジスタ
カウンタ CNT の値と比較レジスタ CCR の値が等しい場合、出力リファレンス信号 OCxREF の極性が変化します。OCxREF=1 (ハイレベル) を有効レベル、OCxREF=0 (ローレベル) をフラットといいます。を無効レベルといいます。
ここで出力される信号は OCxREF です。
デッドゾーンジェネレーターに入る前に、出力比較モードを設定することができ、PWM 波を出力する場合、PWM1 と PWM2 の 2 つのモードから選択できます。
2.3 デッドゾーンジェネレータ
デッド ゾーン ジェネレーターを通過すると、デッド ゾーンを持つ 2 つの相補信号 OCx_DT と OCxN_DT が生成されます。デッド ゾーン制御が追加されない場合、出力制御回路に入力される信号は直接 OCxREF になります。
単純な PWM 波についてはここでは詳しく紹介しません。
2.4 出力制御
デッド ゾーン ジェネレーターによって出力される信号は 2 つのチャネルに分割され、1 つは元の信号で、もう 1 つは反転信号であり、レジスタ CCER のビット CCxP および CCxNP によって具体的に制御されます。極性選択信号を OCx 端子から外部端子 CHx/CHxN に出力するかどうか (つまり有効にするか) は、レジスタ CCER の CxE/CxNE ビットで設定します。
3. 構造
typedef struct
{
uint16_t TIM_Prescaler; //时钟预分频,对应PSC
uint16_t TIM_CounterMode; //时钟计数模式,对应3中计数方法
uint16_t TIM_Period; //定时器周期,对应ARR寄存器
uint16_t TIM_ClockDivision; //时钟分频,设置定时器时钟 CK_INT 频率与死区发生器以及数字滤
//波器,采样时钟频率分频比。可以选择 1、2、4 分频。
uint8_t TIM_RepetitionCounter; //重复计数器,对应RAR
} TIM_TimeBaseInitTypeDef;
typedef struct
{
uint16_t TIM_OCMode; //输出模式,PWM1及PWM2,对应寄存器CCMR1->OCxM
uint16_t TIM_OutputState; //比较输出使能,对应CCER->CCxE
uint16_t TIM_OutputNState; //比较互补输出使能,对应CCER->CCxNE
uint16_t TIM_Pulse; //脉冲宽度,即比较寄存器的值,对应CCR1
uint16_t TIM_OCPolarity; //输出极性,对应CCER->CCxP
uint16_t TIM_OCNPolarity; //互补输出极性,对应CCER->CCxP
uint16_t TIM_OCIdleState; //空闲状态比较输出状态,对应CR2->OIS1
uint16_t TIM_OCNIdleState; //空闲状态下比较互补输出状态,对应CR2->OIS1N
} TIM_OCInitTypeDef;
pwm の設定に使用される主な構造は 2 つあり、1 つはタイムベース初期化構造、もう 1 つは出力比較構造、およびタイムベース初期化構造です。
出力比較の構造は、以下に示す図のレジスタに対応します。
ただし、これら 2 つの構造に加えて、レジスタも有効にする必要があります。
BDER->MOE レジスタに対応し、公式の紹介は次のとおりです
出力ピンを有効にするだけです
4. プログラミング
要約すると、プログラミングの目標は次のとおりです。
1. チャネルの GPIO ピンを構成します。
2. 2 つの構造を構成する
3. クロックソースを有効にし、出力チャネルを有効にします。
次のプログラムは、1Khz、デューティ サイクル 40% の PWM 波を構成します。
void advance_tim1_gpio_config(void)
{
//1.结构体
GPIO_InitTypeDef GPIO_InitStructure;
//2.开时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
//3.配置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//4.初始化
GPIO_Init(GPIOA, &GPIO_InitStructure);
//5.使能(无)
}
void advance_tim1_mode_config()
{
//1.结构体,时基结构体及输出比较结构体
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
//2.开时钟,TIM1的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
//3.配置及初始化
/*--------------------时基结构体初始化-------------------------*/
// PWM 信号的频率 F = TIM_CLK/{(ARR+1)*(PSC+1)}
TIM_TimeBaseStructure.TIM_Period = 9; //ARR寄存器的值
TIM_TimeBaseStructure.TIM_Prescaler = 7199; //PSC分频的值
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数
TIM_TimeBaseStructure.TIM_RepetitionCounter=0; //重复计数器为0
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
/*--------------------输出比较结构体初始化-------------------*/
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //输出模式:PWM1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_Pulse = 4; //设置占空比
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //有效电平
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; //空闲时比较输出状态
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
//4.使能,此处使能为将内部时钟作为TIM1时钟源的使能
TIM_Cmd(TIM1, ENABLE); //使能计数器
TIM_CtrlPWMOutputs(TIM1, ENABLE); //使能输出通道
}
注: ARR レジスタと PSC レジスタは 0 からカウントを開始するため、値を 1 減らす必要があります。
PWM波周波数=TIM_CLK/{(ARR+1)*(PSC+1)}
このうち、TIM1 は APB2 に実装されており、APB2 は一般的に 72Mhz であるため、TIM_CLK は一般的に APB2 の周波数になります。
デューティ サイクル=TIM_OCInitStructure.TIM_Pulse/(ARR+1)
PWM 波形を個人的に設定するには、通常は次の手順に従います。
1. PWM波の周波数を確認する
2. PWM波形の精度を確認(ARRレジスタに相当)
3. デューティ サイクル TIM_OCInitStructure.TIM_Pulse を確認します。
さらに、デューティ サイクルを特別に変更する (つまり、TIM_OCInitStructure.TIM_Pulse の値を変更する) 関数がありますが、これまで知らなかったので、自分で作成しました (この落とし穴は避けてください)。
void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1);
5.説明
この記事で説明したレジスタに加えて、TIM_OC1PreloadConfi() などのいくつかのプリロード関数もあります。
待てよ、この関数は CCMR->OC1PE に相当しますが、この関数は当面必要ないので詳しくは紹介しません。
公式の説明は次のとおりです。また、タイムベース ユニットの場合、特定のレジスタの下にシャドウが存在します。対応するシャドウ レジスタについては詳しく説明しません。
PWM波形制御ESCについては後日記事を掲載します。
参考文献には、「STM32F10x-中国語リファレンス マニュアル」および「STM32 ライブラリ開発実践ガイド - Wildfire ガイド開発ボードに基づく」が含まれます。