STM32(1)-简单实现串口收发与通信

这篇具有很好参考价值的文章主要介绍了STM32(1)-简单实现串口收发与通信。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文通过串口收发实验来说明具体的串口的使用过程,以及与其他外设通过串口进行通信从而实现相关功能。


前言
在STM32里,串口通信是USART,STM32可以通过串口和其他设备进行传输并行数据,是全双工,异步时钟控制,设备之间是点对点的传输。对应的STM32引脚分别是RX和TX端。STM32的串口资源有USART1、USART2、USART3.

串口的几个重要的参数:

波特率,串口通信的速率
空闲,一般为高电平
起始位,标志一个数据帧的开始,固定为低电平。当数据开始发送时,产生一个下降沿。(空闲–>起始位)
数据位,发送数据帧,1为高电平,0为低电平。低位先行。
比如 发送数据帧0x0F 在数据帧里就是低位线性 即 1111 0000
校验位,用于数据验证,根据数据位的计算得来。有奇校验,偶校验和无校验。
停止位,用于数据的间隔,固定为高电平。数据帧发送完成后,产生一个上升沿。(数据传输–>停止位)

一、建立串口的头文件、源文件

打开keil5,这里我选择原子哥的跑马灯实验代码为基础进行拓展:

左侧Hardware添加.c和.h文件,地址是/hardware,确定添加。
STM32(1)-简单实现串口收发与通信

二、编写源文件

首先,编写初始化串口2的函数:
1.配置时钟RCC开启USART和TX/RX对应的GPIO口

 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);//USART2挂载APB1总线
  RCC_APB1PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//GPIOA挂载APB2总线
  //对于哪个应用挂载哪个APB总线,可以根据代码自动补全功能快捷判断

2.初始化GPIO口
usart2对应引脚是PA2和PA3。RX引脚模式应该配置成浮空输入或者上拉输入。TX引脚模式配置成复用推挽输出。
首先需要设置结构体:观察GPIO结构体变量:
STM32(1)-简单实现串口收发与通信
然后针对TX/RX进行不同的配置。如下:


	GPIO_InitTypeDef  GPIO_InitStructure;//声明一个结构体对象
	//TX端口-PA2
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;//这个对象的成员变量GPIO_Pin取值为pin2
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//模式为复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//50MHZ速度
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	//RX端口-PA3
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//这个对象的成员变量GPIO_Pin取值为pin3
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//模式为浮空输入模式
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//50MHZ速度
	GPIO_Init(GPIOA,&GPIO_InitStructure);

3.进行串口的初始化
上面是对发送和接收端的端口的初始化,这里需要对串口初始化以开启串口功能。与GPIO类似,先实例化一个串口结构体对象,然后配置成员变量信息。

他的成员变量包括:
USART_BaudRate :串口通信使用的波特率 一般是9600或者是115200,这里给9600
USART_HardwareFlowControl :是否选择硬件流触发,一般这个也不选,所以选择无硬件流触发。
USART_Mode :串口的模式,发送模式还是接收模式,还是两者都有
USART_Parity :校验位,可以选择奇偶校验和不校验。没有需求就直接无校验
USART_StopBits :停止位 有1、0.5、2位,我们这里选1位停止位
USART_WordLength :数据位 有8位和9位可以选择

USART_InitTypeDef  USART_InitStructure;
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;//收发模式并存
USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
USART_InitStructure.USART_StopBits = USART_StopBits_1;//1位停止位
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//八位数据位
USART_Init(USART2,&USART_InitStructure);

4.引入中断机制
串口初始化中断的目的是为了确保当串口接收到数据时能够及时地响应处理。如果不初始化中断,程序只能在轮询方式下检测串口是否有数据到来,这样会占用较多的CPU资源,并且可能会出现漏接数据的情况。而初始化中断后,当串口接收到数据时,系统就会立即进入中断服务程序进行处理,从而提高了串口数据的处理效率和准确性。
当接收到数据后,触发接收中断,主程序暂停执行。接收完数据后主程序回复执行。当接收到数据时,就触发中断。
初始化中断并配置好成员变量:

	USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);//开启串口2的中断接收
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel =USART2_IRQn;//选择串口2的中断通道
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//子优先级
	NVIC_Init(&NVIC_InitStructure);

编写中断服务函数
当串口接收到数据时,会触发USART2的中断服务程序。在该函数内部,首先判断是否是RXNE标志位被置位,如果是则表示接收到了数据,将数据存储到RX_Data变量中,并设置Flag为1。然后通过调用USART_ClearITPendingBit函数清除RXNE标志位,以便下次能够正确地检测到串口是否有新的数据到来。

void USART2_IRQHandler(void){
	if(USART_GetITStatus(USART2,USART_IT_RXNE)==SET)   //RXNE 标志位为1 表示可以接收数据
	{
		u8 RX_Data=USART_ReceiveData(USART2);
		u8 Flag=1;
		USART_ClearITPendingBit(USART2,USART_IT_RXNE);  //清除RXNE标志位
	}
	}
	

另外,原子哥编写的USART1串口函数是这样的:

void USART1_IRQHandler(void)                	//串口1中断服务程序
	{
	u8 Res;
#if SYSTEM_SUPPORT_OS 		//如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
	OSIntEnter();    
#endif
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
		{
		Res =USART_ReceiveData(USART1);	//读取接收到的数据
		
		if((USART_RX_STA&0x8000)==0)//接收未完成
			{
			if(USART_RX_STA&0x4000)//接收到了0x0d
				{
				if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
				else USART_RX_STA|=0x8000;	//接收完成了 
				}
			else //还没收到0X0D
				{	
				if(Res==0x0d)USART_RX_STA|=0x4000;
				else
					{
					USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
					USART_RX_STA++;
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收	  
					}		 
				}
			}   		 
     } 
#if SYSTEM_SUPPORT_OS 	//如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
	OSIntExit();  											 
#endif
} 

这段代码是USART1的中断处理函数。当串口接收到数据时,会触发USART1的中断服务程序。在该函数内部,首先判断是否是RXNE标志位被置位,如果是则表示接收到了数据,将数据存储到Res变量中。然后通过对USART_RX_STA状态标志位进行操作,判断当前是否已经接收到完整的一帧数据,并将其存储到USART_RX_BUF缓冲区中。同时还需要注意接收错误的情况,如果出现错误需要重新开始接收。最后,如果支持操作系统,则需要在函数开始和结束时调用OSIntEnter和OSIntExit函数,以便操作系统能够正确地管理中断处理。

另外注意,实例化结构体时应该放在函数的一开始,否则会报错。并且,中断主要是用来接收数据的,串口发送数据不需要中断。

编写串口发送数据函数

void USART2_SendByte(USART_TypeDef * USARTx,uint8_t data){//串口收发每次都是一个字节,即8位数据
	
		USART_SendData(USARTx,data);
	//0 表示数据还未转移到移位寄存器 循环等待 1 数据已经被转移到了移位寄存器可以发送数据
	while(!USART_GetFlagStatus(USARTx,USART_FLAG_TXE)); 
	}

这段代码是用于向USARTx串口发送一个字节数据的函数。在函数中,首先调用USART_SendData函数将数据写入USARTx寄存器。然后通过循环等待的方式检查USART_FLAG_TXE标志位是否被置位,如果已经被置位则表示数据已经成功转移到移位寄存器,可以进行下一次发送。否则,需要继续等待直到TXE标志位被置位。该函数的作用是实现简单的串口发送功能。

三、主程序

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "usart2.h"
/************************************************
 ALIENTEK精英STM32开发板实验1
 跑马灯实验
 技术支持:www.openedv.com
 淘宝店铺:http://eboard.taobao.com 
 关注微信公众平台微信号:"正点原子",免费获取STM32资料。
 广州市星翼电子科技有限公司  
 作者:正点原子 @ALIENTEK
************************************************/
 int main(void)
 {	
	delay_init();	    //延时函数初始化	  
	LED_Init();		  	//初始化与LED连接的硬件接口
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); 
	Init_USART2();
	while(1)
	{
		USART2_SendByte(USART2,0x08);
	}
 }
 

可以看到8被不断的发送给串口。

总结

本文简单地介绍了stm32编写串口收发通信的有关方法,但没有涉及较复杂的应用,下一篇文章将深入串口的应用,使用stm32与esp8266通过串口完成通信。文章来源地址https://www.toymoban.com/news/detail-480131.html

到了这里,关于STM32(1)-简单实现串口收发与通信的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32学习笔记(五)串口空闲中断+DMA实现不定长收发(stm32c8t6)

    记录一下学习过程 DMA DMA,全称为: Direct Memory Access,即直接存储器访问, DMA 传输将数据从一个 地址空间复制到另外一个地址空间。 这一过程无需cpu的参与,从而提高cpu使用的效率 DMA相关的参数:1 数据的源地址、2 数据传输的目标地址 、3 传输宽度,4 传输多少字节,5 传

    2024年02月14日
    浏览(47)
  • STM32与Python上位机通过USB虚拟串口通信

    在详细阅读广大网友的教程之后,我对STM32和Python通过USB通信的流程烂熟于心。 尝试用ST公司的NUCLEO-L476RG板子进行简单的回环通信测试,发现还是存在网上无法找到的问题,这个耽搁了几天,期间找到了原因,但没有焊接调试,所以暂时就不以它为例子进行写了。 后采用正点

    2024年02月15日
    浏览(40)
  • STM32F407普通IO口模拟串口实现不定长数据收发

    因为项目中用到的串口比较多,STM32F407VET6自带的串口不够用了,所以只能考虑用模拟串口来实现功能。普通的IO口来模拟串口需要先了解串口的时序图,需要用到两个IO引脚即收发引脚,两个定时器,一个用于发送延时使用,一个用于产生中断接收数据。代码的初始化主要用

    2024年02月07日
    浏览(49)
  • STM32串口通信——DMA中断 (简单配置即可直接使用)

    目录 各函数的功能及使用方法 1.串口调试输出 2. 串口调试输出 接口设置    3. 串口格式化输出 4.用户串口DMA中断初始化函数 使用方法 1.找到系统的串口初始化函数 2.在结束位置添加我们的串口初始化函数  5.用户中断回调函数 使用方法 1.找到系统的中断服务.c文件 打开  

    2024年02月09日
    浏览(43)
  • STM32L4 HAL库通过串口通信改变PWM占空比

    使用串行通信的目的是为了让上位机能控制STM32来改变PWM的输出 这里用的是定时器TIM4的3通道,当然也可以改为其他的定时器,具体请参考手册 偷下懒,直接拿正点原子的例子程序修改了一下。 示例用的是UART1 引脚是PA9(TX),PA10(RX) 主要修改的地方在接收数据的部分,我用l

    2024年02月15日
    浏览(46)
  • STM-32:串口收发数据包—串口收发HEX数据包/串口收发文本数据包

    1、包头包尾和数据载荷重复的问题,传输的数据本身是FF和FE,可能引起误判 解决:限制载荷数据的范围,限幅(例如只发送0~100) 如果无法避免数据与包头包尾重复,则尽量使用固定长度的数据包 增加包头包尾的数量,尽量是其呈现出载荷数据出现不了的状态 2、包头包尾并

    2024年02月03日
    浏览(48)
  • STM32+Cube mx hal库实现CAN通信收发实验

          关于CAN通信的入门教程和基本原理在其他博主发的文章里面都有介绍,笔者只是简单记录下学习过程,文章用到的是正点原子的阿波罗F429开发板,另一个设备是中盛科技的继电器模块(CAN版)。       实现之前看一下继电器模块相关信息          发送数据的格式官方文

    2024年02月16日
    浏览(44)
  • STM32CubeMX+STM32F407+FreeRTos+LAN8720 以太网通信实现数据收发功能

    目录 前言 一、STM32CubeMX配置 二、修改代码 三、硬件测试 总结 该工程应用的以太网芯片是LAN8720,代码是基于STM32CUbeMx6.2.1配置生成的,在CubeMx中配置了ETH和LWIP,还有串口1和FREERTOS,最后通过创建任务函数实现udp的以太网数据收发功能。在测试中,可以在电脑的DOS窗口ping通在

    2024年02月08日
    浏览(60)
  • 江科协STM32教程——STM32 使用串口助手进行LED灯的点亮熄灭灭控制全代码过程(USART串口通信的简单应用)

            使用USART串口通信,通过上位机串口助手发送符串给STM32执行LED灯点亮熄灭操作的流程。         基本的配置如下所示,GPIO口配置的为PA9推挽输出,用于LED灯的操作。其余注意USART_ITConfig和USART_Cmd开启USART接收中断和使能USART运行。         接下来要进行发送字

    2024年03月21日
    浏览(61)
  • 通过串口中断的方式进行ASR-01S模块与STM32通信(问题与解决)

    最近在做一个智能家居的项目,需要实现语音控制的功能,于是我选用了ASR-01S模块与STM32通信,这个模块最大的好处在于有配套的编程软件和语音库,不用自己训练且编程简单(少儿编程的程度)。ASR-01S的代码架构在这不多说,总之在收到语音后它会通过串口发送一串命令给

    2024年04月22日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包