HAL库教程6:串口数据接收

发布者:WanderlustGaze最新更新时间:2019-05-31 来源: eefocus关键字:HAL库  串口  数据接收 手机看文章 扫描二维码
随时随地手机看文章

STM32的串口接收机制

  与阻塞式发送函数HAL_UART_Transmit配套,有个阻塞式的接收函数,HAL_UART_Receive,但此函数不常用,串口接收通常使用中断函数HAL_UART_Receive_IT。HAL库的串口中断比较复杂,主要流程如下:

在这里插入图片描述

  USART1_IRQHandler:由硬件调用,不是HAL库函数,寄存器编程或固件库编程也需要调用此函数;

  HAL_UART_IRQHandler:通过中断类型(发送中断还是接收中断)来判断调用哪个函数;

  UART_Receive_IT:此函数可以指定,每收到若干个数据,调用一次回调函数;这是因为,每收到一个字节,都会把此函数的接收计数器-1,如果接收计数器为零,调用串口接收回调函数HAL_UART_RxCpltCallback(实际上HAL库一共提供了5个回调函数,只有这个函数在接收完成时调用)。

  HAL_UART_RxCpltCallback:弱函数,用户可以在此函数中编写业务逻辑。清除中断标记,是中断处理函数一定要做的事情,但是对于用户函数,把这个操作给隐藏了


使能串口接收中断

  由于串口不方便传参数,所以我通常会定义一些用于串口通信的全局变量。也可以模仿库函数,把这些变量打包成一个结构体。


//UART.c

unsigned char UART1_Rx_Buf[MAX_REC_LENGTH] = {0}; //USART1存储接收数据

unsigned char UART1_Rx_flg = 0;                   //USART1接收完成标志

unsigned int  UART1_Rx_cnt = 0;                   //USART1接受数据计数器

unsigned char UART1_temp[REC_LENGTH] = {0};       //USART1接收数据缓存


  由于这些变量也要在main.c文件中使用,跨文件使用,可以在头文件中做外部声明:


#ifndef __UART_H

#define __UART_H


#ifdef __cplusplus

extern "C" {

#endif

  

#define REC_LENGTH  1

#define MAX_REC_LENGTH  1024 

  

extern unsigned char UART1_Rx_Buf[MAX_REC_LENGTH];

extern unsigned char UART1_Rx_flg ;

extern unsigned int  UART1_Rx_cnt ;

extern unsigned char UART1_temp[REC_LENGTH];

    

#ifdef __cplusplus

}

#endif


#endif 


  要使用中断来接收串口数据,则必须开启中断。并且,每次处理完串口接收中断以后,会自动关闭中断,如果想循环接收数据,则必须在处理完中断以后,再次开启中断。

  我们希望完成初始化以后就开始接收串口数据,所以要修改串口初始化函数。


//main.c

static void MX_USART1_UART_Init(void)

{

  /* USER CODE BEGIN USART1_Init 2 */

  HAL_UART_Receive_IT(&huart1,(uint8_t *)UART1_temp,REC_LENGTH);

  /* USER CODE END USART1_Init 2 */

}


串口接收中断函数处理

  程序的逻辑:

在这里插入图片描述

  如果接收到了指定数量的串口数据(在本例中,指定的数量是1字节),则会执行回调函数HAL_UART_RxCpltCallback。此函数是个弱函数,用户可以根据业务逻辑来“重载”。我们要在此函数中,把串口收到的数据打包,并判断结束符判断数据结束。我们规定,只发送ASCII码,并以0x0a作为结束符。


//UART.c

/**

  * @brief 串口中断回调函数

  * @param 调用回调函数的串口

  * @note  串口每次收到数据以后都会关闭中断,如需重复使用,必须再次开启

  * @retval None

  */  

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)

{

  if(huart->Instance==USART1)

  {

    UART1_Rx_Buf[UART1_Rx_cnt] = UART1_temp[0];

    UART1_Rx_cnt++;

    if(0x0a == UART1_temp[0])

    {

      UART1_Rx_flg = 1;

    }

    HAL_UART_Receive_IT(&huart1,(uint8_t *)UART1_temp,REC_LENGTH);

  }

}

  主函数中,实现“串口应声虫”的功能,收到什么就发送什么。如果串口数据接收完成,则发送出去然后把数组,计数器,标志都恢复初始状态。


//main() while(1)

    if(UART1_Rx_flg)

    {

      HAL_UART_Transmit(&huart1,UART1_Rx_Buf,UART1_Rx_cnt,0x10);    //发送接收到的数据

      for(int i = 0;i        UART1_Rx_Buf[i] = 0;

      UART1_Rx_cnt = 0;

      UART1_Rx_flg = 0;

    }   



  现象:向串口发送ASCII码,单片机收到什么数据,就返回什么数据。注意,发送给串口的数据结尾要有回车键。


在这里插入图片描述

数据阶段的方法与ASCII码

  一组数据怎么判断是否结束?

  2种方法:

  1特定时间,特定的时间内没有收到新的数据,认为这一组数据就结束了。这种方法在定时器的章节来实现。

  2特定字符,通信双方约定,用特定的字符作为结束,比如把0xff作为结束符。收到0xff就把数据截断。就像我们演讲,最后说一句谢谢大家,下边的人就知道了你讲完了,该鼓掌了。谢谢就是结束符。

  但是这种做法有一个弊端,就是正常通信的数据不允许在使用0xff。

  对于ASCII码,正常情况下是不会发送0x0d与0x0a(回车与换行)的,所以可以用作结束符。

  ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言。它是现今最通用的系统,并等同于国际标准ISO/IEC 646。

  ASCII码主要用于英文字符的显示,不包含中文。标准ASCII码只有7位(最高位是校验位),所以只能显示2^7=128个字符,其中0-31还是不能显示的字符,例如回车,作用是控制字符或通信字符。

在这里插入图片描述

  假如,发送的数据是0x31,它可能代表着十六进制的数字0x31,也可能表示十进制的数字49(十六进制与十进制虽然看上去不一样,但表示的数是同样的大小),还可能表示ASCII码,字符’1’。这三者,在传输线上使用示波器来观察,波形是一模一样的,接收方把它理解为0x31还是理解为字符,要看通信双方的约定。



关键字:HAL库  串口  数据接收 引用地址:HAL库教程6:串口数据接收

上一篇:HAL库教程7:STM32的时钟系统
下一篇:HAL库教程5:串口数据发送

推荐阅读最新更新时间:2024-11-04 20:25

STM32高级开发-在GCC和GNU中使用printf打印串口数据
在大家使用keil或是iar开发stm32等arm芯片的时候,想来最不陌生的就是使用print通过串口输出一些数据,用来调试或是其他作用。但是要明确的是由于keil iar gcc 他们使用的标准C语言库虽然都遵循一个标准,但他们底层的函数实现方式都是不同的,那么在GCC中我们能否像在keil中一样重映射print的输出流到串口上呢?答案是肯定的。 keil中的重映射方式及原理 #include //include stm32f10x.h #pragma import(__use_no_semihosting) //标准库需要的支持函数 struct __FILE {
[单片机]
STM32-串口IAP升级
对于写好的程序来说如何烧录到芯片中是十分重要的的过程,在平时测试开发的时候可以直接通过Jlink,swd,usart等方式直接将编译好的程序直接烧录到芯片的Flash中,但是对于已经开发好的产品来说,特别的已经进行了分布部署的设备来说,一个一个升级可以是不可能的事情,一般的升级方式都是通过网络或者其他远程方式来进行固件的升级,但是无论通过什么方式来进行升级,基本上都是将要升级的代码段下载到指定的Flash存储区域中,这也就是IAP升级的主要内容。 IAP升级主要是将不同的程序放置到内部存储区域的不同的位置,然后通过相应的跳转函数,来指向不同的地址空间,这样就可以运行不同的APP程序了。对于STM32来说内置的Flsah分为不同
[单片机]
基于FPGA的PCI总线串口卡设计
     随着计算机测试技术的飞速发展,越来越多的外部设备通过串口与计算机进行通信,实现信息共享以及设备的集中控制和管理。利用串口进行通信具有结构简单、传输距离远、成本低廉等优点,被广泛应用于各个领域。同时,PCI(Peripheral Component Interconnect)总线是一种高性能32/64位局部总线,最大数据传输速率为132 Mb/s,可同时支持多组外设,数据吞吐量大,是目前应用最广泛、最流行的一种高速同步总线。因此,利用PCI总线实现上位机与外部设备的串口通信,可以提高通信能力。   由于大部分I/O 设备没有PCI总线功能,要实现设备与PCI总线的连接,需要PCI接口芯片、通用异步收发器UART(Uni
[嵌入式]
如何用W7100A实现串口转以太网
1. 简介 很长时间以来,RS232在通信领域一直用来作为DTE(Data Terminal Equipment)和DCE(Data Circuit-terminating Equipment)之间的连接器。自从PC机问世,RS232就成为串行通信的标准。串行通信现在仍然被广泛使用。 随着因特网的迅速发展,TCP/IP协议成为应用最多的通信协议。近来由于因特网环境的不断成长,人们对于因特网和串行通信设备之间的通信连接也有了更高要求。如果以太网和RS232连接成功,人们就能够通过以太网控制串行设备。与此同时,各种串行设备可以有效的与以太网通信. 在这篇文档中,我们将使用iMCU7100EVB来实现串口转以太网的功能,同时介绍了一些工
[单片机]
如何用W7100A实现<font color='red'>串口</font>转以太网
STC15F2K60S2串口1程序
此程序为才写的串口1,工作模式1程序,自己测试没问题 //本示例在Keil开发环境下请选择Intel的8058芯片型号进行编译 //假定测试芯片的工作频率为18.432MHz #include reg51.h sfr P4 = 0xc0; sfr P5 = 0xc8; sfr AUXR = 0x8e ; unsigned char temp ; bit flag = 0 ; void UartInit(void) //9600bps@11.0592MHz { SCON = 0x50; //8位数据,可变波特率 AUXR |= 0x40; //定时器1时钟为Fosc,即1T AUXR &=
[单片机]
在CPLD管理下实现高效多串口中断源
摘要:针对嵌入式系统的精简特性,提出一种通过1个中断源高效管理多个串行口的有效方法,不但节省系统资源,而且实现了多个串行口中断的无漏检测与服务。 关键词:嵌入式系统 RS232 多串口 CPLD 中断 近几年来,随着后PC时代的来临,具有简洁、高效等特点的嵌入式系统得到了飞速的发展。嵌入式技术发展到今天已将各种计算机技术多层次、多方面的交叉融合在了一起。嵌入式系统加快了工业设计进程,降低了开发成本及其风险,使用简便,扩展灵活,高效精简,可方便地应用于各工业领域。 中断请求采用边沿触发来进行中断检测,通过将信号送到特定的引线来检测中断。每条引线对应一个可能的硬件中断,因为系统不能辨认哪个设备使用中断线,所以当多个1个的设备被设
[应用]
8051单片机串口编程知识总结
最近,把收集到有关单片机串口编程的资料总结一下,有利于把工作做好,材料整理如下: 单片机串口通信原理: 1、51系列单片机的串口有4个模式,可分别用作串并转换、并串转换、异步串行通信(2种模式)。异步串行通信中,有1+8+1和1+8+1+1两种帧格式,多机通信是特殊的通信方式。 2、基本原理是两组移位寄存器。将并行通信转换成串行通信模式(发送部分),或反之(接收部分)。可全双工运行。 3、速度通过移位脉冲决定。具体一般通过定时器1的自动装载模式产生的溢出脉冲给出。 4、电平上采用的是CMOS逻辑。 5、以上是物理层和数据链路层的单片机串口模块的约定,其他层需要软件人员根据需要自行把握。另外,电平需要根据实际通信环境做变换,如232
[单片机]
STM32用串口下载后,不小心写保护和读保护了,如何解锁?
在STM32的开发过程中,有些时候可能会不小心开启了写保护和读保护,这将导致程序无法正常使用。此时,需要解锁芯片以便重新烧写程序。本文将介绍如何在STM32中解锁写保护和读保护,并提供详实的步骤以供参考。 1. 测试板子 在开始解锁之前,需要测试板子是否在保护状态下。首先,连接板子到电脑,并打开开发环境。在开发环境的终端中输入命令: ``` bash stm32flash /dev/tty.usbserialXXXX -Rs ``` 如果板子上的芯片已经被保护,则会显示以下信息: ``` bash Failed to init device. ``` 如果芯片没有被保护,则会显示以下信息(具体数字可能会有所不同): ``` bas
[单片机]
小广播
设计资源 培训 开发板 精华推荐

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

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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