2023年4月12日 星期三

for stm32,如果要在GPIO的EXTI中斷處理裡面用delay的話,怎麼設計比較好

或許你會直接想說那好辨,就是在 HAL_GPIO_EXTI_Callback 裡做HAL_Delay
但是這會讓你debug到死都會在HAL_Delay裡完成不了,為什麼?
因為預設的SysTick的優先序是排到15去,而後續定義的EXTI的優先層級都比它還高
當然是SysTick在EXTI call back裡會死在那裡 ,參考這裡說明
所以,要調整一下下兩者間的NVIC優先序,如下圖
-------------------------------------


-------------------------------------
這樣就可以在HAL_GPIO_EXTI_Callback 裡呼叫HAL_Delay了
為什麼SysTick會被安排到這麼後面的優先序裡去?可能是因為分時多工會用到
既然是分時多工之用,那一定是會有時間分割上的出入,自然不若GPIO那樣要即時處理電位起伏帶來的事件/中斷來得緊急(優先)之故,畢竟GPIO是在最前線作戰的單位,其所關注的事件一定是有很高的優先處理順序.這點很合理的
「可是,如果我要delay到小於1毫秒的delay,或是不想去修改它們的優先序,如何是好?」
如果不想用Standard Peripheral Library的用操作SysTick暫存器的寫法的話,可以用Timer對counter增減的方式來做delay的依據
參方這位老師的教學,(prescaler 72-1=  72MHz/72 -> 1MHz--> 1us ) 注意,是微秒級,不是奈秒.
-------------------


--------------------
並在main.c裡加入delay_us函數.(當然你也要有「MX_TIM1_Init();」跟「HAL_TIM_Base_Start(&htim1);」啟用TIM1)
-------------------
void delay_us (uint16_t us)
{
	__HAL_TIM_SET_COUNTER(&htim1,0);  // set the counter value a 0
	while (__HAL_TIM_GET_COUNTER(&htim1) < us);  // wait for the counter to reach the us input in the parameter
}
-------------------
之後,再回到我們之前要處理的「HAL_GPIO_EXTI_Callback 」使用它
------------假設我們設定的是下降緣觸發事件--------------
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{   
       //delay一下,事緩則圓--消除突波之用
        delay_us(1000*50);
        delay_us(1000*50);
        //如果此時按鈕線被拉回高電位的話,不處理
        //密技:即便是用在中斷模式,stm32的GPIO 腳位還是可以讀取狀態的
        if(HAL_GPIO_ReadPin(BUTTON_KEY1_GPIO_Port,BUTTON_KEY1_Pin)==  GPIO_PIN_SET)
        {
          return;
        }
       //是的,已經確定是按下狀態
      //處理中 ...
       ....
------------------------------------------------------------------
以上.
(科班出身的都那麼拚了,那非本科出身的,豈不是要更努力才行了?)