#c #embedded #stm32 #interrupt
#c #встроенный #stm32 #прерывать
Вопрос:
Я попытался реализовать код для прерывания GPIO с нуля, но это не работает. Я попытался отладить и просмотреть содержимое каждого регистра, который я использую, они кажутся нормальными. Я публикую соответствующую часть кода, которую я создал, может ли кто-нибудь помочь мне найти ошибку?
Следующая часть кода используется для инициализации порта GPIO, в этом случае я показываю часть, связанную с настройкой режима прерывания.
void GPIO_Init(GPIO_handle_t *pGPIOHandle){ .... //Other non interrupt related code .... //Interrupt mode if(pGPIOHandle-gt;GPIO_PinConfig.GPIO_PinMode == GPIO_MODE_IT_RT){ //Set EXTI to generate an interrupt if rising edge occur and clear of the falling edge EXTI-gt;RTSR1 |= (1 lt;lt; (pGPIOHandle-gt;GPIO_PinConfig.GPIO_PinNumber)); EXTI-gt;FTSR1 amp;= ~(1 lt;lt; (pGPIOHandle-gt;GPIO_PinConfig.GPIO_PinNumber)); }else if(pGPIOHandle-gt;GPIO_PinConfig.GPIO_PinMode ==GPIO_MODE_IT_FT){ //Set EXTI to generate an interrupt if falling edge occur and clear of the rising edge EXTI-gt;FTSR1 |= (1 lt;lt; (pGPIOHandle-gt;GPIO_PinConfig.GPIO_PinNumber)); EXTI-gt;RTSR1 amp;= ~(1 lt;lt; (pGPIOHandle-gt;GPIO_PinConfig.GPIO_PinNumber)); }else if(pGPIOHandle-gt;GPIO_PinConfig.GPIO_PinMode ==GPIO_MODE_IT_RFT){ //Set EXTI to generate an interrupt if rising edge occur and set of the falling edge EXTI-gt;RTSR1 |= (1 lt;lt; (pGPIOHandle-gt;GPIO_PinConfig.GPIO_PinNumber)); EXTI-gt;FTSR1 |= (1 lt;lt; (pGPIOHandle-gt;GPIO_PinConfig.GPIO_PinNumber)); } //Configure the SYSCFG register for the mux selector uint8_t EXTICRx_Index; //EXTICRx index; 0, 1, 2, 3 uint8_t EXTICRx_Position; //Position inside the EXTICRx __RCC_SYSCFG_ENABLE_CLK(); //Clock enable for SYSCFGs EXTICRx_Index = pGPIOHandle-gt;GPIO_PinConfig.GPIO_PinNumber / 4; EXTICRx_Position = pGPIOHandle-gt;GPIO_PinConfig.GPIO_PinNumber % 4; if (pGPIOHandle-gt;pGPIOx == GPIOA){ //Clear and set SYSFG-gt;EXTICR[EXTICRx_Index] amp;= ~(0xf lt;lt; (4 * EXTICRx_Position)); SYSFG-gt;EXTICR[EXTICRx_Index] |= (0x0 lt;lt; (4 * EXTICRx_Position)); }else if(pGPIOHandle-gt;pGPIOx == GPIOB){ //Clear and set SYSFG-gt;EXTICR[EXTICRx_Index] amp;= ~(0xf lt;lt; (4 * EXTICRx_Position)); SYSFG-gt;EXTICR[EXTICRx_Index] |= (0x1 lt;lt; (4 * EXTICRx_Position)); }else if(pGPIOHandle-gt;pGPIOx == GPIOC){ //Clear and set SYSFG-gt;EXTICR[EXTICRx_Index] amp;= ~(0xf lt;lt; (4 * EXTICRx_Position)); SYSFG-gt;EXTICR[EXTICRx_Index] |= (0x2 lt;lt; (4 * EXTICRx_Position)); }else if(pGPIOHandle-gt;pGPIOx == GPIOD){ //Clear and set SYSFG-gt;EXTICR[EXTICRx_Index] amp;= ~(0xf lt;lt; (4 * EXTICRx_Position)); SYSFG-gt;EXTICR[EXTICRx_Index] |= (0x3 lt;lt; (4 * EXTICRx_Position)); }else if(pGPIOHandle-gt;pGPIOx == GPIOE){ //Clear and set SYSFG-gt;EXTICR[EXTICRx_Index] amp;= ~(0xf lt;lt; (4 * EXTICRx_Position)); SYSFG-gt;EXTICR[EXTICRx_Index] |= (0x4 lt;lt; (4 * EXTICRx_Position)); }else if(pGPIOHandle-gt;pGPIOx == GPIOF){ //Clear and set SYSFG-gt;EXTICR[EXTICRx_Index] amp;= ~(0xf lt;lt; (4 * EXTICRx_Position)); SYSFG-gt;EXTICR[EXTICRx_Index] |= (0x5 lt;lt; (4 * EXTICRx_Position)); }else if(pGPIOHandle-gt;pGPIOx == GPIOG){ //Clear and set SYSFG-gt;EXTICR[EXTICRx_Index] amp;= ~(0xf lt;lt; (4 * EXTICRx_Position)); SYSFG-gt;EXTICR[EXTICRx_Index] |= (0x6 lt;lt; (4 * EXTICRx_Position)); }else if(pGPIOHandle-gt;pGPIOx == GPIOH){ //Clear and set SYSFG-gt;EXTICR[EXTICRx_Index] amp;= ~(0xf lt;lt; (4 * EXTICRx_Position)); SYSFG-gt;EXTICR[EXTICRx_Index] |= (0x7 lt;lt; (4 * EXTICRx_Position)); } //Enable the interrupt for that pin EXTI-gt;IMR1 |= (1 lt;lt; (pGPIOHandle-gt;GPIO_PinConfig.GPIO_PinNumber)); } .... //Other no interrupt related code ....
Эта часть кода настраивает NVIC для включения прерывания для этого IRQNumber.
void GPIO_IT_Config(uint8_t IRQNumber, uint8_t EnOrDi){ if(EnOrDi == ENABLE){ if(IRQNumber lt;= 31){ *(NVIC_ISER0) |= (1 lt;lt; IRQNumber); }else if(IRQNumber gt; 31 amp;amp; IRQNumber lt; 64){ *(NVIC_ISER1) |= (1 lt;lt; (IRQNumber % 32)); }else if(IRQNumber gt; 63 amp;amp; IRQNumber lt; 96){ *(NVIC_ISER2) |= (1 lt;lt; (IRQNumber % 64)); } }else if(EnOrDi == DISABLE){ if(IRQNumber lt;= 31){ *(NVIC_ICER0) |= (1 lt;lt; IRQNumber); }else if(IRQNumber gt; 31 amp;amp; IRQNumber lt; 64){ *(NVIC_ICER1) |= (1 lt;lt; (IRQNumber % 32)); }else if(IRQNumber gt; 63 amp;amp; IRQNumber lt; 96){ *(NVIC_ICER2) |= (1 lt;lt; (IRQNumber % 64)); } } }
Эта функция устанавливает приоритет прерывания.
void GPIO_IT_Priority(uint8_t IRQNumber, uint32_t IRQPriority){ //1. first lets find out the ipr register uint8_t iprx = IRQNumber / 4; uint8_t iprx_section = IRQNumber % 4 ; uint8_t shift_amount = ( 8 * iprx_section) ( 8 - 4) ; *( NVIC_PR_BASE_ADDR iprx ) |= ( IRQPriority lt;lt; shift_amount ); }
Комментарии:
1. Есть ли какая-то веская причина для того, чтобы не использовать функции CMSIS для манипуляций с приоритетом NVIC и включения/выключения? Те, кого мы знаем, работают.
2. @энди манго , я хотел бы реализовать свой код из scartch, чтобы улучшить свое понимание встроенного кодирования
3. Я решил ее сам. Ошибка заключалась в том, что я не запрограммировал регистр режима GPIO в качестве входного сигнала.
4. рад, что вы нашли проблему.