https://www.cnblogs.com/Mysterious/p/4804188.html

STM32L0 HAL库 UART 串口读写功能

串口发送功能:

uint8_t TxData[10]= "01234abcde";
HAL_UART_Transmit(&huart2,TxData,10,0xffff);//把TxData的内容通过uart2发送出去,长度是10,timeout的时间是最大值0xffff

串口接收功能1:

uint8_t value='F';
HAL_UART_Receive(&huart2,(uint8_t *)&value,1,1000);//在这个语句停留1000ms内等待接收1个字节数据,把数据存放在value中

串口接收功能2:

HAL_UART_Receive_IT(&huart2,(uint8_t *)&value,1);//程序不会在这个语句停留,直接会按照中断方式把接收数据存放在value中,但是这个语句只能使能一次串口中断。所以要在中断服务函数或者回调函数中重新使能

串口接收功能3:

if(HAL_UART_Receive_IT(&huart2,(uint8_t *)&value,1) != HAL_OK){    //这一句写在main函数的while(1)上面。用于启动程序启动一次中断接收
HAL_UART_Transmit(&huart2, (uint8_t *)&"ERROR\r\n",7,10);
while(1);
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
HAL_UART_Transmit(&huart2, (uint8_t *)&"\r\ninto HAL_UART_RxCpltCallback\r\n",32,0xffff); //验证进入这个函数了
HAL_UART_Transmit(&huart2,(uint8_t *)&value,1,0xffff);      //把接收到的数据通过串口发送出去
HAL_UART_Receive_IT(&huart2,(uint8_t *)&value,1);        //重新打开串口中断
}

串口DMA发送

DMA的TX要这样设置

    uint8_t txData[] = {"HelloWorld\r\n"};
HAL_UART_Transmit_DMA(&huart2,txData,sizeof(txData));//可以通过DMA把数据发出去

DMA接收

if(HAL_UART_Receive_DMA(&huart2, (uint8_t *)rxData, sizeof(rxData)-1) != HAL_OK)//main函数while(1)前,启动一次DMA接收
{
Error_Handler();
}

串口回调函数:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle){

    uint8_t temp[] = {"\r\nin Callback\r\n"};
HAL_UART_Transmit_DMA(&huart2,temp,sizeof(temp)-1);//可以通过DMA把数据发出去 HAL_UART_Receive_DMA(&huart2, (uint8_t *)rxData, sizeof(rxData)-1); //重新使能接收
}

main函数while(1)中不断输出rxData值

HAL_UART_Transmit_DMA(&huart2,rxData,sizeof(rxData)-1);//可以通过DMA把数据发出去

https://www.cnblogs.com/UnfriendlyARM/p/10321838.html

STM32串口接收中断——基于HAL库

写在前面  

  最近需要使用一款STM32L4系列的芯片进行开发,需要学习使用HAL库。在进行串口中断使用的时候遇到了一些小麻烦,写下解决方案供大家参考。

1.UART相关的头文件引用错误

  由于本人直接使用MDK进行开发,没有使用CubeMX,所以一些初始化需要手动进行。在引用UART相关的头文件时,记得将"stm32l4xx_hal_conf.h"文件中的相关宏定义取消注释,如下图:

2.如何接收字符串(多次进入中断)

  接收字符串主要有两种方法,一种是对中断函数进行改造,另一种是对接收回调函数进行改造。
  在阐述这两种方法之前,需要介绍函数“HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)”。该函数的作用是用户自定义一个缓冲区(即参数pData),接受一定数量(由参数Size决定)的字符存入缓冲区中。同时,参数Size还决定着进入回调函数的频率,即每接收Size个字符,就进入一次回调函数。需要注意的是,Size只决定进入回调函数的频率,而不能影响进入接收中断的频率,无论Size是多少,每接收完成一个字符都会进入一次接收中断。

方法1:改造回调函数

  ①首先在主函数中进入主循环前的位置调用一次 HAL_UART_Receive_IT函数,定义一个字符数组getBuffer[]作为缓冲区,参数Size设定为10。即每接收10个字符,就进入一次回调函数。

  ②注册中断函数   

1  void USART1_IRQHandler(void)
2 {
3 HAL_UART_IRQHandler(&UartHandle); //该函数会清空中断标志,取消中断使能,并间接调用回调函数
4 }

  ③在文件“stm32l4xx_hal_uart.h”中,我们可以看到串口接收回调函数的定义。使用“_weak”关键字定义的函数,其具有如下特性: 一般情况下和一般函数相同。但是当有一个同名函数但是不带__weak被定义时,所有对这个函数的调用都是指向后者(不带__weak那个)。也就是说,ST官方提供的这个回调函数需要我们自己进行改写。  

 1    /**
2 * @brief Rx Transfer completed callback.
3 * @param huart UART handle.
4 * @retval None
5 */
6 __weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
7 {
8 /* Prevent unused argument(s) compilation warning */
9 UNUSED(huart);
10
11 /* NOTE : This function should not be modified, when the callback is needed,
12 the HAL_UART_RxCpltCallback can be implemented in the user file.
13 */
14 }

  我们在主函数所在的文件中对回调函数进行改写:

1   uint8_t myBuffer[] = "I have gotten your message: "; //用户提示信息
2 uint8_t Enter[] = "\r\n"; //回车换行
3 uint8_t getBuffer[100]; //用户自定义的缓冲区
4 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
5 {
6 while(HAL_UART_Transmit(UartHandle, (uint8_t*)myBuffer, COUNTOF(myBuffer), 5000)!= HAL_OK); //发送字符串,用户提示信息
7 while(HAL_UART_Transmit(UartHandle, (uint8_t*)getBuffer, 10, 5000)!= HAL_OK); //发送用户自定义缓冲区中的数据
8 while(HAL_UART_Transmit(UartHandle, (uint8_t*)Enter, COUNTOF(Enter), 5000)!= HAL_OK); //发送回车换行
9 }

  以上代码的作用是把用户发送给单片机数据再返回给用户。运行效果如下图:


  我们可以看到,用户向单片机发送了10个字符,单片机向串口助手返回了这10个数据。但是以上程序只能实现一次,当我们再次向单片机发送数据时,单片机却不再返回数据。这是因为我们在中断函数中取消了中断使能,所以导致了进入一次中断后,中断被关闭,无法再次进入中断的现象。为了实现多次数据返回,我们要在中断处理函数中添加一行代码: 

1  void USART1_IRQHandler(void)
2 {
3 HAL_UART_IRQHandler(&UartHandle); //该函数会清空中断标志,取消中断使能,并间接调用回调函数
4 HAL_UART_Receive_IT(&UartHandle, (uint8_t *)&value,1); //添加的一行代码
5 }

  这样就可以实现多次数据返回了,新的执行结果如下图:

 

  可见,函数HAL_UART_Receive_IT还有中断使能的作用。这一功能的实现我们可以在HAL_UART_Receive_IT函数中找到。

方法2:改造中断处理函数

  ①首先在主函数中进入主循环前的位置调用一次 HAL_UART_Receive_IT函数,定义一个字符value作为缓冲区,参数Size设定为1。即每接收1个字符,就进入一次回调函数。使得进入回调函数的频率与进入中断处理函数的频率相同。这样,我们就可以直接在中断函数中对接收的数据进行处理了。

  ②注册中断函数    

 1   uint8_t myBuffer[] = "I have gotten your message: ";
2 uint8_t getBuffer[10];
3 uint8_t Enter[] = "\r\n";
4 void USARTx_IRQHandler(void)
5 {
6 HAL_UART_IRQHandler(&UartHandle); //该函数会清空中断标志,取消中断使能,并间接调用回调函数
7
8 getBuffer[countOfGetBuffer++] = value;
9 if(countOfGetBuffer == 10)
10 {
11 while(HAL_UART_Transmit(&UartHandle, (uint8_t*)myBuffer, COUNTOF(myBuffer), 5000)!= HAL_OK);
12 while(HAL_UART_Transmit(&UartHandle, (uint8_t*)getBuffer, countOfGetBuffer, 5000)!= HAL_OK);
13 while(HAL_UART_Transmit(&UartHandle, (uint8_t*)Enter, COUNTOF(Enter), 5000)!= HAL_OK);
14 countOfGetBuffer = 0;
15 }
16 HAL_UART_Receive_IT(&UartHandle, (uint8_t *)&value,1); //由于接收中断是每接收一个字符便进入一次,所以这一行代码必须添加,否则只能接收一个字符,而无法接收整个字符串
17 }

  以上代码的作用是接收每个来自用户的字符,并依次存入用户自定义的缓冲区中,数量达到10个后,将缓冲区中的所有数据返回给用户,同时清空计数,准备接下来10个字符的接收。运行效果如下图:

写在最后

  看完本文,大家可能对回调函数和中断处理函数的关系产生了疑问。其实是这样的,单片机每完成接收一个字符,就会进入一次中断处理函数,而在中断处理函数中,我们又调用了函数“void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)”,该函数会间接调用回调函数,也就是说回调函数是由中断处理函数间接调用的。而函数“HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)”决定了中断处理函数调用回调函数的频率,若Size为1,则每进入一次中断处理函数都会调用一次回调函数;若Size为10,则每第十次进入中断处理函数时,才会调用回调函数。方法2使用了标准库中断处理数据的思想。

STM32 HAL库 UART 串口读写功能笔记的更多相关文章

  1. STM32L0 HAL库 UART 串口读写功能

    串口发送功能: uint8_t TxData[]= "01234abcde"; HAL_UART_Transmit(&huart2,TxData,,0xffff);//把T ...

  2. STM32 HAL库之串口详细篇

    一.基础认识 (一) 并行通信 原理:数据的各个位同时传输 优点:速度快 缺点:占用引脚资源多,通常工作时有多条数据线进行数据传输 8bit数据传输典型连接图: 传输的数据是二进制:11101010, ...

  3. STM32 HAL库 UART使用printf

    // 添加这个函数 int fputc(int ch,FILE *f) { uint8_t temp[]={ch}; HAL_UART_Transmit(&UartHandle,temp,,) ...

  4. STM32 HAL库关于串口中断烧录程序后可以正常运行,断电重启后无法进入中断的问题分析以及解决方法

    1.情景描述: 最近在做一个项目,X86的上位机通过串口控制MCU,使用串口中断接收上位机数据时,MCU在上电的情况下烧录程序,可以正常接收上位机的数据,在断电重启后,一直进入不了中断回调函数,上电的 ...

  5. (4)STM32使用HAL库实现串口通讯——理论讲解

    一.查询模式 1. 二.中断模式 1.中断接收. 1.1先看中断接收的流程(以 USART2 为例) 在启动文件中找到中断向量 USART2_IRQHandler 找到USART2_IRQHandle ...

  6. stm32 HAL库笔记(零)

    最近在设计四旋翼飞行器,用stm32f407,有三种开发方式可以选择:一.寄存器开发.二:库函数开发.三:HAL库开发,考虑了一下,选择了HAL库,原因如下: 1. 寄存器开发相对较慢,寄存器很多,配 ...

  7. stm32 hal库串口通信资料汇集

    串口的发送接收函数:HAL_UART_Transmit();串口轮询模式发送,使用超时管理机制.HAL_UART_Receive();串口轮询模式发送,使用超时管理机制.HAL_UART_Transm ...

  8. 【情人节选帽子】TCS34725颜色传感器和Python图形界面编程(STM32 HAL库)

    截图 描述: l  STM32 HAL库编程 l  使用模拟IIC通信,方便程序移植 l  Python界面编写,蘑菇头的帽子是什么颜色 l  STM32 HAL库串口通信 l  Python界面使用 ...

  9. 第十六章 IIC协议详解+UART串口读写EEPROM

    十六.IIC协议详解+Uart串口读写EEPROM 本文由杭电网友曾凯峰根据小梅哥FPGA IIC协议基本概念公开课内容整理并最终编写Verilog代码实现使用串口读写EEPROM的功能. 以下为原文 ...

随机推荐

  1. PAT甲级 链表题_C++题解

    链表处理 PAT (Advanced Level) Practice 链表题 目录 <算法笔记> 重点摘要:静态链表 1032 Sharing (25) 1052 Linked List ...

  2. 1.关于Python,你可能不知道的

    启示录 写在前面———— 至于python有多牛逼,这里不介绍了,安装也不说了,网上一堆一堆的安装教程. 本文只介绍需要知道的 常识知识———— 1.python 发音:英 [ˈpaɪθən] 美 [ ...

  3. PowerBuilder学习笔记之调用事件和函数

    2.7.1调用事件和函数 完整语法:[ObjectName]ancestorclass::[type][when]name([argumnetlist]) 说明:ObjectName:指定函数或事件的 ...

  4. 序列方差[NTT]

    也许更好的阅读体验 \(\mathcal{Description}\) 给你一个长度为\(n\)的数组\(a\) 你会得到 \(q\) 条指令, 分两种: \(1\ l\ r\ w\) 表示把 \(l ...

  5. markdown语法之列表与缩进

    在markdown语法中, 用*或+或-在行首表示无序列表.在这些符号之后应该空一格然后输入内容. 例如 + 无序列表 * 无序列表 - 无序列表 会被markdown语法渲染为 无序列表 列表嵌套 ...

  6. MySQL 5.7使用xtabackup报错解决

    报错信息: InnoDB: An optimized (without redo logging) DDLoperation has been performed. All modified page ...

  7. windows下mysql表名区分大小写

    windows下mysql默认是不区分大小写的,但是linux会区分大小写 如何让windows下mysql区分大小写呢? 修改 my.ini 里面的mysqld部分 #区分大小写 lower_cas ...

  8. C# 弹出层移动

    groupPrint.MouseDown += GroupBox1_MouseDown; #region 弹出层移动        [System.Runtime.InteropServices.Dl ...

  9. 20190705-记IIS发布.NET CORE框架系统之所遇

    新手在IIS上发布.NET CORE框架的系统之注意事项 序:本篇随笔是我的处子笔,只想记录自己觉得在系统发布过程中比较重要的步骤,一来,忝作自己的学习笔记,以备不时之需,二来,也希望可以帮助有需要的 ...

  10. [转]Entity Framework 异常: 'OFFSET' 附近有语法错误。\r\n在 FETCH 语句中选项 NEXT 的用法无效

    https://blog.csdn.net/weixin_34321977/article/details/85850064 在使用 EF 的时候,突然发现更新后在服务器中运行出错,异常信息主要包含以 ...