文章目录
- UART简介
- 传输数据帧和波特率
- 定时器1作为串口1波特率发生器
- 串口部分相关寄存器
- TMOD
- AUXR
- PCON
- SCON
- SBUF
- 串口1工作模式1:8位UART,波特率可变总体工作原理
- 如何简单接收一个字符和发送数据
- 一步之遥的设置
- 现象演示
UART简介
通用异步收发传输器(Universal Asynchronous Receiver/Transmitter),通常称作UART,是一种异步收发传输器。是一种串行、异步、全双工的通信协议,并且只要一对传输线就可以实现双向通信,大大降低了成本,但传送速度较慢
传输数据帧和波特率
1. 波特率
异步通讯中由于没有时钟信号所以两个通讯设备之间需要约定好波特率,即每个码元的长度,以便对信号进行解码,图中用虚线分开的每一格就是代表一个码元。常见的波特率为4800、9600、115200等。
单位bit/s–所以波特率就是传输数据速度快慢的反应,比如9600波特率,那就是1s传输9600bit(位)
2. 通讯的起始和停止信号
串口通讯的一个数据包从起始信号开始,直到停止信号结束。数据包的起始信号由一个逻辑0的数据位表示,而数据包的停止信号可由0.5、1、1.5或2个逻辑1的数据位表示,只要双方约定一致即可。
3. 有效数据
在数据包的起始位之后紧接着的就是要传输的主体数据内容,也称为有效数据,有效数据的长度常被约定为5、6、7或8位长。
4. 数据校验
在有效数据之后,有一个可选的数据校验位。由于数据通信相对更容易受到外部干扰导致传输数据出现偏差,可以在传输过程加上校验位来解决这个问题。校验方法有奇校验(odd)、偶校验(even)、0校验(space)、1校验(mark)以及无校验(noparity),它们介绍如下:
- 奇校验要求有效数据和校验位中"1"的个数为奇数,比如一个8位长的有效数据为:01101001,此时总共有4个"1",为达到奇校验效果,校验位为"1",最后传输的数据将是8位的有效数据加上1位的校验位总共9位。
- 偶校验与奇校验要求刚好相反,要求帧数据和校验位中"1"的个数为偶数,比如数据帧:11001010,此时数据帧"1"的个数为4个,所以偶校验位为"0"。
- 0校验是不管有效数据中的内容是什么,校验位总为"0",1校验是校验位总为"1"。
- 在无校验的情况下,数据包(帧)中不包含校验位。
注意:这里我们暂不关心校验以及波特率怎么算的,借用isp软件,进行波特率的生成,因为硬件在收发自己会自动补全数据包(数据流),所以只要关心有效数据位,重点学习对一帧有效数据的解码
定时器1作为串口1波特率发生器
借助isp生成定时器1作为串口1的波特率发生器
1. 波特率9600,
2. 串口1工作方式8位UART,波特率可变,
3. 定时器1(1T)工作在模式0(16位自动重载),
4. 开启串口1的中断,
void UartInit(void) //115200bps@12.000MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x40; //定时器时钟1T模式
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设置定时器模式
TL1 = 0xE6; //设置定时初始值
TH1 = 0xFF; //设置定时初始值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //定时器1开始计时
ES = 1; //串口1中断
EA = 1; //允许所用中断
}
为啥生成代码是这样???为什么这么设置呢????
串口部分相关寄存器
TMOD
这里设置定时器1为 16位自动重载(方便后面哦)的定时器
AUXR
bit6(T1x12):设置串口1为 1T模式
bit0(S1ST2):这里选择定时器1作为串口1(UART1)的波特率发生器
PCON
因为PCON复位值就是不加倍,所以就没配置
SCON
1. SCON可位寻址,也就是可以单独对位操作
2. 配合PCONbit6使用的,这里由于我们设置了PCONbit6为0,所以SM0和SM1用于选择串口1的工作模式,选择8位UART波特率可变(8位有效数据),然后提到了定时器1工作模式,我们之前设置定时器1为模式0(16位自动重载)这里就不要考虑PCON中bit7(SMOD)位,波特率加倍问题了
3. 开启内部串行接收器,这接收器,就会自动把数据搬到串行口数据缓冲寄存器SBUF里面
SBUF
这是两个寄存器,一个是放发送数据的,一个是放接收的数据的
另外串口1中断向量号为(查手册):
串口1工作模式1:8位UART,波特率可变总体工作原理
如何简单接收一个字符和发送数据
发送:
void SendByte(char bat)
{
SBUF = bat;
while(!TI);
TI = 0;
}
void SendString(char *str)
{
while(*str != '\0'){
SendByte(*str);
str++;
}
}
用串口中断接收
void Uart1Handler()interrupt 4
{
char tmp;
if(RI){
RI = 0;
tmp = SBUF;
SendByte(tmp);
SendByte(' ');
SendString("recive\r\n");
}
if(TI){
TI = 0;
}
}
一步之遥的设置
不选对,在考场里,你就等着哭吧
还有一个编码问题,有时候串口打印中文会乱码,推荐直接用GB232或者UTF-8
最后一个调试设置选择文本模式,波特率(匹配就行),和不选自动发送结束符
现象演示
(十六)串口Uart
----- 如有错误欢迎大家批评指正!!!