串行通信是指使用一条数据线,将数据一位一位地依次传输,每一位数据占据一个固定的时间长度。 其只需要少数几条线就可以在系统间交换信息 该通讯分为异步通信和同步通信 单片机串行通讯我采用异步通信 在逻辑上,SBUF只有一个,它既表示发送寄存器,又表示接收寄存器 他们具有同一个单元地址99H。 在物理结构上,则有两个完全独立的SBUF,一个是发送缓冲寄存器SBUF,另一个是接收缓冲寄存器SBUF。 如果写SBUF,数据就是准备发送;如果读SBUF,则读入的数据来自接收的。 CPU对SBUF的读写,实际上是分别访问上述两个不同的寄存器。 例如 a = SBUF; 为写 SBUF = a;为读
对于时钟和中断有TCON控制寄存器 而对于中断也有串行控制寄存器SCON,一样它是可寻址的
SM0和SM1是用来设置工作模式的 方式0多用于拓展IO口,这里用不到 我用的工作方式是1 即 SM0=1 SM1=1 为10位异步收发器传送8位数据 REN为串行接收允许控制位。该位由软件置位或复位。当REN=1,允许接收,当REN=0,禁止接收。
那么我们如何知道数据发送完呢? 有2种方式, 1.查询发送中断标志位TI 当 TI=1表示发送了一帧数据 2.串口中断 但是TI在任何工作方式下必须由软件进行清0才可执行下一次发送数据
同理,接受数据完成后也有一样的方法 1.查询发接收中断标志位RI 当 RI=1表示接收了一帧数据 2.串口中断 RI也必须进行清0
对于中断而言无论是发送还是接收都会引起相同的中断 因此在中断程序中需要查询TI和RI的状态才能判断是接收还是发送产生的中断
还有一个控制寄存器为PCON中的SMOD 为波特率加倍位 (产生高波特率时启用平时不用,比如用11.0592晶振产生57600波特率时就要设置成SMOD=1) SMOD=1时,波特率加倍 PCON=0x80; SMOD=0 时,波特率不加倍。PCON=0x00;
在PCON中只有这一个位与串口有关
对于串口通讯需要设置波特率 波特率=(2^SMOD*fosc)/32*12*(256-T初值)
当T1作为波特率发生器时,最典型的用法是使T1工作在自动再装入的8位定时器方式(即方式2,且TCON的TR1=1,以启动定时器)。这时溢出率取决于TH1中的计数值。 串行口工作之前需对相关寄存器进行配置,设定其工作模式。 1.设置T1的工作方式2(编程TMOD寄存器);
2.计算T1的初值,装载TH1、TL1;
3.启动T1(编程TCON中的TR1位);
4.确定串行口控制(编程SCON寄存器);
如需串行口在中断方式工作时,要进行中断设置编程IE寄存器。
那么我打算写一个通用串口用电脑控制单片机的流水灯 [mw_shl_code=c,true]#include <reg52.h>
#define uchar unsigned char
uchar num;
void UART_init()
{
TMOD = 0x20; //T1工作模式2 8位自动重装
TH1 = 0xfd;
TL1 = 0xfd; //比特率9600
TR1 = 1; //启动T1定时器
SM0 = 0;
SM1 = 1; //串口工作方式1 10位异步
REN = 1; //串口允许接收
EA = 1; //总中断开启
ES = 1; //串口中断开启
}
void main()
{
UART_init(); //初始化设置
while(1);
}
void UART() interrupt 4
{
if(RI) //是否接收完成
{
num = SBUF; //num 取出
P1 = SBUF;
num++;
RI = 0;
SBUF = num;
while(!TI);
TI = 0;
}
}[/mw_shl_code]
使用烧录软件中的串口助手测试 应用成功,下一帖我将把数码管的数字显示写成一个函数打包方便使用,我会把代码进行共享 以上所有内容仅为个人学习及总结,如有错误之处请指点出来谢谢
|