27,373
社区成员
发帖
与我相关
我的任务
分享
#include<reg52.h>
#include<intrins.h>
#include<stdio.h>
#define uchar unsigned char
#define uint unsigned int
sbit dula=P2^6;//液晶显示屏上的显示
sbit wela=P2^7;//液晶显示屏上的显示
sbit adwr=P3^6;//控制ad转换器的写
sbit adrd=P3^7;//控制ad转换器的读
uchar flag;
uchar a;
uchar flag_uart;//中断4的标志位
uchar flag_time;//中断1 的标志位
uchar flag_on ;//在中断4中赋值,通过此变量与switch可以控制选择工作模式
uchar i;
uchar t0_num;
uchar ad_val;//储存ad转换后得到的结果
float ad_vo;//储存电压值
uchar code table []= //数码管的固定编制
{
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71
};
void delayms(uint xms) //固定的延时函数
{
uint i,j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);
}
void init() //初始化函数,是串行口这一部分的设置
{
TMOD=0x21;//0010 0001 定时器工作方式寄存器
//SCON=0x50; 设置串行口控制寄存器。常用的SM0、SM1、REN、TI都可以在这里设置,此处吧SCON设置为0101 0000,SM0 SM1 SM2 REN TB8 RB8 TI RI.即通过SM1SM0设置工作方式为10位异步收发(8位数据)波特率可变。通过REN设置允许串行口接受数据。
TH0=(65536-50000)/256;//装填初值
TL0=(65536-50000)%256;//装填初值
TH1=0xfd;//1111 1101 十进制254,装填初值 ???
TL1=0xfd;//1111 1101 十进制254,装填初值 ???
TR1=1;//定时器1运行控制位:启动定时器1
ET0=1;//定时器0中断允许位:置1时允许定时器1发生中断。
SM0=0;//设定串行口控制寄存器的工作方式选择位
SM1=1;//设定串行口控制寄存器的工作方式选择位
REN=1;//允许串行接收位
EA=1;//全局中断允许位
ES=1;//串行口中断允许位
}
void display(uchar value)//显示函数,分解成三个数,分别显示
{
uchar bai,shi,ge;
bai=value/100;
shi=value%100/10;
ge=value%10;
dula=1;
P0=table[bai];
dula=0;
P0=0xff;
wela=1;
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()//获取ad转换后的值
{
uchar num;//定义一个临时变量num对读取倒的数进行储存
adwr=1;//关闭ad转换
_nop_();//延时函数,延时一个机器周期
adwr=0;//打开ad写入
_nop_();
adwr=1;//关闭ad写入
P1=0xff;//消影
adrd=1;//关闭ad读取
_nop_();
adrd=0;//打开ad读取
_nop_();
num=P1;//把读取到的数据从P1口取出,赋值给变量num
adrd=1;//关闭ad读取
return num;//把读取到的返回值返回。
}
void main()
{
init();//先把文件初始化,即运行一次init中的东西。
wela=1;//打开控制电脑屏幕的wela设置
P0=0x7f;//ADCS,片选信号输入端
wela=0;//关闭位选
while(1)//始终执行while循环内的语句。
{
if(flag_uart==1)//如果发生串行口中断(达到一秒)
{
flag_uart=0;//中断重置
ES=0;//关闭串行口中断允许位,暂时不允许发生串行口中断
TI=1;//发送中断标志位
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;
}
while(!TI);//TI=0时,才能跳出循环,这是中断标志位,
TI=0;
ES=1;//打开串行口中断允许位
}
if(flag_time==1)//如果发生中断1(定时器0),满一定时间发生中断。
{
flag_time=0;
ad_val=get_ad();//利用get_ad()函数获得ad转换之后的结果,赋值给ad_val
ad_vo=(float)ad_val*5.0/256.0;//把获得的模拟量转化成电压值
ES=0;//关闭串行口中断允许位
TI=1;
printf("The voltage is %fV\n",ad_vo);
while(!TI);
TI=0;//利用软件将TI发送中断标志位置0
ES=1;//打开串行口中断允许位
}
display(ad_val);//显示模拟量的大小。。。
}
}
void timer0() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
t0_num++;
if(t0_num==20)
{
t0_num=0;
flag_time=1;
}
}
void ser() interrupt 4
{
RI=0;
a=SBUF;
flag_uart=1;
if(a==1)
{
flag_on=0;
}
else if(a==2)
{
flag_on=1;
}
else
{
flag_on=2;
}
}