基础知识
1.串行通信中最常用的是UART。
2.波特率:每秒钟传输的位数,蓝桥杯单片机里最常用的是9600波特率,烧录的时候要记得改
3.用定时器1来产生波特率,使用使用串口通信的话,定时器1就不能做其他用途,在初始化串行接口模块的时候,除了要配置SCON寄存器之外,还要根据波特率参数设置定时器1的技术初值。
4.与串口相关的寄存器有:
(1)TH1和TL1:设置波特率参数。
(2)TMOD:设置定时器1的工作模式。
(3)SBUF:串行通信数据的发送和接收缓冲器。
(4)SCON:串行接口控制寄存器。
(5)用reg52.h的头文件时,要加一句sfr AUXR=0x8e
5.SCON串口控制寄存器(我写的第二篇关于蓝桥杯的博客里有关于其他两个寄存器的知识)
- TI:串行接口发送完成中断标志位
- RI:串行接口接收完成中断标志位
- RB8:发送数据的第8位
- TB8:接收数据的第8位
- REN=1,允许接收 REN=0,禁止接收
- SM2模式2/3才用
- SM0、SM1:工作模式
- 00:同步移位寄存器(波特率:fosc/12)
- 01:8位的UART 波特率可变
- 10:9位的UART 波特率fosc/12或fosc/64
- 11:9位的UART 波特率可变
6.串口初始化:
(1) 设置定时器1的工作模式,对TMOD寄存器赋值
(2) 计算波特率参数,赋值给TH1和TL1寄存器
(3) 打开定时器1
(4) 设置SCON寄存器
(5) 使能串口中断ES
(6) 使能总中断EA
数据的发送用查询方式,数据的接收用中断方式
例程
#include"reg52.h"
sfr AUXR=0x8e;
void send(unsigned char d);
void ruart();
void selectHC(unsigned char n);
void Init();
void Init()
{
selectHC(5);
P0=0x00;
}
void main()
{
void Init();
ruart();
send(0x5a);
send(0xa5);
while(1);
}
//串口初始化函数
void ruart()
{
TMOD=0x20; //定时器1工作模式为自动重装
TH1=0xfd; //设置波特率为9600
TL1=0xfd; //11.0592M或12M的12分频
AUXR=0x00; //bit7=1:定时器1不分频,0则12分频
TR1=1; //启动定时器1
SCON = 0x50; //串口参数为模式1和允许接收
ES=1; //使能串口中断
EA=1; //使能总中断
}
unsigned char dat;
//串口中断服务函数
void serviceuart() interrupt 4
{
if(RI==1) //接收到一个完整的字节 如果RI==1就说明接收到一个完整的数据
{
RI=0; //人工清零 清除接收完成标志
dat=SBUF; //接收到的数据放在 dat 里面
send(dat+1);
}
}
//发送单个字节函数
void send(unsigned char d)
{
SBUF = d; //将数据放进SBUF缓冲器
while(TI == 0); //等待发送数据完成
TI = 0; //清除发送完成标志
}
void selectHC(unsigned char n)
{
switch(n)
{
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;
}
}
#include "reg52.h"
sfr AUXR=0x8e;
void init();
void uart();
void selectHC(unsigned char n);
void sendByte(unsigned char dat);
void sendString(unsigned char *str);
void working();
void main()
{
init();
uart();
sendString("Welcome to my blog!\r\n");
while(1)
{
working();
}
}
void selectHC(unsigned char n)
{
switch(n)
{
case 4:P2=(P2&0x1f)|0x80;break; //LED灯
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; //锁存
}
}
//初始化
void init()
{
selectHC(5);P0=0x00;
selectHC(4);P0=0xff;
}
//串口初始化(和上一个例程一样)
void uart()
{
TMOD=0X20; //定时器1工作模式为自动重装
TH1=0Xfd; //设置波特率为9600, 11.0592M或12M的12分频
TL1=0Xfd;
TR1=1; //启动定时器1
AUXR=0X00; //bit7=1:定时器1不分频,0则12分频
SCON = 0x50; //串口参数为模式1和允许接收
ES=1; //使能串口中断
EA=1; //使能总中断
}
//串口中断、数据接收
unsigned char dat=0x00;
void serviceuart() interrupt 4
{
if(RI==1) //接收到一个完整的字节 如果RI==1就说明接收到一个完整的数据
{
dat=SBUF; //接收到的数据放在 dat 里面
RI=0; //人工清零 清除接收完成标志
}
}
void working()
{
if(dat!=0x00)//接收字符串
{
switch(dat&0xf0) //取出高四位,判断是a还是b,进行对L1-L4还是L5-L8进行判断
{
case 0xa0: //输入的高4位是a,则对L1-L4进行操作
P0=(P0|0x0f)&(~dat|0xf0); //和我在工厂灯光那个例程里写的一样
dat=0x00;
break;
case 0xb0: //输入的高4位是b,则对L5-L8进行操作
P0=(P0|0xf0)&((~dat<<4)|0x0f);
dat=0x00;
break;
case 0xc0: //输出c0,返回指定信息
sendString("The System is Running...\r\n");
dat=0x00;
break;
}
}
}
//发送单字节
void sendByte(unsigned char dat)
{
SBUF=dat; //将数据放进SBUF缓冲器
while(TI==0); //等待发送数据完成
TI=0; //清除发送完成标志
}
//发送字符串
void sendString(unsigned char *str)
{
while(*str!='\0')
{
sendByte(*str++);
}
}