一、串口基础知识
- 嵌入式系统中的通信
两个或两个以上的主机之间的数据交互 - 通信方式
- 并行通信:多个比特同时通过并行线进行传输(芯片硬件线路的并行)
- 串行通信:将数据拆分成一个个比特,按照先后次序在一根总线上进行发送
- 通信模式
- 单工通信:通过一根总线,一方发送一方接收
- 半双工通信:通过两条信道,一方发送的时候另一方不能接收,一方接收的时候另一方不能发送
- 全双工通信:通过两条信道,允许通信双方同时发送和接收数据
- 数据传输速率
串行通信用比特率来描述数据传输的速率(bps),常用的比特率有1200,2400,4800,9600,115200
若比特率为9600bps,每个比特传输所需要的时间为1/9600s
波特率(Baud)是每秒传输的码元个数,和比特率的转换公式为:比特率 = 波特率 * log2^N ,N代表一个码元携带了N个比特 - 同步通信和异步通信
异步通信:串口通信时,收发双方的比特率按照各自的系统计时且双方之间的误差不能太大(UART,单总线)
同步通信:通信时设备之间还有一条,(SCL)时钟线,发送方通过时钟线控制双方的比特率。(SPI,IIC通信接口)
二、编写程序
编写串口的程序时,一定要注意手册中对寄存器的描写,初始化的时候有一些寄存器是选择串口的工作模式的,一定要理解这些初值对应的工作模式及其对应的计算。
1.初始化
IE的总中断B7,T1的中断允许位B3需要初始化
注意:在这里,串口的使用是需要时钟来控制异步通信的比特率,因此T1需要被串口占用,如果使用串口的同时还想使用时钟,那就只能使用T0时钟了。
TCON的B6位需要置位
TMOD的B5,B4,B3需要置位
SCON的B7,B6,B4位需要置位
PCON的B7,B6需要置位
初始化的难点在于模式的选择,也就是模式对应的波特率计算:
对图1来说,假设选择方式1,12T模式
分析公式中的变量:
SMOD:波特率是否加倍,加倍值为1,不加倍值为0
SYSclk:晶振频率,51单片机为12MHZ
波特率:一般已经选定,为9600,115200等通用数值
TH1:需要计算的值
用这个公式,假设波特率1200,smod加倍
计算结果约为204
代码如下):
void init_uart()
{
IE|=(1<<7)|(1<<4); //set UART
SCON&=~(1<<7);
SCON|=(1<<6)|(1<<4);
PCON&=~(1<<6);
PCON|=(1<<7);
TCON|=(1<<6); //set Timer
TMOD&=~(1<<3);
TMOD&=~(1<<4);
TMOD|=(1<<5);
TL1= 204;
TH1= 204; //forget the TH1 are the right com
}
注意:在初始化的时候,IT负责SBUF的发送,RI负责SBUF的接收,并且两者是或逻辑向主机请求中断,因此在中断响应的时候,需要在SBUF=ch之前先判断是否是IT位为1,在receive=SBUF之前先判断RI位是否为1,这样才能让主机正确响应SBUF的接收or发送请求。
如果不进行逻辑判断,也由于UART串口全双工的特性,会导致发送数据的时候接收函数也被调用,导致主机阻塞数据收发出现问题。
中断服务函数代码如下:
void uart_handler() interrupt 4
{
if(SCON&(1<<0)!=0)
{
rec[pos++]=SBUF;
SCON&=~(1<<0);
}
}
数据传输函数的编写和c语言基本一样,除了多出来一步给SBUF中放想要收发的数据,让串口把数据传输出去。