基于单片机AT89C52的数字电压表设计
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- #include <reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
- #include "intrins.h"
- #define uchar unsigned char
- #define uint unsigned int
-
- #define SMG_NUM 4
- uchar code DisplayNum[16]={
- 0xc0, //0
- 0xf9, //1
- 0xa4, //2
- 0xb0, //3
- 0x99, //4
- 0x92, //5
- 0x82, //6
- 0xf8, //7
- 0x80, //8
- 0x90, //9
- 0x88, //A
- 0x83, //b
- 0xc6, //C
- 0xa1, //d
- 0x86, //E
- 0x8e //F
- };
- //对应关系取字: dp g f e d c b a
- //例如 U 1 1 0 0 0 0 0 1
- uchar code DisplayOther[]={
- 0xff, //0 空
- 0x7f, //1 "."
- 0xbf, //2 "-"
- 0xa7, //3 c
- 0xC1 //3 U 1100 0001
- };
- /***********************************************************************************************************
- 数码管显示相关函数
- ***********************************************************************************************************/
- //数码管位选定义
- sbit smg_we1 = P2^0; //数码管1
- sbit smg_we2 = P2^1; //数码管2
- sbit smg_we3 = P2^2; //数码管3
- sbit smg_we4 = P2^3; //数码管4
- /***********************数码位选函数*****************************/
- void smg_we_switch(uchar i)
- {
- smg_we1 = 1;
- smg_we2 = 1;
- smg_we3 = 1;
- smg_we4 = 1;
- switch(i)
- {
- case 0: smg_we1 = 0; break;
- case 1: smg_we2 = 0; break;
- case 2: smg_we3 = 0; break;
- case 3: smg_we4 = 0; break;
- }
- }
- /********************************************************************
- * 名称 : uchar ChangeFor(uchar dat)
- * 功能 : 交换一个字节位的位置,用于数码管显示
- * 输入 : 需要改变的数
- * 输出 : 改变后的数
- ***********************************************************************/
- #define LED_a 0 //数码管段选的a段接在段选IO口的第0位
- #define LED_b 2
- #define LED_c 6
- #define LED_d 4
- #define LED_e 3
- #define LED_f 1
- #define LED_g 7
- #define LED_dp 5
- uchar ChangeFor(uchar dat)
- {
- uchar temp=0;
- if(dat&0x01) //判断数据的第一位是否为1
- temp|=0x01<<LED_a;//如果为1,放到控制数码管a段的位置
- if(dat&0x02)
- temp|=0x01<<LED_b;
- if(dat&0x04)
- temp|=0x01<<LED_c;
- if(dat&0x08)
- temp|=0x01<<LED_d;
- if(dat&0x10)
- temp|=0x01<<LED_e;
- if(dat&0x20)
- temp|=0x01<<LED_f;
- if(dat&0x40)
- temp|=0x01<<LED_g;
- if(dat&0x80)
- temp|=0x01<<LED_dp;
- return temp;
- }
- uchar dis_smg[SMG_NUM]; //显示缓存数组
- /********************************************************************
- * 名称 : display()
- * 功能 : 数码管显示
- * 输入 : 无
- * 输出 : 无
- ***********************************************************************/
- void DisplayScan()
- {
- static uchar i;
- P0 = 0xff; //消隐
- smg_we_switch(i); //位选
- P0 = ChangeFor(dis_smg[i]); //段选
- i++;
- if(i>=SMG_NUM)
- i=0;
- }
- /***********************************************************************************************************
- ADC0832相关函数
- ***********************************************************************************************************/
- sbit AD0832_CS = P1^2 ; //片选信号
- sbit AD0832_CLK = P1^0; //时钟接口
- sbit AD0832_DI = P1^1; //数据接口 /*因为单片机的管脚是双向的,且ADC0832的数据输入输出不同时进行,为节省单片机引脚,简化电路所以输入输出连接在同一个引脚上*/
- uchar GetAD0832(bit Channel)
- {
- uchar i=0 , Data1 =0 , Data2 = 0 ;
- AD0832_CLK = 0 ; //时钟置低平//时钟12Mhz, 整个转换时间为224us
- //使用芯片准备(参考PDF时序图)
- AD0832_DI = 1 ; //开始信号为高电平
- AD0832_CS = 0 ; //片选信号置低,启动AD转换芯片
- AD0832_CLK = 1 ; //输入开始信号(构成一个正脉冲),时钟上升沿,输入开始信号
- AD0832_CLK = 0 ; //时钟下降沿
- //模拟信号输入模式选择(1:单模信号,0:双模差分信号)
- AD0832_DI = 1 ;
- AD0832_CLK = 1 ; //时钟上升沿,输入开始信号
- AD0832_CLK = 0 ; //时钟下降沿
- //模拟信号输入通道选择(1:通道CH1,0:通道CH0)
- AD0832_DI = Channel ; //选择通道0
- AD0832_CLK = 1; //时钟上升沿,输入开始信号
- AD0832_CLK = 0; //时钟下降沿
- AD0832_DI = 1; //数据线置高,准备接收数据
- for(i=0;i<8;i++) //从高位移入数据
- {
- AD0832_CLK = 1 ;
- AD0832_CLK = 0 ; //时钟下降沿,AD0832输出数据,高位(MSB)先
- Data1 = Data1<<1; //数据左移位,补0
- if(AD0832_DI ==1)
- {
- Data1 = Data1 | 0x01;
- } //如果数据为“1”,移入1,
- } //如果数据为“0”,移入0,
- for(i=0;i<8;i++) //从低位移入数据
- {
- Data2 = Data2>>1; //数据左移位,补0
- if(AD0832_DI ==1)
- {
- Data2 = Data2 | 0x80;
- } //如果数据为“1”,移入1如果数据为“0”,移入0,
- AD0832_CLK = 1;
- AD0832_CLK = 0; //时钟下降沿,AD0832输出数据,高位(MSB)先
- }
- //数据线置高,释放总线,完成一次转换
- AD0832_CLK = 1 ;
- AD0832_DI = 1;
- AD0832_CS = 1;
- if(Data1==Data2) //输出
- {
- return Data2;
- }
- return 0;
- }
- /***********************************************************************************************************
- 主函数
- ***********************************************************************************************************/
- void main (void)
- {
- uchar Read_AD; //用于读取ADC数据
- uint VIN; //电压值变量
- while (1) //主循环
- {
- Read_AD=GetAD0832(0); //读取AD值
- //电压模式
- VIN=Read_AD*7.84; //换算出电压值
- dis_smg[0]=DisplayNum[VIN/1000%10]; //显示电压标志
- dis_smg[1]=DisplayNum[VIN/100%10]&0x7f; //电压十位
- dis_smg[2]=DisplayNum[VIN/10%10]; //电压个位
- dis_smg[3]=DisplayNum[VIN%10]; //电压十分位
- DisplayScan(); //数码管动态扫描
- }
- }
复制代码
所有资料51hei提供下载:
数字电压表设计.zip
(24.34 KB, 下载次数: 122)
|