1.通信接口
(1)通信目的:将一个设备的数据传输到另外一个设备,开展硬件系统。
(2)通信协议:指定通信的规则,通信双方按照协议规则进行数据收发。
名称 | 引脚 | 双工 | 时钟 | 电平 | 设备 |
USART | TX(数据发送引脚),RX(数据接收引脚) | 全双工 | 异步 | 单端 | 点对点 |
I2C | SCL(时钟线),SDA(数据线) | 半双工 | 同步 | 单端 | 多设备 |
SPI | SCLK(时钟线),MOSI(主机输出引脚),MISO(主机输入引脚),CS | 全双工 | 同步 | 单端 | 多设备 |
CAN | CAN_H(差分数据脚),CAN_L(差分数据脚) | 半双工 | 异步 | 差分 | 多设备 |
USB | DP(D+差分数据脚),DM(D-差分数据脚) | 半双工 | 异步 | 差分 | 点对点 |
名词解释:
(1)双工模式:1.全双工:指通信双方能够同时进行通信。(一般有两根通信线)
2.半双工:值通信双方只能进行一方对另一方通信,不可双向同时通信。(一
根数据线)
3.单工:指数据只能从一个设备到另一个设备,而不能反着来。
(2)时钟模式(作用:比如发送一个波形高电平然后低电平,接收后,如何知道是1100还是10,这时需要一个时钟信号)告诉接收方,什么时候需要接收数据。)
1.同步通信:要求接收端时钟频率和发送端时钟频率一致,发送端发送连续的比特流。
2.异步通信:不要求接收端时钟和发送端时钟同步,发送端发送完一个字节后,可经过任意长的时间间隔再发送下一个字节。
补充:如何判断同步异步:看是否有单独的时钟线,接收方可在时钟信号的指引下进行选择。
(3)电平特性
1.单端信号:引脚的高低电平是对GND的电压差,所以单端信号的双方必须要共地,就是双方的GND接在同一给地上。
2差分信号:靠两个差分引脚的电压差来传输信号,在通信时,不需要接GND。
(4)设备特性
1.点对点:只需双方直接传数据。
2.多设备:一方对多方,对多方需要有一个寻址的过程,以确定通信的对象。
2.串口通信
(1)串口是一种应用十分广泛的通讯接口,串口i成本低,容易使用,通信线路简单,可实现两个设备的相互通信。
(2)单片机的串口可以是单片机以单片机,单片机与电脑,单片机与各种各样的模块相互通信,极大的扩展了单片机的应用范围,增强了单片机系统的硬件实力。
2.1串口通信的硬件电路
(1)简单双向串口通信,有两根通信线(发送端TX,接收端RX)
(2)TX与RX要交叉连接。
(3)当只需要单向的数据传输时,可以只接一根通信线。
(4)电平标准不一致时,需要加电平转化芯片。
注:
(1)VCC与GND是供电。TX与RX是通信引脚
(2)TX与RX使用的是TTL电平。TX与RX是单端信号,高低电平是相当于GND的,所以,严格上说,GND也算通信线。
2.2 电平标准
电平标准是数据1与数据0的表达方式,是传输线缆中人为规定的电压和数据的对应关系,串口常用的电平标准有如下三种。
2.2.1 电平标准——TTL电平
+3.3v 或 +5v 表示 1
0v 表示 0
注:如果5v器件就使用5v,3.3v器件就使用3.3v
2.2.2 电平标准——RS232电平
-3v ~ -15v 表示 1
+3v ~ +15v 表示 0
注:RS232一般用在大型器件上。
2.2.3 电平标准——RS485电平
注:RS485是差分信号。
两线压差 +2 ~ +6 表示 1
两线压差 -2 ~ -6 表示 0
优点:抗干扰能力强,通信距离远。
2.3 串口参数及时序
(1)波特率:串口通信的速率。(在二进制下,一个码元为一个Bit,此时波特率 = 比特率 ,若波特率为1000bps,则串口发送速度为1s发1000位)
(2)起始位:标志一个数据帧的开始,固定位低电平(产生下降沿,告诉接收方我要发数据了)
(3)数据位:数据帧的有效载荷,1位高电平,0位低电平,低位先行。
(4)校验位:用于数据验证,根据数据位计算得来。
(5)停止位:用于数据帧间隔,固定位高电平。(产生高电平,告诉接收方我要停止了)
示意图:
2.4 补充:奇偶校验
奇偶校验:用于判断数据传输是否出错。
校验方式:1.无校验
2.奇校验
3.偶校验
校验原理(奇校验为例):在数据位9位的数据帧中,第9位为奇偶校验位,保证发送的数据帧的高电平个数为奇数,如果前八位为0x0F,即00001111,则校验位给0,如果前八位为0x1F,即00011111,则校验位给1。接收方接收到数据后,判断数据帧1的个数,如果为奇,则接收,若为偶,则选择丢弃或重传。
3.USART简介
(1)USART(Universal Synchronous/Asynchronous Receiver/Transmitter)
通用 同步/异步 收/发 器
(2)USART是STM32内部集成的硬件外设,可根据寄存器的一个字节数据自动生成数据帧时序,从TX引脚发送出去,也可自动接收RX引脚的数据帧时序,拼接为一个字节数据,存放在数据寄存器里。(USART电路功能)
(3)自带波特率发生器;最高达4.5Mbits/s。
(4)可配置数据位长度(8/9),停止位长度(0.5/1/1.5/2)
(5)可选校验位(无校验,奇校验,偶校验)
(6)支持同步模式,硬件流控制,DMA,智能片,IrDA,LIN。
(7)STM32F103C8T6的USART资源:USART1,USART2,USART3。其中USART1在APB1上,USART2和USART3在APB2上。
(8)串口发送:低位先行
注:
(1)USART的同步模式只是多个时钟输出,且只支持时钟输出,不支持时钟输入。(不支持两个USART之间进行同步通信,所以这个模式更多是为了兼容别的协议或特殊用途而设计的)
(2)波特率发生器:实际上是一个时钟,比如,APB2总线给个72MHZ频率,然后波特率发生器进行合频,得到我们想要的波特率时钟,最后在这个时钟下进行收发,就是我们指定的通信波特率。
3.1 总结:串口参数一般设置
波特率:9600或115200
数据位:8位
停止位:1位
无校验
4.USART框图
由蓝圈和黄圈围住的寄存器工作流程:若在某时刻给TDR写入了0x55数据,也就是0101 0101,此时,硬件监测到了你写入;1数据,它就会检查,当前移位寄存器是不是有数据正在移位,如果没有,这个0101 0101就会立刻全部移入到发送移位寄存器里面,准备发送。当数据从TDR移动到移位寄存器时,就会置一个标志位,叫TXE(TX Empty),发送寄存器空,检查该标志位,如果置1了,我们就可以在TDR写入下一个数据了。
红圈围起的寄存器工作流程:发送移位寄存器会在发生控制器驱动下向右移位,然后一位一位,把数据输出到TX引脚(当数据移位完成后,新的数据会再次自动的从TDR转移到发送移位寄存器中来,若数据移位未完成,TDR数据会进行等待)
发送与接收数据移位寄存器的标志位:
发送移位寄存器的结束标志位:TXE(TX Empty发送寄存器空)
接收移位寄存器的结束标志位:RXNE(RX not Empty接收移位寄存器未空,当监测到RXNE为1时,就可以把数据读走了)
总结:当数据一旦从TDR转移到移位寄存器了,不管你有没有移位完成,我就立刻把下一个数据放到TDR中等待了,一旦移完了,新的数据就会跟上。
5.USART基本结构
注:
(1)当数据从数据寄存器转移到移位寄存器时,会置一个TXE标志位,我判断这个标志位,接可以知道是不是可以写下一位数据了。
(2)RX的波形通过GPIO输入,在接收控制器控制下,一位一位移入接收移位寄存器,移完一帧后,数据就会同一转运到接收寄存器,在转移时,置一个RXNE标志位,,我们检查该标志位,就可以知道是不是收到数据了,同时,这个标志位也会申请中断(中断作用:在收到数据时,进入中中断函数,然后快速的读取和保持数据了)
6.发送的数据——数据帧
6.1 数据帧——字长设置
字长设置:9位或8位(包含校验位)
设置类型:(1)9位字长,有校验
(2)9位字长,无校验
(3)8位字长,有校验
(4)8位字长,无校验
时钟频率与数据速率一样,接收端可以在时钟上升沿开始采样,这样可以精确定位每一位数据。
为了刚好发一个字节,我们一般选择:9位有校验或8位无校验
6.2 数据帧——配置停止位
设置类型:(1)0.5个停止位
(2)1个停止位
(3)1.5个停止位
(4)2个停止位
6.3 数据帧——波特率发生器
(1)发送器和接收器的波特率由波特率寄存器BRR里的DIV确定。
(2)计算公式:波特率 = Fclkx / (16 * DIV)
注:DIV * 16 的原因是:因为数据采集时,为了防止噪声,对采样时钟进行16倍
波特率,采集中间的数据。
如:要求波特率为9600时的DIV
因为USART的时钟Fclk2 = 72MHZ
由DIV = Fclk2 / (16 * 波特率)= 72MHZ / 16 / 9600 = 468.75 = 1 1101 0100.11
6.4 数据帧——发送数据帧
USART_SendBits(USART1,Byte); #发数据
while(USART_GetFlagStatus(USART1,USART_HAG_TXE) == RESET) #等待数据发送完成
6.5 数据帧——接收数据帧
if(USART_GetITStatus(USART1,USART_IT_RXNE) == SET) #等待移位完成
{
Serial_RxPackage = USART_ReceiveData(USART1); #开始接收数据
USART_ClearITPendingBit(USART1,USART_IT_RXNE); #等待接收完成标志位RXNE
}
7.同时发送多个数据帧——数据包
7.1 HEX数据包
HEX数据包类型:(1)固定包长,含包长包尾
(2)不固定包长,含包头包尾
如上:包头:0xFF 包尾:0xFE、
固定包长与可变包长选择问题:对应HEX数据包,如果载荷会出现和包头包尾重复的情况,那最好选择固定包长,可以避免接收错误,如果载荷不会和包头包尾重复,那可以选择可变包长。
7.2 文本数据包
文本数据包类型:(1)固定长度,含包头包尾
(2)不固定长度,含包头包尾
如上:包头:'@' 包尾:'\r' '\n'
7.3 接收HEX数据包
前言:指定S变量:S变量选择不同模式转变。
static uint8_t RxState = 0; #用来表示不同模式
static uint8_t pRxPackage = 0; #用来判断是否接收够数据
uint8_t RxData = USART_ReceiveData(USART1); #接收数据,存放到RxData中
if(RxState == 0) #模式1
{
if(RxData == 0xFF)
{
RxState = 1;
pRxPackage = 0;
}
}
else if(RxState == 1) #模式2
{
Serial_RXPacket[pRxPackage] = RxData;
pRxPackage++;
if(pRxPackage > 4)
{
RxState = 2;
}
}
else if(RxState == 2) #模式3
{
if(RxData == 0xFE)
{
RxState = 0;
Serial_RxFlag = 1;
}
}
7.4 接收文本数据包
static uint8_t RxStatus = 0; #用来表示不同模式
static uint8_t i = 0; #用来判断是否接收够数据
if(USART_GetITStatus(USART1,USART_IT_RXNE) == SET)
{
if(RxStatus == 0) #模式1
{
if(RxData == '@')
{
RxState = 1;
i = 0;
}
}
else if(RxStatus == 1) #模式2
{
if(USART_ReceiveData(USART) == 'r')
{
RxStatus = 2;
}
else
{
Serial_RxPackage[i] = USART_ReceiveData(USART1)
i++;
}
}
else if(RxStatus == 2) #模式3
{
if(USART_ReceiveData(USART1) == '\n')
{
RxStatus = 0;
Serial_RxFlag = 1;
Serial_RxPackage[i] = '\0';
}
}
}
8.USART相关函数
8.1 标配函数
void USART_DeInit();
void USART_Init();
void USART_StructInit();
void USART_Cmd();
8.2 用于配置同步时钟中输出的
void ClockInit();
void ClockStructInit();
8.3 void USART_DMACmd();
8.4 void USART_SendData()
作用:发送数据(写DR)
8.5 void USART_ReceiveData();
作用:接收数据(读DR)
8.6 标志位标配函数
FlagStatus USART_GetFlagStatus();
void USART_ClearFlag();
ITStatus USART_GetITStatus();
void USART_ClearITPendingBit);