200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > STM32串口通信USART练习

STM32串口通信USART练习

时间:2024-01-15 17:19:04

相关推荐

STM32串口通信USART练习

文章目录

一、STM32的USART介绍二、USART串口通信实践1、任务要求2、所用器材3、主要代码4、代码解析三、效果展示四、总结五、参考资料

一、STM32的USART介绍

通用同步异步收发器(Universal Synchronous Asynchronous Receiver and Transmitter)是一个串行通信设备,可以灵活地与外部设备进行全双工数据交换。有别于 USART 还有一个UART(Universal Asynchronous Receiver and Transmitter),它是在 USART 基础上裁剪掉了同步通信功能,只有异步通信。简单区分同步和异步就是看通信时需不需要对外提供时钟输出,我们平时用的串口通信基本都是 UART。

USART 满足外部设备对工业标准 NRZ 异步串行数据格式的要求,并且使用了小数波特率发生器,可以提供多种波特率,使得它的应用更加广泛。USART 支持同步单向通信和半双工单线通信;还支持局域互连网络 LIN、智能卡(SmartCard)协议与 lrDA(红外线数据协会) SIR ENDEC 规范。

USART 在 STM32 应用最多莫过于“打印”程序信息,一般在硬件设计时都会预留一个USART通信接口连接电脑,用于在调试程序是可以把一些调试信息“打印”在电脑端的串口调试助手工具上,从而了解程序运行是否正确、如果出错哪具体哪里出错等等。

二、USART串口通信实践

1、任务要求

(1)设置波特率为115200,1位停止位,无校验位。

(2)STM32系统给上位机(win10)连续发送“hello windows!”,上位机接收程序可以使用“串口调试助手“,也可自己编程。

(3)当上位机给stm32发送“Stop,stm32”后,stm32停止发送。

2、所用器材

① STM32最小核心板(STM32F103C8T6)

②USB转TTL(ch340芯片)

③ IDE:KEIL5 MDK

④ 实验所用串口:USART1

3、主要代码

主函数main.c

#include "delay.h"#include "usart.h"#include "string.h"u8 Res[50];int main(void){u8 flag=1;u8 len;u8 i;u16 times=0; delay_init();//延时函数初始化NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2uart_init(115200); //串口初始化为115200while(1){if(USART_RX_STA&0x8000){// 获取接收到的数据长度len = USART_RX_STA&0x3FFF;printf("你发送的消息为: \r\n");for(i=0; i<len;i++){USART1->DR=Res[i];while((USART1->SR&0X40)==0);}printf("\r\n\r\n");//判断是否接收到Stop,stm32if(Res[i-1] == '2'){if(Res[i-2] == '3'&&Res[i-3] == 'm'&&Res[i-4] == 't'&&Res[i-5] == 's'&&Res[i-6] == ',')if(Res[i-7] == 'p'&&Res[i-8] == 'o'&&Res[i-9] == 't'&&Res[i-10] == 'S'){flag=0;printf("\r\n\r\n停止发送\r\n\r\n");}}//判断是否接收到Startif (Res[i-1] == 't'){if(Res[i-2] == 'r'&&Res[i-3] == 'a'&&Res[i-4] == 't'&&Res[i-5] == 'S'){flag=1;printf("\r\n\r\n开始发送\r\n\r\n");}}USART_RX_STA=0;}times++;if(times%100==0&&flag==1)printf("hello windows!\r\n"); delay_ms(10);}}

中断函数USART1_IRQHandler

void USART1_IRQHandler(void)//串口1中断服务程序{u8 temp;if(USART_GetITStatus(USART1,USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾){temp=USART_ReceiveData(USART1);//读取接收到的数据if((USART_RX_STA & 0x8000)==0){//接收到了0x0dif(USART_RX_STA & 0x4000){// 接收错误,重新开始if(temp != 0x0a) USART_RX_STA=0;// 接收完成else USART_RX_STA |= 0x8000;}// 还未接收到0x0delse{if(temp == 0x0d) USART_RX_STA |= 0x4000;else{Res[USART_RX_STA & 0x3FFF]=temp;USART_RX_STA++;//接收数据错误,重新开始接收if(USART_RX_STA > 49) USART_RX_STA=0;}}}

串口初始化函数

u16 USART_RX_STA=0; void uart_init(u32 bound){//GPIO端口设置GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);//使能USART1,GPIOA时钟USART_DeInit(USART1); //复位串口 1//USART1_TX GPIOA.9GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9//USART1_RX GPIOA.10初始化GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10 //Usart1 NVIC 配置NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;//子优先级3NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//IRQ通道使能NVIC_Init(&NVIC_InitStructure);//根据指定的参数初始化VIC寄存器//USART 初始化设置USART_InitStructure.USART_BaudRate = bound;//串口波特率USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收发模式USART_Init(USART1, &USART_InitStructure); //初始化串口1USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断USART_Cmd(USART1, ENABLE);//使能串口1 }

4、代码解析

总体流程

中断函数

当接收中断发生时,我定义了一个用来存储接收数据的缓存数组,用来在主函数中判断是否接收到Stop,stm32或者Start,还定义了一个变量用来标记接收状态,判断接收是否完成,其中0~13位用来记录接收到的有效数据的个数,14位用来判断是否接收到回车,有则置为1,15位用来判断是否接收到换行,有则置为1,标志着接收完成。

主函数

先对串口、GPIO口、延时函数以及中断设置进行初始化,我还设置了一个标记变量,用来决定是否发送hello windows。函数开始时发送hello windows,然后等待中断。当上位机有数据发送到单片机时,执行中断函数,开始缓存数据,当接收完毕,接收完成标志位置为1,输出发送的数据,然后对发送的数据进行判断,若为“Stop,stm32",则将标记变量设为0,停止发送,若为”Start“,则将标记变量设为1,继续发送,其他字符将保持原来状态不变。

三、效果展示

连接如图所示,分别连接PA9,PA10以及3.3V和GND引脚,且BOOT0置为1,BOOT1置为0。

USB转TTL连接图,其中RX连接到PA9引脚,TX连接到PA10引脚 ,这是因为PA9引脚的复用模式是发送数据TX,而PA10是接收数据RX。一发一收才能建立起通信。

将程序烧录进STM32

打开串口调试助手设置好相关参数

注意安装好ch340的驱动,并且确保连线正确,不然识别不出端口号

代码效果

四、总结

这次实验让我了解了串口通信的相关内容,同时也搞清楚了中断函数的使用,这次实验大部分时间还是在调试代码上,主要是因为对相关的库函数不够了解。

五、参考资料

正点原子相关库函数模板(可在下载)正点原子串口通信相关视频

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。