b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71
};
void delayms(uint xms);
void init();
void display(uchar value);
uchar get_ad();
void main()
{
//初始化
init();
//为了节省IO端口,ADC0804的片选端CS连接U2锁存器的Q7输出端
//即位选时,P0的最高位
//于是通过位选时对P0赋值置CSAD为0,选通后,以后不必在管
wela = 1;
P0 = 0x7f;
wela = 0;
while (1)
{
//若检测到flag_uart为1,说明串口已经执行过串口中断服务程序, 即收到了数据
if (flag_uart == 1)
{
//手动将flag_uart清0,方便标志位检测
flag_uart = 0;
//检测到收到数据后,先将ES清0,原因是接下来要发送数据,若不关闭串口,
//发送完数据后,单片机会重新申请串口中断flag_uart又为1,又再次发送,一直反复
ES = 0;
//由于下面switch中需要调用puts,printf,在单片机的puts,printf中需要对TI是否为1
//进行检测,就是需要等待TI为1才会将字符发送出去,否则一直等待下去
//所以这里需要先将TI置为1
TI = 1;
//根据执行串口中断后获取的flag_on的值执行相应的动作
switch(flag_on)
{
case 0:
puts("Turn on ad!\n");
TR0 = 1; //开启计数器0
break;
case 1:
printf("Turn off ad!\n");
TR0 = 0; //关闭计数器0
break;
case 2:
puts("Error!\n");
break;
}
//等待发送完毕,因为发送完毕后TI会由硬件清0
while (!TI);
//手动TI清0
TI = 0;
//重新开启串口中断
ES = 1;
}
//通过flag_time判断时间是否到1s, 从而去获取AD转换的值
if (flag_time == 1)
{
//手动将flag_time清0,方便下次检测
flag_time = 0;
//获取AD转换的值
ad_val = get_ad();
//获取浮点数表示的AD实际采集到的电压值
ad_vo = (float)ad_val*5.0/256.0;
//关闭串口中断
ES = 0;
//下面要调用printf,所以将TI置1, 原因见上面
TI = 1;
printf("The voltage is %fV\n", ad_vo);
//检测发送是否完成
while (!TI);
//手动TI清0
TI = 0;
//开启串口中断
ES = 1;
}
//数码管上显示AD转化的值
display(ad_val);
}
}
void delayms(uint xms)
{
uint i, j;
for (i = xms; i > 0; i--)
for (j = 110; j > 0; j--)
;
}
void init()
{
//设定T1定时器工作方式2, T0定时器工作方式1
TMOD = 0x21;
//为T0定时器装入初值
TH0 = (65536 - 50000) / 256;
TL0 = (65536 - 50000) % 256;
//为T1定时器装入初值
TH1 = 0xfd;
TL1 = 0xfd;
//ET1 = 1; 这里不需要开启定时器1中断,因为定时器1工作在方式2,为8位自动重装方式,进入中断也无事可做
//启动T1定时器
TR1 = 1;
//开启定时器0中断
ET0 = 1;
//启动定时器0
//TR0 = 1; TR0的初始化放在主函数的while中,方便检测到串口发送数据后的1s延时,即延时1s从串口发送完数据开始
//设定串口工作方式
//11位异步收发,含9位数据,波特率可变,且由定时器1溢出率控制
SM0 = 1;
SM1 = 1;
//容许串口中断
REN = 1;
//开启总中断
EA = 1;
//开启串口中断
ES = 1;
}
void display(uchar num)
{
uchar bai, shi, ge;
bai = num / 100;
shi = num % 100 / 10;
ge = num % 10;
dula = 1;
P0 = table[bai];
dula = 0;
P0 = 0xff;
wela = 1;
//为了节省IO端口,ADC0804的片选端CS连接U2锁存器的Q7输出端
//即位选时,P0的最高位需要为0
P0 = 0x7e;
wela = 0;
delayms(5);
dula = 1;
P0 = table[shi];
dula = 0;
P0 = 0xff;
wela = 1;
P0 = 0x7d;
wela = 0;
delayms(5);
dula = 1;
P0 = table[ge];
dula = 0;
P0 = 0xff;
wela = 1;
P0 = 0x7b;
wela = 0;
delayms(5);
}
uchar get_ad()
{
uchar adval;
//CS在主函数已经为低电平,/WR初始化为高电平,经过至少tw时间后, /WR拉高
//随后A/D转换器被启动,并且经过1~8个A/D时钟周期和内部Tc时间后,模数转换完成转换
//转换结果存入数据锁存器,同时INTR(其为AD转换结束信号)自动变成低电平,通知单片机本次转换结束
adwr = 1;
_nop_();
adwr = 0; //启动AD转换
_nop_();
adwr = 1;
//读取P1口之前先给其写全1
P1 = 0xff;
//INTR为低电平后,将/CS置低,初始化/RD为1,再将/RD置低(主函数已经置低),