目次
中央揃えのカウントモード(クロック分割係数= 1、ARR = 6)
ライブラリ関数を使用して、割り込み付きの汎用タイマーを構成します
ステップ2:タイマー3を初期化します(ARRとPSCの値を構成します)
一般的なタイマー割り込み実験
タイマー割り込みクロックソース分析
私たちの実験では、APB1バスからのクロックを使用します(AHBクロック周波数は72MHzです)。AHB-> APB1分周器-> APB1で、APB1プリスケーラーの分周係数が1の場合、TIMXCLKのクロック周波数は「 TIMCLK = APB1 = AHB "、APB1プリスケーラの分割係数がN(Nは1ではない)の場合、TIMXCLKのクロック周波数は" TIMCLK = 2xAPB1 = 2xAHB / N "です。
ただし、STが提供する初期化クロックソースライブラリ関数を呼び出すと、APB1分周器のデフォルトの分周係数は2であるため、最終的なTIMXCLK = 2xAPB1 = 2xAHB / 2 = AHBになります。
TIMXCLKクロック周波数= CLK_INTクロック周波数、2番目の周波数分割処理のためにトリガーコントローラーを介してCK_PSCに渡されると、CNTカウンターが受信する最終クロックパルスは「CLK_INT /(CK_PSC + 1)」です(周波数分割係数がCK_PSCである理由) +1については後で説明します)
論理信号図の見方を教えてください
アップカウントモード(クロック分周係数= 1)
まず、CK_INTはTIMERの初期クロックソース、CNT_ENはTIMERイネーブル、CK_CNTはカウンターが受信するパルス周波数(周波数がCK_PSCレジスタで分割された後)、カウンターレジスタのリロード値は36、「割り込みイベント更新」です。 「タイマーオーバーフロー」および「割り込みフラグの更新を1に設定」と同期しますが、手動で割り込みフラグをクリアしないと、割り込み条件が満たされているかどうかに関係なく、システムは常に実行割り込みになります。
中央揃えのカウントモード(クロック分割係数= 1、ARR = 6)
中央揃えのカウントモードは、アップカウントオーバーフローとダウンカウントオーバーフローのそれぞれで割り込みがトリガーされるという点で多少異なります。各割り込み後に割り込みフラグをクリアしないと、割り込み条件が満たされているかどうかに関係なく、割り込み動作が常に存在します。
関連レジスターの紹介
イベント生成レジスタ(TIMx_EGR)
更新イベント割り込みは、汎用タイマーによって実行される通常の割り込みです。
ステータスレジスタ(TIMx_SR)
カウンター(TIMx_CNT)
プリスケーラ(TIMx_PSC)
自動リロードレジスタ(TIMx_ARR)
このレジスタは、カウンタのカウント値がオーバーフローした後、カウンタのオーバーフロー値をリロードするために使用されます。
制御レジスタ1(TIMx_CR1)
このレジスタは、割り込みを要求し、カウンタモードを設定するために使用されます。割り込みがトリガーされると、すべてのレジスタが更新されます。
ライブラリ関数を使用して、割り込み付きの汎用タイマーを構成します
ライブラリ関数の概要
ライブラリ関数名 |
特徴 |
TIMXタイマーを初期化するために使用されます |
|
TIM_Cmd |
TIMxペリフェラルを有効または無効にする |
TIM _ITConfig |
NVICの対応するパラメーターを構成した後、指定されたTIM割り込みを有効または無効にします |
TIM_PrescalerConfig |
TIMxプリスケーラを設定する |
TIM_CounterModeConfig |
TIMxカウンターモードを設定する |
TIM_GetITStatus |
指定されたTIM割り込みが発生するかどうかを確認します |
TIM_ClearITPendingBit |
TIMxの割り込み保留ビットをクリアします |
TIM_GetFlagStatus |
指定したTIMフラグが設定されているか確認してください |
TIM_ClearFlag |
TIMxの保留中のフラグをクリアします |
違いTIM_ClearITPendingBitとTIM_ClearFlag機能
TIM_ClearITPendingBitはいくつかの割り込みフラグビットをクリアし、TIM_ClearFlagはタイマーキャプチャステータスビットタイマートリガーフラグビットなどのタイマーステータスフラグをクリアします。
タイマーパラメータの選択
一般的なタイマーパラメータには、主に2つのPSCプリスケーラ係数とARRカウンタリロード値があります。オーバーフロー時間とは、「0x00からTOPまでの時間」を指します。
設計要件
タイマー割り込み設定により、500msに1回割り込み、割り込みサービス機能でLEDを制御し、LED1状態の反転(点滅)を実現します。
TIMXプログラミングフロー
ステップ1:TIMER3を初期化する
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); // 使能APB1的外设时钟
ステップ2:タイマー3を初期化します(ARRとPSCの値を構成します)
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Down;
TIM_TimeBaseInitStructure.TIM_Period = 0x1C20; // 5000
TIM_TimeBaseInitStructure.TIM_Prescaler = 0x1388; // 7200
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure); // 初始化TIMER3
ステップ3:NVIC埋め込み割り込みベクトルを初期化する
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStructure); // 初始化NVIC嵌入式外部中断
NVICの初期化の前にNVIC割り込みベクトルのグループ化を構成するのはなぜですか?
NVIC割り込みベクトルのグループ化は、すべての割り込みベクトルを制約するために使用されます。ヘッダーファイルだけに入れると、この意味を表現できません。また、異なるヘッダーファイルで異なる割り込みベクトルグループを宣言すると、面倒になります。の。
ステップ4:TIMXの割り込みを構成する
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); // 配置TIMER3的具体中断行为
NVICのTIM割り込みチャネルが開かれたのはなぜですか。また、TIMX割り込みも構成するのはなぜですか。
最初に有効にするのはTIMX割り込みチャネルです。TIMX割り込みモードは非常に複雑で、複数の割り込みモードがあります。したがって、最初にTIMXの合計割り込みチャネルを有効にしてから、さまざまな割り込み条件など、TIMX割り込みの属性をさらに構成します。アップカウントオーバーフロー、ダウンカウントオーバーフロー...
手順5:TIMXペリフェラルを有効にする
TIM_Cmd(TIM3, ENABLE); // 使能TIMER3外设
ステップ6:対応する割り込みサービス関数を記述します
void TIM3_IRQHandler() // 应该在相应的中断文件内编写中断服务函数
{
if(TIM_GetITStatus(TIM3, TIM_IT_Update) == SET) // 由于定时器有多个中断模式,因此我们一定要检查相应的中断标志位
{
LED0 = !LED0;
}
TIM_ClearITPendingBit(TIM3, TIM_IT_Update); // 由于定时器有多个中断模式,因此我们一定要清除相应的中断标志位
}
コード例
Main.c
#include "led.h"
#include "timer.h"
#include "stm32f10x.h"
#include "delay.h"
int main()
{
delay_init(); // 只有初始化系统systick时钟,我们才能调用delay系列函数
LED_InitConfig(); // LED初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // NVIC中断向量分组应该先于NVIC初始化
TIMER_InitConfig(0x1C20, 0x1388); // 初始化TIMER3,其中PR=7200,ARR=5000
while(1)
{
LED1 = !LED1;
delay_ms(250);
}
}
Led.c
#include "led.h"
#include "stm32f10x.h"
void LED_InitConfig()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE); // 使能LED0,LED1的时钟
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure); // 配置LED0的GPIO输出属性
GPIO_ResetBits(GPIOB, GPIO_Pin_5); // 初始化PB5为低电平
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOE, &GPIO_InitStructure); // 配置LED1的GPIO输出属性
GPIO_ResetBits(GPIOE, GPIO_Pin_5); // 初始化PE5为低电平
}
Led.h.
#ifndef _LED_H
#define _LED_H
#include "sys.h"
void LED_InitConfig();
#define LED0 PBout(5)
#define LED1 PEout(5)
#endif
Timer.h
#ifndef _TIMER_H
#define _TIMER_H
#include "sys.h"
void TIMER_InitConfig(u16 ARR, u16 PR);
#endif
Timer.c
運用結果