参考:https://blog.csdn.net/u014470361/article/details/79206352

我这里使用的芯片是 F1 系列的,主要是利用 DMA 数据传输方式实现的,在配置工程的时候要注意配置好 DMA,并开启中断。

  

  如果出现数据长度对,可是数据接收不完整,把Memory勾选即可:

  

1、利用STM32 cubemx 建立一个工程,工程建立请参考我以前的文章:https://www.cnblogs.com/xingboy/p/9597464.html

2、利用STM32 cubemx 生成代码后,我们先定义一些变量来使用

/*    自己添加代码部分    */
volatile uint8_t rx_len=; //接收数据长度
volatile uint8_t recv_end_flag=; //接收完成标记位
uint8_t rx_buffer[]; //接收缓存
char BUFFER_SIZE=; //不定长数据的最大长度,设置为100则最大长度为100

这里为什么要定义volatile 关键字呢?

       主要是因为volatile 关键字提醒编译器定义的变量是易变的,编译后的程序每次需要存储或读取该变量时,会直接从变量地址读取数据。在中断或多线程中使用volatile关键字可以避免不同优化等级时程序出错,提高程序的鲁棒性。

接着对串口初始化添加一些代码,程序如下:

/* USART2 init function */
static void MX_USART2_UART_Init(void)
{ huart2.Instance = USART2;
huart2.Init.BaudRate = ;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
} /* 自己添加代码部分 */
__HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE); //使能idle中断
HAL_UART_Receive_DMA(&huart2,rx_buffer,BUFFER_SIZE); //打开DMA接收,数据存入rx_buffer数组中。 }

3、接收函数我写在了另一个文件上,其他文件要用到上面 main文件里面定义的变量就要声明一个外部变量

extern volatile uint8_t rx_len;
extern volatile uint8_t recv_end_flag;
extern uint8_t rx_buffer[];
extern char BUFFER_SIZE;

4、接着修改串口中断服务函数,在串口中断服务函数里添加接收代码,代码如下:

void USART2_IRQHandler(void)
{
/* USER CODE BEGIN USART2_IRQn 0 */ /* 自己添加代码部分 */
uint32_t tmp_flag = ;
uint32_t temp;
tmp_flag =__HAL_UART_GET_FLAG(&huart2,UART_FLAG_IDLE);   //获取IDLE标志位
if((tmp_flag != RESET))  //idle标志被置位
{
__HAL_UART_CLEAR_IDLEFLAG(&huart2);  //清除标志位
temp = huart2.Instance->SR;   //清除状态寄存器SR(F0的HAL库USART_TypeDef结构体中名字为ISR:USART Interrupt and status register),读取SR可以清楚该寄存器
temp = huart2.Instance->DR;    //读取数据寄存器中的数据,读取DR(F0中为RDR:USART Receive Data register)
        HAL_UART_DMAStop(&huart2); 
     temp = hdma_usart2_rx.Instance->CNDTR;   //获取DMA中未传输的数据个数,NDTR寄存器分析见下面
rx_len = BUFFER_SIZE - temp;         //总计数减去未传输的数据个数,得到已经接收的数据个数
recv_end_flag = ;               //接受完成标志位置1
} /* USER CODE END USART2_IRQn 0 */
HAL_UART_IRQHandler(&huart2);
/* USER CODE BEGIN USART2_IRQn 1 */ /* USER CODE END USART2_IRQn 1 */
}

  上面的 CNDTR 寄存器在 DMA 通道结构体中定义了 CNDTR 寄存器,这个不同的芯片HAL库里面定义的命名有点不同,有兴趣的可以自己去查看一下,那为什么是未传输的数据数呢,STM32的中文手册给出了该寄存器的具体说明。(注意:建立工程的时候要添加串口TX RX 的DMA通道,以及打开DMA中断)

/**
* @brief DMA Controller
*/
typedef struct
{
__IO uint32_t CCR;
__IO uint32_t CNDTR;
__IO uint32_t CPAR;
__IO uint32_t CMAR;
} DMA_Channel_TypeDef;

寄存器说明如下:

5、接着编写接收处理函数,代码如下:

/***************************************************************
*函数名:Data_Turn
*输 入:无
*说 明:串口接收完成,返回串口查看接收情况
*返回值:无
**/
void Data_Turn(void)
{ if(recv_end_flag ==)
{
printf("rx_len=%d\r\n",rx_len); //打印接收长度
HAL_UART_Transmit(&huart2,rx_buffer, rx_len,); //接收数据打印出来
for(uint8_t i=;i<rx_len;i++)
{
rx_buffer[i]=;   //清接收缓存
}
rx_len=;        //清除计数
recv_end_flag=;    //清除接收结束标志位
}
}

6.再主函数里的的while循环里再次打开DMA中断接收

HAL_UART_Receive_DMA(&huart2,rx_buffer,BUFFER_SIZE);            //重新打开DMA接收 

运行效果如下图,我的代码是接收到Do-0:1字符串,判断字符串,返回我需要的字符串,效果正确。

补充一点最近新发现的关于串口中断接收的问题:

  串口中断接收如果使用HAL库的中断接收函数,接收到的数据量远小于设定要接收的数据量,串口一直处于Busy状态,会出现接收死循环的情况,接收的数据跟设定不符会出错

注意:

  测试过程中发现,用接收串口助手的所有数据都没问题,不过接收模块的不定长数据时,如果这个数据之间包含回车换行符会接收不全,例如:AT\r\nOK\r\n,这个就只能接收到AT\r,具体什么原因造成的还没找出原因,有知道的可以告诉我一下。

  不过如果是串口助手发这串数据下来,却又可以全部接收完成,想不通。为了解决这个问题,我又找出了一个中断接收的方法,可以实现了不管中间有没有回车,都可以接收完成。传输门:https://www.cnblogs.com/xingboy/p/10154475.html

STM32 HAL库利用DMA实现串口不定长度接收方法的更多相关文章

  1. STM32 HAL库使用中断实现串口接收不定长数据

    以前用DMA实现接收不定长数据,DMA的方法接收串口助手的数据,全部没问题,不过如果接收模块返回的数据,而这些数据如果包含回车换行的话就会停止接收,例如接收:AT\r\nOK\r\n,就只能接收到AT ...

  2. STM32 HAL库 UART 串口读写功能笔记

    https://www.cnblogs.com/Mysterious/p/4804188.html STM32L0 HAL库 UART 串口读写功能 串口发送功能: uint8_t TxData[10 ...

  3. WS2812B彩灯详细讲解篇(STM32 PWM+DMA控制 STM32 HAL库编程 循环延时控制多种控制方式)

    一.效果展示 观看演示效果:https://www.bilibili.com/video/BV1JT4y1P72Q 二. 基础认识 (一)  小理论 WS2812B是一种智能控制LED光源,将控制电路 ...

  4. STM32 HAL库与标准库的区别_浅谈句柄、MSP函数、Callback函数

    最近笔者开始学习STM32的HAL库,由于以前一直用标准库进行开发,于是发现了HAL库几点好玩的地方,在此分享. 1.句柄在STM32的标准库中,假设我们要初始化一个外设(这里以USART为例)我们首 ...

  5. 【有趣的全彩LED | 编程】用STM32 HAL库让WS2812B为你所动

    一.效果展示 观看演示效果:https://www.bilibili.com/video/BV1dv411Y7x3 使用STM32 HAL库编程 PWM+DMA控制输出,CubeMX生成初始工程 实现 ...

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

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

  7. stm32 HAL库笔记(零)

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

  8. STM32 HAL库详解 及 手动移植

    源: STM32 HAL库详解 及 手动移植

  9. 【书籍连载】《STM32 HAL 库开发实战指南—基于F7》-第一章

    从今天起,每天开始连载一章<STM32 HAL 库开发实战指南—基于F7>.欢迎各位阅读.点评.学习. 第1章  如何使用本书 1.1  本书的参考资料 本书参考资料为:<STM32 ...

随机推荐

  1. HDU5924 Mr. Frog’s Problem

    /* HDU5924 Mr. Frog’s Problem http://acm.hdu.edu.cn/showproblem.php?pid=5924 数论 * */ #include <cs ...

  2. UFLDL教程笔记及练习答案五(自编码线性解码器与处理大型图像**卷积与池化)

    自己主动编码线性解码器 自己主动编码线性解码器主要是考虑到稀疏自己主动编码器最后一层输出假设用sigmoid函数.因为稀疏自己主动编码器学习是的输出等于输入.simoid函数的值域在[0,1]之间,这 ...

  3. qq邮箱的SMTP服务器是什么

    qq邮箱的SMTP服务器是什么 QQ邮箱POP3 和 SMTP 服务器地址设置如下:POP3服务器地址为“pop.qq.com”,SMTP服务器地址为“smtp.qq.com”注:1.SMTP服务器需 ...

  4. yarn架构——本质上是在做解耦 将资源分配和应用程序状态监控两个功能职责分离为RM和AM

    Hadoop YARN架构解读 原Mapreduce架构 原理架构图如下: 图 1.Hadoop 原 MapReduce 架构 原 MapReduce 程序的流程:首先用户程序 (JobClient) ...

  5. hdoj--1276--士兵队列训练问题(数组模拟)

    士兵队列训练问题 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

  6. 三大表连接方式详解之Nested loop join和 Sort merge join

    在早期版本,Oracle提供的是nested-loop join,两表连接就相当于二重循环,假定两表分别有m行和n行       如果内循环是全表扫描,时间复杂度就是O(m*n)       如果内循 ...

  7. BZOJ 3323 splay维护序列

    就第三个操作比较新颖 转化成 在l前插一个点 把r和r+1合并 //By SiriusRen #include <cstdio> #include <cstring> #inc ...

  8. 转:Redis介绍及常用命令大全

    一 Redis介绍 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API.从2010年3月15日起,Redis的开发 ...

  9. 开发辅助 | 前端开发工程师对 UI设计、交互设计的认知

    1.UI 用户界面 UI:User Interfase 用户界面 UID:User Interfase Designer 用户界面设计师,多指移动 app 的界面设计: 2.一个合格的 UI 设计师, ...

  10. Android studio关于点击事件后的页面跳转,选择完成后返回(onActivityResult)

    我这个人喜欢直接上代码,在代码中说明更方便,更直接. 首先在.xml中设置一个button按钮,和一个EditText框,并分别做好id号. 这里我以籍贯测试对象. <LinearLayout ...