在我寫的代碼中,我選擇 PA1 埠作為輸入,并在這個輸入埠上連接了一個按鈕,然后我給這個按鈕寫了一個中斷。
首先,我這樣寫,它不起作用 EXTI->EXTICR[0] |= (0U << 8*1);
然后,我這樣寫,EXTI->EXTICR[0] |= (1U << 8*3); 它奏效了。
我正在嘗試使 PA1 成為輸入。A = 0 這就是為什么我要寫 0U 而我要寫 8*1 埠是 Px1 的原因。
我的代碼:
/* External interrupt at PA1 port */
EXTI->EXTICR[0] |= (1U << 8*3);
但我認為應該是這樣的,
/* External interrupt at PA1 port */
EXTI->EXTICR[0] |= (0U << 8*1);
你能解釋一下,為什么 PA1 輸入是 (1U << 8 3) 而不是 (0U << 8 1)
當我寫
/* External interrupt at PA1 port */
EXTI->EXTICR[0] |= (1U << 8*3);
至此,程式運行成功。但是我不明白為什么我必須寫(1U << 8 3),我不應該寫(0U << 8 1)嗎?
這是我的完整代碼:
/*
* project name : 05_EXTIbuttonSM
* file name : main.c
*
* author : Cem Furkan Demirk?ran
*
* date : 2022.10.27
*
* description : A state machine blink the external LED at different intervals.
* Assigned each speed to a mode, and attach a button to cycle through the modes.
* Used external interrupts to detect button presses and used the handler to
* change the states. Each button press will cycle through these modes.
*/
#include "stm32g0xx.h"
/* 1 Sec is 1600000 */
void delay(volatile uint32_t);
uint32_t ButtonPress = 0;
/* Interrupt Handlers */
void EXTI0_1_IRQHandler(void){
if (ButtonPress != 5) {
ButtonPress ;
}
else {
ButtonPress = 0;
}
delay(100000);
EXTI->RPR1 |= (1U << 1);
}
int main(void) {
/* Enable GPIOA clock */
RCC->IOPENR |= (1U << 0);
/* Setup PA0 as output */
GPIOA->MODER &= ~(3U << 2*0);
GPIOA->MODER |= (1U << 2*0);
/* Setup PA1 as input */
GPIOA->MODER &= ~(3U << 2*1);
GPIOA->MODER |= (0U << 2*1);
/* External interrupt at PA1 port */
EXTI->EXTICR[0] |= (1U << 8*3);
/* Mask and Rising on Px1 */
EXTI->IMR1 |= (1U << 1);
EXTI->RTSR1 |= (1U << 1);
/* Setup NVIC */
NVIC_SetPriority(EXTI0_1_IRQn, 0);
NVIC_EnableIRQ(EXTI0_1_IRQn);
while(1) {
switch(ButtonPress){
case 0:
/* Turn off LED */
GPIOA->ODR = (0U << 0);
break;
case 1:
/* Turn on LED 2sec interval */
GPIOA->ODR |= (1U << 0);
delay(3200000);
GPIOA->ODR ^= (1U << 0);
delay(3200000);
break;
case 2:
/* Turn on LED 1sec interval */
GPIOA->ODR |= (1U << 0);
delay(1600000);
GPIOA->ODR ^= (1U << 0);
delay(1600000);
break;
case 3:
/* Turn on LED 0.5sec interval */
GPIOA->ODR |= (1U << 0);
delay(800000);
GPIOA->ODR ^= (1U << 0);
delay(800000);
break;
case 4:
/* Turn on LED 0.1sec interval */
GPIOA->ODR |= (1U << 0);
delay(160000);
GPIOA->ODR ^= (1U << 0);
delay(160000);
break;
case 5:
/* Turn on LED */
GPIOA->ODR |= (1U << 0);
break;
}
}
return 0;
}
void delay(volatile uint32_t s) {
for(; s>0; s--);
}
uj5u.com熱心網友回復:
在這種情況下,8 表示每個位域的位數,3 或 1 是您要跳過的整個位域的數量。左邊的 0 或 1 是您在位域中輸入的值。
我建議您在這里使用命名常量而不是幻數,以使代碼更易于閱讀。
如果你這樣做:
EXTI->EXTICR[0] |= (1U << 8*3);
這意味著跳過 8 位中的 3 個欄位,并將值 1 放在第四個欄位中。這會在 PB3 上設定一個中斷。
EXTI->EXTICR[0] |= (0U << 8*1);
這意味著跳過 1 個 8 位欄位并將值 0 放入第二個欄位。這會在 PA1 上設定一個中斷。
另請注意,使用|=您只是設定位。如果外圍設備處于其暫存器全為零的默認復位狀態,那么這很好,但如果您已經寫入要更改的欄位,那么您可能還需要使用&和“~”清除一些位。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/522236.html
下一篇:為什么沒有回傳值?
