电压表(1路,ADC0832,LCD1602,上下限)
proteus吧
全部回复
仅看楼主
level 7
#include <reg51.h>
#include "ADC0832.h"
#include"i2c.h"
#include "lcd1602.h"
#define uchar unsigned char
#define uint unsigned int
sbit k1=P1^0;//按钮
sbit k2=P1^1;
sbit k3=P1^2;
sbit k4=P1^3;
sbit beep=P2^3;//蜂鸣器
uchar disp1[]="Volt:00.00V";
uchar disp2[]="H:00.0V L:00.0V";
uint volt=0;//电压
uint limit1=50,limit2=200;//报警阀值
uchar k=0;
void delay(uint i) //延时
{
while(i--);
}
void main()//主函数
{
TMOD|=0X01;
TH0=0X3C;
TL0=0XB0;
ET0=1;//打开定时器0中断允许
EA=1;//打开总中断
TR0=1;//打开定时器
init_1602();
limit1=At24c02Read(0);//初始化存储
limit1<<=8;
limit1+=At24c02Read(1);
if(limit1>500)
{
limit1=50;
At24c02Write(0,limit1>>8);
At24c02Write(1,limit1);
}
limit2=At24c02Read(2);//初始化存储
limit2<<=8;
limit2+=At24c02Read(3);
if(limit2>500)
{
limit2=200;
At24c02Write(2,limit2>>8);
At24c02Write(3,limit2);
}
write_string(1,0,disp1); //显示
write_string(2,0,disp2);
while(1)
{
if(!k3)//上限加
{
if(limit1<limit2)
limit1++;
At24c02Write(0,limit1>>8);
At24c02Write(1,limit1);
delay(10000);
while(!k3);
}
if(!k4)//上限减
{
if(limit1>0)
limit1--;
At24c02Write(0,limit1>>8);
At24c02Write(1,limit1);
delay(10000);
while(!k4);
}
if(!k1)//下限加
{
if(limit2<500)
limit2++;
At24c02Write(2,limit2>>8);
At24c02Write(3,limit2);
delay(10000);
while(!k1);
}
if(!k2)//下限减
{
if(limit2>limit1)
limit2--;
At24c02Write(2,limit2>>8);
At24c02Write(3,limit2);
delay(10000);
while(!k2);
}
}
}
void Timer0() interrupt 1//定时器中断
{
unsigned long i;
TH0=0X3C;//重装定时器
TL0=0XB0;
if(k<10)
k++;
else
{
k=0;
i=ADC0832(0);//测电压
volt=i*5000/255;
//显示
disp1[5]=volt/1000+0x30;
disp1[6]=volt%1000/100+0x30;
disp1[8]=volt%100/10+0x30;
disp1[9]=volt%10+0x30;
disp2[2]=limit2/100+0x30;
disp2[3]=limit2%100/10+0x30;
disp2[5]=limit2%10+0x30;
disp2[10]=limit1/100+0x30;
disp2[11]=limit1%100/10+0x30;
disp2[13]=limit1%10+0x30;
write_string(1,0,disp1); //显示
write_string(2,0,disp2);
//报警控制
if((volt>limit2*10)||(volt<limit1*10))
beep=0;
else
beep=1;
}
}
2024年06月10日 11点06分 1
level 7
#ifndef __LCD1602_H_
#define __LCD1602_H_
/**********************************
当使用的是4位数据传输的时候定义,
使用8位取消这个定义
**********************************/
//#define LCD1602_4PINS
/**********************************
包含头文件
**********************************/
#include<reg51.h>
//---重定义关键词---//
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
/**********************************
PIN口定义
**********************************/
sbit rs=P2^0; //1602数据/命令选择引脚 H:数据 L:命令
sbit rw=P2^1; //1602读写引脚 H:数据寄存器 L:指令寄存器
sbit e =P2^2; //1602使能引脚 下降沿触发
/**********************************
函数声明
**********************************/
void write_com(uchar com); //LCD1602写入8位数据子函数
void write_data(uchar dat); //1602写数据函数
void init_1602(); //LCD1602初始化子程序
void write_string(uchar hang,uchar add,uchar *p); //显示字符串
void delay_uint(uint i);
#endif
2024年06月10日 11点06分 2
level 7
#include "lcd1602.h"
void delay_uint(uint i)
{
while(i--);
}
/********************************************************************
* 名称 : write_com(uchar com)
* 功能 : 1602命令函数
* 输入 : 输入的命令值
* 输出 : 无
***********************************************************************/
void write_com(uchar com)
{
e=0;
rs=0;
rw=0;
P0=com;
delay_uint(20);
e=1;
delay_uint(20);
e=0;
}
/********************************************************************
* 名称 : write_data(uchar dat)
* 功能 : 1602写数据函数
* 输入 : 需要写入1602的数据
* 输出 : 无
***********************************************************************/
void write_data(uchar dat)
{
e=0;
rs=1;
rw=0;
P0=dat;
delay_uint(20);
e=1;
delay_uint(20);
e=0;
}
/********************************************************************
* 名称 : write_string(uchar hang,uchar add,uchar *p)
* 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,调用该函数如下
write_string(1,5,"ab cd ef;")
* 输入 : 行,列,需要输入1602的数据
* 输出 : 无
***********************************************************************/
void write_string(uchar hang,uchar add,uchar *p)
{
if(hang==1)
write_com(0x80+add);
else
write_com(0x80+0x40+add);
while(1)
{
if(*p == '\0') break;
write_data(*p);
p++;
}
}
/********************************************************************
* 名称 : init_1602()
* 功能 : 初始化1602液晶
* 输入 : 无
* 输出 : 无
***********************************************************************/
void init_1602()
{
write_com(0x38);//数据总线为8位,显示2行,5x7点阵
write_com(0x0e);//开显示,有光标,光标闪烁
write_com(0x06);//光标自动右移
delay_uint(1000);//等待设置完成
}
2024年06月10日 11点06分 3
level 7
#ifndef __I2C_H_
#define __I2C_H_
#include <reg51.h>
sbit SCL=P1^6;
sbit SDA=P1^7;
void I2cStart();
void I2cStop();
unsigned char I2cSendByte(unsigned char dat);
unsigned char I2cReadByte();
void At24c02Write(unsigned char addr,unsigned char dat);
unsigned char At24c02Read(unsigned char addr);
#endif
2024年06月10日 11点06分 4
level 7
#include"i2c.h"
#include "lcd1602.h"
/*******************************************************************************
* 函数名 : Delay10us()
* 函数功能 : 延时10us
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void Delay10us()
{
unsigned char a,b;
for(b=1;b>0;b--)
for(a=3;a>0;a--);
}
/*******************************************************************************
* 函数名 : I2cStart()
* 函数功能 : 起始信号:在SCL时钟信号在高电平期间SDA信号产生一个下降沿
* 输入 : 无
* 输出 : 无
* 备注 : 起始之后SDA和SCL都为0
*******************************************************************************/
void I2cStart()
{
SDA=1;
Delay10us();
SCL=1;
Delay10us();//建立时间是SDA保持时间>4.7us
SDA=0;
Delay10us();//保持时间是>4us
SCL=0;
Delay10us();
}
/*******************************************************************************
* 函数名 : I2cStop()
* 函数功能 : 终止信号:在SCL时钟信号高电平期间SDA信号产生一个上升沿
* 输入 : 无
* 输出 : 无
* 备注 : 结束之后保持SDA和SCL都为1;表示总线空闲
*******************************************************************************/
void I2cStop()
{
SDA=0;
SCL=0;
Delay10us();
SCL=1;
Delay10us();//建立时间大于4.7us
SDA=1;
Delay10us();
}
/*******************************************************************************
* 函数名 : I2cSendByte(unsigned char dat)
* 函数功能 : 通过I2C发送一个字节。在SCL时钟信号高电平期间,保持发送信号SDA保持稳定
* 输入 : num
* 输出 : 0或1。发送成功返回1,发送失败返回0
* 备注 : 发送完一个字节SCL=0,SDA=1
*******************************************************************************/
unsigned char I2cSendByte(unsigned char dat)
{
unsigned char a=0,b=0;//最大255,一个机器周期为1us,最大延时255us。
for(a=0;a<8;a++)//要发送8位,从最高位开始
{
SDA=dat>>7; //起始信号之后SCL=0,所以可以直接改变SDA信号
dat=dat<<1;
Delay10us();
SCL=1;
Delay10us();//建立时间>4.7us
SCL=0;
Delay10us();//时间大于4us
}
SDA=1;
Delay10us();
SCL=1;
while(SDA)//等待应答,也就是等待从设备把SDA拉低
{
b++;
if(b>200) //如果超过2000us没有应答发送失败,或者为非应答,表示接收结束
{
SCL=0;
Delay10us();
return 0;
}
}
SCL=0;
Delay10us();
return 1;
}
/*******************************************************************************
* 函数名 : I2cReadByte()
* 函数功能 : 使用I2c读取一个字节
* 输入 : 无
* 输出 : dat
* 备注 : 接收完一个字节SCL=0,SDA=1.
*******************************************************************************/
unsigned char I2cReadByte()
{
unsigned char a=0,dat=0;
SDA=1;//起始和发送一个字节之后SCL都是0
Delay10us();
for(a=0;a<8;a++)//接收8个字节
{
SCL=1;
Delay10us();
dat<<=1;
dat|=SDA;
Delay10us();
SCL=0;
Delay10us();
}
SCL=1;
Delay10us();
SCL=0;
Delay10us();
return dat;
}
/*******************************************************************************
* 函数名 : void At24c02Write(unsigned char addr,unsigned char dat)
* 函数功能 : 往24c02的一个地址写入一个数据
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void At24c02Write(unsigned char addr,unsigned char dat)
{
I2cStart();
I2cSendByte(0xa0);//发送写器件地址
I2cSendByte(addr);//发送要写入内存地址
I2cSendByte(dat);//发送数据
I2cStop();
delay_uint(10000);
}
/*******************************************************************************
* 函数名 : unsigned char At24c02Read(unsigned char addr)
* 函数功能 : 读取24c02的一个地址的一个数据
* 输入 : 无
* 输出 : 无
*******************************************************************************/
unsigned char At24c02Read(unsigned char addr)
{
unsigned char num;
I2cStart();
I2cSendByte(0xa0); //发送写器件地址
I2cSendByte(addr); //发送要读取的地址
I2cStart();
I2cSendByte(0xa1); //发送读器件地址
num=I2cReadByte(); //读取数据
I2cStop();
return num;
}
2024年06月10日 11点06分 5
level 7
#ifndef __ADC0832_H_
#define __ADC0832_H_
//---包含头文件---//
#include<reg51.h>
//---重定义关键词---//
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
//******************adc0832****************************//
sbit ADCLK=P3^5;//时钟,初始状态为0
sbit ADDI=P3^6;//数据输入
sbit ADCS=P3^7;
//---定义全局函数---//
unsigned int ADC0832(unsigned char channel);
#endif
2024年06月10日 11点06分 6
level 7
#include "ADC0832.h"
#include "intrins.h"
//读取AD值
unsigned int ADC0832(unsigned char channel) //AD转换,返回结果
{
unsigned char i = 0;
unsigned char j;
unsigned int dat = 0;
unsigned char ndat = 0;
if (channel == 0) channel = 2;//通道1
if (channel == 1) channel = 3;//通道2
ADDI = 1;//输入引脚拉高
_nop_();//延时1us
_nop_();//延时1us
ADCS = 0;//片选
_nop_();//延时1us
_nop_();//延时1us
ADCLK = 1;//拉高时钟
_nop_();//延时1us
_nop_();//延时1us
ADCLK = 0;//拉低时钟
_nop_();//延时1us
_nop_();//延时1us
ADCLK = 1;//拉高时钟
ADDI = channel & 0x1;
_nop_();//延时1us
_nop_();//延时1us
ADCLK = 0;//拉低时钟
_nop_();//延时1us
_nop_();//延时1us
ADCLK = 1;//拉高时钟
ADDI = (channel >> 1) & 0x1;
_nop_();//延时1us
_nop_();//延时1us
ADCLK = 0;//拉低时钟
ADDI = 1;//输出1
_nop_();//延时1us
_nop_();//延时1us
dat = 0; //存储清零
ADDI =1;
for (i = 0; i < 8; i++)//循环8次
{
dat |= ADDI;//读取引脚
ADCLK = 1; //拉高时钟
_nop_();//延时1us
_nop_();//延时1us
ADCLK = 0;//拉低时钟
_nop_();//延时1us
_nop_();//延时1us
dat <<= 1;//左移
if (i == 7) dat |= ADDI;//读取引脚
}
for (i = 0; i < 8; i++)//循环8次
{
j = 0;
j = j | ADDI; //读取引脚
ADCLK = 1;//拉高时钟
_nop_();//延时1us
_nop_();//延时1us
ADCLK = 0;//拉低时钟
_nop_();//延时1us
_nop_();//延时1us
j = j << 7;//左移7位
ndat = ndat | j; //合并数据
if (i < 7) ndat >>= 1;//去掉符号
}
ADCS = 1; //清除片选
ADCLK = 0;//拉低时钟
ADDI=1;
dat <<= 8;//数据移位
dat |= ndat;//合并数据
return(ndat);
}
2024年06月10日 11点06分 7
1