Включить прерывание GPIO с нуля

#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. рад, что вы нашли проблему.