My code does not set the GPIOs as inputs on my Nucleo-G071RB. The MODER register ist completly set (0xffffffff) and the GPIOs work as outputs.
What did I wrong?
Code:
#include <libopencm3/stm32/gpio.h>
void setupGpio(void);
void setupGpio(void) {
// set input
gpio_mode_setup(GPIOB, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, GPIO_ALL);
}
int main(void){
setupGpio();
while (1)
{
// Loop with pin read
}
}
You need to enable peripheral clock first. Not only GPIO but almost all peripherals need this.
Modify your function as below:
void setupGpio(void) {
rcc_periph_clock_enable(RCC_GPIOB); // Enable GPIOB clock
gpio_mode_setup(GPIOB, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, GPIO_ALL);
}
Related
experts.
I am new to STM32.
So I downloaded some sample code from github.
https://github.com/yohanes-erwin/stm32f103-keil
And I download the simple led blinking code of it to the STM32F103C6 developing board but it doesn't work at all.
The original program embedded on the chip had been erased successfully ( originally the led was always on and LCD screen shows some text, but now after I download the code, the led is off and screen off. So I think the downloading is successful.) but the code does not work.
When I download the original code to the chip, it works again. So I think the chip isn't broken.
I think it's because of compatibility of sample code and my chip. The sample code was written for STM32F103C8. But it was a very simple code. What is the reason?
Here is the code.
#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
void delay(unsigned int nCount);
GPIO_InitTypeDef GPIO_InitStruct;
int main (void)
{
// Enable clock for GPIOA
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// Configure PA4 as push-pull output
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
while (1)
{
/* Toggle LED on PA0 */
// Reset bit will turn on LED (because the logic is interved)
GPIO_ResetBits(GPIOA, GPIO_Pin_4);
delay(1000);
// Set bit will turn off LED (because the logic is interved)
GPIO_SetBits(GPIOA, GPIO_Pin_4);
delay(1000);
}
}
// Delay function
void delay(unsigned int nCount)
{
unsigned int i, j;
for (i = 0; i < nCount; i++)
for (j = 0; j < 0x2AFF; j++);
}
I am really new to STM32 world so I came across this while reading:
void HAL_NVIC_SetPendingIRQ(IRQn_Type IRQn);
This will cause the interrupt to fire, as it would be generated by the hardware. A distinctive feature
of Cortex-M processors it that it is possible to programmatically fire an interrupt inside the ISR
routine of another interrupt.
I got this from the book Mastering STM32 (by Carmine Noviello page 208). From this I have understood that If we set this pending bit even from the main function, then the interrupt is generated.
So to try this out, I have written this code:
while (1)
{
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET);
for(int i = 0; i <10000000; i++);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET);
for(int i = 0; i <10000000; i++);
HAL_NVIC_SetPendingIRQ(EXTI0_IRQn);
}
}
along with this call back function
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_PIN){
HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_15);
}
I have programmed GPIO_PIN_0 as source of interrupt and when I press the push button connected to PA0 the Interrupt works perfectly i.e. ISR is executed. To my surprice HAL_NVIC_SetPendingIRQ function doesn't generate interrupt. I don't understand why?
More Info:
I am using STM32F411VET6 DISCO board
I am using STM32CubeIDE to program the board
Thank you #Tagli. I have found the function HAL_GPIO_EXTI_IRQHandler inside stm32f4xx_hal_gpio.c file. Defalult definition was like this:
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);
}
}
I got why the GPIO was not being toggled. It was the same reason you have commented above.
I have modified to prove it.
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
/* EXTI line interrupt detected */
HAL_GPIO_EXTI_Callback(GPIO_Pin);
if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET)
{
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
HAL_GPIO_EXTI_Callback(GPIO_Pin);
}
}
Now the callback function is called when the HAL_NVIC_SetPendingIRQ(EXTI0_IRQn); is being called
Currently I am working on ADC analog watchdog,I want to write a interrupt code for Analog watchdog.I adjusted analog watchdog via reference manual of stm32f4xx and ı started ADC with dma and Analog watchdog timer for interrupt.But when ı run code interrupt doesnt work.What is the problem?
My ADC and DMA Configurations
void adc_ayar()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
ADC_InitStruct.ADC_Resolution=ADC_Resolution_12b;
ADC_InitStruct.ADC_ScanConvMode=ENABLE;
ADC_InitStruct.ADC_ExternalTrigConvEdge=ADC_ExternalTrigConvEdge_None;
ADC_InitStruct.ADC_ExternalTrigConv=0;
ADC_InitStruct.ADC_DataAlign=ADC_DataAlign_Right;
ADC_InitStruct.ADC_ContinuousConvMode=ENABLE;
ADC_InitStruct.ADC_NbrOfConversion=bufferlength;
ADC_Init(ADC1,&ADC_InitStruct);
ADC_CommonInitStruct.ADC_DMAAccessMode=ADC_DMAAccessMode_Disabled;
ADC_CommonInitStruct.ADC_Mode=ADC_Mode_Independent;
ADC_CommonInitStruct.ADC_Prescaler=ADC_Prescaler_Div4;
ADC_CommonInitStruct.ADC_TwoSamplingDelay=ADC_TwoSamplingDelay_20Cycles;
ADC_CommonInit(&ADC_CommonInitStruct);
ADC_Init(ADC1,&ADC_InitStruct);
ADC_ITConfig(ADC1,ADC_IT_AWD,ENABLE);
ADC_Cmd(ADC1,ENABLE);
ADC_DMACmd(ADC1,ENABLE);
ADC_DMARequestAfterLastTransferCmd(ADC1,ENABLE);
ADC1->CR1|=1<<6|1<<23;
ADC_AnalogWatchdogSingleChannelConfig(ADC1,ADC_Channel_0);
ADC_AnalogWatchdogThresholdsConfig(ADC1,2500,300);
ADC_AnalogWatchdogCmd(ADC1,ADC_AnalogWatchdog_SingleRegEnable);
ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_3Cycles);
ADC_ITConfig(ADC1,ADC_IT_AWD,ENABLE);
}
void dma_ayar()
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
DMA_DeInit(DMA2_Stream0);
DMA_InitStruct.DMA_Channel=DMA_Channel_0;
DMA_InitStruct.DMA_Priority=DMA_Priority_VeryHigh;
DMA_InitStruct.DMA_DIR=DMA_DIR_PeripheralToMemory;
DMA_InitStruct.DMA_PeripheralBaseAddr=(uint32_t) & ADC1->DR;
DMA_InitStruct.DMA_Memory0BaseAddr=(uint32_t) & adc_value;
DMA_InitStruct.DMA_BufferSize=2;
DMA_InitStruct.DMA_FIFOMode=DMA_FIFOMode_Enable;
DMA_InitStruct.DMA_FIFOThreshold=DMA_FIFOThreshold_Full;
DMA_InitStruct.DMA_MemoryBurst=DMA_MemoryBurst_Single;
DMA_InitStruct.DMA_PeripheralBurst=DMA_PeripheralBurst_Single;
DMA_InitStruct.DMA_Mode=DMA_Mode_Circular;
DMA_InitStruct.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord;
DMA_InitStruct.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord;
DMA_InitStruct.DMA_MemoryInc=DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
DMA_Init(DMA2_Stream0,&DMA_InitStruct);
DMA_Cmd(DMA2_Stream0,ENABLE);
}
ADC interrupt code
void ADC_IRQHandler()
{
if(ADC_GetITStatus(ADC1,ADC_IT_AWD))
{
sayac++;
GPIO_ToggleBits(GPIOD,GPIO_Pin_12|GPIO_Pin_13);
ADC_ClearITPendingBit(ADC1,ADC_IT_AWD);
}
}
If I have well understand what you want to do, you should use
void HAL_ADC_LevelOutOfWindowCallback(ADC_HandleTypeDef *hadc)
instead of
void ADC_IRQHandler()
So, I am trying to toggle a LED based on an interrupt from a button.
Ideally the when the button is pressed the LED should toggle i.e. switch on if its off and vice versa. But when I execute this code it toggles and returns to its original state.
Expected Result:
LED OFF » Button pressed » LED ON
Practical Result:
LED OFF » Button pressed » LED ON » LED OFF
I have added a delay for debouncing so bouncing is out of the picture. Also the GPIO's ODR is set in the ISR when the button is pressed so how is it getting cleared while exiting the ISR?
I would really appreciate your help! Thank you.
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/exti.h>
#include <libopencm3/cm3/nvic.h>
#define LEDPIN (GPIO13)
static void exti_setup(void)
{
/* Enable GPIOA and AFIO clock. */
rcc_periph_clock_enable(RCC_GPIOB);
rcc_periph_clock_enable(RCC_AFIO);
/* Enable EXTI0 interrupt. */
nvic_enable_irq(NVIC_EXTI15_10_IRQ);
/* Set GPIO12 (in GPIO port B) to input */
gpio_set_mode(GPIOB, GPIO_MODE_INPUT,GPIO_CNF_INPUT_FLOAT, GPIO12);
/* Configure the EXTI subsystem. */
exti_select_source(EXTI12,GPIOB);
exti_set_trigger(EXTI12, EXTI_TRIGGER_BOTH);
exti_enable_request(EXTI12);
}
static void gpio_setup(void)
{
/* Enable clock for GPIO port C */
rcc_periph_clock_enable(RCC_GPIOC);
/* Set LEDPIN (in GPIO port C) as opendrain output */
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, LEDPIN);
}
void delay(){
int i;
for (i = 0; i < 1000000; i++)
{
__asm__("nop");
}
}
void handler(){
delay();
gpio_toggle(GPIOC, GPIO13);
}
int main(void)
{
gpio_setup();
exti_setup();
while (1) {
__asm__("nop");
}
return 0;
}
void exti15_10_isr()
{
exti_reset_request(EXTI12);
handler();
}
Not open drain but push-pull
Butttons should not use EXTI as it makes debouncing more complicated, often floods the uC with interrupts, Use timer interrupt instead to read the key and debounce.
As #dev_eng rightly pointed out the issue was the interrupt being configured as both RISING/FALLING edge.
Configuring it with single EDGE that is either RISING or FALLING solved my problem.
I am trying to set up a communication between my STM32F4 - Discovery with Open 407V-D development board and a peripheral using UART3 as a RS-485 bus.
I have problem with my communication becouse Rx state of UART remain busy.
Could somebody please explain me what am I doing wrong?
Should I somehow edit HAL_UART_IRQHandler or what setting am I missing?
Here is my code:
#include "main.h"
#include "stm32f4xx_hal.h"
UART_HandleTypeDef huart3;
uint8_t Ocular_1_RxBuffer[4];
uint8_t Ocular_1_TxBuffer[2] = {0x01,0x86};
__IO ITStatus UartReady;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART3_UART_Init(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART3_UART_Init();
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET); //set RS 485 into transmit mode
while (1)
{
int Timeout = 1000000;
while(huart3.gState != HAL_UART_STATE_READY) //wait for UART
{
Timeout--;
if(Timeout == 0)
Error_Handler();
}
Timeout = 1000000;
if(HAL_UART_Transmit_IT(&huart3, (uint8_t*)Ocular_1_TxBuffer, 2) != HAL_OK) //Send request
{
Error_Handler();
}
while(huart3.RxState != HAL_UART_STATE_READY) //wait for UART
{
Timeout--;
if(Timeout == 0)
Error_Handler();
}
Timeout = 1000000;
if(HAL_UART_Receive_IT(&huart3, (uint8_t*)Ocular_1_RxBuffer, 4) != HAL_OK) //Response
{
Error_Handler();
}
while(UartReady == RESET) //Wait for response
{
Timeout--;
if(Timeout == 0)
Error_Handler();
}
}
}
I have successfully received response from my peripheral device, but my code generate Error_Handler() after HAL_UART_RxCpltCallback() function.
Could somebody please explain this behavior to me?
My callback functions:
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *UartHandle)
{
/* Set transmission flag: transfer complete */
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);
UartReady = RESET;
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
/* Set transmission flag: transfer complete */
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);
UartReady = SET;
}
Please mention the number of bytes you are receiving in current scenario.?
Some debugging tips are -
Try increasing the size of your buffer and check if you are receiving any data.
Make sure you are re initialising your buffer after 4 bytes are read. If not the buffer can overflow and may lead to error handler.
Make sure you transmitter always sends 4 bytes.
Confirm if your buad rate matches on both devices. Also settings like parity and all are same in receiver and transmitter.
After every 4 bytes you need to call the HAL_UART_Receive_IT() again to configure and wait for next interrupt.
Add Error callback too, and confirm if execution moves to this callback. If then add prints in driver to find out whats the error cause, whether its like overrun error / Noise error / Parity Error etc.