首先打开proteus软件导入各个元器件,并连线。
接下来介绍下adc0808的导入方法
频率发生器的导入方法:
接下来就要编写c程序了,代码都是经过测试的,可以方型复制使用。
#include"reg52.h" // 引入头文件
#define uint unsigned int // 把无符号整型简写成 uint
sbit START = P3^0; // START接到P3.0口
sbit EOC = P3^1; // EOC接到P3.1口
sbit OE = P3^2; // OE接到P3.2口
sbit RS = P3^3; // RS接到P3.3口
sbit RW = P3^4; // RW接到P3.4口
sbit E = P3^5; // E接到P3.5口
uint dianya=0; // 定义 电压=0
unsigned char str[]={"0123456789.V"}; // 定义lcd显示需要的字符
// 延时函数(不精确的延时)
void delay(uint t){
uint i=0, j=0;
for(i=0; i<t; i++){
for(j=0; j<120; j++);
}
}
// 模拟转数字 ADC函数 根据时序表来写
void adc(){
START=0;
START=1;
delay(5);
START=0;
while(EOC != 1);
OE = 1;
dianya =P2;
OE = 0;
}
// lcd写数据函数 写dat首字母
void xdat(unsigned char dat){
RS = 1;
RW = 0;
E = 0;
P1 = dat;
delay(5);
E = 1;
E = 0;
}
// lcd写命令函数 写命令首字母xml
void xml(unsigned char ml){
RS = 0;
RW = 0;
E = 0;
P1 = ml;
delay(5);
E = 1;
E = 0;
}
// lcd初始化函数
void lcdinit(){
xml(0x38);
xml(0x0c);
xml(0x06);
xml(0x01);
}
// 更新显示函数
void gengxin(){
uint v1=0, v2=0, v3=0; // 定义电压的个位,十分位,百分位变量
dianya=dianya*100/51; // 根据电压显示和实际的比例做出先扩大100倍在缩小51倍
v1 = dianya/100; // 个位是电压值÷100的整数部分
v2 = (dianya%100)/10; // 十分位是电压值÷100的余数在÷10的整数部分
v3 = dianya%10; // 百分位是电压值÷10的余数
xml(0x80+0x04); // 写lcd从第一行第5个字符开始写
delay(5); // 延时5毫秒
xdat(str[v1]); // 写字符串str的第v1位
delay(5); // 延时5毫秒
xdat(str[10]); // 写字符串str的第10位(.)
delay(5); // 延时5毫秒
xdat(str[v2]); // 写字符串str的第v2位
delay(5); // 延时5毫秒
xdat(str[v3]); // 写字符串str的第v3位
delay(5); // 延时5毫秒
xdat(str[11]); // 写字符串str的第11位(V)
delay(5); // 延时5毫秒
}
// 主函数
void main(){
lcdinit(); // lcd初始化
while(1){
adc(); // 读电压值
gengxin(); // 更新显示电压值
}
}
最后就是编译成hex文件并导入proteus中仿真了,然后调节滑动变阻器,就可以发现电压表的值和lcd的值是一样的了,肯定会有误差,而且这个误差没有办法消除。
经过了一段时间的学习,回来又复习一下原来学习的东西,从新写了一遍,大家看看是不是有所进步呢?今天发现proteus也会卡顿,弄得1602没有任何反应,最后我的解决办法是把89c51删除了,从新导入了一个89c52,从新连线,问题解决了。更新一下下面的写法,并使用了c语言的指针语法,证明51中可以使用指针。
下面是程序把1602的显示初始化等函数分成了另外一个文件
下面是主程序adc.c文件的内容,他来调用1602文件中的函数
#include"1602_lcd.h" sbit start = P3^5; sbit eoc = P3^6; sbit oe = P3^7; void adc(uint * pd) { start = 0; start =1; delay(2); start=0; while(eoc != 1); oe=1; *pd=P2; oe=0; } void display(uc*sp,uint * pd) { uint dianya,v1,v2,v3; dianya=*pd*100/51; v1=dianya/100; v2=dianya/10%10; v3=dianya%10; writecom(0x80); writedat(*(sp+v1)); writedat('.'); writedat(*(sp+v2)); writedat(*(sp+v3)); writedat('V'); } int main() { uc str[]="0123456789"; uint dianya=0; uc *sp=str; uint * pd = &dianya; lcd_init(); while(1) { adc(pd); display(sp,pd); } return 0; }
下面是1602的头文件
#include<reg52.h> #define uint unsigned int #define uc unsigned char sbit RS = P3^0; sbit RW = P3^1; sbit E = P3^2; //初始化1602 void lcd_init(); // 写命令函数 void writecom(uc com); // 写数据函数 void writedat(uc dat); // 延时函数 void delay(uc t);
下面是1602头文件所对应的.c文件文章来源:https://www.toymoban.com/news/detail-510585.html
#include"1602_lcd.h" // 延时函数 void delay(uc t) { uc i=0, j=0; for(i=0;i<t;i++) { for(j=0;j<120;j++); } } // 写数据函数 void writedat(uc dat) { RS = 1; RW = 0; E = 0; P1 = dat; delay(5); E = 1; E = 0; } // 写命令函数 void writecom(uc com) { RS = 0; RW = 0; E = 0; P1 = com; delay(5); E = 1; E = 0; } //初始化1602 void lcd_init() { writecom(0x38); writecom(0x0c); writecom(0x06); writecom(0x01); }
上面这种写法是把1602单独写成了一个库文件的方式,以后需要用到1602的时候只需要把库文件1602.c和1602.h导入项目后,就能调用里面写好的函数了,不用从头在想一遍过程了。可以节省一些时间。文章来源地址https://www.toymoban.com/news/detail-510585.html
到了这里,关于51单片机制作简易数字电压表的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!