![]() |
發布時間: 2025-5-12 23:46
正文摘要:大家好!我最近在學習STM32的外部中斷,遇到一個問題,在這里請教大家。因為程序簡單,附件里也有程序,所以就不畫圖了,大致描述一下: 1,用STM32F103C8T6的最小系統寫了一個最簡單的程 ... |
按鍵消抖了嗎 |
Y_G_G 發表于 2025-5-15 16:23 謝謝,學到了很多知識 |
紅花無常 發表于 2025-5-15 13:52 對于按鍵中斷,并不是絕對需要的,可以不用中斷,直接在主程序中掃描按鍵就可以了 但有時候是要中斷的,比如按鍵級別要求要高的,或者是按鍵要喚醒單片機的,這個時候就會用到中斷 而且,按鍵不是中斷還是在主程序中掃描,都是需要去抖動和識別按鍵的 不然的話,你這個 if(KEY按下) { 按鍵處理相關代碼; } 如果按鍵一直按著,程序就一直在執行 |
Y_G_G 發表于 2025-5-15 10:04 您說的這個意思我能明白,只是,如果這樣的話,是不是中斷都可以不要了,像下面這樣就行了。我一直沒搞清楚的就是這個。 main() { if(KEY按下) { 按鍵處理相關代碼; } } |
紅花無常 發表于 2025-5-14 21:35 假設你是按鍵觸發,那么好,你全聲明一個全局變量 u8 key_f = 0;//這個變量就是用來通知主程序的 在中斷程序中 EXTI9-5中斷 { key_f = 1; } 主程序中 main() { if(key_f) { key_f = 0; 按鍵處理相關代碼; } } key_f 在中斷記錄, 在主程序中清除,這是提供一個思路,原理就大概是這么個原理 |
Y_G_G 發表于 2025-5-14 12:39 好的,謝謝。原則我明白了,具體是通過何種方式實現呢?比如,在觸發中斷后,有一連串的操作,耗時6-7秒。現在我知道,不能在中斷中處理這么多任務,只能在主程序里處理。那么,該怎么通知主程序呢?是讓主程序不斷在while循環里掃描,看中斷標志位是否為1嗎?那樣的話,是不是都可以不用外部中斷了,直接在主程序里掃描那個IO口的電平判斷按鈕是否按下即可。 |
1,中斷中不要做太多的任務,delay這種延時更加不要加,不管是按鍵也好,ADC也好,還是其它的什么,中斷事件只要觸發某個事件的標志就可以了,再在主函數中根據對應的標志進行處理 比如ADC,串口之類的,就只管把數據保存就可以了,不要在中斷中處理,當然,STM32有DMA,那是以后的事了 2,長時間延時,可以用定時器來進行,類似于SysTick的方式,不要死等,讓單片機500mS什么事都不做,這不是一個好習慣 |
lose2836 發表于 2025-5-14 00:06 謝謝!看來問題應該就是出在這里。主函數里有DELAY,主函數正在執行DELAY時,發生了中斷,中斷函數里也有DELAY,中斷函數里執行完DELAY后,關閉了計時器,導致主函數里的DELAY也關閉了。 所以如果在中斷函數里需要延時,最好是用定時計數器重新寫一個。 |
紅花無常 發表于 2025-5-13 10:40 void Delay_us(uint32_t xus) { SysTick->LOAD = 72 * xus; //設置定時器重裝值 SysTick->VAL = 0x00; //清空當前計數值 SysTick->CTRL = 0x00000005; //設置時鐘源為HCLK,啟動定時器 while(!(SysTick->CTRL & 0x00010000)); //等待計數到0 SysTick->CTRL = 0x00000004; //關閉定時器 } 打個斷點仿真下就看到了,中斷運行后卡到了deay函數等待計數到0。感覺是在main中delay時,進入中斷,中斷delay后閉定時器,中斷完回到main中的delay,這時的計數器已經關閉了。卡到“while(!(SysTick->CTRL & 0x00010000));”這一句。在while中添加個檢測計數器是否關閉,如果關閉的,打開計時器。 while(!(SysTick->CTRL & 0x00010000)) //等待計數到0 { if(SysTick->CTRL == 0x00000004) { SysTick->CTRL = 0x00000005; //設置時鐘源為HCLK,啟動定時器 } |
中斷里只要有延時函數,不論長短(即使幾微秒),都會卡死;注釋掉延時函數,就好了。 |
謝謝大家,我剛才把延時全部調整成了1毫秒,問題依然存在。估計是前面那個朋友說的,是延時函數的優先級問題。 |
嗯,一般人很少會在中斷里面用放延時函數的,像你這種直接在中斷里面放4個delay_ms(500)加一個delay_ms(100),更加少見,大概就像,你正常情況下每秒鐘必須呼吸一次(中斷需要要循環訪問,后臺自動控制決定的),然后你訓練拳法,沒呼吸一次要打300拳法(你一個中斷占用了2秒多),你不管你的肺抗不扛得住,憋暈過去也要打完300拳法(你也不管其他中斷會不會沖突是吧,),打完拳你也不呼氣(按鍵中斷的標簽去除了,但是按鍵彈起來了嗎) void EXTI9_5_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line8)==SET) { Delay_ms(100); if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8) == 0) { Buzzer_ON(); Delay_ms(500); Buzzer_OFF(); Delay_ms(500); Buzzer_ON(); Delay_ms(500); Buzzer_OFF(); Delay_ms(500); } } EXTI_ClearITPendingBit(EXTI_Line8); } |
應該是中斷級別的我問題,高級中斷里調用了更高級中斷DELAY(SYSTICK). |
中斷里面不要放軟件延時函數,另外中斷里面的代碼一定要精簡,最好控制在100us以內 |