I would like to use the pin PC3 as an external interrupt. Whenever I enable the interrupt I end up in the infinite loop.
This is how I init a gpio and its interrupt:
__HAL_RCC_GPIOC_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI3_IRQn);
I have checked hardware and all signals are like they should be.
I tried PB0 and PC3 and the result is the same.
Anyone who knows how to play with stm32l4 and exti?
The infinite loop:
Default_Handler:
Infinite_Loop:
b Infinite_Loop
.size Default_Handler, .-Default_Handler
I dont even reach an interrupt here (I have a break point there)
void EXIT3_IRQnHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_3);
if(!HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_3))
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_7);
HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_14);
}
EXTI_ClearITPendingBit(EXTI3_IRQn);
}
Maybe that is important to mention that I also have SPI configuration in the same project (SPI1).
If ISR name is not correct it will use some default error code (its name depends on configuration), as happens in your case.
In my code its named EXTI3_IRQHandler not EXTI3_IRQnHandler.
Check in your startup file (in my setup it is called startup_stm32l432xx.s) for ISR names to be used.
Related
Currently, I am working on optimizing current consumption by using STOP Mode of the STM32L053C6T6 processor.
I'm facing a problem that I can not get through, and I'm very happy if you can help.
First of all, I would like to explain the algorithm in a very simplified way.
In the while loop, I print to Pc "STARTED" through the UART-Serial converter. Next, I set the RTC alarm to 10 seconds later. And the finally I sleep the MCU by using STOP MODE. After 10 seconds, MCU wakes up properly. So far everything is normal. After MCU wake up, I call the System Clock Config function. I print "woken-up" on the PC screen through UART. I can work this way forever But I do not like the current that circuit consume.
To reduce the power consumption, I set all the pins to analog before entering sleep mode. this method worked very well on reducing current consumption. But after all the pins are analog and MCU goes sleep and wake up, the MCU can not send to string to PC. I think UART Module does not work properly...
But I/O's and systick timer are running. I can understand this by toggling the LED in a certain delay(with HAL_DELAY)
Why I can not make it work with reinit all peripherals?
Here is my main code
int main(void){
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ADC_Init();
MX_I2C1_Init();
MX_RTC_Init();
MX_TIM22_Init();
MX_USART1_UART_Init()
MX_USART2_UART_Init();;
Init_RTC();
HAL_Delay(500);
while(1)
{
printf("Started\n\r");
for(uint16_t count1 = 0;count1<25;count1++){
HAL_GPIO_TogglePin(STATE_LED0_GPIO_Port,STATE_LED0_Pin);
HAL_Delay(25);
}
SetAlarm(10);
EnterStopMode();
printf("Woken-Up\n\r");
HAL_Delay(1000);
}
}
void EnterStopMode(void){
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_All;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* Disable GPIOs clock */
__HAL_RCC_GPIOA_CLK_DISABLE();
__HAL_RCC_GPIOB_CLK_DISABLE();
// STOP Moda girme komutu
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
HAL_Delay(1000);
SystemClock_Config();
HAL_Delay(500);
MX_GPIO_Init();
MX_USART2_UART_Init();
Solved
Well, I checked the Hal functions line by line. And I saw that after first peripheral initialization (uart,i2c,adc etc.), Hal functions do not allow re-init again by checking that particular peripherals instant state.
For example, In HAL_UART_Init(&huart2) function, In order to Init the low level hardware: (GPIO,CLOCK) the instant uart modules state must be UART_STATE_RESET.
In here
if(huart->gState == HAL_UART_STATE_RESET)
{
/* Allocate lock resource and initialize it */
huart->Lock = HAL_UNLOCKED;
/* Init the low level hardware : GPIO, CLOCK */
HAL_UART_MspInit(huart);
}
To overcome this problem, I reset that particular state of peripheral init. Because without not clearing those flags, uart init functions does not enter HAL_UART_MspInit(huart);
I know that is bulky solution, but it works for now.
void EnterStopMode(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/* Configure all GPIO port pins in Analog Input mode (floating input trigger OFF) */
GPIO_InitStruct.Pin = GPIO_PIN_All;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* Disable GPIOs clock */
__HAL_RCC_GPIOA_CLK_DISABLE();
__HAL_RCC_GPIOB_CLK_DISABLE();
HAL_TIM_Base_Stop_IT(&htim22);
HAL_ADC_Stop_IT(&hadc);
/* Enter Stop Mode */
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
/* init the SYS Clocks */
SystemClock_Config();
/*Init IO's */
MX_GPIO_Init();
/* Clear Peripheral States for MspInit *7
huart1.gState = HAL_UART_STATE_RESET;
huart2.gState = HAL_UART_STATE_RESET;
hi2c1.State = HAL_I2C_STATE_RESET;
hadc.State = HAL_ADC_STATE_RESET;
MX_USART2_UART_Init();
MX_USART1_UART_Init();
MX_I2C1_Init();
MX_RTC_Init();
MX_TIM22_Init();
MX_ADC_Init();
HAL_ADCEx_Calibration_Start(&hadc,ADC_SINGLE_ENDED);
}
I am trying to write a simple code to receive and resend data using usart but the code is not working. Can someone give suggestions on the possible flaws in the code.Please note that I am using USART at baud rate 9600 with clock frequency 4MHz.
#include<pic.h>
void main()
{ TRISB=0X00;
TXEN=1;
SYNC=0;
BRGH=1;
SPEN=1;
CREN=1;
//RCEN=1;
SPBRG=0X19;
INTCON=0X80;
TRISC7=1;
TRISC6=0;
RCIE=1;
TXIE=1;
while(1);
}
void interrupt rectrans()
{
if(RCIF==1)
{
TXREG=RCREG;
while(!TRMT);
RCIF=0;
}
else if(TXIF==1)
{TXIF=0;
}
}
I think you should enable GIE bit or Global Interrupt Enable bit for activating any interrupt as you can see from the attached diagram with this answer.. Try to add GIE=1; to enable global interrupt... You can see and AND gate to which GIE bit is connected only all any other interrupt will pass if GIE bit is high
I've bought an STM32F411 nucleo board and now I'm trying to understand various bits and pieces of the HAL. Starting with external interrupts seemed to be a good idea, because the board has a push button which is connected to PC13. So I've set up a simple toggle-the-frequency blinky. The code below is a bit simplified:
#define LED_PIN GPIO_PIN_5
#define BTN_PIN GPIO_PIN_13
static uint32_t blink_period = 250;
int main(void)
{
HAL_Init();
SystemClock_Config();
__GPIOA_CLK_ENABLE();
GPIO_InitTypeDef pinConfig;
pinConfig.Pin = (LED_PIN);
pinConfig.Pull = GPIO_NOPULL;
pinConfig.Mode = GPIO_MODE_OUTPUT_PP;
pinConfig.Speed = GPIO_SPEED_FAST;
HAL_GPIO_Init(GPIOA, &pinConfig);
__GPIOC_CLK_ENABLE();
pinConfig.Pin = (BTN_PIN);
pinConfig.Pull = GPIO_NOPULL;
pinConfig.Mode = GPIO_MODE_IT_FALLING;
pinConfig.Speed = GPIO_SPEED_LOW;
HAL_GPIO_Init(GPIOC, &pinConfig);
HAL_NVIC_SetPriority(EXTI15_10_IRQn, 0x0F, 0x00);
HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
while (1)
{
HAL_GPIO_TogglePin(GPIOA, LED_PIN);
HAL_Delay(blink_period);
}
}
void EXTI15_10_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(BTN_PIN);
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == BTN_PIN)
{
if (blink_period == 500)
{
blink_period = 250;
}
else
{
blink_period = 500;
}
}
}
When I push the button, an interrupt is generated and the blinky frequency changes from 1 to 2 Hz (or vice-versa). This works as intended, but why? I forgot to clear the pending interrupt flag, so the ISR should be called over and over. The datasheet clearly states that
When the selected edge occurs on the external interrupt line, an interrupt request is generated. The pending bit corresponding to the interrupt line is also set. This request is
reset by writing a ‘1’ in the pending register.
Reading a bit further reveals that this is a bit different for events:
When the selected edge occurs on the event line, an event pulse is generated. The pending bit corresponding to the event line is not set.
However, I'm not setting the button pin mode to any of the GPIO_MODE_EVT_... modes so I'm not using the event mechanism (to be honest I don't yet know what that even is - I just think that I'm not using it. Any hints are welcome).
So somewhere I should have to call void HAL_NVIC_ClearPendingIRQ (IRQn_Type IRQn), shouldn't I? It seems that clearing the flag by software is not necessary, because the ISR is not called more than once per falling edge. I've added a breakpoint in HAL_GPIO_EXTI_Callback to verify this.
Edit
As mentioned in the comments, the flag clearing code is in ST's implementation of the GPIO interrupt handler:
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
/* EXTI line interrupt detected */
if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET)
{
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
HAL_GPIO_EXTI_Callback(GPIO_Pin);
}
}
This handler needs to be called by the actual ISR (which is done in my code) and it clears the pending flag corresponding to the GPIO_Pin argument. So I have to write an ISR which sorts out which flags are set, and call HAL_GPIO_EXTI_IRQHandler for each, which in turn calls my HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin), again with the pin as an argument. For each external interrupt, the pin number would get checked some ~3 times (in the ISR, in the handler and in the callback)!
If that is the solution, I want my problem back.
You don't have to call HAL_NVIC_ClearPendingIRQ (IRQn_Type IRQn) because the pending bit in the NVIC will be cleared automatically upon entering HAL_GPIO_EXTI_IRQHandler.
The HAL_GPIO_EXTI_IRQHandler() implementation clears the pending bit in the peripheral, not in the NVIC. If it didn't clear the pending bit by calling __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin), then the handler would be called again and again. The point is that you must distinguish between the interrupt pending bit in the peripheral and the pending bit in the NVIC.
I'm trying to set up an external interrupt on my LPC812 uC. I've made the following code
#include "LPC8xx.h"
#define RLED 7 // red LED
bool pause = false;
void PININT0_IRQHandler(void)
{
pause = !pause;
}
int main(void) {
LPC_GPIO_PORT->DIR0 |= 1<<RLED; // set pin as output
LPC_GPIO_PORT->SET0 = 1<<RLED;
NVIC_EnableIRQ(PININT0_IRQn);
while (1)
{
if(!pause)
{
LPC_GPIO_PORT->CLR0 = 1<<RLED;
}
}
}
But it isn't working. Am I missing something?
I'm not familiar with NXP MCUs.
But at least place break piont inside PININT0_IRQHandler, to understand clearly that interrupt is not generated.
Also it will be nice to clear interrupt flag inside handler.
Some peripherals need interrupt permission in peripheral registers in addition to NVIC setup.
Did you setup input pin somewhere?
Your code only initialize GPIO 7 pin as output.
I have a board that is connected to USB on a STM32F107 with the following pins
USB_OTG_VBUS : PA9
USBDM : PA11
USBDP : PA12
I have a project that needs to use both Virtual Com Port and USB Mass Storage. It needs to re-enumerate the USB then do a software reset to enable the different USB class.
I have tried various different things to get it to re-enumerate but so far have been unable to, the only way to re-enumerate is to unplug usb cable.
These are some of the functions i have tried with no success
USB_OTG_DisableGlobalInt(&USB_OTG_dev);
USB_OTG_WRITE_REG32(&USB_OTG_dev.regs.GREGS->GINTSTS, 0xBFFFFFFF);
USB_OTG_CoreReset(&USB_OTG_dev);
USBD_DeInit(&USB_OTG_dev);
DCD_DevDisconnect(&USB_OTG_dev);
NVIC_SystemReset();
Would anyone have any ideas on how to get the USB to re-enumerate when it is configured with only these 3 pins for the STM32F107?
If you're using a demo board, it has the functionality to disconnect the USB through a microcontroller pin. If you're not using a demo board, you need to come up with that ability yourself, by disconnecting the pull-up resistor on the USB_DM/USB_DP line...
Before initializing USB peripheral, configure D+ pin (USBP) as GPIO output push-pull and set low (0V) for 5ms. Then initiate standard USB configuration including GPIO. After this procedure USB host recognizes new device and starts enumeration.
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA, GPIO_Pin_12);
delay_ms(5);
//call your USB Init here
Worked for me.
source
Had a similar problem. Try this:
USB_OTG_dev.regs.GREGS->GCCFG = 0;
Wait a bit and then init the USB again.
I used the answer from #viteo and tweaked it a little as I had some compile errors. This code works on the Blue Pill development board (STM32F103C8), which includes a 1.5k pullup resistor on the PA12 (USB_DP) line. Therefore, this code forces the USB_DP line low for a short time, which is like the USB cable has been unplugged and reconnected, thereby forcing the host to re-enumerate the bus when the USB is subsequently configured.
Edit USB_DEVICE/App/usb_device.c and add the code inside the USB_DEVICE_Init_PreTreatment block
void MX_USB_DEVICE_Init(void)
{
/* USER CODE BEGIN USB_DEVICE_Init_PreTreatment */
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_RESET);
HAL_Delay(100);
/* USER CODE END USB_DEVICE_Init_PreTreatment */