adc0832数字电压表(程序 仿真图)
基于ADC0832和LCD160128设计的数字电压表

学习情境3-数字电压表的设计之基于ADC0832和LCD160128设计的数字电压表☆点名,复习1、ADC0832的引脚及其功能,以及与单片机的硬件连接?2、PCF8591的引脚及其功能,以及与单片机的硬件连接?引言:新课讲授3.4基于ADC0832和LCD160128设计的数字电压表3.4.1 LCD160128简介LCD160128是一种图形点阵液晶显示模组。
它用T6963C作为控制器,KS0086作为驱动的160(列)X128(行)的全点阵液晶显示。
具有与INTER8080时序相适配的MPU接口功能,并有专门的指令集,可完成文本显示和图形显示的功能设置。
LCD160128液晶显示器的工作电压为+5V士10%,能够显示显示10个(/行)X8共120个(16 X 16点阵)的中文字符,共有13条操作指令。
1.芯片引脚及其功能表1引脚功能2.与主控制器的通信(1)读状态在数据读写操作之前必须进行状态检查。
T6963C的状态可以从数据总线中读取。
此时RD#和CE#引脚为低电平,WR#和C/D#引脚为高电平。
状态字格式如下所示:MSB LSBSTA7 D7STA6D6STA5D5STA4D4STA3D3STA2D2STA1D1STA0D0表2 状态子STA0 指令读写状态0:禁止;1:使能;STA1 数据读写状态0:禁止;1:使能;STA2 自动模式数据读状态0:禁止;1:使能;STA3 自动模式数据写状态0:禁止;1:使能;STA4 保留STA5 控制器操作状态0:禁止;1:使能;STA6 读屏/考屏错误标志0:无错误;1:错误;STA7 闪烁状态检查0:关显示;1:正常显示注意1:必须同时检查STA0与STA1的状态,由于硬件中断可能引起数据错误操作。
注意2:STA0与STA1用于大多数模式的状态检查。
注意3:STA2与STA3用于自动模式数据读写使能,此模式下,STA0与STA1无效。
状态检查流程:图1 状态检查流程图注意4:如果使用MSB=0命令,则必须先读取状态操作。
数字电压表程序及仿真图

//************************************************//**用adc0809进行电压测量,lcd1602显示,精度0.001v**//************************************************#include "reg51.h"#include "intrins.h"#define uchar unsigned char#define uint unsigned intuchar code table []="ID: " ; //欢迎显示,包括空格在内<=16 uchar code table1 []="Name: " ;//欢迎显示,包括空格在内<=16//************管脚定义************************sbit ADC_OE = P3^0; //ADC输入允许信号端口sbit ADC_EOC = P3^1; //ADC转换结束信号输出端sbit ADC_START= P3^2; //ADC启动转换信号输入端sbit ADC_CLK = P3^3; //ADC时钟输入端sbit lcd_rs = P3^4; //液晶数据命令选择端sbit lcd_en = P3^5; //液晶使能//************参数定义************************uchar num; //LCD1602开机显示数组数uchar AD_data; //AD转换原始数据uchar dis1[] = " Current Voltage";uchar dis2[] = {' ',' ',' ',' ','V','=','0','.','0','0','0','v',' ',' ',' ',' ',}; //初始化数组,用来保存电压显示//************子函数定义************************void delay(uchar z); //delay延时子程序void init_lcd(); //LCD1602初始化函数void InitTimer0(); //定时器0初始化函数void write_com(uchar com); //LCD1602写指令函数void write_data(uchar date); //LCD1602写数据函数void write_welcome(); //LCD1602开启显示欢迎函数void init_ADC(); //ADC初始化函数void AD_covert(); //AD转换子程序void ADC_change(); //ADC转换函数void write_adc(); //ADC显示函数//************主函数************************void main(){init_lcd(); //LCD1602初始化write_welcome(); //LCD1602开启显示欢迎InitTimer0(); //定时器0初始化init_lcd(); //LCD1602初始化init_ADC(); //ADC初始化while(1){AD_covert(); //AD转换ADC_change(); //ADC转换函数write_adc(); //ADC显示}}//************delay延时子程序************************void delay(uchar z){uchar x,y;for(x=0;x<z;x++)for(y=0;y<114;y++);}//************LCD1602初始化函数************************void init_lcd(){lcd_en = 0; // 将使能端置0write_com(0x38); //设置16*2显示,5*7点阵,8位数据接口write_com(0x08); //写一个字符后地址指针加1write_com(0x01); //显示清零,数据指针清零write_com(0x06); //写一个字符后地址指针加1write_com(0x0c); //关显示,光标不显示不闪烁}//************定时器0初始化函数************************void InitTimer0(){TMOD = 0x02; //定时器0工作方式2TH0 = 0x14; //初值位20TL0 = 0x14;EA = 1; //开总中断ET0 = 1; //允许T0中断TR0 = 1; //启动T0}//************LCD1602写指令函数************************void write_com(uchar com){lcd_rs = 0; // 选择写指令P2 = com; // 将要写的命令送到数据总线上delay(5); // 延时5ms,待数据稳定lcd_en = 1; // 由于初始化已将lcd_en置为0,使能端给一个高脉冲,delay(5); // 延时5ms,待数据稳定lcd_en = 0; // 将使能端置0以完成脉冲}//************LCD1602写数据函数************************void write_data(uchar date){lcd_rs = 1; // 选择写数据P2 = date; // 将要写的数据送到数据总线上delay(5); // 延时5ms,待数据稳定lcd_en = 1; // 由于初始化已将lcd_en置为0,使能端给一个高脉冲,delay(5); // 延时5ms,待数据稳定lcd_en = 0; // 将使能端置0以完成脉冲}//************LCD1602开启显示欢迎函数******************void write_welcome(){write_com(0x80); // 现将数据指针定位到第一行第一个字处for(num=0;num<16;num++) //做简短延时{write_data(table[num]);delay(5);}write_com(0x80+0x40); // 现将数据指针定位到第二行第一个字处for(num=0;num<16;num++) //做简短延时{write_data(table1[num]);delay(20);}delay(50000);}//************中断函数************************void Timer0()interrupt 1{ADC_CLK = ~ADC_CLK; //时钟不断取反}//***********ADC初始化函数************************void init_ADC(){ADC_OE = 0; //ADC输入允许信号端口置1ADC_EOC = 1; //ADC转换结束信号输出端置1ADC_START= 1; //ADC启动转换信号输入端置1ADC_CLK = 1; //ADC时钟输入端置1}//***********AD转换子程序***********************void AD_covert(){ADC_START= 0;ADC_CLK = 0;_nop_(); //延时空循环,一个机器指令的时间ADC_START= 1;ADC_CLK = 1;_nop_(); //延时空循环,一个机器指令的时间ADC_START= 0;ADC_CLK = 0; //在START上产生一个正脉冲while(ADC_EOC); //等待上次转换完成_nop_();delay(100);while(ADC_EOC == 0){ADC_CLK = 1;delay(1);ADC_CLK = 0;delay(1);}P1 = 0xff;_nop_();ADC_OE = 1;_nop_();AD_data = P1;ADC_OE = 0;}//***********ADC转换函数************************void ADC_change(){double v;uchar val_integer;uint val_decimal;v = AD_data*0.0196078; //5v时输出的数字量是2.55,为使5v时输出5.00 val_integer = (uchar)v; //电压整数部分val_decimal = (uint)((v-val_integer)*1000);//将电压小数点后三位转换为整数(dis2[6]) = val_integer+0x30; //电压整数转换为ASSII(dis2[8]) = val_decimal/100+0x30; //电压小数第一位转换为ASSII(dis2[9]) = val_decimal/10%10+0x30; //电压小数第二位转换为ASSII(dis2[10]) = val_decimal/10%10+0x30; //电压小数第三位转换为ASSII}//************LCD1602显示adc函数******************void write_adc(){write_com(0x80); // 现将数据指针定位到第一行第一个字处for(num=0;num<16;num++)//做简短延时{write_data(dis1[num]);delay(1);}write_com(0x80+0x40); // 现将数据指针定位到第二行第一个字处for(num=0;num<16;num++)//做简短延时{write_data(dis2[num]);delay(1);}}。
第15章 采用ADC0832的两路电压表设计

{Wr1602Cmd(0x80+0x03);
i=RdAdc0832(0);
//读取Adc0832 0通道的
值
i=(i*5000/255);
Wr1602Dat('C');
//显示Adc0832 0通道的
值
Wr1602Dat('H');
Wr1602Dat('0');
Wr1602Dat('=');
Wr1602Dat('0'+i/1000);//个位
// LCD1602初始化函数
{ delay_ms(20);
Wr1602Cmd(0x38);
delay_ms(5);
Wr1602Cmd(0x38);
delay_ms(5);
Wr1602Cmd(0x06);
Wr1602Cmd(0x0c);
Wr1602Cmd(0x01); //清屏
Wr1602Cmd(0x80); //设置地址
Wr1602Dat('.');
Wr1602Dat('0'+i%1000/100); //小数点后一位
Wr1602Dat('0'+i%1000%100/10); //小数点后两位
Wr1602Dat('0'+i%1000%100%10); //小数点后三位
Wr1602Dat('V');
Wr1602Cmd(0xC0+0x03);
CLK=0;_nop_();_nop_();_nop_();_nop_();
DIO=Hx;_nop_();_nop_();_nop_();_nop_();//写通道号位
ADC0832的数字电压表设计说明

目录1. 引言 (1)2. 方案设计 (1)2.1设计要求 (1)2.2设计方案 (1)3. 硬件设计 (2)3.1单片机最小系统 (2)3.2显示驱动部分 (2)3.3转换电路 (3)3.4单片机驱动部分 (3)4. 软件设计 (4)4.1软件流程 (4)4.2子程序模板 (5)5实验结果与讨论 (5)5.1实验仿真 (5)5.2结果讨论 (5)6心得体会 (6)7参考文献 (13)8附录8.1程序 (7)8.2原理图 (7)1. 引言随着片机技术的飞速发展,,现代的电子产品几乎渗透到了社会的各个领域,有力地推动了社会生产力的发肢和社会信息化程度的提商,人们为了寻求最好的科技,为了方便人类在使用科技产品的快速性,准确性。
例如数字电压表能够准确的,快速的量出电压。
利用ADC0832和AT89C52的结合再通过LCD来显示出来。
ADC0832是一个8位D/A转换器。
单电源供电,从+5V〜+15V均可正常工作。
基准电压的围为土10V;电流建立时间为1卩S; CMOS:艺,低功耗20mWADC0832 转换器芯片为20引脚,双列直插式封装。
该转换器由输入寄存器和DAC寄存器构成两级数据输入锁存。
使用时数据输入可以采用两级锁存(双锁存)形式,或单级锁存(一级锁存,一级直通)形式,或直接输入(两级直通)形式。
2. 方案设计2.1设计要求按系统要实现功能,设计必须达到以下的几个步骤的要求(1)主电路系统是由ADC0832单片机AT89C52和LCD显示屏组成。
(2)ADC083是模拟数字转换芯片,是将外侧电压信号转换成数字信号再通过AT89C52处理,再通过LCD显示出来(3)能测量0-5V的数字电压(4)测量误差不大于0.1V2.2设计方案2.1.1 单片机的选择本设计选用单片机AT89C52它是一种带8K字节闪烁可编程可擦除只读存储器的低电压,足够本设计之用,高性能CMOS位微处理器该器件采用ATME高密度非易失存储器制造技术制造,与工业标准的MCS-51指令系统及8052产品引脚兼容,功能强大、使用方便的AT80C52单片机适用于许多较为复杂的应用场合。
单片机数字电压表(带仿真图C程序)

基于51单片机数字电压表本模块采用ADC0832模数转换芯片,LCD1602液晶显示,测量范围0-5V,精度误差0.01V看了很多网上的课程设计或者毕业论文,得出以下几点:1.数字电压表的方案有很多种,有的采用ADC0809,或者ADC0808等,他们都是8温AD,并口传输数据,具有速率高的优点。
但是硬件复杂,与单片机电路繁琐,焊接起来比较麻烦。
所以本设计采用ADC0832,同样8位AD,特点是串口传输数据,硬件接口简单,且精度误差一致,速率也比较快,对于要求不高的系统非常适合。
2.显示电路,网上采用LED显示居多,本设计采用LCD1602液晶显示,具有硬件搭设简单,显示美观等优点3.本设计方便移植,只需将LCD1602三个控制端口,ADC0832 四个控制端口修改即可。
注意LCD1602数据传输接口是单片机的P0口,如下图,需要接上拉电阻4.程序采用C代码编写,亲测直接可以使用,若需仿真文件,请用E-mail联系邮系。
邮箱:gnsywb@5.网上很多设计数据转换程序有误,不够正确。
在转换过程中,中间变量需设置为int 类型,虽然8位AD输出最高位255,但是余数转换过程中会大于255。
若设计char型,会造成显示输出有误。
void convert(uchar a){ uint temp; //特别注意这里需定义int型(余数将大于255)dis[0]=a/51; //取个位temp=a%51;temp=temp*10; dis[1]=temp/51; //取小数点后第一位temp=temp%51;temp=temp*10; dis[2]=temp/51; //取小数点后第二位}具体电路图如下:1.利用电压表与测量显示电压对比附录:C程序/******************************************** 功能:单片机数字电压表ADC0832+LCD16021,测量范围0-5V2,2路输入电压,可自行设定3,测量精度误差0.01V,LCD液晶显示编写者:小子在西藏gnsywb@编写日期:2012-11-5*********************************************/ #include <reg52.h>#include <intrins.h>#define uint unsigned int#define uchar unsigned charsbit lcdrs=P2^4;sbit lcdrw=P2^5;sbit lcden=P2^6; //1602控制端口sbit DI=P3^4;sbit DO=P3^4; //DI和DO与单片机共接口sbit Clk=P3^3;sbit CS=P3^5;//ADC0832控制端口uchar dis[3]={0x00,0x00,0x00}; //显示缓冲区uchar date=0; //AD值uchar CH; //ADC0832通道值/*****************************************AD0832转换程序******************************************/uchar ADC0832(uchar CH){uchar i,dis0,dis1;Clk=0; //拉低时钟DI=1; //初始化_nop_();CS=0; //芯片选定_nop_();Clk=1; //拉高时钟_nop_();if(CH==0) //通道选择{Clk=0; //第一次拉低时钟DI=1; //通道0的第一位_nop_();Clk=1; //拉高时钟_nop_();Clk=0; //第二次拉低时钟,ADC0832 DI接受数据DI=0; //通道0的第二位_nop_();Clk=1;_nop_();}else{Clk=0;DI=1; //通道1的第一位_nop_();Clk=1;_nop_();Clk=0;DI=1; //通道1的第二位_nop_();Clk=1;_nop_();}Clk=0; //第三次拉低时钟,此前DI两次赋值决定通道DI=1; //DI开始失效,拉高电平,便于DO数据传输for(i= 0;i<8;i++) //读取前8位的值{_nop_();dis0<<= 1;Clk=1;_nop_();Clk=0;if (DO)dis0|=0x01;elsedis0|=0x00;}for (i=0;i<8;i++) //读取后8位的值{dis1>>= 1;if (DO)dis1|= 0x80;elsedis1|= 0x00;_nop_();Clk=1;_nop_();Clk=0;}if(dis0==dis1) //两次结束数据比较,若相等date=dis0; //则赋值给dat_nop_();CS=1; //释放ADC0832DO=1; //拉高输出端,方便下次通道选择DI端有效Clk=1; //拉高时钟return date;}/***********************************************数据转换程序功能:将0-255级换算成0.00-5.00的电压数***********************************************/void convert(uchar a){uint temp; //特别注意这里需定义int型(余数将大于255)dis[0]=a/51; //取个位temp=a%51;temp=temp*10;dis[1]=temp/51; //取小数点后第一位temp=temp%51;temp=temp*10;dis[2]=temp/51; //取小数点后第二位}/***************************************** LCD1602驱动程序******************************************/ void delay(uchar z){uint x,y;for(x=z;x>0;x--)for(y=122;y>0;y--);}void write_cmd(uchar cmd)//lcd1602写命令函数{lcdrs=0;lcdrw=0; //选择指令寄存器lcden=1;P0=cmd; //写数据delay(5);lcden=0; //使能拉低lcden=1;}void write_date(uchar date)//lcd1602写数据函数{lcdrs=1;lcdrw=0; //选择数据寄存器lcden=1;P0=date; //写数据delay(5);lcden=0; //使能拉低lcden=1;}void init_lcd1602()//lcd1602初始化{write_cmd(0x01); //清屏write_cmd(0x38); //功能设置write_cmd(0x0c); //显示设置write_cmd(0x06); //输入方式从左到右delay(1);}/***************************************** 显示函数*****************************************/ void display(void){uchar i;write_cmd(0x80);for(i=0;i<3;i++){if(i==1) write_date('.'); //第二位显示小数点write_date (0x30+dis[i]);delay(5);}write_date('V'); //最后一位后显示字符'V'}/************************************************ 主函数***************************************************/ void main(void){CH=0; //选择通道0或1init_lcd1602();//液晶1602显示初始化while(1) //主循环{date=ADC0832(CH);//启动ADC0832转换并接受数据delay(1);convert(date); //数据转换成BCD码display(); //显示数值}}。
基于51+ADC0832+LCD1602+仿真图四位电压显示测试OK汇编

//********************************//说明:调用VR2时,ADC0832将模拟电压转换为数字电压并显示在LCD1602上//********************************#include<reg51.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned int#define delay4us(){_nop_();_nop_();_nop_();_nop_();}//********************************//ADC引脚定义//********************************sbit CS=P3^0;sbit CLK=P3^1;sbit DIO=P3^2;//********************************//LCD端口定义//********************************sbit RS=P2^0;sbit RW=P2^1;sbit E=P2^2;//********************************//一位整数、两位小数的数字电压显示缓冲//********************************uchar Display_Buffer[]="0.000V";//********************************//LCD第一行显示信息//********************************uchar code Line[]="TEST OK DC ";//********************************//延时子程序//********************************void DelayMS(uint x){uchar t;while(x--)for(t=0;t<120;t++);}//********************************//LCD忙状态检测//********************************bit LCD_BUSY_CHECK(){bit result;RS=0;RW=1;E=1;delay4us();result=(bit)(P0&0x80);E=0;return result;}//********************************//写LCD命令//********************************void LCD_Write_Command(uchar cmd){while(LCD_BUSY_CHECK()); //判断LCD是否忙碌RS=0;RW=0;E=0;_nop_();P0=cmd;delay4us();E=1;delay4us();E=0;}//********************************//设置LCD显示位置//********************************void Set_Disp_Pos(uchar pos){LCD_Write_Command(pos|0x80);}//********************************//写LCD数据//********************************void LCD_Write_Data(uchar dat){while(LCD_BUSY_CHECK()); //判断LCD是否忙碌RS=1;RW=0;E=0;P0=dat;delay4us();E=1;delay4us();E=0;}//********************************//LCD初始化//********************************void LCD_Initialise(){LCD_Write_Command(0x38);DelayMS(1);LCD_Write_Command(0x0C);DelayMS(1);LCD_Write_Command(0x06);DelayMS(1);LCD_Write_Command(0x01);DelayMS(1);}//********************************//获取AD转换结果(0通道)//********************************uchar GET_AD_RESULT(){uchar i;uchar dat1=0;uchar dat2=0;//起始控制位CS=0;CLK=0;DIO=1;_nop_(); _nop_();CLK=1;_nop_(); _nop_();//第一个下降沿之前,社DI=1/0//选择单端/差分(SGL\DIF)模式中的单端输入模式CLK=0;DIO=1;_nop_(); _nop_();CLK=1;_nop_(); _nop_();//第二个下降沿之前,设DI=0/1,选择CH0\CH1CLK=0;DIO=0;_nop_(); _nop_();CLK=1;DIO=1;_nop_(); _nop_();//第三个下降沿之前,设DI=1CLK=0;DIO=1;_nop_(); _nop_();//第四个至第十一个,共八个下降沿读数据(MSB_LSB) for(i=0;i<8;i++){CLK=1;_nop_(); _nop_();CLK=0;_nop_(); _nop_();dat1=dat1<<1|DIO;}//第十一个至第十八个,共八个下降沿读数据(LSB_MSB) for(i=0;i<8;i++){dat2=dat2|((uchar)(DIO)<<i);CLK=1;_nop_(); _nop_();CLK=0;_nop_(); _nop_();}CS=1;//如果MSB_LSB和LSB_MSB读取的结果相同,则返回读取的结果,否则返回0 return(dat1==dat2)?dat2:0;}//***************************//主函数//***************************void main(){uchar i;uint d;uint c;LCD_Initialise();DelayMS(10);while(1){//获取AD转换值,最大值为255对应于最高电压5.00V//本例中设计为三个显示数位,故用500d=GET_AD_RESULT()*5000.0/255;//将AD转换后的数据分解为3个数位Display_Buffer[0]=d/1000+'0';Display_Buffer[2]=d%1000/100+'0';Display_Buffer[3]=d%100/10+'0';Display_Buffer[4]=d%10+'0';Set_Disp_Pos(0x00);i=0;while(Line[i]!='\0')LCD_Write_Data(Line[i++]);Set_Disp_Pos(0x46);i=0;while(Display_Buffer[i]!='\0')LCD_Write_Data(Display_Buffer[i++]);}}。
adc0832数字电压表(程序+仿真图)
adc0832数字电压表(程序+仿真图)仿真图:/*********************************包含头文件********************************/#include <reg51.h>#include <intrins.h>/*********************************端口定义**********************************/sbit CS = P3^5;sbit Clk = P3^3;sbit DATI = P3^4;sbit DATO = P3^4;sbit P20=P2^0 ;/*******************************定义全局变量********************************/unsigned char dat = 0x00; //AD值unsigned char count = 0x00; //定时器计数unsigned char CH; //通道变量unsigned char dis[] = {0x00, 0x00, 0x00}; //显示数值/*******************************共阳LED 段码表*******************************/unsigned char code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8, 0x80,0x90};char code tablewe[]={ 0xfd,0xfb,0xf7,0xef,0xdf,0xfe };/**************************************** ************************************函数功能:AD转换子程序入口参数:CH出口参数:dat***************************************** ***********************************/unsigned char adc0832(unsigned char CH){unsigned char i,test,adval;adval = 0x00;test = 0x00;Clk = 0; //初始化DATI = 1;_nop_();CS = 0;_nop_();Clk = 1;_nop_();if ( CH == 0x00 ) //通道选择{Clk = 0;DATI = 1; //通道0的第一位_nop_();Clk = 1;_nop_();Clk = 0;DATI = 0; //通道0的第二位_nop_();Clk = 1;_nop_();}else{Clk = 0;DATI = 1; //通道1的第一位_nop_();Clk = 1;_nop_();Clk = 0;DATI = 1; //通道1的第二位_nop_();Clk = 1;_nop_();}Clk = 0;DATI = 1;for( i = 0;i < 8;i++ ) //读取前8位的值{_nop_();adval <<= 1;Clk = 1;_nop_();Clk = 0;if (DATO)adval |= 0x01;elseadval |= 0x00;}for (i = 0; i < 8; i++) //读取后8位的值{test >>= 1;if (DATO)test |= 0x80;elsetest |= 0x00;_nop_();Clk = 1;_nop_();Clk = 0;}if (adval == test) //比较前8位与后8位的值,如果不相同舍去。
ADC0832程序完整版-源码
ADC0832程序完整版源码+Proteus仿真来源:互联网作者:后都出现了一些奇怪的问题,有的根本没法读取数据,有的数据有错误。
当参考电压为5V时,如果把输入电压从0一直调到5V,读取的数据应该是从0到255,2.5V 时应该是128。
但是我发现一些源码在输入0~2.5V时读取出来的是0~255,到2.5V时读取的数据为0,从2.5到5V,读出的值又从0增加到255,始终不正确。
今天下午特地查阅的ADC0832英文原版的DataSheet,又参考了一篇中文文档,终于写出了其完整的程序,并且先后读取了MSB FIRST DATA和LSB FIRST DATA,进行比较,如果两个数据相等,返回读取的数据,否则返回0,这样可以避免读取发生错误,更稳定可靠。
并通过了Proteus仿真。
下图是ADC0832的时序图:其中T-SetUp为250ns,由于使用的是51单片机,晶振11.0592MHz,机器周期比这个值大,可以不考虑,但为了防止出现异常,还是延时了两个机器周期。
注意在第11个时钟下降沿之后,DO上的电平既是MSB FIRST输出的最后一位,又是LSB FIRST输出的第一位。
以下是读取ADC0832的代码。
[cpp] view plaincopysbit CS_0832 = P1^0;sbit CLK_0832 = P1^1;sbit DO_0832 = P1^2; // DI、DO不同时有效,可共用一个接口sbit DI_0832 = P1^2;extern void _nop_ ( void );#define pulse0832() _nop_();_nop_();CLK_0832=1;_nop_();_nop_();CLK_0832=0 //把模拟电压值转换成8位二进制数并返回unsigned char read0832(){unsigned char i, ch = 0, ch1 = 0;CS_0832=0; // 片选,DO为高阻态DI_0832=1;// 此处暂停T-SetUp: 250ns (由pulse0832完成)pulse0832(); // 第一个脉冲,起始位,DI置高DI_0832=1;pulse0832(); // 第二个脉冲,DI=1表示双通道单极性输入DI_0832=1;pulse0832(); // 第三个脉冲,DI=1表示选择通道1(CH2)// 51单片机为准双向IO口:应先写入1再读取DI_0832=1;// MSB FIRST DATAfor(i = 0; i < 8; ++i) {pulse0832();ch <<= 1;if(DO_0832==1)ch |= 0x01;}// MSB FIRST输出的最后一位与LSB FIRST输出的第一位是在// 同一个时钟下降沿之后,故此处先执行读取,后执行pulse// LSB FIRST DATAfor(i = 0; i < 8; ++i) {ch1 >>= 1;if(DO_0832==1)ch1 |= 0x80;pulse0832();}CS_0832=1; // 取消片选,一个转换周期结束return (ch==ch1) ? ch : 0; // 返回转换结果}。
基于ADC0832数字电压表
阿坝师范高等专科学校电子信息工程系课程设计基于ADC0832数字电压表学生姓名任银鹏专业名称电子信息工程技术班级电信班学号20113026基于ADC0832数字电压表一、设计要求设计一个在单片机AT89S52作用下基于ADC0832数字电压表.二、系统设计方案1. 模块图2. 模块作用该电压表由单片A/D转换器构成,在很大的电压情况下,电压表去测量时会对其并联很大的电阻分掉高压,然后再进行测量,这本来很大的电压,到后来测出来的电压就会很小,这就是A/D转换实现低压电压表测量高压三、硬件原理1.LCD1602图3.1 LCD1602外观如图3.1 LCD1602外观,从LCD1602参数手册知道芯片工作电压为4.5~5.5V,工作电流20mA。
模块最佳工作电压为5V。
引脚作用说明如下表3.1:表3.1引脚作用说明从参数手册知道LCD1602与单片机8051系列连接方式如图3.2所示,LCD1602引用电路如图3.3:图3.2 LCD1602与单片机8051系列连接方式图3.3 LCD1602引用电路如图3.3 LCD1602引用电路,单片机P2口与LCD1602的7-14脚连接,单片机14脚与LCD1602的6脚连接,单片机15脚与LCD1602的4脚连接。
2. ADC0832ADC0832具有8位分辨率;双通道A/D转换;输入输出电平与TTL/CMOS相兼容;5V电源供电时输入电压在0-5V之间,工作频率为250KHz,转换时间为32us;一般功耗仅为15Mw的特点。
ADC0832芯片引脚说明如图3.4:图3.4ADC0832芯片引脚说明:cs:片选使能,低电平芯片使能;cho:模拟输入通道0,或作为IN+/-使用;ch1:模拟输入通道:1,或作为IN+/-使用;GND:芯片参考0电位;DI:数据信号输入,悬着通道控制;DO:数据信号输出,转换数据输出;CLK:芯片时钟输入;Vcc/REF:电源输入及参考电压输入。
基于ADC0832的数字电压表
//基于ADC0832的数字电压表#include<reg51.h> //包含单片机寄存器的头文件#include<intrins.h> //包含_nop_()函数定义的头文件//ADC0832端口引脚定义sbit CS=P3^0; //将CS位定义为P3.0引脚sbit CLK=P3^6; //将CLK位定义为P3.6引脚sbit DIO=P3^7; //将DIO位定义为P3.7引脚//全局变量声明unsigned char code digit[10]={"0123456789"}; //定义字符数组显示数字unsigned char code Str[]={"Volt="}; //说明显示的是电压//液晶端口定义sbit RS=P2^0; //寄存器选择位,将RS位定义为P2.0引脚sbit RW=P2^1; //读写选择位,将RW位定义为P2.1引脚sbit E=P2^2; //使能信号位,将E位定义为P2.2引脚sbit BF=P0^7; //忙碌标志位,,将BF位定义为P0.7引脚/*****************************************************函数功能:延时1ms(3j+2)*i=(3×33+2)×10=1010(微秒),可以认为是1毫秒***************************************************/void delay1ms(){unsigned char i,j;for(i=0;i<10;i++)for(j=0;j<33;j++);}/*****************************************************函数功能:延时若干毫秒入口参数:n***************************************************/void delaynms(unsigned char n){unsigned char i;for(i=0;i<n;i++)delay1ms();}/*****************************************************函数功能:判断液晶模块的忙碌状态返回值:result。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
仿真图:
/*********************************包含头文件********************************/ #include <reg51.h>
#include <intrins.h>
/*********************************端口定义**********************************/ sbit CS = P3^5;
sbit Clk = P3^3;
sbit DATI = P3^4;
sbit DATO = P3^4;
sbit P20=P2^0 ;
/*******************************定义全局变量********************************/ unsigned char dat = 0x00; //AD值
unsigned char count = 0x00; //定时器计数
unsigned char CH; //通道变量
unsigned char dis[] = {0x00, 0x00, 0x00}; //显示数值
/*******************************共阳LED段码表*******************************/ unsigned char code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
char code tablewe[]={ 0xfd,0xfb,0xf7,0xef,0xdf,0xfe };
/**************************************************************************** 函数功能:AD转换子程序
入口参数:CH 出口参数:dat
****************************************************************************/ unsigned char adc0832(unsigned char CH)
{
unsigned char i,test,adval;
adval = 0x00;
test = 0x00;
Clk = 0; //初始化
DATI = 1;
_nop_();
CS = 0;
_nop_();
Clk = 1;
_nop_();
if ( CH == 0x00 ) //通道选择
{
Clk = 0;
DATI = 1; //通道0的第一位
_nop_();
Clk = 1;
_nop_();
Clk = 0;
DATI = 0; //通道0的第二位
_nop_();
Clk = 1;
_nop_();
}
else
{
Clk = 0;
DATI = 1; //通道1的第一位
_nop_();
Clk = 1;
_nop_();
Clk = 0;
DATI = 1; //通道1的第二位
_nop_();
Clk = 1;
_nop_();
}
Clk = 0;
DATI = 1;
for( i = 0;i < 8;i++ ) //读取前8位的值{
_nop_();
adval <<= 1;
Clk = 1;
_nop_();
Clk = 0;
if (DATO)
adval |= 0x01;
else
adval |= 0x00;
}
for (i = 0; i < 8; i++) //读取后8位的值
{
test >>= 1;
if (DATO)
test |= 0x80;
else
test |= 0x00;
_nop_();
Clk = 1;
_nop_();
Clk = 0;
}
if (adval == test) //比较前8位与后8位的值,如果不相同舍去。
若一直出现显示为零,请将该行去掉
dat = test;
_nop_();
CS = 1; //释放ADC0832
DATO = 1;
Clk = 1;
return dat;
}
/**************************************************************************** 函数功能:延时子程序
****************************************************************************/ void delay(void)
{
int k;
for(k=10;k<500;k++);
}
/**************************************************************************** 函数功能:将0-255级换算成0.00-5.00的电压数值
****************************************************************************/ void convdata(unsigned char i)
{
dis[0] = i/51; //个位
dis[1] = (i%51)*10/51*2; //小数点后第一位
dis[2] = ((i%51)*10%51)*10/51*2; //小数点后第二位
}
/**************************************************************************** 函数功能:数码管显示子程序
****************************************************************************/ void display(void)
{
P2=0xff;
P0=tab[dis[0]] & 0x7f; //显示个位和小数点
delay();
P2=0xfd;
P2=0xff;
P0=tab[dis[1]]; //显示小数点后第一位
delay();
P2=0xfb;
P2=0xff;
P0=tab[dis[2]]; //显示小数点后第二位
delay();
P2=0xf7;
P2=0xff;
P0=0xff; //显示小数点后第二位
delay();
P2=0xfe;
}
/**************************************************************************** 函数功能:主程序
****************************************************************************/ void main(void)
{
P2=0xff; //端口初始化
P0=0xff;
delay();
CH = 0x00; //在这里选择通道0x00或0x01
TMOD = 0x01; //设置中断
TH0=(65536-50000)/256;//定时器1初值定时50ms
TL0=(65536-50000)%256;
IE = 0x82;
TR0 = 1;
while(1) //主循环
{ dat = adc0832(CH);
convdata(dat); //数据转换
display(); //显示数值
}
}
/**************************************************************************** 函数功能:定时器中断延时程序这一段的作用时隔一段时间抽样一次否侧显示的最后一位
会不稳定
**************************************************************************** void timer0(void) interrupt 1
{
TMOD = 0x01;
TH0=(65536-50000)/256;//定时器1初值定时50ms
TL0=(65536-50000)%256;
IE = 0x82;
TR0 = 1
count++;
if (count == 0x01)
{
count = 0x00;
dat = adc0832(CH);
}
}。