I am trying to read a string. I want to make sure the number of LED pulses lets us know many bytes it received. The issue is that I cannot make the LED blink more than two times. I guess that means I am only receiving 2 bytes. What am I doing wrong? If I write a script to send 10 random bytes, the LED only pulses 2 times.
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f4xx_hal.h"
/* USER CODE BEGIN Includes */
#include <stdbool.h>
/* USER CODE END Includes */
/* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart1;
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
volatile uint8_t pdiddy_increment = 0;
int pdiddy[15];
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void Error_Handler(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE END PFP */
/* USER CODE BEGIN 0 */
// detect if anything is in serial buffer
uint8_t Serial_Available(UART_HandleTypeDef *huart)
{
uint32_t RX_State;
RX_State = huart->Instance->SR & UART_FLAG_RXNE;
//something is in the buffer
if (RX_State > 0)
{
return 1;
}
//nothing is there
return 0;
}
void read_reg(UART_HandleTypeDef *huart)
{
uint32_t ORE_State;
pdiddy[pdiddy_increment] = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);
pdiddy_increment++;
ORE_State = huart->Instance->SR & UART_FLAG_ORE;
if (ORE_State)
{
HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
while(1)
{
//do nothing and stay
}
}
}
/* USER CODE END 0 */
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* 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)
{
while (Serial_Available(&huart1))
{
read_reg(&huart1);
HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
HAL_Delay(500);
HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
HAL_Delay(500);
}
}
/* USER CODE END 3 */
}
in read_reg
while(1)
{
//do nothing and stay
}
Is that correct?
in read_reg
while(1)
{
//do nothing and stay
}
Is that correct?
Yes, that is my lazy error handler. Once you get into that, you just need to restart the micro. It never enters that since ORE never trips, so I am going to assume overrun is not the issue.
OK, I changed my code around a little bit so that the read reg function returns something. It looks like it is hitting the ORE flag. Not sure why it never hits that while(1) loop.
I am not even sure why do this change really changed anything at all.
Anyone try something similar? It seems like this is how you would read in a byte at a time I mean, if you go to the HAL, it is essential the same code, but it iterates over the known buffer size instead of the RXNE flag. Not sure why iterating over RXNE would cause on overflow, but iterating over the buffer size does not.
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f4xx_hal.h"
/* USER CODE BEGIN Includes */
#include <stdbool.h>
/* USER CODE END Includes */
/* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart1;
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
uint8_t volatile pdiddy_increment = 0;
int pdiddy[15];
uint8_t value;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void Error_Handler(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE END PFP */
/* USER CODE BEGIN 0 */
// detect if anything is in serial buffer
uint8_t Serial_Available(UART_HandleTypeDef *huart)
{
uint32_t RX_State;
RX_State = huart->Instance->SR & UART_FLAG_RXNE;
//something is in the buffer
if (RX_State > 0)
{
return 1;
}
else
{//nothing is there
return 0;
}
}
uint8_t read_reg(UART_HandleTypeDef *huart)
{
uint32_t ORE_State;
//pdiddy[pdiddy_increment] = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);
//pdiddy_increment++;
ORE_State = huart->Instance->SR & UART_FLAG_ORE;
if (ORE_State>0)
{
//HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
//while(1)
//{
// HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
//do nothing and stay
//}
ORE_State = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);
return 0;
}
//return (pdiddy[pdiddy_increment]);
return (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);
}
/* USER CODE END 0 */
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* 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)
{
while (Serial_Available(&huart1))
{
value = read_reg(&huart1);
if (value == 0)
{
HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
HAL_Delay(900);
HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
HAL_Delay(900);
}
pdiddy_increment++;
}
while (pdiddy_increment>0)
{
HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
HAL_Delay(100);
HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
HAL_Delay(100);
pdiddy_increment--;
}
pdiddy_increment = 0;
}
/* USER CODE END 3 */
}
/** System Clock Configuration
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
/**Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = 16;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = 16;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
RCC_OscInitStruct.PLL.PLLQ = 4;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
/**Configure the Systick interrupt time
*/
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
/**Configure the Systick
*/
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
/* USART1 init function */
static void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
}
/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
PA2 ------> USART2_TX
PA3 ------> USART2_RX
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin : B1_Pin */
GPIO_InitStruct.Pin = B1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(B1_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pins : USART_TX_Pin USART_RX_Pin */
GPIO_InitStruct.Pin = USART_TX_Pin|USART_RX_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pin : LD2_Pin */
GPIO_InitStruct.Pin = LD2_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LD2_GPIO_Port, &GPIO_InitStruct);
}
/* USER CODE BEGIN 4 */
//check to see if anything is in the serial buffer before trying to read
/*uint8_t Serial_Available(UART_HandleTypeDef *huart)
{
uint8_t RX_State;
RX_State = huart->Instance->SR | UART_FLAG_RXNE;
if (RX_State > 0)
{
return 1;
}
else
{
return 0;
}
}*/
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @param None
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler */
/* User can add his own implementation to report the HAL error return state */
while(1)
{
}
/* USER CODE END Error_Handler */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
OK...looks like I need to do it with interrupts.
Sorry to ask off-topic but can you explain this:
ORE_State = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);
why ()(...)? what does this syntax do?
what are -> -> here? I know & is bit-wise "AND".
thanks!
ORE_State = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);
See
C operators.
-> is a structure dereference. Since all peripherals are defined as structure pointers.
(uint8_t)(foo) is an
explicit type conversion.
So you say that:
ORE_State = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);
means that DR is a member of Instance which is a part of haurt? then you "and" it with 0x00ff?
where can I find these peripheral definitions?
Thanks, but I still didn't start using ARM MCUs and that is why I ask. You seem to use Keil not GCC so I guess it will be different.
sorry for jumping in xD
I am using Atollic, which uses GCC.
If you are starting out from scratch, using just GCC with ARM is pretty intimidating (I assume you are doing this all via command line), or I at least think it would be.
Well, I haven't started yet but I read about GCC with Eclipse being the best solution, especially that keil or iar are so pricey and code limited. I am not sure if the limit will be enough for projects.
What is the best way to use ARM MCUs? << this is the most difficult question.
If you are using Atollic with GCC then why that header library form keil? isn't it gonna be different in terms of syntax and all with gcc?
The header library is from STMicro's own drivers with cubemx.
Keil just gives you a tool chain, which gives you a debugging and compile environment (or at least I thought they did)
Eclipse is free, but it has a pretty big learning curve.
Atollic is basically just Eclipse with there own customized GCC compiler. However, they set up the environment for you, so there is no work in that regard.
The question is how you want to learn. Do you want to just use the drivers that ST provides? Or do you want to do everything from scratch? Do you want to learn with a generic JTAG?
There is no best solution.
For syntax, what do you mean? At the end of the day, it is all done in C/C++. Do you mean the constructs of setting up an object or the handler types? That is specific to the driver you use. Do you mean register names? That is specific to the CMSIS library, which should be the same, no matter which platform you use.