串行通信的初步认识
通信方式分类
1、按照数据传送方式:
并行通信:通信时数据的各个位同时传送,可以实现字节为单位的通信。
但是通信线多,占用资源多,成本高。
串行通信:一次只能发送一位,要发送8次才能发送一个字节。(从低位开始发送)
2、按照数据同步方式:
同步通信 :发送端在发送串行数据的同时,提供一个时钟信号,并按照一定的约定(例如:在时钟信号的上升沿的时候,将数据发送出去)发送数据,接收端根据发送端提供的时钟信号来接收数据。如:I2C、SPI等有时钟信号的协议,都属于这种通信方式。
异步通信 :接收方并不知道数据什么时候会到达,收发双方可以有各自自己的时钟。发送方发送的时间间隔可以不均,接收方是在数据的起始位和停止位的帮助下实现信息同步的。
3、按照数据传输方向:
单工通信:只允许一方向另外一方传送信息(即单方面传送),比如电视遥控机等。
半双工通信:数据可以在双方之间相互传播,同一时间只能其中一方发给另外一方,比如对讲机。
全双工通信:发送数据的同时也能够接收数据,两者可以同时进行,比如视频通话。
UART串口通信
UART(通用异步收发器)是一种通用串行数据总线,用于异步通信。该总线双向通信,可以实现全双工传输和接收。通过发送和接收数据来使单片机与单片机、单片机与电脑、单片机与各式各样的模块互相通信。
对于51单片机,以STC89C52RC为例,有两个引脚专门用来通信:一个是RXD,一个是TXD,其基本模型如下:
其中,GND必须连接在一起,因为GND是电平基准。
如果单片机1要给单片机2发送11110 0100这个数据,先发送一个0,持续一段时间,再发送一个0,再持续一段时间......以此类推,逐次把所有的位都发送出去。
1、持续时间是多长时间?
引入波特率 ,也叫比特率:发送二进制数据的速率,习惯上用baud表示。发送一位二进制数据的持续时间为:1/baud。
如果单片机1和单片机2要通信,必须要保持波特率的一致。
2、数据什么时候开始、结束?
UART串口通信里规定:当没有通信信号发生的时候,通信线路保持高电平。在发送数据之前,先发送一个0表示起始位(这个0的持续时间也是1/baud)。之后再发送8位的数据位,最后再发送一位1表示停止位。
RS232通信接口
串口通信可以实现单片机与单片机通信,也可实现单片机与电脑通信。对于电脑,其CPU就相当于一个单片机。
通常,台式电脑上有RS232接口(九针九孔,也叫公头母头),但笔记本电脑一般没有,通常用USB虚拟的串口。
RS232接口及其各个针孔功能:
RS232电平标准:
高电平1:-3V~-15V;低电平0:+3V~+15V,为负逻辑。
其不能直接与单片机相连(会烧坏单片机),通常情况下用MAX232转换芯片来实现我们单片机电压与电脑电压之间的转换。
缺点:传输距离有限,最大传输距离标准值为50英尺,实际上也只能用在15米左右。且接口使用一根信号线和一根信号返回线而构成共地的传输形式,这种共地传输容易产生共模干扰,所以抗噪声干扰性弱。
电平转换芯片
MAX232转换芯片
MAX232芯片是美信(MAXIM)公司专为RS-232标准串口设计的单电源电平转换芯片,使用+5v单电源供电。
TTL/CMOS数据从11引脚(T1IN)、10引脚(T2IN)输入转换成RS-232数据从14(T1OUT)、7脚(T2OUT)送到电脑DB9插头;DB9插头的RS-232数据从13引脚(R1IN)、8引脚(R2IN)输入转换成TTL/CMOS数据后从12引脚(R1OUT)、9引脚(R2OUT)输出。
USB转串口通信
我们在工业上常使用RS232串口通信,但在商业上大部分为USB转UART技术。
USB转串口设备是一种将计算机的USB接口转换为通用串口(如RS232、RS485等)的转换器**。**这种设备使得没有串口的老式设备(如编程器、机械控制系统等)能够通过USB接口与现代计算机连接。
串行口通信相关寄存器
SCON:串行控制寄存器
|-----|--------|-----|-----|-----|-----|-----|----|----|
| 地址 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
| 98H | SM0/FE | SM1 | SM2 | REN | TB8 | RB8 | TI | RI |
SCON用于选择串行通信的工作方式,和某些控制功能,其格式如上,可位寻址。通常只考虑SM0、SM1、REN、TI和RI。
SM0/FE:当PCON寄存器中的SMOD0为1,该位用于帧错误检测;当PCON寄存器中的SMOD0为0时,该位与SM1一起指定串行通信的工作方式,具体如下:
REN:允许/禁止穿行接收控制位。由软件置位REN,REN=1为允许串行接收状态,可启动串行接收器RXD,开始接收信息;软件复位REN,即REN=0,则禁止接收;
TI:发送中断请求标志位。在模式1中,停止位开始发送时由内部硬件置1,表示向主机请求中断;中断响应后需要软件复位,即TI=0。初始化为0。
RI:接收中断请求标志位。在模式1中,接收到停止位时由内部硬件置1;中断响应后由软件复位0,初始化为0。
PCON:电源控制寄存器
|-----|------|-------|----|-----|-----|-----|----|-----|
| 地址 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
| 87H | SMOD | SMOD0 | / | POF | GF1 | GF0 | PD | IDL |
不可位寻址。
SMOD:波特率选择位,就是决定波特率是否加倍。用软件置位SMOD,当SMOD=1时,使波特率加倍;当SMOD=0时,各工作方式的波特率不加倍。复位时默认SMOD=0。
SMOD0:帧错误检测有效控制位,当SMOD0=1时,SCON寄存器中的SM0/FE位用于FE功能(帧错误检测);当SMOD0=0时,SCON寄存器中的SM0/FE位用于SM0功能,与SM1一起指定串行口工作方式。
SBUF:串行口数据缓冲寄存器
SBUF寄存器有2个,一个是发送寄存器,另一个是接收寄存器(名字都一样),但在逻辑上SBUF只有一个(地址都为99H),物理结构上,这是俩个完全独立的寄存器。如果CPU写SBUF,数据就会被送入发送寄存器准备发送;如果CPU读SBUF,则读入的数据一定来自接收寄存器。
简单来讲:a=SBUF,代表单片机从计算机接收到了数据(接收到的数据自动存在接收寄存器SBUF中)并且从接收寄存器SBUF读取数据并赋给a。SBUF=a,代表单片机要给计算机发送a数据,只需将a赋给发送寄存器SBUF就行,发送寄存器SBUF会自动给计算机发送SBUF中的数据。
波特率的设置
为选择波特率,关键在于定时器/计数器1的溢出率。
溢出率:单位时间内(1秒)定时器/计数器溢出的次数。
通常用的是定时器T1的模式2。模式2中,不再是 TH1 代表高 8 位,TL1 代表低 8 位了,而只有 TL1 在进行计数,当 TL1 溢出后,不仅仅会让 TF1 变 1,而且还会将 TH1 中的内容重新自动装到 TL1 中。这样有一个好处,就是我们可以把想要的定时器初值提前存在 TH1 中,当 TL1 溢出后,TH1 自动把初值就重新送入 TL1 了,全自动的,不需要程序中再给 TL1 重新赋值了。
代码设计
UART串口通信初始化
cpp
void UART_Init(){
SCON=0x40; //0100 0000
PCON=0;
/*
*通过定时器T1来设置波特率
*/
TMOD&=0x0F; //0000 1111,清零定时器T1
TMOD|=0x20; //0010 1111,设置T1定时模式
TL1 = 0xFA; //设定定时初值
TH1 = 0xFA; //设定定时器重装值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
}
其中,要禁止定时器1中断。如果允许中断,当中断服务程序执行时,可能会引入额外的延迟或抖动,这会干扰波特率发生器的正常工作,导致数据传输错误或不稳定。
此处SCON=0x40,说明REN=0,不允许接收数据;若需要单片机接收数据,将REN置1,即:SCON=0x50。
串口发送一个字节
cpp
void UART_SendByte(unsigned char Byte)
{
SBUF=Byte;
while(TI==0);//检测是否完成发送
TI=0;
}
串口中断函数模版
cpp
void UART_Routine() interrupt 4
{
if(RI==1)
{
执行程序
RI=0;
}
}
注意,中断函数要进行条件判断,因为串口接收和发送字节都能产生中断请求(即:当TI为1或RI为1时都能产生中断请求),通过条件判断来区分接收和发送。