在串口通信的程序设计中,主要有串口初始化和数据收发两个部分。
在初始化函数中,基本步骤如下:
<1> 设置定时器1的工作模式,也就是对TMOD寄存器赋值。(八位重装)
<2> 计算波特率参数,并赋值给TH1和TL1寄存器。
<3> 打开定时器1。
如果使用的是STC 12系统单片机,则要设置AUXR寄存器。
<4> 设置SCON寄存器。
<5> 使能串口中断ES。
<6> 使能总中断EA。
数据的发送通常采用查询的方式,而数据的接收则采用中断。
TI:发送中断标志位。发送前必须用软件清零,发送过程中TI保持零电平,发送完一帧数据后,硬件自动置 “1”,如果再发送必须用软件再清零。
RI:接收中断标志位。接收前,必须用软件清零,接收过程中RI保持零电平,接收完一帧数据后,硬件自动置“1”,如果再接收必须用软件再清零。
SCOM = 0x50 // 0101 0000 SM1 = 1 ,工作方式1 REN = 1 允许接收
sfr AUXR = 0x8E ; //首先定义AUXR寄存器
//串口配置函数中
AUXR = 0x00;//如果使用T2作波特率发生器,则写为AUXR = 0x40
还不是特别理解,先上代码:
#include"reg52.h"
sfr AUXR = 0x8E;
typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;
u8 code SMG[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xf8,0x80,
0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f}; //共阳数码管显示字符转换表
u8 LedBuff[8] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; //数码管显示缓冲区
u8 RxdByte = 0;
u8 T0RH = 0;
u8 T0RL = 0;
void Timer0Init(u16 ms);
void T1_UART_Init(u16 baud);
void LedScan();
void main()
{
EA = 1; //打开使能总中断
Timer0Init(1); //配置T0定时1ms
T1_UART_Init(9600); //T1配置波特率为9600
while(1)
{
LedBuff[1] = SMG[RxdByte & 0x0F]; //在数码管上显示接收字节的低四位
LedBuff[0] = SMG[RxdByte >> 4]; //在数码管上显示接收字节的高四位
}
}
void Timer0Init(u16 ms) //定时器0初始化函数
{
T0RH = (65536 - 11059200/12*ms/1000)/256; //T0定时器的高8位
T0RL = (65536 - 11059200/12*ms/1000)%256; // T0定时器的低8位
TMOD = (TMOD & 0x0F)|0x01; //定时器T0工作在模式1
TH0 = T0RH; //加载T0重载值
TL0 = T0RL;
TR0 = 1; //打开T0定时器
ET0 = 1; //允许T0中断
}
void LedScan()
{
static u8 i = 0;
P2 = (P2&0x1f)|0xe0; //打开段选通道
P0 = 0xff; //关闭所有段选,消隐
P2 = (P2&0x1f)|0xc0; //打开位选通道
P0 = 0x01<<i; //位选
P2 = (P2&0x1f)|0xe0; //打开段选通道
P0 = LedBuff[i]; //段选
if(i<7) //一个扫描循环结束(8位数码管,8ms)
{
i++;
}
else
i = 0; //重新开始下一次循环
}
void InterruptTimer0()interrupt 1
{
TH0 = T0RH; //重新加载重载值
TL0 = T0RL;
LedScan(); //数码管扫描显示
}
void T1_UART_Init(u16 baud) //串口配置函数,baud为通信波特率
{
AUXR = 0x00;
SCON = 0x50; //0101 0000配置串口工作在模式1,REN=1,允许接受
TMOD = (TMOD & 0x0F) | 0x20; //配置T1工作在模式2
TH1 = 256 - (11059200/12/32)/baud; //计算T1重载值
TL1 = TH1; //初值等于重载值
ET1 = 0; //T1用作波特率发生器,禁止T1中断
ES = 1; //使能串口中断
TR1 = 1; //启动T1
}
void InterruptUART()interrupt 4
{
if(RI) //接收到字节
{
RI = 0; //手动清零接收中断标志位
RxdByte = SBUF; //接收到的数据保存到接收字节变量中
SBUF = RxdByte; //接收到的数据再直接发回,提示输入信息是否正确接收
}
if(TI) //字节发送完毕
{
TI = 0; //手动清零发送中断标志位
}
}
理解了更深一点的代码(都写在注释里头)
sfr AUXR=0x8e;
void TimeT1_UART_init(uint baud)
{
AUXR=0x00;//T1用作波特率发生器,T2用作时,写0x40
SCON=0x50;//0101 0000 串口工作模式1 允许接收
TMOD=0x20;//T1在工作模式2,自动重载
TH1=256-(11059200/12/32)/baud;//计算T1重载值
TL1=TH1;//初值等于重载值
ET1=0;//T1用作波特率发生器时,禁止T1中断
ES=1;//串口中断打开
TR1=1;//启动T1
EA=1;//总中断打开
}
uchar dat;
void Tnterrupt_UART() interrupt 4
{
if(RI)//RI=1,即为接收到字节的标志
{
RI=0;//手动清0字节接受中断标志
dat = SBUF;//接受到的数据保存到变量中
SBUF= dat;//接受到的数据再直接发回,验证输入信息是否正确
}
if(TI)//TI=1,即为发送完毕字节的标志
{
TI=0;//手动清0字节发送完毕中断标志
}
}