feat: Enhance UART reception handling with IDLE line detection and hex dump functionality
This commit is contained in:
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"editor.formatOnSave": false
|
||||||
|
}
|
||||||
112
Core/Src/main.c
112
Core/Src/main.c
@ -22,6 +22,8 @@
|
|||||||
/* Private includes ----------------------------------------------------------*/
|
/* Private includes ----------------------------------------------------------*/
|
||||||
/* USER CODE BEGIN Includes */
|
/* USER CODE BEGIN Includes */
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
/* USER CODE END Includes */
|
/* USER CODE END Includes */
|
||||||
|
|
||||||
@ -45,8 +47,9 @@ UART_HandleTypeDef huart1;
|
|||||||
UART_HandleTypeDef huart2;
|
UART_HandleTypeDef huart2;
|
||||||
|
|
||||||
/* USER CODE BEGIN PV */
|
/* USER CODE BEGIN PV */
|
||||||
static uint8_t rx_buf[16];
|
static uint8_t rx_buf[64];
|
||||||
static volatile uint8_t rx_complete = 0;
|
static bool rx_complete = false;
|
||||||
|
static volatile uint16_t rx_length = 0;
|
||||||
/* USER CODE END PV */
|
/* USER CODE END PV */
|
||||||
|
|
||||||
/* Private function prototypes -----------------------------------------------*/
|
/* Private function prototypes -----------------------------------------------*/
|
||||||
@ -55,13 +58,65 @@ static void MX_GPIO_Init(void);
|
|||||||
static void MX_USART1_UART_Init(void);
|
static void MX_USART1_UART_Init(void);
|
||||||
static void MX_USART2_UART_Init(void);
|
static void MX_USART2_UART_Init(void);
|
||||||
/* USER CODE BEGIN PFP */
|
/* USER CODE BEGIN PFP */
|
||||||
|
static void hex_dump(const uint8_t *data, uint16_t len);
|
||||||
/* USER CODE END PFP */
|
/* USER CODE END PFP */
|
||||||
|
|
||||||
/* Private user code ---------------------------------------------------------*/
|
/* Private user code ---------------------------------------------------------*/
|
||||||
/* USER CODE BEGIN 0 */
|
/* USER CODE BEGIN 0 */
|
||||||
static char heartbeat_buf[64];
|
static char heartbeat_buf[64];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Print hex dump in ESP-IDF style
|
||||||
|
* @param data: pointer to data buffer
|
||||||
|
* @param len: length of data
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
static void hex_dump(const uint8_t *data, uint16_t len)
|
||||||
|
{
|
||||||
|
char line_buf[80];
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < len; i += 16) {
|
||||||
|
// Print address
|
||||||
|
int pos = snprintf(line_buf, sizeof(line_buf), "0x%08lx ", (unsigned long)(data + i));
|
||||||
|
|
||||||
|
// Print hex values (first 8 bytes)
|
||||||
|
for (int j = 0; j < 8; j++) {
|
||||||
|
if (i + j < len) {
|
||||||
|
pos += snprintf(line_buf + pos, sizeof(line_buf) - pos, "%02x ", data[i + j]);
|
||||||
|
} else {
|
||||||
|
pos += snprintf(line_buf + pos, sizeof(line_buf) - pos, " ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Space between two groups
|
||||||
|
pos += snprintf(line_buf + pos, sizeof(line_buf) - pos, " ");
|
||||||
|
|
||||||
|
// Print hex values (second 8 bytes)
|
||||||
|
for (int j = 8; j < 16; j++) {
|
||||||
|
if (i + j < len) {
|
||||||
|
pos += snprintf(line_buf + pos, sizeof(line_buf) - pos, "%02x ", data[i + j]);
|
||||||
|
} else {
|
||||||
|
pos += snprintf(line_buf + pos, sizeof(line_buf) - pos, " ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print ASCII representation
|
||||||
|
pos += snprintf(line_buf + pos, sizeof(line_buf) - pos, " |");
|
||||||
|
for (int j = 0; j < 16 && (i + j) < len; j++) {
|
||||||
|
uint8_t c = data[i + j];
|
||||||
|
if (c >= 32 && c <= 126) {
|
||||||
|
pos += snprintf(line_buf + pos, sizeof(line_buf) - pos, "%c", c);
|
||||||
|
} else {
|
||||||
|
pos += snprintf(line_buf + pos, sizeof(line_buf) - pos, ".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pos += snprintf(line_buf + pos, sizeof(line_buf) - pos, "|\r\n");
|
||||||
|
|
||||||
|
// Send line to UART1
|
||||||
|
HAL_UART_Transmit(&huart1, (uint8_t *)line_buf, (uint16_t)pos, HAL_MAX_DELAY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* USER CODE END 0 */
|
/* USER CODE END 0 */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -96,6 +151,8 @@ int main(void)
|
|||||||
MX_USART1_UART_Init();
|
MX_USART1_UART_Init();
|
||||||
MX_USART2_UART_Init();
|
MX_USART2_UART_Init();
|
||||||
/* USER CODE BEGIN 2 */
|
/* USER CODE BEGIN 2 */
|
||||||
|
/* Enable UART IDLE interrupt */
|
||||||
|
__HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE);
|
||||||
/* Start UART2 reception in interrupt mode */
|
/* Start UART2 reception in interrupt mode */
|
||||||
HAL_UART_Receive_IT(&huart2, rx_buf, sizeof(rx_buf));
|
HAL_UART_Receive_IT(&huart2, rx_buf, sizeof(rx_buf));
|
||||||
/* USER CODE END 2 */
|
/* USER CODE END 2 */
|
||||||
@ -121,16 +178,19 @@ int main(void)
|
|||||||
|
|
||||||
/* Check if data received from UART2 */
|
/* Check if data received from UART2 */
|
||||||
if (rx_complete) {
|
if (rx_complete) {
|
||||||
rx_complete = 0;
|
rx_complete = false;
|
||||||
|
uint16_t len = rx_length;
|
||||||
|
|
||||||
/* Print received buffer as hex to UART1 */
|
/* Print header */
|
||||||
char hex_buf[64];
|
char header[32];
|
||||||
int hex_len = snprintf(hex_buf, sizeof(hex_buf), "RX: ");
|
int header_len = snprintf(header, sizeof(header), "RX[%u]:\r\n", len);
|
||||||
for (int i = 0; i < (int)sizeof(rx_buf) && hex_len < (int)sizeof(hex_buf) - 4; i++) {
|
HAL_UART_Transmit(&huart1, (uint8_t *)header, (uint16_t)header_len, HAL_MAX_DELAY);
|
||||||
hex_len += snprintf(hex_buf + hex_len, sizeof(hex_buf) - hex_len, "%02X ", rx_buf[i]);
|
|
||||||
}
|
/* Print received buffer as hex dump */
|
||||||
hex_len += snprintf(hex_buf + hex_len, sizeof(hex_buf) - hex_len, "\r\n");
|
hex_dump(rx_buf, len);
|
||||||
HAL_UART_Transmit(&huart1, (uint8_t *)hex_buf, (uint16_t)hex_len, HAL_MAX_DELAY);
|
|
||||||
|
/* Clear buffer before re-arming */
|
||||||
|
memset(rx_buf, 0, sizeof(rx_buf));
|
||||||
|
|
||||||
/* Re-arm UART2 reception */
|
/* Re-arm UART2 reception */
|
||||||
HAL_UART_Receive_IT(&huart2, rx_buf, sizeof(rx_buf));
|
HAL_UART_Receive_IT(&huart2, rx_buf, sizeof(rx_buf));
|
||||||
@ -297,14 +357,34 @@ static void MX_GPIO_Init(void)
|
|||||||
/* USER CODE BEGIN 4 */
|
/* USER CODE BEGIN 4 */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Rx Transfer completed callback
|
* @brief UART IDLE line detected callback
|
||||||
* @param huart: UART handle
|
* @note This is called from USART2_IRQHandler when IDLE interrupt occurs
|
||||||
* @retval None
|
* @retval None
|
||||||
*/
|
*/
|
||||||
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
|
void UART_IDLE_Callback(UART_HandleTypeDef *huart)
|
||||||
{
|
{
|
||||||
if (huart->Instance == USART2) {
|
if (huart->Instance == USART2) {
|
||||||
rx_complete = 1;
|
if (huart->RxState != HAL_UART_STATE_BUSY_RX) {
|
||||||
|
/* Not in reception state, ignore */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* Calculate how many bytes were actually received */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RxXferCount is a countdown timer maintained by the HAL library that
|
||||||
|
* decrements with each byte received. Subtracting it from the total
|
||||||
|
* gives you the actual number of bytes that made it into the buffer.
|
||||||
|
*/
|
||||||
|
rx_length = sizeof(rx_buf) - huart->RxXferCount;
|
||||||
|
|
||||||
|
/* Only process if we actually received data */
|
||||||
|
if (rx_length > 0) {
|
||||||
|
/* Abort the ongoing reception */
|
||||||
|
HAL_UART_AbortReceive_IT(&huart2);
|
||||||
|
|
||||||
|
/* Signal that data is ready */
|
||||||
|
rx_complete = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -219,7 +219,15 @@ void USART1_IRQHandler(void)
|
|||||||
void USART2_IRQHandler(void)
|
void USART2_IRQHandler(void)
|
||||||
{
|
{
|
||||||
/* USER CODE BEGIN USART2_IRQn 0 */
|
/* USER CODE BEGIN USART2_IRQn 0 */
|
||||||
|
/* Check for IDLE line detection */
|
||||||
|
if (__HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE)) {
|
||||||
|
/* Clear IDLE flag by reading SR and DR */
|
||||||
|
__HAL_UART_CLEAR_IDLEFLAG(&huart2);
|
||||||
|
|
||||||
|
/* Call custom IDLE callback */
|
||||||
|
extern void UART_IDLE_Callback(UART_HandleTypeDef *huart);
|
||||||
|
UART_IDLE_Callback(&huart2);
|
||||||
|
}
|
||||||
/* USER CODE END USART2_IRQn 0 */
|
/* USER CODE END USART2_IRQn 0 */
|
||||||
HAL_UART_IRQHandler(&huart2);
|
HAL_UART_IRQHandler(&huart2);
|
||||||
/* USER CODE BEGIN USART2_IRQn 1 */
|
/* USER CODE BEGIN USART2_IRQn 1 */
|
||||||
|
|||||||
Reference in New Issue
Block a user