2025-02-13 6:50 AM - last edited on 2025-02-13 7:57 AM by mƎALLEm
I'm using an STM32G071G8U6TR and a CP2102N-Axx-xQFN28 to communicate over USB. I am managing to get messages onto the STM32 but it seems that the first few characters of the message are coming through jumbled,
#include "main.h"
#include "UART_Polling.h"
#include "stdbool.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart2;
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART2_UART_Init(void);
/* USER CODE BEGIN PFP */
static uint16_t Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength);
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
uint32_t cycle;
/*********************** 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 *************/
uint8_t tx_buff[] = {65, 66, 67, 68, 69, 70, 71, 72, 73, 74}; //Transmitter Buffer
uint8_t true_buff[] = {77, 101, 115, 115, 97, 103, 101, 32, 114, 101, 99, 101, 105, 118, 101, 100, 10, 13}; //True buffer - 18 Characters long
uint8_t false_buff[] = {78, 111, 32, 109, 101, 115, 115, 97, 103, 101, 10, 13}; //False buffer - 12 Characters long
uint8_t v_set_buff[] = {86, 97, 108, 117, 101, 32, 115, 101, 116, 32, 65, 51, 51, 46, 52, 10, 13}; //Value Set buffer - 17 characters long
uint8_t i_set_buff[] = {73, 110, 99, 114, 101, 109, 101, 110, 116, 32, 115, 101, 116, 32, 51, 51, 46, 52, 10, 13}; //Increment Set buffer - 20 Character long
uint8_t idn_buff[] = {"FLANN MICROWAVE"};
uint8_t status_ref[] = {48, 48, 48, 48, 48, 48, 48, 48, 10, 13}; //Status bit - 10 characters long
uint8_t comm_error[] = {"UNKNOWN COMMAND"};
uint8_t rx_buff[30] = {"##############################"};
uint8_t process_buff[30] = {"##############################"};
uint8_t i=0;
uint8_t temp = 0;
bool uart_received = false;
bool query;
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
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();
/* 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_USART2_UART_Init();
/* USER CODE BEGIN 2 */
HAL_GPIO_WritePin(debug_LED_GPIO_Port, debug_LED_Pin, GPIO_PIN_SET);
HAL_UART_Receive_IT(&huart2, rx_buff, 10);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
//PollingInit();
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if (rx_buff[0] != 0x23)
{
while(i<30)
{
if (rx_buff[i] == 0x3F) // If ?
{
tx_buff[0] = 0x74; //t
tx_buff[1] = 0x65; //e
tx_buff[2] = 0x73; //s
tx_buff[3] = 0x74; //t
tx_buff[4] = 0x20; //' '
tx_buff[5] = 0x72; //r
tx_buff[6] = 0x65; //e
tx_buff[7] = 0x63; //c
tx_buff[8] = 0x65; //e
tx_buff[9] = 0x69; //i
tx_buff[10] = 0x76; //v
tx_buff[11] = 0x65; //e
tx_buff[12] = 0x64; //d
tx_buff[13] = 0x0A;
tx_buff[14] = 0x0D;
HAL_UART_Transmit_IT(&huart2, tx_buff, 15);
}
if (rx_buff[i] > 96)
{
process_buff[i] = rx_buff[i] - 32;
rx_buff[i] = 0x23;
}
else
{
process_buff[i] = rx_buff[i];
rx_buff[i] = 0x23;
}
if (process_buff[i] == 0x3F)
{
query = true;
HAL_GPIO_TogglePin(debug_LED_GPIO_Port, debug_LED_Pin);
}
HAL_Delay(100);
i++;
}
process_buff[28] = 0x0A;
process_buff[29] = 0x0D;
HAL_UART_Transmit_IT(&huart2, process_buff, 30);
tx_buff[i] = 10;
i++;
tx_buff[i] = 13;
//HAL_UART_Transmit_IT(&huart2, tx_buff, 15);
HAL_Delay(1000);
i = 0;
while (i < 30)
{
rx_buff[i] = 0x23;
i++;
}
}
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief USART2 Initialization Function
* None
* @retval None
*/
static void MX_USART2_UART_Init(void)
{
/* USER CODE BEGIN USART2_Init 0 */
/* USER CODE END USART2_Init 0 */
/* USER CODE BEGIN USART2_Init 1 */
/* USER CODE END USART2_Init 1 */
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart2.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetTxFifoThreshold(&huart2, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetRxFifoThreshold(&huart2, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_DisableFifoMode(&huart2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART2_Init 2 */
/* USER CODE END USART2_Init 2 */
}
/**
* @brief GPIO Initialization Function
* None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(debug_LED_GPIO_Port, debug_LED_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin : debug_LED_Pin */
GPIO_InitStruct.Pin = debug_LED_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(debug_LED_GPIO_Port, &GPIO_InitStruct);
/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}
/* USER CODE BEGIN 4 */
/**
* @brief Compares two buffers.
* pBuffer1, pBuffer2: buffers to be compared.
* BufferLength: buffer's length
* @retval 0 : pBuffer1 identical to pBuffer2
* >0 : pBuffer1 differs from pBuffer2
*/
static uint16_t Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength)
{
while (BufferLength--)
{
if ((*pBuffer1) != *pBuffer2)
{
return BufferLength;
}
pBuffer1++;
pBuffer2++;
}
return 0;
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
uart_received = true; /*Set Message Received varible*/
HAL_UART_Receive_IT(&huart2, rx_buff, 30); /*Load the message into the rx buffer*/
}
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
This is the code I am currently using. At the moment once it receives a message it's meant to scan through and check for a '?', if it does see this it responds with 'test received' and then loads the received buffer into another buffer before sending that back. When I use PuTTY to send messages I get these responses.
The message sent is CL_VALUE_SET? I get a good response for the first message, the second time I send a message I don't get any response and the third time it doesn't see the ? it seems.
2025-02-13 7:52 AM
Hello @GTann.1
Please refer to the example Projects/STM32G081B-EVAL/Examples/UART/UART_HyperTerminal_DMA to implement your application.
2025-02-13 8:04 AM - edited 2025-02-13 8:05 AM
Doesn't seem to be any synchronization between reception and processing.
The call-back is waiting for a lot of characters, and not entirely consistent from first to second. Doesn't clear the buffer, and doesn't really know how much valid data has been received.
Things that need to be volatile, and not.
Might I suggest starting with collecting singular characters, and using a circular buffering scheme, where you can determine the amount of data available to work with.
2025-02-26 6:08 PM
First, you enabled the UART interrupt for 10 bytes but your CL_VALUE_SET? is 13 bytes, or 14/15 if your console send CR and/or LF. For explanation on what's happening, we'll just assume your console sends a LF after the text.
So the first interrupt your buffer will have CL_VALUE_S because you set to receive 10 bytes. You set the flag for uart_received, but where do you check for the flag? Anyways.
Then you enable interrupt again, but for 30 bytes. But the UART is currently filling the buffer with the rest of the text, ET?\n but you won't get an interrupt yet because you are waiting for 26 more bytes.
However, in your while loop you iterate through the 30 bytes and find the ? in ET?\n. That is why you get a response the first time.
After that it looks like you set your Rx buffer with "#" symbols. Not sure why? From here, things are getting out of sync.
So what you're doing is not a great approach as you're setting the interrupt for a specific amount of bytes but if your string messages are different lengths, things are not going to work as you would like. You need to either interrupt on 1 bytes at time and save the byte to a circular buffer to parsed outside of the callback, or use UART with idle detection.
You should learn to use sprintf or snprintf so you don't have to write one character for each index of the array. And use strlen to get the length of the string.
sprintf((char*)tx_buff, "test received");
HAL_UART_Transmit_IT(&huart2, tx_buff, strlen((char*)tx_buff));
See the attached project which uses a NUCLEO-G071RB, the same family as your STM32. It uses UART DMA (circular mode) with idle detection.
Here is a screenshot of Docklight communicating with the Nucleo
See this github project which explains how the DMA in circular mode with idle detection works and how to save data to a circular buffer and parse the data to a message queue
https://github.com/karlyamashita/Nucleo-G071RB_UART_DMA_Idle_Circular/wiki