【C51单片机】数字电压表设计

您所在的位置:网站首页 液晶显示的数字 【C51单片机】数字电压表设计

【C51单片机】数字电压表设计

2024-07-13 13:37| 来源: 网络整理| 查看: 265

第一次写博客呀多多关照~

1、实现的功能

采用ADC0809和AT89C51单片机及显示电路完成0~5V、0~15V两个量程的直流电压的检测,并通过LCD1602液晶屏实时显示。通过开关SW1和SW2选择5V或15V,当所测电压超过量程时,报警电路的小灯闪烁、蜂鸣器发出警报,同时液晶屏显示QAQ(哈哈哈闲着没事干就加了),当两个开关同时按下也会触发报警电路。

至于两个档位的区别,为了模拟实际的电压表,所以设计的数字电压表显示的精度不一样,15V量程的精度为0.1V,5V量程的精度为0.001V。

2、Proteus仿真原理图

在这里插入图片描述 (想说一下,我这里ADC0809的out输出接了上拉电阻,要不然显示屏显示不正常,但是参考别人的不接上拉电阻也可以正常工作QAQ)

3、仿真结果

选择5V量程: 在这里插入图片描述 选择15V量程: 在这里插入图片描述

4、完整的代码

使用keil编写的c语言代码.

#include #define uchar unsigned char //宏定义无符号字符型 #define uint unsigned int //宏定义无符号整型 sbit START=P2^7; //AD启动转换信号 sbit OE=P2^5; //数据输出允许信号 sbit EOC=P2^6; //AD转换结束信号 sbit CLK=P2^4; //时钟脉冲 sbit RS=P2^0; //LCD1602数据/命令选择端(H/L) sbit RW=P2^1; //LCD1602数/写选择端(H/L) sbit E=P2^2; //LCD1602使能信号 sbit led=P3^0; sbit buzzer=P3^1; sbit SW1=P3^2; //5V量程选择开关 sbit SW2=P3^3; //15V量程选择开关 sbit addr_a=P3^5; sbit addr_b=P3^6; sbit addr_c=P3^7; //函数声明 uint ADC(); /* AD转换函数 */ void delayMS(uint xms); /* 延时函数 */ bit lcd_busy_check(); /* 忙检测函数 */ void lcd_write_com(uchar com); /* LCD1602写入8位命令子函数 */ void lcd_write_data(uchar date); /* LCD1602写入8位数据子函数 */ void init_lcd(); /* LCD1602初始化子程序 */ void lcd_show_string1(uchar a[]); /* 第一行从头开始显示字符串 */ void lcd_show_string2(uchar a[]); /* 第二行从头开始显示字符串 */ void lcd_show_string(uchar add,uchar a[]); /* 指定位置显示字符串 */ void display(); /* 显示函数 */ void alarm(); /* 报警函数 */ void range(); /* 量程选择函数 */ //定义全局变量 unsigned int volt; unsigned long vo; unsigned char code table[]="0123456789"; /**************************函数功能:AD转换子程序***************************/ uint ADC() { START=0; //确保进入正常AD转换状态 OE=0; //转化初始化 START=1; START=0; //AD开始转换 while(EOC==0); //外部中断等待AD转换结束 OE=1; //读取转换的AD值 volt=P1; OE=0; //输出转换结束 return volt; } /**********************函数功能:液晶屏LCD1602显示子程序****************/ /*延时函数:DelayMS()*/ void delayMS(uint xms) { uint i,j; for(i=xms;i>0;i--) for(j=110;j>0;j--); } /*忙检测函数:lcd_busy_check()*/ bit lcd_busy_check() { bit result; RS=0; RW=1; E=1; delayMS(10); result=(bit)(P0&0x80); E=0; return result; } /*写命令函数:lcd_write_com()*/ void lcd_write_com(uchar com) { RS=0; E=0; RW=0; P0=com; delayMS(5); E=1; delayMS(5); E=0; } /*写数据函数:lcd_write_data()*/ void lcd_write_data(uchar date) { RS=1; E=0; RW=0; P0=date; delayMS(5); E=1; delayMS(5); E=0; } /* LCD1602初始化函数:init_lcd()*/ void init_lcd() { E=0; //默认开始状态为关使能端 lcd_write_com(0x38); //显示模式设置 lcd_write_com(0x01); //显示清屏,将上次的内容清除 lcd_write_com(0x0c); //开显示,不显光标,光标不闪 lcd_write_com(0x06); //读一个字符光标加1 } /* 指定位置显示字符串函数:lcd_show_string() */ /* 参数 add 地址 第一行 0~27 */ /* 第二行 40~67 */ /* a[] 字符串 "abc" */ void lcd_show_string(uchar add,uchar a[]) { uchar i; lcd_write_com(0x80+add); for(i=0;a[i]!='\0';i++) { lcd_write_data(a[i]); } } /* 第一行显示字符串 */ void lcd_show_string1(uchar a[]) { uchar i; lcd_write_com(0x80); for(i=0;a[i]!='\0';i++) { lcd_write_data(a[i]); } } /* 第二行显示字符串 */ void lcd_show_string2(uchar a[]) { uchar i; lcd_write_com(0x80+0X40); for(i=0;a[i]!='\0';i++) { lcd_write_data(a[i]); } } /* LCD1602显示函数:display()*/ void display1() //5V的显示 { uint v_1v,v_100mv,v_10mv,v_1mv; //定义变量用于显示 vo = volt*19.6; //转换值处理 (满量程为5V,转换分辩率为8位即最大值是255,5/255=19.6mV,即1代表19.6mV) v_1v = vo/1000; //1伏显示位 v_100mv = vo/100%10; //100毫伏显示位 v_10mv = vo/10%10; //10毫伏显示位 v_1mv = vo/1%10; //1毫伏显示位 lcd_write_com(0x80+0x40+0x05); //选中第二行第5个位置 lcd_write_data(table[v_1v]); lcd_write_data('.'); lcd_write_data(table[v_100mv]); lcd_write_data(table[v_10mv]); lcd_write_data(table[v_1mv]); lcd_write_data('V'); //显示电压的单位V lcd_write_data(' '); lcd_write_data(' '); lcd_write_data(' '); } void display2() //15V的显示 { uint v_10v,v_1v,v_100mv; vo = volt*19.6; v_10v = vo/10000; //10伏显示位 v_1v = vo/1000%10; //1伏显示位 v_100mv = vo/100%10; //100毫伏显示位 lcd_write_com(0x80+0x40+0x05); lcd_write_data(table[v_10v]); lcd_write_data(table[v_1v]); lcd_write_data('.'); lcd_write_data(table[v_100mv]); lcd_write_data('V'); lcd_write_data(' '); lcd_write_data(' '); lcd_write_data(' '); lcd_write_data(' '); lcd_write_data(' '); } void display3() //报警时的显示 { lcd_write_com(0x01); lcd_show_string1(" QAQ "); delayMS(50); lcd_show_string2(" Ooooooops "); delayMS(50); } /***************************函数功能:报警********************************/ void alarm() { int i; display3(); //调用报警时的显示 for(i=0;i量程5V lcd_show_string1("Range:"); //LCD1602显示->第一行为Range: lcd_show_string2("Volt:"); //LCD1602显示->第二行为Volt: addr_a=0; addr_b=0; addr_c=0; ADC(); //调用模数转换程序 if(volt>=0xFF) //当大于5v时,使用LED和蜂鸣器报警 { alarm(); } else //否则取消报警 { led=0; //控制发光二极管D2灭 buzzer=0; //控制蜂鸣器不发声 display1(); //调用显示程序1 } } else if((SW1!=0)&&(SW2==0)) //按下SW2 { lcd_show_string(0x06,"0~15V "); //LCD1602显示->量程15V lcd_show_string1("Range:"); //LCD1602显示->第一行 lcd_show_string2("Volt:"); //LCD1602显示->第二行 addr_a=1; addr_b=0; addr_c=0; ADC(); volt=3*volt; //转换的值*3,变为15v范围 if(volt>=0x2FD) //当大于15v时,使用LED和蜂鸣器报警 { alarm(); } else //否则取消报警 { led=0; //控制发光二极管D2灭 buzzer=0; //控制蜂鸣器不发声 display2(); //调用显示程序2 } } else if((SW1==0)&&(SW2==0)) //同时按下SW1、SW2的误操作,报警 { alarm(); } else { //SW1、SW2均未按下,提示选择量程 lcd_show_string1(" Choose range "); delayMS(1); lcd_show_string2(" 5V or 15V "); delayMS(1); } } /***************************函数功能:主程序********************************/ void main(void) { TMOD=0x01; //设定定时计数工作方式 TH0=0XFF; //为定时器初赋值 TL0=0XB4; EA=1; //开总中断 ET0=1; //开定时器0中断 TR0=1; //开启定时器0 led=0; buzzer=0; init_lcd(); //LCD1602初始化函数 while(1) { range(); } } /**************************函数功能:定时器0时钟信号*************************/ void timer() interrupt 1 { TH0=0XFF; //初值重置 TL0=0XF0; CLK=~CLK; //取反 产生时钟信号 }


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3