STM32-USART HAL库接收任意长度数据详细解析

发布者:Serendipitous55最新更新时间:2019-02-12 来源: eefocus关键字:STM32  USART  HAL库 手机看文章 扫描二维码
随时随地手机看文章

前言:

最近在调试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  USART  HAL库 引用地址:STM32-USART HAL库接收任意长度数据详细解析

上一篇:STM32-基本定时器Timer的使用
下一篇:STM32—RTC

推荐阅读最新更新时间:2024-03-16 16:23

STM32在KEIL平台反汇编代码分析
  不同的平台的汇编代码是不一样的,最早的汇编在50年代就发明了,比很多人的父母的年龄都大,老掉牙,不用学习怎么写汇编。一个公司有一个人知道怎么写汇编就够了。但要学习读汇编 为什么学习汇编?   1 性能 直接翻译为机器语言,性能最高。优秀的C语言效率只能达到汇编的80%左右。其他高级语言跟汇编一比差得更远。语言越高级性能越差。很多bootloader和BIOS用汇编写,汇编操作的是电脑,手机刚刚上电时,硬件和初始化的那些命令,它们的性能的要求比较高,效率高开机速度更快。   2 分析问题。个人认为,编程人与机器对话,我们写C,写JAVA,但是电脑并不认识这些语言,电脑只认识0和1;所以需要一个人来翻译这些语言,这个翻译官就是编
[单片机]
STM32单片机实现DMA+ADC+UART功能
突然想测试一下STM32单片机ADC采样速率问题,按照常规方法,可以通过ADC采样,然后将采样值打印出来。但是这种方法在处理和打印数据的时候会占用很多时间,导致处理数据的时间超过了ADC的采样时间。于是想到了ADC采样的数据用DMA功能存储,并通过串口打印。但是串口打印依然要占用单片机时间,那能不能串口数据的输出也采用 DMA功能呢?这样ADC采样的数据通过DMA直接存储,然后串口通过DMA功能直接输出采样到的数据。这样速度程序执行速度不就极大的提升了吗?说干就干,使用STM32F103C8T6单片机,标准库函数,keil5软件,编写一个测试程序。 首先实现ADC采样并通过DMA存储 #ifndef __ADC_H #de
[单片机]
<font color='red'>STM32</font>单片机实现DMA+ADC+UART功能
STM32的中断(优先级,开关总中断)
一:综述 STM32 目前支持的中断共为 84 个(16 个内核+68 个外部), 16 级可编程中断优先级的设置(仅使用中断优先级设置 8bit 中的高 4 位)和16个抢占优先级(因为抢占优先级最多可以有四位数)。 二:优先级判断 (一)中断优先级概念 STM32(Cortex-M3)中有两个优先级的概念——抢占式优先级和响应优先级,有人把响应优先级称作'亚优先级'或'副优先级',每个中断源都需要被指定这两种优先级。 (二)中断响应次序 (1)具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断嵌套,或者说高抢占式优先级的中断可以嵌套低抢占式优先
[单片机]
openmv舵机云台 自动追踪色块 STM32源程序
之前做的舵机云台自动瞄色块的装置 现在已经拆掉了,所以没有图片 就是类似19年国赛电磁的发挥部分要求 单片机源程序如下: #include control.h u8 key = 0; u8 mode = 0; u8 sign = 0; u16 mode_r = 0; u16 mode_p = 0; void TIM1_UP_IRQHandler(void) //TIM1中断 { if(TIM_GetITStatus(TIM1,TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 { TIM_ClearITPendingBit(T
[单片机]
基于STM32和CAN总线的电动车电池管理系统设计
  随着电池能源的广泛应用,石油资源的枯竭和环境污染,电动汽车以其节能环保的优势引起越来越多的重视,在电动汽车的研究和发展上,车载电池及其管理系统的研究与制造占据着重要位置。电动汽车动力电池在应用中的主要问题表现在:生产过程中,电池的工艺,技术以及成组技术还不能保证其初始性能具有良好的一致性;使用过程中,对过充电、过放电、过温度、过电流等非常敏感,这类情况的发生会明显缩短电池寿命,甚至会导致电池报废。电池组是几十个甚至上百个单体电池串联,单体电池之间存在不一致性,随着连续的充放电循环,电池间的不一致性加剧,电池组的可用容量受容量最小的单体电池制约。对于这些情况,电池的初始性能必须要依靠企业生产工艺的优化,生产过程关键参数的控制来改
[单片机]
基于<font color='red'>STM32</font>和CAN总线的电动车电池管理系统设计
STM32外设资源查询方法,对比C8T6和ZET6
对应不同型号的单片机的外设资源需要找相应的单片机的数据手册,比如STM32F103ZET6数据手册,STM32F103C8T6数据手册. 根据FLASH大小STM32F103ZET6 - 为HD型,STM32F103C8T6 - 为MD型。 STM32F103家族系列芯片外设对比 STM32F103ZET6 外设资源数据手册一览 从上图也可以看到ZET6一共有11个定时器,包括2个高级定时器、4个通用定时器、2个基本定时器…当然还有2个看门狗和1个系统定时器。 再由这个两个图也可以看出TIM1/8是高级定时器、TIM2/3/4/5是通用定时器、TIM6/7是基本定时器。 高级定时器
[单片机]
<font color='red'>STM32</font>外设资源查询方法,对比C8T6和ZET6
STM32_TIM定时-中断
今天讲解STM32F103定时器定时-中断功能,在昨天定时器延时的软件工程上添加TIM3定时的功能,自己也可以试着将昨天的工程添加修改得到。 今天的软件工程下载地址(360云盘): https://yunpan.cn/cPnJ9KYcXbPsP 访问密码 acd8 工程现象:间隔(定时器定时)500ms LED变化一次, 并且串口打印 STM32F103ZE有8个定时器(TIM1 – TIM8), 改工程以TIM3定时为例。 STM32F10x的资料可以在我360云盘下载: https://yunpan.cn/crBUdUGdYKam2 访问密码 ca90 关于TIM延时,我把重要的几点在下面分别讲述,工程中
[单片机]
STM32_TIM定时-中断
基于STM32嵌入式系统的智能控制网络终端设计
0 引言   智能网络终端是实现智能化管理的嵌入式终端设备。通常具有安全门禁系统和自动化控制的基本功能。本文重点介绍基于STM32的智能嵌入式终端的网络控制功能的设计和实现。 1 智能网络通信实现方案   将嵌入式系统与Internet连接起来实现远距离信息获取和控制功能的本质是嵌入式系统本身能够实现TCP/IP网络通信协议。该协议的解决方案总体上可分为两大类。第一类是直接在嵌入式设备上实现TCP/IP,使之直接连上Internet。这实质上是由MCU及内部固化TCP/IP协议的芯片组成应用系统的核心,MCU可以直接拨号上网,这种方法的硬件电路相对简单,也不需要中间环节的支持。但是由于使用了TCP/IP协议芯片,因此需要大容
[安防电子]
基于<font color='red'>STM32</font>嵌入式系统的智能控制网络终端设计
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved