基于单片机89C51模拟电压表系统(双量程)

编程

  • 项目名称:模拟电压表系统设计

  • 项目功能:实现0 ~ 5V、5 ~ 10V双量程电压测量并显示

    本项目是在这次疫情下,大三学期的课程设计,自己辛苦了一夜,最后成绩得了优(哈哈哈哈)。下面简单说明一下本项目,为像我一样笨手笨脚的同学提供些经验(嘻嘻嘻嘻)。

硬件部分

  • MCU:89C51
  • 显示模块:LCD1602
  • 模数转换:ADC0808
  • 警报:蜂鸣器
  • 电压采集:采集电路

软件部分:

该部分无非是驱动及数据处理。

首先是驱动:

LCD1602.h

#ifndef __LCD1602_H__

#define __LCD1602_H__

#define uchar unsigned char

#define uint unsigned int

/******LCD端口设置******/

sbit LcdEn = P3^7;

sbit LcdRw = P3^6;

sbit LcdRs = P3^5;

/******定义测量按键******/

sbit Start = P3^2;

sbit Stop = P3^3;

void LcdDisplay();

void LcdPrintL1(char* str); /*第一行整屏左移显示*/

void LcdPrint1(char* str); /*第一行显示*/

void LcdPrint11(char* str); /*第一行显示,不清屏·*/

void LcdPrint2(char* str); /*第二行显示,不清屏*/

void WriteCom(uchar comData);

void WriteData(uchar Data);

void Delay_ms(unsigned int n);

void Delay_10ms();

#endif

LcdDisplay.c

/******LCD驱动及显示******/

#include<reg51.h>

#include"LCD1602.h"

#define uchar unsigned char

#define uint unsigned int

extern code uchar table1[];

extern code uchar table2[];

extern code uchar table3[];

extern code uchar table4[];

extern code uchar table5[];

uchar num = 0;

/*-----------------LCD驱动程序----------------*/

/*******LCD写命令*******/

void WriteCom(uchar comData){

LcdRs = 0; //写命令

LcdRw = 0; //写选择端

//Delay_ms(5); //

P0 = comData; //将数据送达数据线

LcdEn = 1; //开始能

Delay_ms(5);

LcdEn = 0; //关始能

}

/******LCD写数据*******/

void WriteData(uchar Data){

LcdRs = 1; //写数据

LcdRw = 0; //写选择

P0 = Data;

Delay_ms(5);

LcdEn = 1;

Delay_ms(5);

LcdEn = 0;

}

/*---------------LCD初始化---------------*/

void LcdDisplay(){

LcdRw = 0;

LcdEn = 0;

WriteCom(0x38); //设置16x2显示,5x7点阵,8位数据接口

WriteCom(0x0c); //设置开显示,不显示光标

Delay_ms(1);

WriteCom(0x06); //写一个字符后地址指针加1

WriteCom(0x01); //显示清零,数据指针清零

Delay_ms(1);

WriteCom(0x80); //光标位置初始化

while(table1[num]!=""){ //没有换行符,一直执行

WriteData(table1[num]);

num++;

Delay_ms(2);

}

Delay_ms(1000);

}

/*---------------LCD显示指令--------------*/

/*******第一行显示指令*******/

void LcdPrint1(char* str){

uchar i = 0;

WriteCom(0x01);

WriteCom(0x80);

for(i=0;str[i]!=0;i++)

WriteData(str[i]);

}

/*******第一行显示指令,不清屏*******/

void LcdPrint11(char* str){

uchar i = 0;

// WriteCom(0x01);

WriteCom(0x80);

for(i=0;str[i]!=0;i++)

WriteData(str[i]);

}

/******第二行显示指令******/

void LcdPrint2(char* str){

uchar i = 0;

WriteCom(0x80 + 0x40);

for(i=0;str[i]!=0;i++)

WriteData(str[i]);

}

/******第一行整屏左移显示指令******/

void LcdPrintL1(char* str){

uchar i = 0;

WriteCom(0x01); //显示清零,指针清零

WriteCom(0x80);

for(i=0;str[i]!=0;i++)

WriteData(str[i]);

Delay_ms(150);

num = 0;

while(table4[num]!=""){

WriteCom(0x18); //整屏左移指令

num++;

Delay_ms(150); //控制移动速度

}

}

ADC0808.h

#ifndef __ADC0808_H__

#define __ADC0808_H__

#define uchar unsigned char

#define uint unsigned int

/******ADC0808端口设置******/

sbit START = P3^1; /*A/D转换启动信号,正脉冲有效*/

sbit EOC = P3^0; /*转换结束信号,高电平有效;该信号在A/D转换过程中为低电平,其余时间为高电平*/

sbit OE = P3^4; /*转换允许信号*/

/******定义ADC数据选择端口******/

sbit a = P1^0;

sbit b = P1^1;

sbit c = P1^2;

/******定义量程选择端口******/

sbit K1 = P1^3;

sbit K2 = P1^4;

uint ReadData();

void AdStar();

void SetData0(uchar addr,uint Data);

void SetData1(uchar addr,uint Data);

void DataSelector();

#endif

BuzzerWarning.c

/******BuzzerWarning******/

#include<reg51.h>

#include"LCD1602.h"

#include"ADC0808.h"

#define uchar unsigned char

#define uint unsigned int

extern code uchar table5[];

extern code uchar table6[];

sbit SPEAKER = P1^7;

void BuzzerWarning0_5V(){

uint t,i;

//SPEAKER = 1;

//LcdPrint11(table5);

for(t=0;t<3;t++){

for(i=0;i<35;i++)

Delay_10ms();

SPEAKER =~ SPEAKER;

}

SPEAKER = 1;

Delay_ms(800);

}

主函数部分:

main.c

#include<reg51.h>

#include<intrins.h>

#include"LCD1602.h"

#include"ADC0808.h"

#include<stdio.h>

#define uchar unsigned char

#define uint unsigned int

code uchar tablea[]="0123456789";

code uchar tableb[]="Voltage:00.00 V";

code uchar table1[]={"System ready."};

code uchar table2[]={"Press STAR to start measuring."};

code uchar table3[]={"Measuring... "};

code uchar table4[]={"Measurement end."};

code uchar table5[]={"Maximum range."};

code uchar table6[]={"Minimum range"};

uchar res = 0;

bit flag1 = 0;

bit flag2 = 1;

bit flag3 = 1;

uchar k = 1;

void Interrupt_eint();

void StartInt0();

void StopInt1();

void main(void){

/*------系统初始化------*/

LcdDisplay();

Interrupt_eint();

while(!IE0 && !IE1) LcdPrintL1(table2);

/*------系统运行------*/

while(1){

StartInt0();

StopInt1();

}

}

下面是数据处理部分及按键部分,由于老师要求有两个按键即:开始按键、结束按键;又由于在系统启动后会有字幕的提示信息,且提示信息是以滚动的方式显示的,所以这个项目的按键部分采用了中断的方式进行实现(效果:在提示信息显示及系统运行的任何时候都可以随时按下按键)。

注意:在系统刚启动后,只能按下 START按键,按下STOP按键无效,这是在程序中设计好的。

下面是程序:

Interrupt.c

/******利用外部中断函数实现按键功能******/

#include<reg51.h>

#include"LCD1602.h"

#include"ADC0808.h"

#define uchar unsigned char

#define uint unsigned int

extern code uchar tablea[];

extern code uchar tableb[];

extern code uchar table1[]; /*系统准备就绪*/

extern code uchar table2[]; /*请按“Start”开始测量*/

extern code uchar table3[]; /*正在测量*/

extern code uchar table4[]; /*测量结束*/

extern code uchar table5[];

extern code uchar table6[];

extern uchar res; /*接收数据*/

extern bit flag2;

extern bit flag3;

void BuzzerWarning0_5V();

/******中断初始化******/

void Interrupt_eint(){

EX0 = 1; //开启外部中断0

IT0 = 0; //设置外部中断0触发模式:低电平触发

EX1 = 1; //开启外部中断1

IT1 = 0; //设置外部中断1触发模式

EA = 1; //开启总中断

PX0 = 1; //将外部中断的优先级提高

}

/******外部0中断服务函数******/

void StartInt0() interrupt 0{

if(IE0 && flag2 == 1){ //按下START

Delay_10ms();

flag2 = 0;

LcdPrint1(table3);

LcdPrint2(tableb);

while(!IE1){

WriteCom(0x80+0x40+8);

AdStar();

res = ReadData();

if(flag3){

SetData0(8,res);

if((res*1.0/255*500)/100 == 5){//判断电压是否超过或等于 5 V

LcdPrint11(table5);

BuzzerWarning0_5V();

}

else

LcdPrint11(table3);

}

else{

SetData1(8,res);

if(res*1.0/255*500*3 >= 1000){//判断电压是否超过或等于 10 V

LcdPrint11(table5);

BuzzerWarning0_5V();

}

else if(res*1.0/255*500*3/100 < 5){

LcdPrint11(table6);

BuzzerWarning0_5V();

}

else

LcdPrint11(table3);

}

}

}

}

/******外部1中断服务函数******/

void StopInt1() interrupt 2{

if(IE1 && flag2 == 0){ //按下STOP

Delay_10ms();

flag2 = 1;

LcdPrint1(table4);

LcdPrint2(tableb);

res = ReadData();

if(flag3)

SetData0(8,res);

else

SetData1(8,res);

while(!IE0);

}

}

以上就是所有的源程序啦。程序中也有些小细节,大多都有注释。

下面是Protues的仿真原理图:

5V时候的仿真:

好啦,以上就是所有内容啦,祝大家学习愉快!!!

原文链接:https://www.cnblogs.com/this-is-changjiang/archive/2020/07/29/13398590.html

以上是 基于单片机89C51模拟电压表系统(双量程) 的全部内容, 来源链接: utcz.com/z/518865.html

回到顶部