/*******************************************************************
时间:2017-11-7晚
地点:重庆光电学院
系统晶振:12MHz
实现功能:直接采集并显示电压值,按键按下数码管显示采集到的电压值,按键再次按下关闭ADC
*******************************************************************/
#include "reg52.h"
#include "intrins.h"
#define nop() _nop_() //宏定义一个机器周期
#define uchar unsigned char
#define uint unsigned int
#define ADC_Data P1
#define SMG_DData P0/*数码管段码端口*/
#define SMG_WData P2/*数码管位码端口*/
//引脚定义
sbit CS_0804 = P3^5;
sbit WR_0804 = P3^6;
sbit INT_0804 = P3^0;
sbit RD_0804 = P3^7;
sbit K1 = P3^1;
sbit K2 = P3^2;
bit value_flag = 0; //标志位
//段码表
uchar code SMG_Dcode[]={0x3F,/*0*/0x06,/*1*/0x5B,/*2*/0x4F,/*3*/0x66,/*4*/0x6D,/*5*/0x7D,/*6*/0x07,/*7*/0x7F,/*8*/0x6F,/*9*/};
//位码表
uchar code SMG_Wcode[]={0xfe,0xfd,0xfb,0xf7};
/*******************************************************************
延时函数
*******************************************************************/
void Delay(uint xms)
{
/*
uint i,j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);unsigned char i=0;
*/
uchar x,y;
for(x=xms;x>0;x--)
{
for(y=0;y<250;y++)
{
nop();
nop();
nop();
nop();
}
}
}
/*******************************************************************
获取ADC寄存器值函数
说明:只是获取的ADC内部电压寄存器的值,没有进行任何的转换
而电压值的转换部分将放在显示部分
*******************************************************************/
uchar GetAdcvalue()
{
uchar DiaoYa = 0;
WR_0804 = 1;//先使其为高电平
CS_0804 = 0;//芯片选通使能
WR_0804 = 0;
WR_0804 = 1;//相当于给了一个低电平脉冲启动转换
nop();nop();nop();nop();
while(INT_0804 == 1);//等待转换结束
RD_0804 = 0;//读数据
INT_0804 = 1;
DiaoYa =ADC_Data;//返回电压寄存器中的值(注意,此时未转换成具体电压)
RD_0804 = 1;
return DiaoYa;//返回电压寄存器中的值
}
/*******************************************************************
显示AD转换后的电压值
说明:此函数主要实现两个功能【一是将ADC0804电压寄存器中的值转换为
实际电压值;二是将实际电压值用数码管显示出来】
*******************************************************************/
void DisVoltage(uchar V_0804)
{
double Voltage0 = (double)V_0804;
uchar Ge = 0;//用于存取个位数值
uchar Xiao1 = 0;//用于存取小数点后第一位数值
uchar Xiao2 = 0;//用于存取小数点后第二位数值
uchar Xiao3 = 0;//用于存取小数点后第三位数值
Voltage0 = (5*(Voltage0/255))*1000;//电压值已经转换并且*1000用于提取小数点后三位
//提取每一位的数值
Ge = ((uint)Voltage0)/1000%10;
Xiao1 = ((uint)Voltage0)/100%10;
Xiao2 = ((uint)Voltage0)/10%10;
Xiao3 = ((uint)Voltage0)%10;
//显示
SMG_WData = 0xff;//消隐
SMG_DData = SMG_Dcode[Ge] | 0x80;
SMG_WData = SMG_Wcode[0];
Delay(4);
SMG_WData = 0xff;//消隐
SMG_DData = SMG_Dcode[Xiao1];
SMG_WData = SMG_Wcode[1];
Delay(4);
SMG_WData = 0xff;//消隐
SMG_DData = SMG_Dcode[Xiao2];
SMG_WData = SMG_Wcode[2];
Delay(4);
SMG_WData = 0xff;//消隐
SMG_DData = SMG_Dcode[Xiao3];
SMG_WData = SMG_Wcode[3];
Delay(4);
SMG_WData = 0xff;
}
/*******************************************************************
检测按键是否被按下
*******************************************************************/
void Scan_keyoutCmd(void)
{
if(K1 == 0) //检测按键是否按下
{
Delay(10); //延时去抖动
if(K1 == 0) //确定按键按下
{
value_flag = ~ value_flag; //取反标志位
}
while(K1 == 0); //检测松手
}
}
/*******************************************************************
主函数
*******************************************************************/
void main()
{
//K1=1;K2=1;
//CS_0804 = 1;
value_flag = 0; //打开标志位
while(1)
{
Scan_keyoutCmd();//单片机循环检测是否有按键按下【启动或停止】应运程序
if(value_flag == 1) //如果标志打开启动单片机运行程序
{
DisVoltage(GetAdcvalue());
}
else if(value_flag == 0) //如果标志关闭停止单片机运行程序
{
CS_0804 = 1; //关闭ADC
}
}
}