STM32_Day03(串口通信)

STM32_Day03(串口通信)
什么是通信?
1,数据交互
2,信息传递
3,条件:两个端 发送端 接收端

1.通信基础知识
1.1 时钟信号划分
同步通信:通信双方根据同步信号通信,比如双方有一个共同的时钟信号(SPI全双工 I2C半双工)
发送数据的时候会出现阻塞状态,需要等待数据传输完毕,程序才会执行到下一行

    异步通信:通信双方有自己独立的系统时钟,大家约定好通信的速度。异步通信不需要同步信号,但是并不是说通信的过程不同步(UART)

发送数据的时候没有阻塞状态,执行发送数据语句后直接执行下一行语句
1.2 通信方式划分
串行通信:指的是同一时刻只能收或发一个bit位信息。因此只用1根信号线即可。
串行传输:数据一位一位串起来,逐个传输,数据按位顺序传输。
优点:占用引脚资源少
缺点:速度相对较慢
在这里插入图片描述

 并行通信:指的是同一时刻可以收或发多个bit位的信息,因此需要多根信号线才行
 并行传输:使用多根线同时传输一个字的多个位,如 8 根线一次传输 8 个位。
 优点:速度快
 缺点:占用引脚资源多

在这里插入图片描述

1.3 通信方向划分
单工:要么收,要么发,只能做接收设备或者发送设备。比如收音机
一根信号线只能单向发送或单向接收

半双工:可以收,可以发,但是不能同时收发, 比如对讲机

一根信号线可以接收数据也可以发送数据,但是两者不能同时进行

全双工:可以在同一时刻既接收,又发送。 手机 

两根信号线,一根发送数据,另一根接收数据,真正实现同时收发数据,速度快
在这里插入图片描述

Tips:总线协议(电气协议)补充
TTL电平:数字电路中,由TTLhttps://baike.baidu.com/item/%E7%94%B5%E5%AD%90%E5%85%83%E5%99%A8%E4%BB%B6/9042493?fromModule=lemma_inlink组成电路使用的电平。电平是个电压范围,规定输出高电平>2.4V,输出低电平<0.4V。在室温下,一般输出高电平是3.5V,输出低电平是0.2V。最小输入高电平和低电平:输入高电平>=2.0V,输入低电平<=0.8V,https://baike.baidu.com/item/%E5%99%AA%E5%A3%B0%E5%AE%B9%E9%99%90/5802189?fromModule=lemma_inlink是0.4V。
RS-232:RS232电平
1:-15~-3V 0:+3~+15V RS232采用负逻辑电平 非法状态:-3 ~ +3V

   RS-485 :半双工、是电气协议(逻辑1:+2V–+6V 逻辑0: -6V— -2V)是二线制差分信号,也就是实际传输的数据是通过判断这两条信号线上的电压差来实现的,RS-485总线弥补了RS-232通信距离短,速率低的缺点,RS-485的速率可高达10Mbit/s,理论通讯距离可达1200米;RS-485和RS-232的单端传输不一样,是差分传输,使用一对双绞线

串口扩展(周末:自己整理)
https://docs.qq.com/doc/DQU5Ca3Fid3pKQkZx

2.USART
中文参考手册(564),英文(775)
Universal Synchonous Asynchronous receiver transmitter

USART:支持同步/异步 ,全双工 ,串行
UART:没有时钟线,只支持异步,全双工 ,串行
3.串口通信协议
在这里插入图片描述

数据帧格式:
空闲状态:信号线保持高电平
起始位:把电平拉低 1位 数据包起始
数据位:8位/9位
校验位(可选):奇偶校验
奇校验: 数据位上的1的个数 + 校验位上1的个数 = 奇数
偶校验: 数据位上的1的个数 + 校验位上1的个数 = 偶数
停止位:1位 将电平拉高,表示数据包发送结束,回到空闲状态

波特率:每秒传输的数据位数 bps bit/s 1Byte = 8bit
常用的波特率:9600 bit/s 115200 bit/s

4.USART功能框图
在这里插入图片描述

Tx:数据发送端
Rx:数据接收端
流控概念
在两个设备正常通信时,由于处理速度不同,就存在这样一个问题,有的快,有的慢,在某些情况下,就可能导致丢失数据的情况。如台式机与单片机之间的通讯,接收端数据缓冲区已满,则此时继续发送来的数据就会丢失。流控制能解决这个问题
nRTS:请求以发送(Request To Send),n表示低电平有效。当本设备准备好接收新数据时就会将nRTS变成低电平;当接收寄存器已满时,nRTS将被设置为高电平。
nCTS:清除以发送(Clear To Send) 为输入信号,低电平有效。用于判断是否可以向对方发送数据,低电平说明本设备可以向对方发送数据。该引脚只适用于硬件流控制
SCLK:发送器时钟输出引脚。这个引脚仅适用于同步模式。(UART是异步通信)

发送过程:由CPU和DMA向发送数据寄存器(TDR)中写入要发送的数据,由发送移位寄存器将数据按位移到发送端口输出。
接收过程:由CPU和DMA读取接收数据寄存器(RDR)中的数据。

5.相关寄存器
在这里插入图片描述

串口控制寄存器
USART_CR 决定帧格式:起始位+数据位+校验位+停止位
(设备功能初始化、通信帧格式配置)
USART_CR1
USART_CR2
USART_CR3

波特率寄存器
USART_BRR 决定通信速度:bit/s

中断和状态寄存器
USART_ISR
在这里插入图片描述
在这里插入图片描述

数据接收寄存器
USART_RDR 决定接收的数据:将要接收数据的读取
在这里插入图片描述

数据发送寄存器
USART_TDR 决定发送的数据:将要发送的数据写入

6.串口发送实验
实验要求
通过单片机以1s间隔向电脑发送“helloworld”
6.1 观察实物
找到通信接口 丝印“P4”
在这里插入图片描述

6.2 分析原理图

在这里插入图片描述

为什么要加电平转换芯片?
CH340:电平转换芯片,可以转换TTL电平—USB电平。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

数据选择器/多路复用器
S和E进行控制

在这里插入图片描述
在这里插入图片描述

6.3 STM32CubeMX配置

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6.4 代码编写
1)实现单个字符发送Uart_putchar();

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

2)实现字符串发送函数 Uart_puts();
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7.串口收发实验
代码编写
1.实现字符接收函数 Uart_getchar();
在这里插入图片描述

2.实现字符串接收函数 Uart_gets();
在这里插入图片描述

3.实现收发功能

void Uart_putchar(uint8_t ch);
void Uart_puts(uint8_t *p);
uint8_t Uart_getchar();
void Uart_gets(uint8_t *p);

uint8_t buf[32]={0};


		Uart_gets(buf);
		Uart_puts(buf);

void Uart_putchar(uint8_t ch)
{
	while(!(USART1->ISR & (1<<7))){}		//等待发送寄存器为空
		//ISR的第七位为1,说明发送寄存器为空,此时写入要发送的数据
		//当发送寄存器为空时,while(!1);跳出循环,继续向下执行
	USART1->TDR = ch;
}

void Uart_puts(uint8_t *p)
{
	while(*p)
	{
		Uart_putchar(*p);
		p++;
	}
}

uint8_t Uart_getchar()
{
	uint8_t ch;
	while(!(USART1->ISR & (1<<5))){}
	ch = USART1->RDR;
	return ch;
}

void Uart_gets(uint8_t *p)
{
	uint8_t ch;
	while(1)
	{
	ch = Uart_getchar();
	if(ch != '\n')
	{
		*p = ch;
	}else
	{
		*p='\0';
		break;
	}
		p++;
	}
}

8.printf的重定向
int printf(const char * format,…)
printf函数底层调用的是fputc函数,fputc是将要发送的数据写入到标准输出流stdout
int fputc(int /c/, FILE * /stream/)
因此如果想让printf将数据输出到串口,需要重写fputc

WEAK弱符号
weak 顾名思义是“弱”的意思,所以如果函数名称前面加上__weak 修饰符,我们一般称这个函数为“弱函数”。
加上了__weak 修饰符的函数,用户可以在用户文件中重新定义一个同名函数,最终编译器编译的时候,会选择用户定义的函数,如果用户没有重新定义这个函数,
那么编译器就会执行__weak 修饰的函数,并且编译器不会报错。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

int fputc(int ch,FILE *p)
{
	while(!(USART1->ISR & (1<<7))){}
	USART1->TDR = ch;
	return ch;
}

9.scanf的重定向
重写fgetc函数,将输入重定向到串口。
在这里插入图片描述

int fgetc(FILE *p)
{
	int ch;
	while(!(USART1->ISR & (1<<5))){}
	ch = USART1->RDR;
	return ch;
}

10.HAL库函数
HAL库572页
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

串口发送函数
HAL_StatusTypeDef HAL_UART_Transmit (UART_HandleTypeDef * huart, uint8_t * pData, uint16_t Size, uint32_t Timeout)
功能:以阻塞模式通过串口发送数据
参数:UART_HandleTypeDef * huart 设备的句柄
uint8_t * pData 要输出的缓存区首地址
uint16_t Size 发送的数据量
uint32_t Timeout 超时时间
返回值:发送状态
串口接收函数
HAL_StatusTypeDef HAL_UART_Receive (UART_HandleTypeDef * huart, uint8_t * pData, uint16_t Size, uint32_t Timeout)
功能:以阻塞模式通过串口接收数据
参数:UART_HandleTypeDef * huart 设备的句柄
uint8_t * pData 输入缓存区首地址
uint16_t Size 接收的数据量
uint32_t Timeout 超时时间
返回值:接收状态
在这里插入图片描述

作业
1、通过串口接收指令(字符串)来控制板载的LED的亮灭(用HAL库和重定向实现)
控制指令:
B_ON 打开蓝灯
B_CL 关闭蓝灯
Y_ON 打开黄灯
Y_CL 关闭黄灯
G_ON 打开绿灯
G_CL 关闭绿灯

2、第一个作业完成之后,自行整理其他通信协议
完成作业后,拍视频发到群里

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值