使用单片机AT89C52和ADC0832芯片设计数字电压表,通过测量0-5V之间的直流电压值,并将测得的电压数值信息显示在LED数码管(SH3461BS),从而达到测量电压的目的。
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- #include <reg52.h>
- #define uchar unsigned char
- #define uint unsigned int
- #include <intrins.h>
- //数码管段选定义 0 1 2 3 4 5 6 7 8 9
- uchar code smg_du[]={0x28,0xee,0x32,0xa2,0xe4,0xa1,0x21,0xea,0x20,0xa0,
- 0x60,0x25,0x39,0x26,0x31,0x71,0xff}; //段码
- //数码管位选定义
- uchar code smg_we[]={0xef,0xdf,0xbf,0x7f};
- uchar dis_smg[8] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8};
- uchar smg_i = 3; //显示数码管的个位数
- sbit SCL=P2^2; //SCL定义为P1口的第3位脚,连接ADC0832SCL脚
- sbit DO=P2^3; //DO定义为P1口的第4位脚,连接ADC0832DO脚
- sbit CS=P2^0; //CS定义为P1口的第4位脚,连接ADC0832CS脚
- uint p1[9];
- /***********************1ms延时函数*****************************/
- void delay_1ms(uint q)
- {
- uint i,j;
- for(i=0;i<q;i++)
- for(j=0;j<120;j++);
- }
- /***********读数模转换数据********************************************************/
- //请先了解ADC0832模数转换的串行协议,再来读本函数,主要是对应时序图来理解,本函数是模拟0832的串行协议进行的
- // 1 1 0 通道
- // 1 1 1 通道
- unsigned char ad0832read(bit SGL,bit ODD)
- {
- unsigned char i=0,value=0,value1=0;
- SCL=0;
- DO=1;
- CS=0; //开始
- SCL=1; //第一个上升沿
- SCL=0;
- DO=SGL;
- SCL=1; //第二个上升沿
- SCL=0;
- DO=ODD;
- SCL=1; //第三个上升沿
- SCL=0; //第三个下降沿
- DO=1;
- for(i=0;i<8;i++)
- {
- SCL=1;
- SCL=0; //开始从第四个下降沿接收数据
- value<<=1;
- if(DO)
- value++;
- }
- for(i=0;i<8;i++)
- { //接收校验数据
- value1>>=1;
- if(DO)
- value1+=0x80;
- SCL=1;
- SCL=0;
- }
- CS=1;
- SCL=1;
- if(value==value1) //与校验数据比较,正确就返回数据,否则返回0
- return value;
- return 0;
- }
- /***********************数码显示函数*****************************/
- void display()
- {
- uchar i;
- for(i=0;i<smg_i;i++)
- {
- P1 = 0xff; //消隐
- P3 = smg_we[i]; //位选
- P1 = dis_smg[i]; //段选
- delay_1ms(1);
- }
- }
-
- /************ 排序***************/
- void pingjun_zhi(uint *p)
- {
- static uint value;
- static uchar i,j;
- for(j=1;j<9;j++) //先对整个数组的9个值进行从小到大的排列
- for(i=0;i<9 - j;i++)
- {
- if(p[i] > p[i+1])
- {
- value = p[i];
- p[i] = p[i+1];
- p[i+1] = value;
- }
- }
- }
- /*****************主函数********************/
- void main()
- {
- static uchar i,j;
- uint temp;
- while(1)
- {
- display(); //数码管显示函数
- if(i % 3 == 0) //循环10次
- {
- pingjun_zhi(p1); //把数从小到大排序
-
- p1[j++] = ad0832read(1,0); //循环255个周期读取一次0832,因CPU运行比较快,没必要每次循环都去读取,选择通过CH0输入
- if(j >= 9)
- {
- j = 0;
- temp = p1[3] ; //取个中间值
- temp = temp * 100 / 255 * 4.5 * 2;
- dis_smg[2]=smg_du[temp/100%10] & 0xdf; //得到百位
- dis_smg[1]=smg_du[temp/10%10]; //十位
- dis_smg[0]=smg_du[temp%10]; //个位 ADC0832为8位ADC,数值为0~255,我们将其分开放入l_tmpdate数组中显示
- }
- }
- i++;
- }
- }
复制代码
所有资料51hei提供下载:
ADC0832数字电压表仿真图+C程序.rar
(43.6 KB, 下载次数: 63)
|