串口的初始化:
- 设定定时器的工作方式 TMOD = …
- 根据设定的波特率和晶振频率(以及SMOD),计算定时器的初值。
- 启动定时器 TR1 = 1;
- 设定串行口的工作方式 SCON = …
- 串行口开中断 ES = 1,打开总中断EA = 1。
串口中断程序:
- 从SBUF里取数据
- RI清0
- 发送数据
- 判断是否发送完成;TI清0
- (可通过设定标志位来把代码移动到主函数里)
下面是例程的注释,程序实现在上位机上输入字符,下位机(单片机)返回“I get ”+输入的字符。
#include "reg51.h"
typedef unsigned char u8;
typedef unsigned int u16;
u8 flag,r,i; //定义标志位,取数据的变量r和发送字符的变量i
u8 code table[] = "I get ";
void UsartInit()
{
TMOD = 0x20; //设定定时器1为工作方式2,8位自动重装
TH1 = 0xF3; //装入初值(波特率4800,晶振12M,加倍)
TL1 = 0xF3;
PCON = 0x80; //SMOD是TCON的最高位,此处设SMOD为1,1000 0000
TR1 = 1; //启动定时器1
SCON = 0x50; //设置串口为工作方式1,允许接收位REN置1,0101 0000
ES = 1; //串口中断允许
EA = 1; //打开总中断
}
void main()
{
UsartInit(); //串口初始化
while(1) //持续等待中断的出现
{
if(flag == 1) //中断发生且中断程序跑完
{
ES = 0; //把中断允许先关掉,防止下面发送数据时又申请中断
for (i=0;i<6;i++)
{
SBUF = table[i]; //一位一位地发送数据
while(!TI); //判断是否发送完成
TI = 0; //TI在发送数据完成后自动置1,把TI清0
}
SBUF = r; //发送最初接收的数据
while(!TI);
TI = 0; //同上清0
ES = 1; //中断允许重新打开
flag = 0; //标志位清0,等待下次数据的输入
}
}
}
void Usart() interrupt 4
{
r = SBUF; //从SBUF里取接受到的数据
RI = 0; //RI在接收数据完成后自动置1,把RI清0
flag = 1; //标志位置为1
}