给大家分享一个用ADC0832模数转换芯片设计的电压表设计,内含protues电路图和带有注释的keil工程文件
ADC0832电压表仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机电压表源程序如下:
- #include <reg52.h>
- #include <intrins.h>
- #define uint unsigned int
- #define uchar unsigned char
-
- sbit CS =P3^4; //片选使能端
- sbit DI =P1^1; //数据信号输入端,选择通道控制(SIG/DIF和ODD/EVEN)
- sbit DO =P1^1; //数据输出端
- sbit CLK =P1^0; //时钟脉冲
- sbit S_1 = P2^3;
- sbit S_2 = P2^4;
- sbit S_3 = P2^5;
- sbit S_4 = P2^6;
- unsigned char wd[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //不带小数点的段选码
- unsigned char yd[]={0x40,0x79,0x024,0x30,0x19,0x12,0x02,0x78,0x00,0x10};//带小数点的段选码
- // ===========延时子程序=================
- void delay_ms(unsigned int x)
- {
- unsigned int i,j;
- for(i=0;i<x;i++)
- for(j=0;j<123;j++); //延时1ms
- }
- /*=============读ADC0832函数=============*/
- /*=============采集并返回=================*/
- unsigned int Adc0832(unsigned char channel) //AD转换,返回结果
- {
- uchar i=0;
- uchar j;
- uint dat=0; //正向输入数据
- uchar ndat=0; //反向输入数据
- //****************初始化操作**************
- if(channel==0)channel=2; //10B对应SGL/DIF=1,ODD/EVEN=0
- if(channel==1)channel=3; //11B对应SGL/DIF=1,ODD/EVEN=1
- //****************写操作,将通道数据写入ADC0832**************
- DI=1; _nop_();_nop_(); //发起始位,固定为1(1位)
- CS=0;_nop_();_nop_(); //拉低CS端,让ADC0832使能
- CLK=1;_nop_();_nop_(); //拉高CLK端,DI端的数据移入ADC0832内部的多路移位寄存器
- CLK=0;_nop_();_nop_(); //拉低CLK端,形成下降沿1,第一个周期开始
- CLK=1; //拉高CLK端,在第一个时钟周期内,DI为高电平,表示启动位
- //紧接着输入两位配置位进行通道选择
- DI=channel&0x1;_nop_();_nop_(); //假设选取通道0,则10&01=0,即SGL/DIF=0,为差分输入(2位)
- CLK=0;_nop_();_nop_(); //拉低CLK端,形成下降沿2,第二个周期开始
- CLK=1; //拉高CLK端
- DI=(channel>>1)&0x1;_nop_();_nop_(); //假设选取通道0,则01&01=1,ODD/EVEN=1,表示通道0
- CLK=0; //拉低CLK端,形成下降沿3
- DI=1;_nop_();_nop_(); //控制命令结束
- dat=0;
- //*************读操作,将AD转换的数从DO口输出****************
- for(i=0;i<8;i++) //每一个CLK下降沿输出一位数,先输出高位
- {
- dat|=DO; //收数据,“|”位或,如果2位中有一位为1,则结果为1,否则为0
- CLK=1;_nop_();_nop_();
- CLK=0;_nop_();_nop_(); //形成一次时钟脉冲
- dat<<=1;
- if(i==7)dat|=DO;
- }
-
- for(i=0;i<8;i++) //每一个CLK下降沿输出一位数,先输出低位
- {
- j=0;
- j=j|DO; //收数据
- CLK=1;_nop_();_nop_();
- CLK=0;_nop_();_nop_(); //形成一次时钟脉冲
- j=j<<7;
- ndat=ndat|j;
- if(i<7)ndat>>=1;
- }
- //*********************结束AD转换,并返回转换的数***********************
- CS=1; //拉低CS端
- CLK=0; //拉低CLK端
- DO=1; //拉高数据端,回到初始状态
- dat<<=8;
- dat|=ndat;
- return(dat); //返回数据
- }
- //============数码管显示函数==========================
- void display(uchar p) //数码管显示函数
- {
- uchar S1,S2,S3;
-
- S1=p/51; //个位
- S2=(p*10/51)%10; //十分位
- S3=(p*100/51)%10; //百分位
-
- //个位
- S_1 = 1; //第一个数码管
- S_2 = 0;
- S_3 = 0;
- S_4= 0;
- P0=yd[S1]; //选取带有小数点的段选码
- delay_ms(5); //延时
- S_1 = 0; //消隐
-
- //十分位
- S_1 = 0;
- S_2 = 1; //取第二个数码管
- S_3= 0;
- S_4= 0;
- P0=wd[S2]; //选取不带有小数点的段选码
- delay_ms(5);
- S_2 = 0; //消隐
-
- //百分位
- S_1 = 0;
- S_2 = 0;
- S_3= 1; //取第三个数码管
- S_4= 0;
- P0=wd[S3]; //选取不带有小数点的段选码
- delay_ms(5);
- S_3= 0; //消隐
- }
- //===========主函数================
- int main(void)
- {
- while(1) //无限循环
- display(Adc0832(0));//数码管显示
- //Adc0832(0):选择通道0,单端模式
- //调用Adc0832(0),SIG/DIF=0,ODD/EVEN=1,表示工作在差分输入方式,且CH0为-,CH1为+
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码 Keil代码与Proteus8.8仿真下载:
基于ADC0832简易数字电压表.zip
(64.85 KB, 下载次数: 1077)
|