1. 通信的三个概念
通信的过程可以分为三个步骤:首先,发送方按照固定编码格式进行编码;其次,将编码后的信息发送到传输介质上;最后,接收方收到后进行解码得到有效信息。
- 串口通信概念1
同步和异步:发送方和接收方的时钟节拍一致叫同步,否则叫异步。如下雨所示,最上边的一根线就是同步信号线,发送端和接收端在相同的节拍下工作。 同步使用场景:当发送端和接收端频率固定时,使用同步信号。可以想象接收端一直在接收发送端的消息。 异步场景:在通信的双方频率不固定时,使用异步通信。 - 电平信号和差分信号
电平信号:电平信号需要两根信号线,一根是参考线GND(0伏),另一根是信号线。电平信号值是信号线和参考电瓶线的差值。 **差分信号:**没有参考线,有两根信号线,差分信号的信号值:两根信号线的电压差。 **两种信号线特点:**电平信号容易受干扰,适合短距离传输。差分信号抗干扰能力强,适合长距离传输。 电平信号的准备: RS232准备:-3~-15表示1, 3 ~15 表示0;TTL标准:+5表示1,0表示0.我们电脑后边的串口就是TTL标准的电平。 - 并行通信和串行通信
并行和串行主要说的是通信线的根数,就是发送方和接收方同时可以传递的信息量的多少。比如对电平信号来说,两个可以传送1位二进制,三根可传送两位2进制;传送8位需要9根。 对差分信号来说,两根线可同时发送一位二进制,传送8位需要16根线。 但是,实际上用的最多的还是串口通信,因为节省材料,并且现在串口用的最多的是传送调试信息。日常生活中网络通信,USB通信通过:异步,串行,差分方式。
2 串口通信的基本原理
- 三根通信线:RX TX GND
实际串口通信中,有9根线,但只有三根有效,就是RX TX GND。 - 波特率,数据位,奇偶校验位,停止位
这是SECURECRT链接串口输出调试信息的设置。 波特率:就是一秒内传输的二进制位数,常见的有9600,115200.双方的波特率不一致,收发就会出现问题。 数据位:发送端是一个周期一个周期的,通常将发送信息编码成ACSII码,因此就是一个周期内发送8位。 开始位:开始位设置为双方约定的高电平和低电平,当发送方收到二进制流时,就知道从哪里开始了。 停止位:停止位是串口通信双方事先指定的,是由通信线上的电平变化来反映的。常见的停止位有1位,1.5位,2位。 奇偶校验位:就是把数据位一一加起来,如果是偶数则奇偶校验位就是1,如果是奇数则奇偶校验位是0(看自己定义)。 - 信息是以二进制流的方式在信道上传输
- DB9接口介绍
DB9是串口通信早期比较常用的一种规范。DB9中有9根线,3根为通信线,剩下的6根和流控(作用是控制发送流的速度)有关,现在一般都禁用流控,所以6根没有用。
3. 串口通信工作框图
从上图中可以看出,整个串口控制器包括Transmitter和receiver两部分,两部分功能彼此独立,transmitter负责向外发送信息,receiver负责从外部接受信息。 Transmitter由发送缓冲区和发送移位器组成。我们发送信息时,编码成二进制流,然后将一帧数据写入发送缓冲区(剩下的发送就是硬件自动完成的),单位了说明上图,具体来说明工作过程。然后,发送移位器会自动从发送缓冲区中读取一帧数据,通过移位一位一位发送在Tx通信线上。 接收缓冲区由Receiver 和 接收移位器构成。二进制流时通过Rx通信线进入我的接收移位器,然后接收移位器自动移位将该二进制位保存入接收缓冲区中,接收完一帧数据后产生一个中断给CPU,cpu收到中断后即可知道receiver收满了一帧数据,就会来处理这帧数据。 上面的过程,对于我们软件工程师来说,就是设置相应的寄存器,具体硬件细节根本不用我们管。设置寄存器时需要注意,要设置串口控制器的波特率发生器,就是要设置发送/接收的节拍时钟。波特率发生器其实就是个时钟分频器,它的工作需要源时钟(APB总线来),然后内部将源时钟分频(软件设置寄存器来配置),得到目标时钟,然后再用目标时钟产生波特率(硬件自动的)。
4. 具体实现
虽然可以直接设置寄存器的值,*(volatile unsigned int *) XXX地址值XX = 0xXXXX ,但是为了代码清楚整洁,写成如下方式。 首先,定义寄存器;然后,初始化操作;最后,定义uart_putc函数发送(就是给寄存器赋值)。
#define GPAOCON 0XE0200000
#define UCON0 0XE2900004
#define ULCON0 0XE2900000
#define UMCON0 0xE290000C
#define UFCON0 0xE2900008
#define UBRDIV0 0XE2900028
#define UDIVSLOT0 0XE290002C
#define UTRSTA0 0XE2900010
#define UTXH0 0XE2900020
#define URXH0 0XE2900024
#define rGPA0CON (*(volatile unsigned int *)GPAOCON)
#define rUCON0 (*(volatile unsigned int *)UCON0)
#define rULCON0 (*(volatile unsigned int *)ULCON0)
#define rUMCON0 (*(volatile unsigned int *)UMCON0)
#define rUFCON0 (*(volatile unsigned int *)UFCON0)
#define rUBRDIV0 (*(volatile unsigned int *)UBRDIV0)
#define rUDIVSLOT0 (*(volatile unsigned int *)UDIVSLOT0)
#define rUTRSTA0 (*(volatile unsigned int *)UTRSTA0)
#define rUTXH0 (*(volatile unsigned int *)UTXH0)
#define rURXH0 (*(volatile unsigned int *)URXH0)
void uart_init(void)
{
rGPA0CON &= ~(0xff<<0);
rGPA0CON |= 0x00000022;
rULCON0 = 0x3;
rUCON0 = 0x5;
rUMCON0 = 0;
rUFCON0 = 0;
rUBRDIV0 = 35;
rUDIVSLOT0 = 0x0888;
}
void uart_putc(char c)
{
while(!(rUTRSTA0 & (1 << 1)))
rUTXH0 = c;
}
结果如下:(正在审核,先上图片)
|