#include
#include
#define uchar unsigned char
#define uint unsigned int
sbit dula = P2 ^ 6;
sbit wela = P2 ^ 7;
uchar flag, a, num, num1;
uchar bai = 0, shi = 0, ge = 0, dData = 0;
uchar code table[] = {
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71
};
void delayms(uint xms);
void display(uchar, uchar, uchar);
void init();
void main()
{
init();
while(1)
{
if (flag == 1)
{
//flag手动清0,便于下次检测
flag = 0;
//关闭串口中断
ES = 0;
//将8位数据分解成百,十,个位
dData = a;
bai = dData / 100;
shi = dData % 100 / 10;
ge = dData % 10;
//num1计数,达到满255清0
num1++;
if (num1 == 255)
num1 = 0;
//发送字符(序号)
SBUF = num1;
//检测是否发送完毕
while(!TI);
//TI手动清0
TI = 0;
//发送字符(上位机发送过来的数据)
SBUF = a;
//检测是否发送完毕
while(!TI);
//TI手动清0
TI = 0;
//重新开启串口中断
ES = 1;
}
display(bai, shi, ge);
}
}
void init()
{
//设置定时器1为工作方式2
TMOD = 0x20;
//波特率为2400bps,给计时器1初值
TH1 = 0xf4;
TL1 = 0xf4;
//启动定时器1
TR1 = 1;
//ET1 = 1; 这里不需要开启定时器1中断,因为定时器1工作在方式2,为8位自动重装方式,进入中断也无事可做
//设置串口工作方式1
//10位异步收发(8位数据), 波特率可变(由定时器溢出率控制)
SM0 = 0;
SM1 = 1;
//容许串口中断
REN = 1;
//开启总中断
EA = 1;
//开启串口中断
ES = 1;
}
void delayms(uint xms)
{
uint i, j;
for (i = xms; i > 0; i--)
for (j = 110; j > 0; j--)
;
}
void display(uchar bai, uchar shi, uchar ge)
{
dula = 1;
P0 = table[bai];
dula = 0;
P0 = 0xff;
wela = 1;
P0 = 0xfe;
wela = 0;
delayms(5);
dula = 1;
P0 = table[shi];
dula = 0;
P0 = 0xff;
wela = 1;
P0 = 0xfd;
wela = 0;
delayms(5);
dula = 1;
P0 = table[ge];
dula = 0;
P0 = 0xff;
wela = 1;
P0 = 0xfb;
wela = 0;
delayms(5);
}
void ser() interrupt 4
{
//RI为接收中断标志位, 在方式0时, 当串行接收第8位数据结束时, 或在其他方式, 串行接收停止位的
//中间时, 由内部硬件使RI置1, 向CPU发出中断申请, 也必须在中断服务程序中, 用软件将其清0,取消
//此中断申请, 以方便下一次中断申请检测, 即这样才能产生下一次中断.
//这里RI清0, 因为程序既然产生了串口中断, 肯定是收到或发送了数据, 在开始时没有发送任何数据
//那必然是收到了数据, 此时RI会被硬件置1, 所以进入串口中断服务程序后必须由软件清0, 这样才能
//产生下一次中断.
if (RI)
{
RI = 0;
//将SBUF中的数据读走给a, 这是此中断服务程序最重要的目的
a = SBUF;
//将标志位flag置1, 以方便在主程序中查询判断是否已经收到数据
flag = 1;
}
}
三. 程序小结
1. 因为SBUF中每次只能存储8位字节数据, 所以该程序每次只能发送8位字节数据.
2. 当以十六进制发送FF时, 单片机接收上位机发送的数据后, 会将FF当成一个8位字节数据发送给上位机,
3. 程序缺陷
有哪位前辈可以指点一下, 在下先谢过了.