stm32通用定時器用做外部脈衝計數器的例程
最近幾天要用到stm32對外部輸入脈衝進行計數,很自然想到定時器,可是手上資料沒有講解stm32定時器如何用作外部計數器的,在網上找例程,也沒找到幾個正確的,自己硬著頭皮仔細研究參考手冊,終於知道如何配置了,並寫了一個例程,希望將來對一些網友有用。
其實stm32通用定時器做計數器,對外部脈衝計數,還是比較簡單的,使用外部時鐘模式2即可輕鬆實現,但要注意,這種模式下,外部輸入脈衝訊號一定要接在相應TIM的ETR引腳上,不能接在TIMx_CHy引腳上。
使用stm32定時器的外部時鐘模式2,主要就是通過配置TIMx_SMCR暫存器相應位。步驟如下:
1. 若不需要濾波器,置TIMx_SMCR暫存器中的ETF[3:0]=0000
2. 設定預分頻,TIMx_SMCR暫存器中的ETPS[1:0]
3. 設定ETR的檢測極性,TIMx_SMCR暫存器中的ETP位
4. 開啟外部時鐘模式2,置TIMx_SMCR暫存器中的ECE=1
5. 啟動計數器,置TIMx_CR1暫存器中的CEN=1
我的例程是利用定時器2,定時產生週期1s的方波訊號,通過PB5(LED0)輸出,通過導線將PB5的方波訊號輸入到TIMER3的ETR引腳PD2上,通過TIMER3對該方波訊號計數,計數次數到了之後,更改LED1的狀態。
以下程式已經過測試,可行。
//timer2 ,定時器模式
void TIM2_Int_Init(u16 arr,u16 psc)
{
RCC->APB1ENR |= 1<<0;//TIM2時鐘使能
TIM2->ARR = arr;
TIM2->PSC = psc;
TIM2->DIER |= 1<<0;//允許更新中斷
TIM2->DIER |= 1<<6;//使能觸發中斷
MY_NVIC_Init(1,2,TIM2_IRQChannel,2);//搶佔1,子優先順序2,組2
TIM2->CR1 |= 1<<0;//使能定時器
}
//定時器2中斷服務程式
void TIM2_IRQHandler(void)
{
if(TIM2->SR&0X0001)//溢位中斷
{
LED0=!LED0;
//PB5,硬體連線:將PB5連線至TIM3_ETR引腳PD2上
}
TIM2->SR&=~(1<<0);//清除中斷標誌位
}
//通用定時器3 用作外部計數器 初始化
//arr:計數自動重灌值。
void TIM3_Int_Init(u16 arr)
{
RCC->APB2ENR|=1<<5;//開啟GPIOD埠時鐘
GPIOD->CRL &= 0xfffff0ff;
GPIOD->CRL |= 0x00000400;//PD.2 浮空輸入
RCC->APB1ENR |= 1<<1;//使能TIM3時鐘
TIM3->ARR=arr; //設定計數器自動重灌值
TIM3->PSC=0; //不分頻
TIM3->SMCR &= ~(0xf<<8);//無濾波
TIM3->SMCR &= ~(3<<12);//關閉預分頻
TIM3->SMCR |= 1<<15;//ETR被反相,低電平或下降沿有效
TIM3->SMCR |= 1<<14;//使能外部時鐘模式2
TIM3->DIER |= 1<<0;//允許更新中斷
TIM3->DIER |= 1<<6;//允許觸發中斷
MY_NVIC_Init(1,3,TIM3_IRQChannel,2);//搶佔1,子優先順序3,組2
TIM3->CNT = 0x0;//清零計數器
TIM3->CR1 |= 1<<0;//使能定時器,開啟計數。
}
//定時器3中斷服務程式
void TIM3_IRQHandler(void)
{
if(TIM3->SR&0X0001)//溢位中斷
{
LED1=!LED1;
}
TIM3->SR&=~(1<<0);//清除中斷標誌位
}
int main(void)
{
Stm32_Clock_Init(9);//系統時鐘設定
uart_init(72,9600);//串列埠初始化為9600
delay_init(72); //延時初始化
LED_Init();
//初始化與LED連線的硬體介面
BEEP_Init(); //初始化蜂鳴器埠
KEY_Init(); //初始化與按鍵連線的硬體介面
TIM3_Int_Init(20); //計數次數
TIM2_Int_Init(4999,7199);//時鐘週期0.1ms,計數5000次=定時0.5s
while(1);
}
實驗結果:LED0 :1s點亮一次,LED1: 20s點亮一次。