stc51单片机串口接收多字节数据
简介
51单片机有2个定时器,一个做串口波特率,一个做数据截止帧延时检测,硬件平台测试使用的是stc8的单片机,但是可以往51移植
代码
#include "stc8.h"
unsigned char flag=0; //定义标志位,用来判断接收了多少个字符
void UartInit(void) //9600bps@24.000MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x40; //定时器1时钟为Fosc,即1T
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设定定时器1为16位自动重装方式
TL1 = 0x8F; //设定定时初值
TH1 = 0xFD; //设定定时初值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
ES = 1; //打开串口中断
}
void time0init() //定时器0初始化
{
TMOD &= 0xF0;
TL0 = 0; //65536-11.0592M/12/1000
TH0 = 0; //定时器时间要大于串口接收一帧的时间,一般以1.5倍即可
TR0 = 0; //启动定时器
ET0 = 1; //使能定时器中断
EA = 1; //打开中断
}
void main()
{
time0init();
UartInit();
while (1);
}
void TM1_Isr() interrupt 1 //定时器0中断,触发中断就意味着串口没有接收数据,定时器0定时结束
{
SBUF = flag; //将接收到的数据长度通过串口返回
while(!TI); //判断是否发送完成
TI = 0; //清除串口发送标志位
flag = 0; //数据长度清零
TR0 = 0; //关闭定时器0
}
void ser() interrupt 4 //接收中断函数
{
if(RI) //判断串口接收标志位
{
flag++; //数据长度自加
RI=0; //清除串口接收标志位
}
TR0 = 0; //关闭定时器0
TL0 = 0; //定时器赋初值,调试后发现需要关闭定时器再赋值才能发挥作用
TH0 = 0;
TR0 = 1; //打开定时器
//串口每接收一次就会赋初值,重新打开定时器0,所以,是串口接收一个数据帧,定时器还没触发中断,就重新赋值,清零,串口接收完,
//不进行清零操作,定时器会到时间触发中断,在中断函数中完成处理,并关闭定时器,等待串口接收数据后打开定时器
}