STM32使用串口空闲中断接收不定长数据帧-USART_IT_IDLE使用(不使用DMA方式)
- 前言
- 串口空闲中断介绍
- 清中断方法
- 串口中断处理函数
- 串口中断用到的全局变量定义
- 串口初始化(使能接收中断、空闲中断)
- 使用举例
- 测试结果
前言
最近在使用STM32的HAL库的时候,发现竟然没有集成IDLE中断处理,本身写的HAL库处理逻辑就挺繁琐,效率又不高,还缺胳膊少腿的。平时项目中的串口接收数据都是不定长的,而IDLE中断在这一块作用是非常大的,可以大大简化数据接收过程的判断。本文将介绍基于HAL库IDLE中断接收不定长数据。
串口空闲中断介绍
STM32的IDLE的中断在串口无数据接收的情况下,是不会一直产生的,产生的条件是这样的,当清除IDLE标志位后,必须有接收到第一个数据后,才开始触发,一断接收的数据断流,没有接收到数据,即产生IDLE中断。IDLE位不会再次被置高直到RXNE位被置起(即又检测到一次空闲总线)。RXNE接收中断可以不用开启,减少进中断的次数。
USART_IT_IDLE中断,是串口收到一帧数据后,发生的中断,也可以叫做一包数据。
USART_IT_IDLE和USART_IT_RXNE区别
当接收到1个字节,会产生USART_IT_RXNE中断
当接收到一帧数据,就会产生USART_IT_IDLE中断
注意:串口空闲中断在MDK纯软件仿真模式下,是无法进入串口空闲中断的,必须借助真实的硬件环境(如STM32开发板等)。
清中断方法
__HAL_UART_CLEAR_FLAG(&huart1, UART_FLAG_RXNE);
__HAL_UART_CLEAR_IDLEFLAG(&huart1);
串口中断处理函数
void USART1_IRQHandler(void)
{
uint8_t res = 0;
if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE) != RESET)
{
HAL_UART_Receive(&huart1, &res, 1, 1000);
if(rxConut < RX_BUFFER_SIZE)
{
aRxBuffer[rxConut] = res;
rxConut++;
}
__HAL_UART_CLEAR_FLAG(&huart1, UART_FLAG_RXNE);
}
if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE) != RESET)
{
bFlagOneFrame = true;
rxConut = 0;
__HAL_UART_CLEAR_IDLEFLAG(&huart1);
}
}
串口中断用到的全局变量定义
#define RX_BUFFER_SIZE 256
uint8_t aRxBuffer[RX_BUFFER_SIZE];
uint16_t rxConut = 0;
bool bFlagOneFrame = false;
串口初始化(使能接收中断、空闲中断)
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();
}
__HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE);
__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);
}
使用举例
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "cJSON.h"
#include "main.h"
#include "usart.h"
#include "gpio.h"
#include "cmd_queue.h"
char *strJSON;
cJSON *objJson;
float f1;
char *json_string = "{\"SV\":60,\"KP\":5.0,\"KI\":100,\"KD\":300}";
#define RX_BUFFER_SIZE 256
uint8_t aRxBuffer[RX_BUFFER_SIZE];
uint16_t rxConut = 0;
bool bFlagOneFrame = false;
uint8_t ucTemp;
void USART1_IRQHandler(void)
{
uint8_t res = 0;
if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE) != RESET)
{
HAL_UART_Receive(&huart1, &res, 1, 1000);
if(rxConut < RX_BUFFER_SIZE)
{
aRxBuffer[rxConut] = res;
rxConut++;
}
__HAL_UART_CLEAR_FLAG(&huart1, UART_FLAG_RXNE);
}
if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE) != RESET)
{
bFlagOneFrame = true;
rxConut = 0;
__HAL_UART_CLEAR_IDLEFLAG(&huart1);
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef * huart)
{
}
void test_cjson(void);
void cJsonQueParse(char *str);
void SystemClock_Config(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
queue_reset();
while (1)
{
if(true == bFlagOneFrame)
{
cJsonQueParse((char *)aRxBuffer);
bFlagOneFrame = false;
}
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
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();
}
}
void cJsonQueParse(char *str)
{
cJSON* cjson = cJSON_Parse((const char *)str);
if(cjson == NULL)
{
printf("cjson parse error...\r\n");
}
else
{
char *json_data = cJSON_PrintUnformatted(cjson);
printf("%s\n",json_data);
printf("/*********************以下就是提取的数据**********************/\n");
double fSV = cJSON_GetObjectItem(cjson,"SV")->valuedouble;
printf("SV: %.4f\n",fSV);
double fKP = cJSON_GetObjectItem(cjson,"KP")->valuedouble;
printf("KP: %.4f\n",fKP);
double fKI = cJSON_GetObjectItem(cjson,"KI")->valuedouble;
printf("KI: %.4f\n",fKI);
double fKD = cJSON_GetObjectItem(cjson,"KD")->valuedouble;
printf("KD: %.4f\n",fKD);
free(json_data);
cJSON_Delete(cjson);
}
}
void test_cjson(void)
{
double grade[4]= {66.51,118.52,61.53,128.54};
int time[4]= {123,456,789,150};
cJSON *measurements = cJSON_CreateObject();
cJSON_AddStringToObject(measurements,"AAA","26.55666");
cJSON_AddNumberToObject(measurements,"BBB",13);
cJSON_AddNumberToObject(measurements,"CCC",13.55666);
cJSON_AddFalseToObject(measurements,"gender");
cJSON_AddStringToObject(measurements,"status","0x8000");
cJSON *item1 = cJSON_CreateObject();
cJSON_AddStringToObject(item1,"item1_string","China");
cJSON_AddNumberToObject(item1,"item1_num",2021);
cJSON_AddItemToObject(measurements,"item1",item1);
objJson = cJSON_GetObjectItem(measurements, "AAA");
f1 = strtod(objJson->valuestring, NULL);
char *json_data = cJSON_PrintUnformatted(measurements);
printf("%s\n",json_data);
free(json_data);
cJSON_Delete(measurements);
}
int fputc(int ch,FILE *f)
{
uint8_t temp[1]= {ch};
HAL_UART_Transmit(&huart1,temp,1,2);
}
void Error_Handler(void)
{
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line)
{
}
#endif
测试结果
资料来源:
https://www.cnblogs.com/ZzJan/p/13530768.html
https://blog.csdn.net/zhangxuechao_/article/details/79126474
https://blog.csdn.net/qq_42263055/article/details/114852446
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)