串行通信概述
波特率的计算
UART数据发送与接收
串口控制寄存器scon
练习内容
注意:定时器在发送和接收数据完毕都会产生中断,中断标志位TI或RI变为1;TI或RI需手动软件清零;
一、串口初始化代码思路
1、定义辅助寄存器AUXR(地址为0x8e)并清零(AUXR=0x00)(未进行此操作无法进行通信)
2、定时器1产生波特率,需要使用到定时器,首先要对控制定时器的寄存器进行配置,具体如下图。设置定时器1工作模式为自动重装8位定时器用于产生波特率(TH1、TL1=0xfd,设置波特率为9600)
3、启动定时器开始产生波特率(TR1=1)
4、设置串口工作模式,异步8位UART,允许接收(SCON=0x50);
5、打开中断允许(ES,EA=1)
具体代码
#include "reg52.h"
unsigned char dat=0;
sfr AUXR=0x8e;
void init_uart()
{
AUXR=0x00;
TMOD=0x20;//选择定时器1工作模式2
TH1=0xfd;//设置波特率9600
TL1=0xfd;//重装值
TR1=1;//启动定时器1
SCON=0x50;//设置串口工作模式
ES=1;//串口中断
EA=1;//总中断
}
void sendbyte(unsigned char dat)
{
SBUF=dat;
while(TI==0);//等待发送完成
TI=0;//清零
}
void serviceuart() interrupt 4
{
if(RI==1)//接收完毕
{
RI=0;//清零
dat=SBUF;//读取接收到的数据
sendbyte(dat+1);
}
}
void main()
{
init_uart();
sendbyte(0x5a);
sendbyte(0xa5);
while(1)
{
}
}
进阶应用
1、\r 回车 ,\n换行
2、注意这种写法P0=(P0|0x0f)&(~command|0xf0);//高四位不变,低四位取反
3、控制灯光的指令包括两部分,一是高4位,二是低四位,板子上的led从左到右对应P0口的低位到高位
#include "reg52.h"
sfr AUXR=0x8e;
void hc573(unsigned char channel)//锁存器
{
switch(channel)
{
case 4:P2=(P2&0x1f)|0x80;break;
case 5:P2=(P2&0x1f)|0xa0;break;
case 6:P2=(P2&0x1f)|0xc0;break;
case 7:P2=(P2&0x1f)|0xe0;break;
case 0:P2=(P2&0x1f)|0x00;break;//P0未被打通
}
}
void initsystem()//系统初始化
{
hc573(5);//关闭蜂鸣器
P0=0x00;
hc573(4);//关灯(led高电平熄灭)
P0=0xff;
}
void init_uart()//串口初始化
{
AUXR=0x00;
TMOD=0x20;
TH1=0xfd;
TL1=0xfd;
TR1=1;
SCON=0x50;
ES=1;
EA=1;
}
void sendbyte(unsigned char dat)
{
SBUF=dat;
while(TI==0);
TI=0;
}
void sendstring(unsigned char *str)
{
while(*str!='\0')
{
sendbyte(*str++);
}
}
unsigned char command=0x00;
void serviceuart() interrupt 4//串口中断
{
if(RI==1)
{
command=SBUF;
RI=0;
}
}
void translate()
{
if(command!=0x00)
{
switch(command & 0xf0)//取出高四位,低四位清零
{
case 0xa0:
P0=(P0|0x0f)&(~command|0xf0);//高四位不变,低四位取反
command=0x00;break;
case 0xb0:
P0=(P0|0xf0)&((~command<<4)|0x0f);
command=0x00;break;
case 0xc0:
sendstring("The system is running...\r\n");
command=0x00;break;
}
}
}
void main()
{
initsystem();
init_uart();
sendstring("Welcome to the lcx's system!\r\n");
while(1)
{
translate();
}
}