STM32採用普通的IO口來測量PWM的頻率
阿新 • • 發佈:2019-01-03
STM32測量外部輸入訊號的頻率的方法有很多:
- 採用內部定時器輸入捕獲功能。
- 採用普通的IO口設定外部中斷+定時器的當時測量PWM訊號的頻率。
這兩種方式比較推薦使用第一種,比較使用內部的資源可以節省CPU資源的利用,
當然當內部資源不夠使用的時候,或者是說,硬體電路設計的時候沒有連線相應的應引腳只能使用第二種方式了。
本次由於硬體電路設計的不足,導致需要測量PWM輸入訊號的引腳沒有接到相應的通道上,對此使用了第二種方式:
注意:這裡定時器中斷的優先順序要高於外部中斷的優先順序
思路如下:
- 設定PWM輸入訊號的引腳為外部中斷的方式,並且觸發方式為GPIO_MODE_IT_RISING_FALLING 上升,下降沿均可觸發。
- 其次使能一個定時器TIM4,定時中斷時間看自己需要測量頻率來設定。(本次設定為2us –> 最大可測量的頻率為50KHz)
- 外部中斷中,上升沿到來,清空計數器TIM4->CNT=0,置一個上升沿的標誌位為1,代表計算PWM時間的開始tim4_PWM_cnt++。
- 下降沿到來,置一個下降沿的標誌為1.
- 下一次上升沿到來,判斷上一次是否為下降沿的標誌,如果是,則代表PWM一個週期的時間已經到達。讀取時間。PWM_Cycle = timer4_PWM_cnt*2. 並且把計數變數清零tim4_PWM_cnt = 0
- 接著下一次下降沿到來,判斷上一次是否為上升沿的標誌,如果是,則代表一個週期高電平結束,讀取時間,即為脈寬 PWM_Duty = timer4_PWM_cnt*2。
具體c語言實現程式碼如下:
if(__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_11) != RESET)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_11);//呼叫中斷處理公用函式
if(PWM_EN()==1) //上升沿觸發
{
TIM4->CNT=0;//這裡清空TIM4計數。重新開始計數
if((PWM_FLAG_DOWM==1)&&(PWM_FLAG_UP==2))//判斷上一次是否為下降沿
{
PWM_Cycle = timer4_PWM_cnt*2 ;
timer4_PWM_cnt=0;
}
PWM_FLAG_CNT = 1;
PWM_FLAG_UP = 1;//上升沿標誌
PWM_FLAG_DOWM = 2;//上升沿標誌
}
else//下降沿觸發
{
if((PWM_FLAG_DOWM==2)&&(PWM_FLAG_UP == 1))//下降沿判斷上一個狀態是否為上升沿
{
PWM_Duty = timer4_PWM_cnt*2;
}
PWM_FLAG_DOWM=1;//下降沿標誌
PWM_FLAG_UP=2;//下降沿標誌
}
void TIM4_Init(u16 arr,u16 psc)
{
TIM4_Handler.Instance=TIM4; //通用定時器4
TIM4_Handler.Init.Prescaler=psc; //分頻係數
TIM4_Handler.Init.CounterMode=TIM_COUNTERMODE_UP; //向上計數器
TIM4_Handler.Init.Period=arr; //自動裝載值
TIM4_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1; //時鐘分頻因子
HAL_TIM_Base_Init(&TIM4_Handler);
HAL_TIM_Base_Start_IT(&TIM4_Handler);//使能定時器4和定時器4更新中斷:TIM_IT_UPDATE
}
void TIM4_IRQHandler(void)
{
HAL_TIM_IRQHandler(&TIM4_Handler);
if(PWM_FLAG_CNT == 1)//PWM上升沿到來標誌
{
timer4_PWM_cnt++;
}
}