历史上的今天
今天是:2024年12月07日(星期六)
2021年12月07日 | 基于51单片机和ADC0808 ADC0809的自动数字电压表设计
2021-12-07 来源:eefocus
前言:
之前讲过基于数码管显示的自动数字电压表,接下来讲一下基于LCD1602显示的相关设计,分别利用的是TI公司的ADC0808和ADC0809。
硬件和软件设计
基于51单片机+ADC0808+LCD1602 测试电压范围为2.1~25V(超出这个范围,程序会卡死),精度<0.05
仿真图如下:


部分代码如下:
#include #define LEDDATA P0 #define v20_on {s3=0;s2=0;s1=1;} //宏定义不同量程,不同的开关状态 #define v2_on {s3=0;s2=1;s1=0;} #define v02_on {s3=1;s2=0;s1=0;} unsigned char code dispcode[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00}; unsigned char dispbuf[8]={0,0,0,0,0,0,0,0}; unsigned char getdata; unsigned long temp; unsigned char i,k,l,m; unsigned char code mytable0[]=" Welcome to use "; unsigned char code mytable1[]="Auto Voltmeter!"; unsigned char code line0[]=" Voltmeter "; //初始化显示 unsigned char code line1[]=" Value: V "; //引脚定义 sbit lcdrs=P2^0; sbit lcden=P2^1; sbit s3=P3^7; sbit s2=P3^6; sbit s1=P3^5; sbit OE=P3^0; sbit EOC=P3^1; sbit ST=P3^2; void delay(unsigned int z) //延时子函数 z*1ms { unsigned int x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); } void write_com(unsigned char c) //写命令子函数 { lcdrs=0; //低电平选择为 写指令 lcden=0; LEDDATA=c; //把指令写入P0口 delay(5); //参考时序图 lcden=1; //开使能 delay(5); //读取指令 lcden=0; //关闭使能 } void write_data(unsigned char d) //写数据子函数 { lcdrs=1; //高电平选择为 写数据 LEDDATA=d; //把数据写入P0口 delay(5); //参考时序图 lcden=1; //开使能 delay(5); //读取数据 lcden=0; //关闭使能 } void initialize() //LCD初始化函数 { unsigned char num; lcden=0; write_com(0x38); //设置16x2显示,5x7点阵显示,8位数据接口 write_com(0x0c); //00001DCB,D(开关显示),C(是否显示光标),B(光标闪烁,光标不显示) write_com(0x06); //000001N0,N(地址指针+-1) write_com(0x01); //清屏指令 每次显示下一屏内容时,必须清屏 write_com(0x80+0x10); //第一行,顶格显示 for(num=0;num<17;num++) { write_data(mytable0[num]); delay(10); } write_com(0x80+0x50); //第二行,从第一格开始显示 for(num=0;num<15;num++) { write_data(mytable1[num]); delay(10); } for(num=0;num<16;num++) { write_com(0x1c); //0001(S/C)(R/L)**; S/C:高电平移动字符,低电平移动光标; R/L:高电平左移,低电平右移 delay(300); } delay(1000); write_com(0x01); //清屏指令 每次显示下一屏内容时,必须清屏 write_com(0x80); for(num=0;num<14;num++) { write_data(line0[num]); delay(10); } write_com(0x80+0x40); for(num=0;num<15;num++) { write_data(line1[num]); delay(10); } } 基于51单片机+ADC0809+LCD1602 测试电压范围为0~5V,精度约为0.01 以AT89C51单片机为核心,起着控制作用。系统包括LCD1602液晶显示电路、复位电路、时钟电路、模数转换电路电路。设计思路分为五个模块:复位电路、晶振电路模块、AT89C51、LCD1602液晶显示电路、模数转换器电路这五个模块。 部分代码如下: //<程序名>:数字电压表 ** //<功能>:使用LCD显示被检测电压,精度为0.05V,范围是0~5V。 ** #include"includes.h" #define TIME0H 0x3C #define TIME0L 0xB0 uchar uc_Clock=0; //定时器0中断计数 bit b_DATransform=0; //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<把电压显示在LCD上>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> void vShowVoltage(uint uiNumber) { uchar ucaNumber[3],ucCount; if(uiNumber>999) uiNumber=999; ucaNumber[0]=uiNumber/100; //把计算数字的每个位存入数组。 ucaNumber[1]=(uiNumber-100*(int)ucaNumber[0])/10; ucaNumber[2]=uiNumber-100*(int)ucaNumber[0]-10*ucaNumber[1]; for(ucCount=0;ucCount<3;ucCount++) { vShowOneChar(ucaNumber[ucCount]+48); //从首位到末位逐一输出。 if(ucCount==0) vShowOneChar('.'); } } //************************************************************************************************* //* * //* ********************************主函数****************************** * //* * //************************************************************************************************* void main() { TMOD=0x01; //定时器0,模式1。 TH0=TIME0H; TL0=TIME0L; TR0=1; //启动定时器。 ET0=1; //开定时器中断。 EA=1; //开总中断 vdInitialize(); vWriteCMD(0x84); //写入显示起始地址(第一行第4个位置) vShowChar("voltage"); vWriteCMD(0xC9); vShowChar("(V)"); while(1) { if(b_DATransform==1) { b_DATransform=0; vWriteCMD(0xC4); vShowVoltage(uiADTransform()); } } } //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<定时器0中断函数>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> void t0() interrupt 1 { if(uc_Clock==0) { uc_Clock=5; b_DATransform=1; } else uc_Clock--; TH0=TIME0H; //恢复定时器0。 TL0=TIME0L; } 文件地址: 链接:https://pan.baidu.com/s/146k5nKjulFsZeTJUKEvQDQ 提取码:cukz 

史海拾趣
|
对于DAC和ADC这两者来说,最重要的是记住输入或输出都是数字信号,所以,信号是被量化的。也就是说,N比特字代表2的N次方个可能状态之一,因此,N比特DAC(具有一个固定参考)只能有2的N次方可能的模拟输出,而N比特ADC只能有2的N次方个数字输出。模 ...… 查看全部问答> |
|
我想做个示波器 里面要保存大概500个波形,显示采用液晶显示器 时间采样单位是微秒级别的。 采用什么芯片啊? 板子我们公司没人做? 能找到外协么? 我对嵌入式不是太熟悉 高手们指点下, 怎么开始做啊? 要自己买个开发板么?… 查看全部问答> |
|
我用的是au1200 cpu ,我的硬件没有网络,是通过把bootloaser烧写到nor flash,内核放到sd卡里来启动的。我在调试触摸屏,触摸屏驱动没有问题了,现在每次重新启动启动都需要手动校准触摸屏,这样用户肯定是不同意的,所以我想把注册表的内容永久 ...… 查看全部问答> |
|
1. 用组合逻辑搭的话,有什么综合和布线策略可以保证延时的精度呢?2. 另外,刚刚看到说明文档,说pll输出时钟的最小相移是VCO周期除以8,这个时间是可以满足的。不过我自己做了个实验如下:10M输入,输出三个100M,相移分别为c0:0.31ns,c1:0.62ns ...… 查看全部问答> |
|
数据类型 字节 数据范围 说明 sfrb 1 字节类型的特殊功能寄存器或外围模块 sfrw 1 字类型的特殊功能寄存器或外围模块 unsigned char 1 0~255 ...… 查看全部问答> |
|
我的IO口置高以后,用示波器一测量,才1.4V~1.5V,不知道是怎么回事? 我的IO是接在一个10K电阻上,再经过一个10K电阻的分压,给一个SC1815做开关信号控制,SC1815又控制着一个小继电器,上电后,继电器老是来回熄合,“啪啪”来回开关,真是郁闷 ...… 查看全部问答> |
|
2812搜查令+TMS320F2812 DSP编程之AD采样精度的校准算法(转载) F2812内部集成了ADC转换模块。该模块是一个12位、具有流水线结构的模数转换器,内置双采样保持器(S/H),可多路选择16通道输入,快速转换时间运行在25 MHz、ADC时钟或12.5 Msps,16个转换结果寄存器可工作于连续自动排序模式或启动/停止模式。在实 ...… 查看全部问答> |




