目录
1. 通信是什么
2. 电平信号和差分信号
3. 通信的分类
3.1 时钟信号划分
3.1.1 同步通信
3.1.2 异步通信
3.2 通信方式划分
3.2 通信方向划分
4. USART和UART(串口通信)
4.1 串口通信协议
4.2.1 TTL
4.2.3 RS485
4.3 三种电平协议下串口通信硬件连接
4.3.1 TTL电平标准下的硬件物理层--uart
4.3.2 思考:为什么还要有RS232、RS485?
4.3.3 RS232电平标准下的硬件物理层
4.3.3.1 典型电路
1. RS485电平标准下的硬件物理层
1.1 典型电路
1.2 特点
5. USART功能框图
6. 串口相关寄存器
6.1 串口控制寄存器---数据位长度、校验位、停止位
6.2 波特率设置寄存器
6.3 中断和状态寄存器
6.4 数据发送寄存器
6.5 数据接收寄存器
7. 串口发送实验
7.1 线路分析
7.2 cubeMX配置
7.3 练习:循环发送A-Z到串口
8. printf的重定向
1. 通信是什么
至少有收发双方,进行信号 数据的交互
2. 电平信号和差分信号
1.电平信号:电平信号有一根是参考电平线,信号线的信号值有信号线和参考电平线之间的电压差决定;
2.差分信号:差分信号没有参考电平线,传输一路数据需要两根信号线,信号线的信号值由两根信号线的电压差决定。
区别:
(1)信号值的表示不同:电平信号的信号值是信号线和参考电平线的电压差决定;差分信号的信息值是由两条信号线的电压差决定;
(2)传输相同路数的信号,电平信号用的数据线根数比差分信号少。比如传输3路信号,电平信号需要1根参考电平+3根数据线;而差分信号需要2x3=6根数据线;
(3)现在通信大部分是差分信号,因为差分信号的抗干扰性更强,可以在更短的周期传输一个数据。
3. 通信的分类
3.1 时钟信号划分
3.1.1 同步通信
通信双方根据同步信号通信,比如双方有一个共同的时钟信号(SPI全双工 I2C半双工)
3.1.2 异步通信
通信双方有自己独立的系统时钟,大家约定好通信的速度。异步通信不需要同步信号,但是并不是说通信的过程不同步(UART)
3.2 通信方式划分
串行通信:指的是同一时刻只能收或发一个bit位信息。因此只用1根信号线即可。
串行传输:数据一位一位串起来,逐个传输,数据按位顺序传输。
优点:占用引脚资源少
缺点:速度相对较慢
并行通信:指的是同一时刻可以收或发多个bit位的信息,因此需要多根信号线才行
并行传输:使用多根线同时传输一个字的多个位,如 8 根线一次传输 8 个位。
优点:速度快
缺点:占用引脚资源多
3.2 通信方向划分
单工:要么收,要么发,只能做接收设备或者发送设备。比如收音机
一根信号线只能单向发送或单向接收
半双工:可以收,可以发,但是不能同时收发, 比如对讲机
一根信号线可以接收数据也可以发送数据,但是两者不能同时进行
全双工:可以在同一时刻既接收,又发送。 手机
两根信号线,一根发送数据,另一根接收数据,真正实现同时收发数据,速度快
4. USART和UART(串口通信)
USART: 支持同步\异步通信、全双工、串行
UART :没有时钟线,只支持异步通信、全双工、串行
实际上他们是一种被包含的关系,当USART选择放弃其实中线的时候就是UART
4.1 串口通信协议
波特率: 码元/s 9600 115200 4800 bit/s
4.1 三种逻辑电平标准
4.2.1 TTL
TTL电平:逻辑1: 2.4V--5V 逻辑0: 0V--0.5V
TTL电平下的串口协议
假设发送的数据为:01010101
-
-
- RS232
-
电平标准:+3V~+15V对应0,
-3V~-15V对应1
RS232电平下的串口协议
假设发送的数据为:01010101
需要注意的是:
rs232 的逻辑电平和TTL 不一样但是协议一样。
4.2.3 RS485
RS-485仅是一个电气标准,描述了接口的物理层,像协议、时序、串行或并行数据以及链路全部由设计者或更高层协议定义。 RS-485定义的是使用平衡多点传输线的驱动器和接收器的电气特性。
RS-485能够进行远距离传输主要得益于使用差分信号进行传输,当有噪声干扰时仍可以使用线路上两者差值进行判断,使传输数据不受噪声干扰。
半双工、是电气协议(逻辑1:+2V–+6V 逻辑0: -6V— -2V)是二线制差分信号,也就是实际传输的数据是通过判断这两条信号线上的电压差来实现的,RS-485总线弥补了RS-232通信距离短,速率低的缺点,RS-485的速率可高达10Mbit/s,理论通讯距离可达1200米;RS-485和RS-232的单端传输不一样,是差分传输,使用一对双绞线
共模抑制
4.3 三种电平协议下串口通信硬件连接
4.3.1 TTL电平标准下的硬件物理层--uart
现在的Soc都内置了串口控制器,串口数据线一般都是两根线,一根发送(TX)一根接收(RX),用的TTL电平,当然也会有一根地线;
需要注意的是:
有的串口还有CTS、RTS接口,这是和自动流控相关,不是必要功能,用于保证数据传输的正确性,现在基本不用了,因为串口常用作打印输出或者用于连接低速的设备,对数据正确性没有太高要求;
因为uart外设本来输出的就是TTL电平,所以也称这种连线方式叫UART
因为是异步通信,所以通信速度较慢
不需要进行电平协议的转换,所以电路简单
4.3.2 思考:为什么还要有RS232、RS485?
(1)串口协议只是规定了数据传输时的协议,也就是规定了先传输1还是先传输0的问题,但是什么电压表示数据1,什么电压表示0,这并没有做规定;
(2)UART是相对于Soc这端来说的,Soc端集成了串口控制器,控制器支持串口协议(比如开始位、停止位、数据位、校验位等),用的是TTL电平;
(3)实际中两个设备的串口控制器要通信,中间是有一段距离的,Soc的引脚一般电平都比较低,数据能传输的有效距离很短;并且不同的设备所使用的电压也不一样,不能直接相连;
(4)需要中间电路负责来解决电压不匹配、传输距离等问题,于是有了RS232、RS485;
(5)RS232、RS485都是从电气层面(也就是物理器件)来区分的,具体的通信协议都是串口协议,但是使用的电压范围、是电平信号还是差分信号等不同;
4.3.3 RS232电平标准下的硬件物理层
(1)RS232是串口协议在电气层面的实现,RS-232标准接口定义了电压范围,规定逻辑“1”的电平为-5V~-15 V,逻辑“0”的电平为+5 V~+15V;
(2)Soc的串口引脚一般是3.3V或者5V的电压,所以Soc的串口引脚要使用RS232必须添加TTL电平转RS232电平的转换芯片;
(3)RS232的接口有多种(DB9接口、四线接口、三线接口),但是起主要作用的都是TX和RX引脚,可以简单理解成,RS232和UART的区别就是使用的电压范围不一样;
4.3.3.1 典型电路
DB9接口有9根线,最主要的就是RxD和TxD,其余的线是用于保证数据传输的正确性;
(1)优点:RS232标准接口的传输距离更长,在15米左右;
(2)接口的信号电平值较高,易损坏接口电路的芯片,又因为与TTL电平不兼容故需使用电平转换芯片才能与Soc的串口引脚连接;
1. RS485电平标准下的硬件物理层
RS-485收发器
RS-485是差分传输,如果用单片机控制RS-485接口的设备,需要用到收发器,这一点和CAN总线是类似的,如下是一个MCU控制一个RS-485的图示。
RS-485数据链路
上面讲到的RS-485收发器的工作原理,下面简单描述RS-485的数据链路。
主机发送给从机或者从机发送给主机,都会占用到A和B线,所以RS-485多用在半双工模式。
1.1 典型电路
TTL到485的转换同样需要电平转换芯片来做,下面是常用的一个MAX485电平转换芯片原理图。
1.2 特点
RS485传输距离长,抗干扰能力强、通信速率高
5. USART功能框图
问:UART数据发送和接收的流程
Tx:数据发送端
Rx:数据接收端
发送过程
发送过程:
由CPU或者DMA往TDR中写入数据
然后由硬件自动检测发送移位寄存器中是否有数据正在移位,
如果此时有数据正在移位,则数据等待当前移位寄存器移位完成后再往移位寄存器中放,此过程也是硬件执行。当TDR中的数据放到移位寄存器中的那一刻,TDR空,这时候标志位TXE置1,它来表示发送数据寄存器空。
如果此时没有数据正在移位,则直接由硬件将TDR中的数据放到发送移位寄存器中。
需要注意的是当TDR中的数据在等待往移位寄存器中放的时候,如果此时CPU或者DMA继续向TDR中写入数据,会将TDR中的数据覆盖掉。
接收过程:
接收过程:
首先数据线通过RX口连到接收移位寄存器
接收移位寄存器对紫色线的电平进行读取,将读取到的数据放到最高位,读下一位数据时,先把已有的位整体往右移一位,然后再将读到的数据放到最高位,以此往复,直到读满8位。
读满八位以后整体往RDR中放,此时RDR非空,标志位RXNE置1,它来表示RDR非空。
6. 串口相关寄存器
6.1 串口控制寄存器---数据位长度、校验位、停止位
字长设置由M1\M0共同决定
校验位设置
停止位设置
6.2 波特率设置寄存器
6.3 中断和状态寄存器
USART_ISR
第七位:发送数据标记,当发送数据寄存器为空,这个位置为1,也就是数据写入到发送数据寄存器之后,发送数据移位寄存器,从发送数据寄存器中将数据全部移走之后ISR第七位置1
第五位:接收数据标记,当接收数据寄存器非空,这个位置为1,数据被接受数据移位寄存器搬到接收数据寄存器中以后,ISR第五位置1
6.4 数据发送寄存器
USART_TDR 决定发送的数据:将要发送的数据写入
6.5 数据接收寄存器
USART_RDR决定接收的数据:将要接收数据的读取
7. 串口发送实验
7.1 线路分析
7.2 cubeMX配置
7.3 练习:循环发送A-Z到串口
void sendChar(char ch)
{ while(USART1->ISR);USART1->TDR=ch;
}
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* Configure the System Power */SystemPower_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */char ch='A';/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */sendChar(ch);ch++;if(ch >'Z'){ch='A';}}/* USER CODE END 3 */
}
去掉延时后出现乱序
出现乱码的原因:
数据往TDR中写入的速度过快,导致数据还没来得及往移位寄存器中放,就被覆盖了。
解决方法:
在CPU往TDR中写入数据之前,先判断TDR是否为空
因为TXE标志位置1时标志着TDR空。
所以在往TDR中写入数据之前用while卡死,退出的条件为,检测到TXE置1
void sendChar(char ch)
{ while(!(USART1->ISR & (1<<7)));//等待TXE置1,即TDR空USART1->TDR=ch;
}
HAL库函数实现发送和接收
简单的发送
接收和发送测试
8. printf的重定向
int printf(const char * format,...)
printf函数底层调用的是fputc函数,fputs是将要发送的数据写入到标准输出流stdout
__weak int fputc(int /*c*/, FILE * /*stream*/)
因此如果想让printf将数据输出到串口,需要重写fputc
WEAK弱符号
weak 顾名思义是“弱”的意思,所以如果函数名称前面加上__weak 修饰符,我们一般称这个函数为“弱函数”。
加上了__weak 修饰符的函数,用户可以在用户文件中重新定义一个同名函数,最终编译器编译的时候,会选择用户定义的函数,如果用户没有重新定义这个函数,
那么编译器就会执行__weak 修饰的函数,并且编译器不会报错。
自己写个重定向函数:
勾选上C库
#include<stdio.h>
int fputc(int ch, FILE * p)
{
while(!(USART1->ISR & 1<<7));//等待TDR为空,即TXE置1,跳出while,然后往TDR中放数据
USART1->TDR=ch;
}
作业:上位机控制实验
电脑向串口发送
F_ON 风扇打开
F_OF 风扇关闭
M_ON 马达打开
M_OF 马达关闭
L_ON LD1打开
L_OF LD1关闭
A_ON 全部打开
A_OF 全部关闭