历史上的今天
返回首页

历史上的今天

今天是: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库并不是一个好的解决方法;若别人要移植你的程序,会给别人移植程序带来困难。

推荐阅读

史海拾趣

Array Microsystems Inc公司的发展小趣事

随着技术的不断成熟和产品的广泛应用,Array Microsystems Inc开始寻求市场拓展的机会。公司积极与各大电子设备制造商建立合作关系,将其阵列传感器技术应用于智能手机、平板电脑等消费电子产品中。通过与这些企业的战略合作,Array Microsystems Inc不仅扩大了市场份额,还提升了品牌知名度。同时,公司还积极开拓海外市场,将产品推向全球范围。

Barry Industries Inc公司的发展小趣事

Barry Industries Inc深知品质是企业生存和发展的关键。因此,公司始终将品质管理放在首位,从原材料采购到生产流程控制,再到产品出厂检验,每一个环节都严格把控品质。同时,公司还注重品牌建设,通过提升产品形象和服务水平,逐渐树立了良好的品牌形象。

德力康(DLK)公司的发展小趣事

随着电子行业的不断发展和变革,DLK公司也面临着转型升级的压力。为了适应市场需求的变化,DLK公司开始加快转型升级的步伐。一方面,公司加强了对新能源汽车、物联网等新兴领域的研究和开发;另一方面,公司积极探索智能制造、工业互联网等新技术在连接器生产中的应用。通过转型升级,DLK公司不仅提高了生产效率和产品质量,而且增强了企业的竞争力和可持续发展能力。

Hitachi (Renesas )公司的发展小趣事

DLK公司一直将技术创新作为企业发展的核心驱动力。公司拥有一支高素质的研发团队,不断投入大量资金进行技术研发和产品创新。通过引进先进的生产设备和技术,结合自主研发,DLK公司成功开发出了一系列具有自主知识产权的连接器产品。这些产品不仅具有更高的性能和更稳定的品质,而且能够满足不同客户的个性化需求。技术创新使DLK公司在激烈的市场竞争中保持了领先地位。

Dantona Industries公司的发展小趣事

在公司的成长过程中,Dantona Industries始终将技术创新作为核心竞争力。他们投入大量资源研发新产品,不断提高产品的性能和质量。一次,公司面临了一项重大的技术难题,需要开发一款具有更高集成度和更低功耗的芯片。Daniel Tona带领团队日夜兼程,经过数月的努力,终于成功突破了技术瓶颈,推出了这款具有划时代意义的芯片。这一创新不仅为公司赢得了市场的认可,也为整个电子行业树立了新的标杆。

Daburn公司的发展小趣事

随着公司规模的不断扩大,Daburn开始积极拓展国际市场。公司通过参加国际展览、与国外企业建立合作关系等方式,将产品推向全球市场。同时,Daburn还注重与当地企业的合作,共同开发符合当地市场需求的产品。这种市场拓展策略让Daburn在国际舞台上获得了更多的机会和挑战。

问答坊 | AI 解惑

第四讲 利用Boost和Buck-Boost实现LED驱动

不管我们是否要控制输出电压或输出电流,Boost调节器都要比Buck调节器更难设计。持续导通状态(CCM)Boost转换器中的平均感应电流等于负载电流(LED电流)乘以1/(1-D),这里D是占空度。Boost电压调节器需要设计者考虑到输入电压的限制来保证电感的 ...…

查看全部问答>

跪求技术文档,老式LCD显示屏怎么用?

古董级LCD没找到应用文档,请教用过他的大虾或是有文档的告诉我一下几个引脚的作用,帮助我能点亮显示一下吧!…

查看全部问答>

ucos ii 下GPRS模块通过拨号方式进行tcp连接,不知如何下手?

    现在mcu是stm32 芯片,gprs模块是华为gtm900 ,通过查找资料如果不用模块内部的协议栈的话,自己得在ucos ii上实现ppp协议与tcp/ip协议栈,现在在网上下载了ucip1-0-3,里面就是src 目录下,有相关代码,里面还有makefile,似乎应该在li ...…

查看全部问答>

有谁能给个数字示波器测试开关电源时主要测试的项目

有谁能给个数字示波器测试开关电源时主要测试的项目;例如初级采样电阻的测量,整流桥输出波形测试; 以及输出波形测试,PWM波形测试时候的注意事项,没用过数字示波器测试,担心损坏,当时用的是模拟示波器,表笔负极与电源的地线相连;当时是选 ...…

查看全部问答>

非常实用的免费工具-工程师必备!芯片查询,pdf下载软件!

软件操作说明:1、本软件是纯绿色软件,无需安装,解压直接使用。2、设置pdf保存地址,Save Path为保存地址,默认是在桌面,点后面Change,更改pdf保存地址。2、Part Name 栏输入需要查找器件的名称(至少包含三个字符),然后单击“Search”或者回 ...…

查看全部问答>

【我要奉献】EDK 原理工具和技巧指南

本辅导资料介绍了利用嵌入式开发套件(EDK)创建和测试硬件处理器系统设计的步骤。本辅导资料的系统要求如下:Xilinx Spartan-3A DSP 开发板(XC3SD1800A-4FGG676C)EDK 11.1ISE® 11.1 赛灵思EDK套件是帮助工程师在赛灵思FPGA器件内实现嵌入式 ...…

查看全部问答>

刚答完题、说说心得

刚刚做了430的试题、感觉题目都不错、挺基础的~果断放弃AVR、专攻430!…

查看全部问答>

今天用Launchpad的ADC10做了一个采集片内温度,12864显示。

这个程序 只贴部分吧了,至于12864串行显示模块,大家看我前面的帖子吧, 完整的程序可以实现温度的测量了,就是我对参考电压选择还是有点不理解,求大神指点一二! unsigned char s1[]={\"当前片内温度显示\"}; unsigned char s2[]={\"温度: ...…

查看全部问答>

分享了一些调好的程序,BMP显示,触摸校准,触摸写字

基于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的相应引脚上输出高 ...…

查看全部问答>