历史上的今天
今天是:2025年02月12日(星期三)
2019年02月12日 | STM32-USART HAL库接收任意长度数据详细解析
2019-02-12 来源:eefocus
前言:
最近在调试STM32L152 HAL库串口接收任意长度数据程序,详细解析下接收任意长度数据的方法。
硬件平台:STM32L152
软件平台:keil v5+cubeMX
函数库:HAL库
STM32L152 —USART
STM32L152 USART 的HAL库中接收函数:
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
该函数的参数Size固定,使用时很不方便,只能接收固定长度的数据。
本文详细解析HAL库UASRT接收函数并修改成接收任意长度。PS:仅适用于接收数据结尾为换行符0x0a,若接收数据为其他格式,可根据数据的特点进行修改。
1.HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 200);
开始接收终端,设定一个初始长度200,接收的任意字节数不大于200就行。
2.中断处理函数
void USART1_IRQHandler(void)
{
HAL_UART_IRQHandler(&huart1);
}
3.在HAL_UART_IRQHandler(&huart1)的定义找到接收终端函数 :UART_Receive_IT(huart);
void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
{
uint32_t tmp_flag = 0, tmp_it_source = 0;
tmp_flag = __HAL_UART_GET_FLAG(huart, UART_FLAG_PE);
tmp_it_source = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_PE);
/* UART parity error interrupt occurred ------------------------------------*/
if((tmp_flag != RESET) && (tmp_it_source != RESET))
{
huart->ErrorCode |= HAL_UART_ERROR_PE;
}
tmp_flag = __HAL_UART_GET_FLAG(huart, UART_FLAG_FE);
tmp_it_source = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_ERR);
/* UART frame error interrupt occurred -------------------------------------*/
if((tmp_flag != RESET) && (tmp_it_source != RESET))
{
huart->ErrorCode |= HAL_UART_ERROR_FE;
}
tmp_flag = __HAL_UART_GET_FLAG(huart, UART_FLAG_NE);
/* UART noise error interrupt occurred -------------------------------------*/
if((tmp_flag != RESET) && (tmp_it_source != RESET))
{
huart->ErrorCode |= HAL_UART_ERROR_NE;
}
tmp_flag = __HAL_UART_GET_FLAG(huart, UART_FLAG_ORE);
/* UART Over-Run interrupt occurred ----------------------------------------*/
if((tmp_flag != RESET) && (tmp_it_source != RESET))
{
huart->ErrorCode |= HAL_UART_ERROR_ORE;
}
tmp_flag = __HAL_UART_GET_FLAG(huart, UART_FLAG_RXNE);
tmp_it_source = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_RXNE);
/* UART in mode Receiver ---------------------------------------------------*/
if((tmp_flag != RESET) && (tmp_it_source != RESET))
{
UART_Receive_IT(huart);
}
tmp_flag = __HAL_UART_GET_FLAG(huart, UART_FLAG_TXE);
tmp_it_source = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_TXE);
/* UART in mode Transmitter ------------------------------------------------*/
if((tmp_flag != RESET) && (tmp_it_source != RESET))
{
UART_Transmit_IT(huart);
}
tmp_flag = __HAL_UART_GET_FLAG(huart, UART_FLAG_TC);
tmp_it_source = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_TC);
/* UART in mode Transmitter end --------------------------------------------*/
if((tmp_flag != RESET) && (tmp_it_source != RESET))
{
UART_EndTransmit_IT(huart);
}
if(huart->ErrorCode != HAL_UART_ERROR_NONE)
{
/* Clear all the error flag at once */
__HAL_UART_CLEAR_PEFLAG(huart);
/* Set the UART state ready to be able to start again the process */
huart->State = HAL_UART_STATE_READY;
HAL_UART_ErrorCallback(huart);
}
}.
4.接下来是修改UART_Receive_IT(huart) 函数;
u8 flag,Rx_Size;
static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart)
{
uint16_t* tmp;
uint32_t tmp_state = 0;
tmp_state = huart->State;
if((tmp_state == HAL_UART_STATE_BUSY_RX) || (tmp_state == HAL_UART_STATE_BUSY_TX_RX))
{
if(huart->Init.WordLength == UART_WORDLENGTH_9B)
{
tmp = (uint16_t*) huart->pRxBuffPtr;
if(huart->Init.Parity == UART_PARITY_NONE)
{
*tmp = (uint16_t)(huart->Instance->DR & (uint16_t)0x01FF);
huart->pRxBuffPtr += 2;
}
else
{
*tmp = (uint16_t)(huart->Instance->DR & (uint16_t)0x00FF);
huart->pRxBuffPtr += 1;
}
}
else
{
if(huart->Init.Parity == UART_PARITY_NONE)//本例串口为非奇偶校验
{
*huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);
if(((uint8_t)(huart->Instance->DR & (uint8_t)0x00FF))==0x0a) flag++; //当收到0x0A换行符时认为接收结束。
Rx_Size++;
}
else
{
*huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x007F);
}
}
// if(--huart->RxXferCount == 0) // 原程序根据设定的接收缓存RxXferCount减为0时认为接收结束,注释掉,修改为if(flag== 1);
if(flag== 1)
{
flag=0;
__HAL_UART_DISABLE_IT(huart, UART_IT_RXNE);
/* Check if a transmit process is ongoing or not */
if(huart->State == HAL_UART_STATE_BUSY_TX_RX)
{
huart->State = HAL_UART_STATE_BUSY_TX;
}
else
{
/* Disable the UART Parity Error Interrupt */
__HAL_UART_DISABLE_IT(huart, UART_IT_PE);
/* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */
__HAL_UART_DISABLE_IT(huart, UART_IT_ERR);
huart->State = HAL_UART_STATE_READY;
}
HAL_UART_RxCpltCallback(huart);
return HAL_OK;
}
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
5.编写UART串口回调函数,重新开启接收中断并清标志;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance==USART1)
{
HAL_UART_Transmit(&huart3 ,(uint8_t *)aRxBuffer,Rx_Size ,200);//用串口3打印出 来接收的数据,可忽略
HAL_UART_Receive_IT(&huart1,(uint8_t *)aRxBuffer, 200);//重新开中断
for(u8 i=0;i Rx_Size=0;//清除接收的计数,下次接收重新计数 } } 以上修改,便可接收结尾为0x0a的任意长度的数据。但修改HAL库并不是一个好的解决方法;若别人要移植你的程序,会给别人移植程序带来困难。
下一篇:STM32—RTC
史海拾趣
|
不管我们是否要控制输出电压或输出电流,Boost调节器都要比Buck调节器更难设计。持续导通状态(CCM)Boost转换器中的平均感应电流等于负载电流(LED电流)乘以1/(1-D),这里D是占空度。Boost电压调节器需要设计者考虑到输入电压的限制来保证电感的 ...… 查看全部问答> |
|
ucos ii 下GPRS模块通过拨号方式进行tcp连接,不知如何下手? 现在mcu是stm32 芯片,gprs模块是华为gtm900 ,通过查找资料如果不用模块内部的协议栈的话,自己得在ucos ii上实现ppp协议与tcp/ip协议栈,现在在网上下载了ucip1-0-3,里面就是src 目录下,有相关代码,里面还有makefile,似乎应该在li ...… 查看全部问答> |
|
有谁能给个数字示波器测试开关电源时主要测试的项目;例如初级采样电阻的测量,整流桥输出波形测试; 以及输出波形测试,PWM波形测试时候的注意事项,没用过数字示波器测试,担心损坏,当时用的是模拟示波器,表笔负极与电源的地线相连;当时是选 ...… 查看全部问答> |
|
软件操作说明:1、本软件是纯绿色软件,无需安装,解压直接使用。2、设置pdf保存地址,Save Path为保存地址,默认是在桌面,点后面Change,更改pdf保存地址。2、Part Name 栏输入需要查找器件的名称(至少包含三个字符),然后单击“Search”或者回 ...… 查看全部问答> |
|
本辅导资料介绍了利用嵌入式开发套件(EDK)创建和测试硬件处理器系统设计的步骤。本辅导资料的系统要求如下:Xilinx Spartan-3A DSP 开发板(XC3SD1800A-4FGG676C)EDK 11.1ISE® 11.1 赛灵思EDK套件是帮助工程师在赛灵思FPGA器件内实现嵌入式 ...… 查看全部问答> |
|
今天用Launchpad的ADC10做了一个采集片内温度,12864显示。 这个程序 只贴部分吧了,至于12864串行显示模块,大家看我前面的帖子吧, 完整的程序可以实现温度的测量了,就是我对参考电压选择还是有点不理解,求大神指点一二! unsigned char s1[]={\"当前片内温度显示\"}; unsigned char s2[]={\"温度: ...… 查看全部问答> |
|
基于LM4f120 launchpad和扩展板的,直接上传 1、串口 2、显示BMP 3、触摸屏校准 4、触摸屏应用-写字 $(\'flv_qEM\').innerHTML=(AC_FL_RunContent(\'width\', \'500\', \'height\', \'375\', \'allowNetworking\', \'internal\', ...… 查看全部问答> |
|
【晒心得】STM32F03开发板--点亮LEDS(寄存器操作) 昨天在CoIDE环境下使用固件库写的程序,今天想用一下操作寄存器的方法,跟51、msp430单片机一样配置寄存器。 STM32F0308开发板-上LED的电路图: 从图中可以看出两个发光二极管负极接地,那么要点亮LED,只需要将STM32的PC8、PC9的相应引脚上输出高 ...… 查看全部问答> |




