2021-10-31

目录

一、串口通信协议

1、UART简介

2、 UART通信协议

(1)起始位

(2)数据帧

(3)奇偶校验位

(4)停止位

(5)下个起始位

(6)波特率

二、STM32的USART串口通信(中断)

3、要求

2、工程的建立

三、建立STM32与PC之间的通信基础

1、串口助手的使用

2、效果呈现
一、串口通信协议

1、UART简介
嵌入式开发中,UART串口通信协议是我们常用的通信协议(UART、I2C、SPI等)之一,全称叫做通用异步收发传输器(Universal Asynchronous Receiver/Transmitter),是异步串口通信协议的一种,工作原理是将传输数据的每个字符一位接一位地传输,它能将要传输的资料在串行通信与并行通信之间加以转换,能够灵活地与外部设备进行全双工数据交换。

注:在此开发板中,是有USART(Universal Synchronous Asynchronous Receiver and Transmitter通用同步异步收发器)串口的,USART相当于UART的升级版,USART支持同步模式,因此USART 需要同步始终信号USART_CK(如STM32 单片机),通常情况同步信号很少使用,因此一般的单片机UART和USART使用方式是一样的,都使用异步模式。因为USART的使用方法上跟UART基本相同,所以在此就以UART来讲该通信协议了。

2、 UART通信协议
(1)起始位
当未有数据发送时,数据线处于逻辑“1”状态;先发出一个逻辑“0”信号,表示开始传输字符。

(2)数据帧
紧接着起始位之后。资料位的个数可以是4、5、6、7、8等,构成一个字符。通常采用ASCII码。从最低位开始传送,靠时钟定位。

(3)奇偶校验位
资料为加上这一位后,使得“1”的位数应为偶数(偶校验)或奇数(奇校验),以此来校验资料传送的正确性。

(4)停止位
它是一个字符数据的结束标志。可以是1位、1.5位、2位的高电平。 由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。适用于停止位的位数越多,不同时钟同步的容忍程度越大,但是数据传输率同时也越慢。

(5)下个起始位
处于逻辑“1”状态,表示当前线路上没有资料传送,进入空闲状态。

处于逻辑“0”状态,表示开始传送下一数据段。

(6)波特率
表示每秒钟传送的码元符号的个数,是衡量数据传送速率的指标,它用单位时间内载波调制状态改变的次数来表示。

常用的波特率有:9600、115200……

时间间隔计算:1秒除以波特率得出的时间
二、STM32的USART串口通信(中断)
3、要求
2、完成一个STM32的USART串口通讯程序,要求:

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

2)STM32系统给上位机(win10)连续发送“hello windows!”。win10采用“串口助手”工具接收。

2、工程的建立
在我们前面的学习中已经介绍过两种建立工程的方式,分别是STM32CubeMX生成基础代码和使用大佬的工程模板文件。这里我们还是选择用大佬"洋桃电子"编写好的工程文件来完善即可。

我们要实现的功能是USART串口通信,所以我们也照葫芦画瓢创建一个usart.c文件并添加到我们的Basic文件夹里,然后我们下一步该做什么呢,相信你心中一定有答案了,初始化!接下来我们就来看看我们的代码怎么写。

usart.c:
#include “usart.h”

//使UASRT串口可用printf函数发送
//在usart.h文件里可更换使用printf函数的串口号
#if 1
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE {
int handle;
};
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
_sys_exit(int x){
x = x;
}
//重定义fputc函数
int fputc(int ch, FILE *f){
while((USART_n->SR&0X40)==0);//循环发送,直到发送完毕
USART_n->DR = (u8) ch;
return ch;
}
#endif

/*
USART1串口相关程序
*/

#if EN_USART1 //USART1使用与屏蔽选择
u8 USART1_RX_BUF[USART1_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15, 接收完成标志
//bit14, 接收到0x0d
//bit13~0, 接收到的有效字节数目
u16 USART1_RX_STA=0; //接收状态标记
/*
USART1专用的printf函数
当同时开启2个以上串口时,printf函数只能用于其中之一,其他串口要自创独立的printf函数
调用方法:USART1_printf(“123”); //向USART2发送字符123
*/
void USART1_printf (char *fmt, …){
char buffer[USART1_REC_LEN+1]; // 数据长度
u8 i = 0;
va_list arg_ptr;
va_start(arg_ptr, fmt);
vsnprintf(buffer, USART1_REC_LEN+1, fmt, arg_ptr);
while ((i < USART1_REC_LEN) && (i < strlen(buffer))){
USART_SendData(USART1, (u8) buffer[i++]);
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
}
va_end(arg_ptr);
}
void USART1_Init(u32 bound){ //串口1初始化并启动
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟
//USART1_TX PA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure);
//USART1_RX PA.10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
//Usart1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//USART 初始化设置
USART_InitStructure.USART_BaudRate = bound;//一般设置为9600;
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); //初始化串口
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启ENABLE/关闭DISABLE中断接收到数据时中断 读寄存器DR清零,也可软件手动清零
USART_Cmd(USART1, ENABLE); //使能串口
}

void USART1_IRQHandler(void){ //串口1中断服务程序(固定的函数名不能修改)
u8 Res;
//以下是字符串接收到USART1_RX_BUF[]的程序,(USART1_RX_STA&0x3FFF)是数据的长度(不包括回车)
//当(USART1_RX_STA&0xC000)为真时表示数据接收完成,即超级终端里按下回车键。
//在主函数里写判断if(USART1_RX_STA&0xC000),然后读USART1_RX_BUF[]数组,读到0x0d 0x0a即是结束。
//注意在主函数处理完串口数据后,要将USART1_RX_STA清0
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){ //接收中断(接收到的数据必须是0x0d 0x0a结尾)
Res =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据
printf("%c",Res); //把收到的数据以 a符号变量 发送回电脑
if((USART1_RX_STA&0x8000)0){//接收未完成
if(USART1_RX_STA&0x4000){//接收到了0x0d
if(Res!=0x0a)USART1_RX_STA=0;//接收错误,重新开始
else USART1_RX_STA|=0x8000; //接收完成了
}else{ //还没收到0X0D
if(Res
0x0d)USART1_RX_STA|=0x4000;
else{
USART1_RX_BUF[USART1_RX_STA&0X3FFF]=Res ; //将收到的数据放入数组
USART1_RX_STA++; //数据长度计数加1
if(USART1_RX_STA>(USART1_REC_LEN-1))USART1_RX_STA=0;//接收数据错误,重新开始接收
}
}
}
}
}
#endif

咱们有了usart.c文件就要有一个usart.h文件来声明咱们刚刚定义的函数,然后方便我们在main.c文件中调用,那么现在我们就来创建这个文件吧。

usart.h:
#ifndef __USART_H
#define __USART_H
#include <string.h>
#include “stdio.h”
#include “sys.h”
#define USART_n USART1 //定义使用printf函数的串口,其他串口要使用USART_printf专用函数发送

#define USART1_REC_LEN 200 //定义USART1最大接收字节数
#define EN_USART1 1 //使能(1)/禁止(0)串口1
extern u8 USART1_RX_BUF[USART1_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
extern u16 USART1_RX_STA; //接收状态标记

//函数声明
void USART1_Init(u32 bound);//串口1初始化并启动
void USART1_printf(char* fmt,…); //串口1的专用printf函数
#endif
这个文件里装的都是一些函数声明以及一些变量的定义。现在俺们就需要把这两个文件保存并添加进俺们的Basic文件夹里啦,上次我忘了说如何将.h文件添加进咱们的工程中,有的小伙伴就向我反应咱们的编译有问题,今天我就来教教大家如何将.h文件添加进来。

首先咱们还是点击“仙女棒”,然后选择 C/C++ 。
在这里插入图片描述
在这里插入图片描述
在介绍完我们的usart文件之后,我们再来讲讲我们的main.c文件该如何编写,相信大家现在都知道咱们的第一步是啥啦,没错,就是调用我们的初始化函数,然后剩下的只需要将咱们的串口输出函数写在while循环中就OK啦。

main.c:

#include “stm32f10x.h” //STM32头文件
#include “delay.h”
#include “usart.h”

int main (void){//主程序
//初始化程序
RCC_Configuration(); //时钟设置
USART1_Init(115200); //串口初始化(参数是波特率)
//主循环
while(1){
printf("hello windows "); //纯字符串发送数据到串口

    delay_ms(1000); //延时
}

}
三、建立STM32与PC之间的通信基础
在我们之前的学习中就已经建立过板子与我们的PC之间的通信了,也许你还没反应过来,但是这是我们已经做过的事情啦。仔细回想一下我们是怎样将USB-TTL与板子连接并且烧录程序的呢,实际上这就是一种通信连接啊,将板子的发送接到PC的接收,板子的接收接到PC的发送。只是我们之前没有实现UASAT串口发送功能而已。

1、串口助手的使用
所以我们现在暂时不要动烧录时的接线,咱们直接打开咱们的串口助手。(我这里用的是“洋桃电子”家的串口助手,我将它放入百度网盘供大家下载。

链接:https://pan.baidu.com/s/1QsM4UWR557wzmJqYCL2hcw
提取码:1111

咱们现在打开安装好的串口助手,如下图:

在这里插入图片描述
端口号我们可以参考咱们FlyMCU中烧录程序那个端口,我的是COM4端口,大家根据自己的来。是否还记得之前程序编写的时候我让大家记得波特率为 115200 ,我说后面咱们要用的,现在就派上用场啦 。然后我们是在PC上接收来自板子上的“hello windows”,所以我们选择接受模式中的“字符”,设置完成后如下图:
在这里插入图片描述

2、效果呈现

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值