STM32F103 UART button event delay slow - stm32

I'm testing very basic transmission with UART1 on my STM32F103C8T6 using CUBE MX and Keil v5.
I've prepared project in CUBE MX enabling UART and went to Keil.
All is working fine to be honest, if I press button on board (PA0), transmitted string changes correctly from stringa1 to stringa2, but it stays on stringa2 for 3 or 4 cycles even if I press and release the button very quickly.
It seems like a problem of synchronization or sort of timing, in shorts, even if button has been released, HAL is sending stringa2 like I have still my finger on button PA0.
What could be the problem?
int main(void)
{
/* USER CODE BEGIN 1 */
char *stringa1 = "ciao\r\n";
char *stringa2 = "pressed\r\n";
/* USER CODE END 1 */
/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/*
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
HAL_Delay(500);
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
HAL_Delay(500);
*/
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)){
HAL_UART_Transmit(&huart1, (uint8_t*) stringa1, strlen(stringa1), 10);
} else {
HAL_UART_Transmit(&huart1, (uint8_t*) stringa2, strlen(stringa2), 10);
}
HAL_Delay(500);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}

Related

How can I use hardware timer with cmsis-rtos2?

I know very well how to setup timer with hal API in stm32cubemx but I'm new to keil-rtx and cubemx does not support it. I wanna have a timer with less than 1 ms interval.
I want to know how to use hardware timer with rtos2?
I'm using stm32f407 microcontroller.
I've already increased kernel tick frequency and configured RTOS timer but it's not a good solution.
Here's an example of using the timer on the STM32F407 microcontroller with a 1 millisecond period:
#include "stm32f4xx.h"
void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
// Code to be executed every 1 millisecond
}
}
void TIM3_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 999;
TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t)(SystemCoreClock / 1000000) - 1;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
/* TIM IT enable */
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
/* Enable the TIM3 global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* TIM3 enable counter */
TIM_Cmd(TIM3, ENABLE);
}
int main(void)
{
/* TIM3 configuration */
TIM3_Config();
while (1)
{
// main loop code
}
}
This code sets up TIM3 as a timer with a 1 millisecond period. The interrupt service routine (ISR) TIM3_IRQHandler will be called every 1 millisecond and execute the code inside it.
You can use any timer you want.
Read the reference manual of your STM and you can program it bare metal or using STM-supplied libraries.

Bootloader Jump the Application I2C problem

I am trying to jump user application from boot code:
Boot code only include below lines:
int main()
{
HAL_Init();
SystemClock_Config();
// Jump proccess start
uint32_t reset_handler_add=*((volatile uint32_t*)(FLASH_APP_START_ADDRESS+4));
void (*app_reset_handler)(void) = (void*)reset_handler_add;
HAL_RCC_DeInit();
HAL_DeInit();
__HAL_RCC_SYSCFG_CLK_DISABLE();
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
__disable_irq();
SCB->VTOR = FLASH_APP_START_ADDRESS;
uint32_t msp_value = *((volatile uint32_t*)(FLASH_APP_START_ADDRESS));
__set_MSP(msp_value);
app_reset_handler();
while(1);
}
Also #define FLASH_APP_START_ADDRESS 0x080A0000 this is application code start address.
But when I jump the User application I2C not working .
In the User application I stuck in while (HAL_I2C_GetState(hi2c) != HAL_I2C_STATE_READY) function when I jump the User App. But If User App work on the base 0x080000000 address everything successfull, When I jump I have problem.
I changed flash.Ld file on User app:
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K
CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K
FLASH (rx) : ORIGIN = 0x080A0000, LENGTH = 256K
}
And changed #define VECT_TAB_OFFSET 0xA0000 value.
Where is the faults ?
There is an I2C init problem in stm32 microcontrollers. I dont know if your issue is related to the bootloader code but I had the same symptoms.
The easiest fix I found for this is to init the I2C clk before initializing the SDA and SCL pins:
void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(i2cHandle->Instance==I2C1)
{
/* USER CODE BEGIN I2C1_MspInit 0 */
/* USER CODE END I2C1_MspInit 0 */
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_I2C1_CLK_ENABLE(); // <------ move this line here
/**I2C1 GPIO Configuration
PB6 ------> I2C1_SCL
PB7 ------> I2C1_SDA
*/
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
...

STM32 UART : HAL_UART_Transmit_IT Not working with Task

My UART tx Working with blocking mode and before FreeRtoss kernel start. But if I try to transmit inside task Not working( see below code ). Is any special code needed ?
enter code here
void StartDefaultTask(void *argument)
{
/* USER CODE BEGIN 5 */
/* Infinite loop */
for(;;)
{
HAL_UART_Transmit_IT(&huart2, hi, sizeof(hi));
osDelay(1000);
}
/* USER CODE END 5 */
}

STM32F103 | libopencm3 | GPIO toggle using interrupt issue

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.

uVision Led lights

This is the first time i am programming a mikrokontroler, i'm using uVison and have an stm32 to program on.,
I have two LED light on it on the pins: PIN_4 and PIN_5 with a tutorial i know how to make one blink (the code below) but i dont know how to make them bot blink with not the same delay. Like i want to make PIN_4 led be wit a delay of 100ms and PIN:5 led with a delay of 50ms. The code below is the code for one Led light.
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_4); //Toggle the state of pin PC9
HAL_Delay(100); //delay 100ms
}
/* USER CODE END 3 */
}
You have 2 options.
First, you can set a timer for counting milliseconds. You can generate a code from STMCubeMX for 50ms timer. Then, in timer callback function, you should set pins to high or low.
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
timer_counter++; //50ms
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_5);
if(timer_counter>=2) //100ms
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_4);
timer_counter = 0;
}
}
Second option is that delay in main.
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_5); //Toggle the state of pin PB5
HAL_Delay(50); //delay 50ms
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_4); //Toggle the state of pin PB4
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_5); //Toggle the state of pin PB5
HAL_Delay(50); // delay 50ms
}
/* USER CODE END 3 */
}