当前位置: 首页 > news >正文

STM32-USART串口实现接收数据三种方法(1.根据\r\n标志符、2.空闲帧中断、3.根据定时器辅助接收)

本章概述思维导图:

USART串口初始化配置

串口初始化配置在(STM32-USART串口初始化章节有详细教程配置),本章不做讲解直接代码示例,本章重点在于串口实现接收数据三种方法;

配置USART1串口接收初始化函数步骤:

1. 开时钟

2. 对串口1模块开启复位时钟,在取消复位;

3. 配置GPIO模式

4. 通过在USART_CR1寄存器上置位UE位来激活USART

5. 编程USART_CR1的M位来定义字长。

6. 在USART_CR2中编程停止位的位数。

7. 利用USART_BRR寄存器选择要求的波特率。

8. 设置USART_CR1中的TE位,发送一个空闲帧作为第一次数据发送。

9. 设置USART_CR1的RE位。激活接收器,使它开始寻找起始位。

10. 设置USART_CR1的IDLEIE位。当USART_SR中的IDLE为’1’时,产生USART中断

11.设置USART_CR1的RXNEIE位。当USART_SR中的ORE或者RXNE为’1’产生USART中断。

12. 调用中断设置优先级函数;

代码示例:

/*USART1串口初始化函数形参bps——>保持通信的波特率PA10设置为输入模式,PA9设置为复用输出模式;
*/
void USART1_Init(u32 bps)
{
//  1. 开时钟RCC->APB2ENR|=1<<2;//开启PA时钟;RCC->APB2ENR|=1<<14;//开启USART1时钟
//  2. 对串口1模块开启复位时钟,在取消复位;RCC->APB2RSTR|=1<<14;//开启USART1复位时钟,复位这一步可以省略配置USART1步骤RCC->APB2RSTR&=~(1<<14);//取消复位时钟,关闭复位
//  3. 配置GPIO模式GPIOA->CRH&=0xfffff00f;//清空PA10、PA9引脚模式GPIOA->CRH|=0x000008b0;//PA10输入PA9输出
//  4.通过在USART_CR1寄存器上置位UE位来激活USARTUSART1->CR1|=1<<13;
//  5.编程USART_CR1的M位来定义字长。USART1->CR1&=~(1<<12);
//  6.在USART_CR2中编程停止位的位数。USART1->CR2&=~(0x3<<12);
//  7.利用USART_BRR寄存器选择要求的波特率。USART1->BRR=72000000/bps;
//  8.设置USART_CR1中的TE位,发送一个空闲帧作为第一次数据发送。USART1->CR1|=1<<3;
//  9.设置USART_CR1的RE位。激活接收器,使它开始寻找起始位。USART1->CR1|=1<<2;
//  10.设置USART_CR1的IDLEIE位。当USART_SR中的IDLE为’1’时,产生USART中断USART1->CR1|=1<<4;
//  11.设置USART_CR1的RXNEIE位。当USART_SR中的ORE或者RXNE为’1’产生USART中断。USART1->CR1|=1<<5;
//  12.调用中断优先级函数STM32_SetNVICPriority(USART1_IRQn ,1,1);
}

USART串口中断服务函数

/*串口1中断服务函数
*/
void USART1_IRQHandler()
{u8 c;if(USART1->SR&1<<5)//判断是否为:接收中断;每接收一个字符就会触发一次中断{c=USART1->DR;//将数据赋值给cUSART1->DR=c;//将数据发生给上位机软件,使得显示界面上显示。}
}

USART1串口1接收实现三种方法

判断串口数据发送完一次数据有三种方法:

1. 是发送数据时以(\r\n)标志为结尾,检测到(\n)时就知道数据完成一次发送

2. 串口初始化函数中开启空闲帧中断

3,定时器辅助串口接收,判断串口1发送一字节和下一字节的间隔时间。超过定时器 初始设定的时间说明字符串数据发送完成

方法1:这里判断一次数据发送完成时根据(\r\n结束标志符)

代码示例:

u8 USART1_buffer[1024];//缓冲区数组,用来接收数据
u16 USART1_cnt=0;//缓冲区数组下标
u8 USART1_flag=0;//联合主函数标志位
/*USART1串口1中断服务函数
*/
void USART1_IRQHandler(void)
{u8 dat;if(USART1->SR&1<<7)//没接收到一个字符触发标志位{dat=USART1->DR;//读取数据if(USART1_cnt<1024){USART1_buffer[USART1_cnt]=dat;//将读取的数据放入到缓冲区数组里if(USART1_buffer[USART1_cnt] == '\n')//判断是否到结束标注位"\r\n"{USART1_buffer[USART1_cnt-1]='\0';//将'\r'写入'\0'结束USART1_flag=1;//数据接收完成}else{USART1_cnt++;}}else{USART1_buffer[USART1_cnt-1]='\0';USART1_cnt=0;}}
}

代码讲解:

创建缓冲区数组用来接收字符,只要字符不为:' \n ';就一直接收;当字符为:' \n '时;将' \r'位置写入' \0 '表示接收完成,同时将标志位置1,联合主函数使用;

主函数代码示例:


#include "USART1.h"
#include "stdio.h"
int main()
{USART1_Init(115200);//USART1串口1初始化函数while(1){if(USART1_flag){printf("buffer=%s\tcnt=%d\n",USART1_buffer,USART1_cnt);USART1_cnt=0;//下标清零USART1_flag=0;//标志位置0;}}
}

代码运行结果图:

数据发送图:

数据成功接收图:

方法2:开启空闲帧中断

在串口初始化函数中配置USART1_CR1的IDLEIE:IDLE中断使能位

中断服务函数配置示例代码:

/*USART1串口1中断服务函数
*/
void USART1_IRQHandler(void)
{u8 dat;if(USART1->SR&1<<5)//每接收到一个字符触发标志位{dat=USART1->DR;//读取数据if(USART1_cnt<1024){USART1_buffer[USART1_cnt]=dat;//将读取的数据放入到缓冲区数组里USART1_cnt++;}else{USART1_cnt=0;} }if(USART1->SR&1<<4)//空闲帧标志,这是全部发送完触发一次{dat=USART1->DR;USART1_flag=1;//数据接收完成}USART1->SR=0;
}

主函数示例代码:

#include "USART1.h"
#include "stdio.h"
int main()
{USART1_Init(115200);//USART1串口1初始化函数while(1){if(USART1_flag){USART1_buffer[USART1_cnt]='\0';//写入结束标志符printf("buffer=%s\tcnt=%d\n",USART1_buffer,USART1_cnt);USART1_cnt=0;//下标清零USART1_flag=0;//标志位置0;}}
}

代码运行结果图:

数据发送图:

数据成功接收图:

方法3:定时器辅助串口接收

定时器辅助串口接收,判断串口1发送一字节和下一字节的间隔时间。超过定时器 初始设定的时间说明字符串数据发送完成

配置步骤:

第一步:算出发送一个字节数据要多少时间:

1m=1000ms=1000000us;

1000000/(115200/10)=86.80555555us;发送一字节数据需要86.8055微秒;

判断第一个字节数据和第二字节数据的间隔时间有没有超过10ms

第二步:在串口1初始化函数中关闭空闲帧中断并且串口中断服务函数里关闭空闲帧中断; 在定时器2初始化函数里关闭使能计数器,并且关闭定时器。设定定时时间10毫 秒

第三步:在串口第一次接收一字节数数时,在串口1中断服务函数里清空计数器并且开启定 时器。

第四步:如果数据全部返送完成,在定时器2中断服务函数里将标志位置一并且关闭定时器 等待下一次数据发送玩出触发定时器2中断

第三步示例代码:

/*USART1串口1中断服务函数
*/
void USART1_IRQHandler(void)
{u8 dat;if(USART1->SR&1<<5)//每接收到一个字符触发标志位{dat=USART1->DR;//读取数据if(USART1_cnt<1024){TIM2->CNT=0;//清空计数器TIM2->CR1|=1<<0;//开启定时器USART1_buffer[USART1_cnt]=dat;//将读取的数据放入到缓冲区数组里USART1_cnt++;}else{USART1_flag=1;} }USART1->SR=0;
}

第四步示例代码:

/*定时器2中断服务函数
*/
void  TIM2_IRQHandler(void)
{if(TIM2->SR&1<<0){USART1_flag=1;//定时时间到标志位置1TIM2->SR&=~(1<<0);TIM2->CR1&=~(1<<0);//关闭定时器}
}

主函数示例代码:


#include "USART1.h"
#include "stdio.h"
#include "TIM.h"
int main()
{USART1_Init(115200);//USART1串口1初始化函数TIM2_Init(7200,10000);//定时器2设置定时时间为10毫秒while(1){if(USART1_flag){USART1_buffer[USART1_cnt]='\0';//给缓冲区数组写入结束标识符;printf("buffer=%s cnt=%d\n",USART1_buffer,USART1_cnt);USART1_cnt=0;//下标清零USART1_flag=0;//标志位置0;}}
}

代码运行结果图:

数据发送图:

数据成功接收图:


制作不易!喜欢的小伙伴给个小赞赞!喜欢我的小伙伴点个关注!有不懂的地方和需要的资源随时问我哟!

http://www.lryc.cn/news/601425.html

相关文章:

  • 数据结构第1问:什么是数据结构?
  • 三、构建一个Agent
  • 栈----5.柱状图中最大的矩形
  • RabbitMq 常用命令和REST API
  • 基于分组规则的Excel数据分组优化系统设计与实现
  • 阿里 Qwen3 四模型齐发,字节 Coze 全面开源,GPT-5 8 月初发布!| AI Weekly 7.21-7.27
  • GPT 生成一个打字练习页面
  • maven optional 功能详解
  • 盛最多水的容器-leetcode
  • 时间长了忘记jupyter的环境是哪个了
  • k8s的csi对接GPFS
  • 系统架构设计师-【2025年上半年综合知识题】-真题回忆版分享
  • 动手学深度学习笔记04(上)
  • 物联网发展:从概念到应用的演变历程
  • Sql server开挂的OPENJSON
  • haproxy七层代理(知识点+相关实验部署)
  • C++算法竞赛篇(六)一维数组题型讲解
  • Rust实战:高效开发技巧
  • 【Java实例】服务器IP一站式管理
  • Rust Web 全栈开发(十二):构建 WebAssembly 应用
  • day69—动态规划—爬楼梯(LeetCode-70)
  • LeetCode 923.多重三数之和
  • PMO如何赋能AI产品项目治理和价值交付︱商汤绝影PMO总监陈福龙
  • 0-1BFS(双端队列,洛谷P4667 [BalticOI 2011] Switch the Lamp On 电路维修 (Day1)题解)
  • 【C++】论如何封装红黑树模拟实现set和map
  • Java全栈面试实战:从JVM到AI的技术演进之路
  • JavaScript手录07-数组
  • LangChain实现RAG
  • JavaSE-String类
  • Rust赋能智能土木工程革新