In the code I wrote, I chose the PA1 port as an input and connected a button to this input port, then I wrote an interrupt to this button.
first, I write like this and it didn't work EXTI->EXTICR[0] |= (0U << 8*1);
then, I wrote like this, EXTI->EXTICR[0] |= (1U << 8*3); and it worked.
I am trying to make PA1 to be an input. and A = 0 this is why i want to write 0U and i want to write 8*1 cause of port is Px1.
my code :
/* External interrupt at PA1 port */
EXTI->EXTICR[0] |= (1U << 8*3);
But I think it should be like,
/* External interrupt at PA1 port */
EXTI->EXTICR[0] |= (0U << 8*1);
Can you explain, why PA1 input is (1U << 83) and not (0U << 81)
When I write
/* External interrupt at PA1 port */
EXTI->EXTICR[0] |= (1U << 8*3);
This, the program is working successfully. But I didn't understand why I have to write (1U << 83), shouldn't I write (0U << 81)?
This is my FULL code :
/*
* 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--);
}
CodePudding user response:
In this case, 8 means the number of bits per bitfield, and 3 or 1 is the number of whole bitfields you want to skip. The 0 or 1 on the left is the value you put in the bitfield.
I would advise you to use named constants here rather than magic numbers, to make the code easier to read.
If you do:
EXTI->EXTICR[0] |= (1U << 8*3);
This means skip 3 fields each of 8 bits and put the value 1 in the fourth field. This sets up an interrupt on PB3.
EXTI->EXTICR[0] |= (0U << 8*1);
This means skip 1 field of 8 bits and put the value 0 in the second field. This sets up an interrupt on PA1.
Note also that using |=
you are only setting bits. If the peripheral is in its default reset state of having the register at all zeros then this is fine, but if you have already written to the field you want to change then you may also need to clear some bits with &
and '~' too.