一般的なタイマー割り込み実験の詳細な説明

目次

一般的なタイマー割り込み実験

タイマー割り込みクロックソース分析

論理信号図の見方を教えてください

アップカウントモード(クロック分周係数= 1)

中央揃えのカウントモード(クロック分割係数= 1、ARR = 6)

関連レジスターの紹介

イベント生成レジスタ(TIMx_EGR)

ステータスレジスタ(TIMx_SR)

カウンター(TIMx_CNT)

プリスケーラ(TIMx_PSC)

自動リロードレジスタ(TIMx_ARR)

制御レジスタ1(TIMx_CR1)

ライブラリ関数を使用して、割り込み付きの汎用タイマーを構成します

ライブラリ関数の概要

タイマーパラメータの選択

設計要件

TIMXプログラミングフロー

ステップ1:TIMER3を初期化する

ステップ2:タイマー3を初期化します(ARRとPSCの値を構成します)

ステップ3:NVIC埋め込み割り込みベクトルを初期化する

ステップ4:TIMXの割り込みを構成する

手順5:TIMXペリフェラルを有効にする

ステップ6:対応する割り込みサービス関数を記述します

コード例

Main.c

Led.c

Led.h.

Timer.h

Timer.c

運用結果


一般的なタイマー割り込み実験

タイマー割り込みクロックソース分析

 

私たちの実験では、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)

 

このレジスタは、割り込みを要求し、カウンタモードを設定するために使用されます。割り込みがトリガーされると、すべてのレジスタが更新されます。

ライブラリ関数を使用して、割り込み付きの汎用タイマーを構成します

ライブラリ関数の概要

ライブラリ関数名

特徴

TIM_TimeBaseInit

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

 

運用結果

 

 

おすすめ

転載: blog.csdn.net/weixin_45590473/article/details/108048325