別看原子哥老師的程式碼寫的落落長,
反正就把握一個原則:
測量器TIM8的slave mode用reset mode (即:一有輸入,即觸發一次reset /update 事件)
測量器TIM8的slave mode用reset mode (即:一有輸入,即觸發一次reset /update 事件)
TIM8的trigger是TI1FP1 (即,以timer input filter polarity channel1 做為觸源)
至於direct & indirect ,是看pdf 教材來的
別隨便用chatGPT的code,那會讓你更迷糊的
至於待測物--PWM訊號源的話,先以TIM3 CHANNEL2為PWM源,跳線PB5<->PC6 (TIM8 channel1的GPIO pin),時鐘的基本設定上,因為考量到TIM1的最長週期為65535個count 約0.0009秒,即900微秒...
「這麼短,如果遇到超過1亳秒的週期豈不是掛了」
「先從小的測,測出來正確再放大」
TIM3的初設定:72-1分頻,ARR為100-1,佔空比為50
初版程式如下:
------------------------------------------
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM3_Init();
MX_TIM8_Init();
MX_USART1_UART_Init();
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2);
HAL_Delay(5000);
HAL_TIM_Base_Start(&htim8);
HAL_TIM_IC_Start_IT(&htim8,TIM_CHANNEL_1);
HAL_TIM_IC_Start_IT(&htim8,TIM_CHANNEL_2);
while (1)
{
HAL_Delay(100);
if(1)
{
printf(" period :%i ; hi-time:%i \r\n",period,high_time);
}
}
}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
period = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
high_time = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);
}
------------------------------------------
結果輸出的值是period為7198,hi-time為3598.都要加2才是正確的7200 & 3600
(其中的+1是因為「從0起算」;另一個加一是什麼?知道的朋友請開示一下)
驗算一下:7200* 1/72000000 = 0.0001 sec ,佔空比50%,故為3600 * 1/72000000=0.00005 sec
「那,放大到10ms的週期,要怎麼改?」
「就在TIM8的update事件都加上365536,就這麼簡單」
「可是update事件也可能是因為TIM3 rising edge引發的,也可能是TIM8自己的reset引發的,
如何是好?」
這就好好安排「update 」及「capture compare」兩個中斷的順序了
我們打算先在input capture做一個旗標,確定是真的已經進入了一個偵測流程了(而且要排除在半路遇到下降緣引發的input capture 中斷),日後的update interrupt 再來進行計次,
所以中斷的優先高低是input capture 高於 update
「一定要這麼複雜嗎?」
「一定要,因為預設是update優於input capture」
「一定要,因為預設是update優於input capture」
然後,code小改一下...
1.main那裡要呼叫「__HAL_TIM_ENABLE_IT(&htim8,TIM_IT_UPDATE);」
(別忘了配置了什麼中斷就要用這方式enable起來)
---------------------------------
uint8_t begin_capture=0;
uint32_t overflow_count=0;
//讓timer8一直count下去吧
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM8 && begin_capture==1)
{
overflow_count++;
}
}
//加上over flow之後的推算
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1 )
{
//測得rsing edge,但是否為一個新的測量流程?
if(begin_capture==0)
{
begin_capture=1;
overflow_count=0;
return;
}else{
//測量完畢
begin_capture=0;
//別忘了+2
period = (HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1)+2)+
(overflow_count>0?(65536*(overflow_count-1)):0);
}
}
//測得falling edge ,而且還是「測量中」才算數
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2 && begin_capture==1)
{
high_time = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2)+2+
(overflow_count>0?(65536*(overflow_count-1)):0);
}
}
---------------------------------
我們再去把TIM3改成很長的週期:預分頻為7200-1,ARR為50000-1,pulse為2500
程式輸出結果為
period:360000000 & hi-time:18000000
算一下 360000000*72Mhz=5sec; 18000000 * 72Mhz=0.25秒,
正確無誤,
而且也不必像正點原子哥的程式那麼複雜
「為什麼那個overflow要減一才能乘65536?」
「因為第一次的input capture calback後還是執行了update中斷了,所以要把最初的那次扣掉」
(事實上我也是實驗,先修改/扣除...再回想,才了解這一點的,要學的東西太多了)
附記:
STM32 timer系列可以參考這個播放 清單, 這位老師也是座寶山....
STM32 timer系列可以參考這個播放 清單, 這位老師也是座寶山....