#include <common.h>
#define uchar unsigned char
float v_low = 2.8;//電壓范圍下限
float v_high = 4.5;//電壓范圍上限
uchar BUF[2];//從at24c04中讀取的數據存儲在這
uchar w_buf[2]; //寫入at24c04中的數據存在這里
//延時函數大約1ms
void delay_ms(int ms)
{
int i;
while(ms--)
{
for(i=0;i<100;i++);
}
}
//連續寫入兩個數據
void AT24C04_Write(uchar dat_1,uchar dat_2)
{
AT24C04_Start(); //起始信號
AT24C04_SendByte(0xa0); //發送設備地址+寫信號
AT24C04_SendByte(0x00); //發送存儲單元地址
AT24C04_SendByte(dat_1); //寫入數據1
AT24C04_SendByte(dat_2); //寫入數據2
AT24C04_Stop(); //停止信號
}
//連續讀出兩個數據
void AT24C04_ReadPage()
{
uchar i;
AT24C04_Start(); //起始信號
AT24C04_SendByte(0xa0); //發送設備地址+寫信號
AT24C04_SendByte(0x00); //發送存儲單元地址
AT24C04_Start(); //起始信號
AT24C04_SendByte(0xa1); //發送設備地址+讀信號
for (i=0; i<2; i++)
{
BUF[i] = AT24C04_RecvByte();
if (i == 1)
{
AT24C04_SendACK(1); //最后一個數據需要會NAK
}
else
{
AT24C04_SendACK(0); //回應ACK
}
}
AT24C04_Stop(); //停止信號
}
//LCD顯示數字處理函數
void show_num(uchar num,uchar flag)
{
uchar temp[3],i;
float re_val;//電壓實際值
float read_low,read_h; //將從AT24C04中讀取電壓范圍數據轉化成對應小數形式
re_val = num/255.0*5.0; //實際電壓計算公式
num = re_val*10; //保留一位小數
AT24C04_ReadPage();//從AT24C04中讀取電壓范圍數據,存儲在BUF數組中
// BUF[0]表示下限,BUF[1]表示上限
//存入AT24C04中的數據是uchar unsigned型,在這里轉化成float型
read_low =BUF[0]/10.0;
read_h= BUF[1]/10.0;
if(re_val >= read_low && re_val <= read_h) //如果電壓在范圍內
{
temp[0] = num/10 + '0';
temp[1] = '.';
temp[2] = num%10 + '0';
}else if(re_val < read_low ) //如果低于設定值
{
temp[0] = 'L';
temp[1] = 'O';
temp[2] = 'W';
}else if(re_val > read_h ) //如果高于設定值
{
temp[0] = 'H';
temp[1] = 'I';
temp[2] = 'G';
}
for(i=0;i<3;i++)//用液晶顯示結果
{
LCD_Manifest(flag,3+i,temp[i]);
}
//顯示電壓范圍的上限
num = read_h * 10;
temp[0] = num/10 + '0';
temp[1] = '.';
temp[2] = num%10 + '0';
for(i=0;i<3;i++)//用液晶顯示結果
{
LCD_Manifest(1,12+i,temp[i]);
}
//顯示電壓范圍的下限
num = read_low * 10;
temp[0] = num/10 + '0';
temp[1] = '.';
temp[2] = num%10 + '0';
for(i=0;i<3;i++)//用液晶顯示結果
{
LCD_Manifest(2,12+i,temp[i]);
}
}
//主函數
void main()
{
uchar val;//電壓值
LCD_Init(); //液晶初始化
IIC_Init();//I2C總線初始化
w_buf[0] =v_low*10;
w_buf[1] =v_high*10;
AT24C04_Write(w_buf[0],w_buf[1]); //將數據寫入AT24C04
LCD_Manifest(1,0,'V');//在lcd1602中顯示字符
LCD_Manifest(1,1,'1');
LCD_Manifest(1,2,':');
LCD_Manifest(2,0,'V');
LCD_Manifest(2,1,'2');
LCD_Manifest(2,2,':');
LCD_Manifest(1,10,'H');
LCD_Manifest(1,11,':');
LCD_Manifest(2,10,'L');
LCD_Manifest(2,11,':');
while(1)
{
//按鍵檢測程序
if(key_1 == 0)//調節范圍的下限
{
delay_ms(100); //延時消除抖動
if(key_1 == 0)
{
//v_low = v_low - 0.1;
// if(v_low < 0.0)
//v_low = v_high;
w_buf[0] =v_low*10;
w_buf[1] =v_high*10;
AT24C04_Write(w_buf[0],w_buf[1]); //將數據寫入AT24C04
}
}
if(key_2 == 0)//調節范圍的上限
{
delay_ms(100); //延時消除抖動
if(key_2 == 0)
{
v_high = v_high + 0.1;
if(v_high > 5.0)
v_high = v_low;
w_buf[0] =v_low*10;
w_buf[1] =v_high*10;
AT24C04_Write(w_buf[0],w_buf[1]); //將數據寫入AT24C04
}
}
ADC_Send_Byte(0x90,0x41);//通道一ADC轉換
val=ADC_Receive_Byte(0x90);//讀取AD轉換的值
show_num(val,1);
ADC_Send_Byte(0x90,0x42);//通道二ADC轉換
val=ADC_Receive_Byte(0x90);//讀取AD轉換的值
show_num(val,2);
}
}
#include<iic.h>
void IIC_Init()//總線初始化
{
SCL=1;
IIC_DELAY();
SDA=1;
IIC_DELAY();
}
void IIC_Start() //啟動信號
{
SDA=1;
IIC_DELAY();
SCL=1;
IIC_DELAY();
SDA=0;
IIC_DELAY();
}
void IIC_Stop()//停止信號
{
SDA=0;
IIC_DELAY();
SCL=1;
IIC_DELAY();
SDA=1;
IIC_DELAY();
}
void IIC_Ack() //應答信號
{
unsigned char i;
SCL=1;
IIC_DELAY();;
while((SDA==1)&&(i<255))i++;
SCL=0;
IIC_DELAY();
}
void IIC_Write_Byte(u8 date)//寫一個字節
{
u8 i,temp;
temp=date;
for(i=0;i<8;i++)
{
temp=temp<<1;
SCL=0;
IIC_DELAY();
SDA=CY;//最高位將移入PSW寄存器的CY位中,然后將CY賦給SDA
IIC_DELAY();
SCL=1;
IIC_DELAY();
}
SCL=0;
IIC_DELAY();
SDA=1;
IIC_DELAY();
}
u8 IIC_Read_Byte()//讀一個字節
{
u8 i,temp;
for(i=0;i<8;i++)
{
SCL=0;
IIC_DELAY();
temp=(temp<<1)|SDA;
IIC_DELAY();
SCL=1;
IIC_DELAY();
}
SCL=0;
IIC_DELAY();
SDA=1;
IIC_DELAY();
return temp;
}
#include <reg51.h>
#include"lcd1602.h"
void delay(u8 z)//延時函數
{
unsigned char x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void LCD_Write_Cmd(u8 com )//液晶寫命令
{
LCD_RS=0;//選擇寫命令模式
LCD_dat=com;//將要寫的命令字送到數據總線上
delay(1);
LCD_E=1;//使能端給一高脈沖,高脈沖有效
delay(1);
LCD_E=0;
}
void LCD_Write_Data(u8 date)//數據寫命令
{
LCD_RS=1;//選擇寫數據模式
LCD_dat=date;
delay(1);
LCD_E=1;//使能端給一高脈沖,高脈沖有效
delay(1);
LCD_E=0;
}
void LCD_Init()//液晶初始化
{
LCD_WR=0;
LCD_Write_Cmd(0x38);//設置16*2顯示,5*7點陣,8位數據接口
LCD_Write_Cmd(0x0c);//設置開顯示,不顯示光標
LCD_Write_Cmd(0x06);//寫一個字符后地址指針自動加1
LCD_Write_Cmd(0x80);//數據指針定位到第一行第一個字處
}
// 使得寫命令和寫數據通過一個函數完成
void LCD_Manifest(u8 row,u8 add,u8 date)
{
if(row==1) LCD_Write_Cmd(0x80+add);
if(row==2)LCD_Write_Cmd(0xc0+add);
LCD_Write_Data(date);
}
#include"iic.h"
#include"pcf8591.h"
//ADC發送字節[命令]數據函數
void ADC_Send_Byte(u8 addr,u8 com)
{
IIC_Start();//啟動總線
IIC_Write_Byte(addr);//發送器件地址
IIC_Ack();
IIC_Write_Byte(com);//發送數據
IIC_Ack();
IIC_Stop();//結束總線
}
//ADC讀字節數據函數
u8 ADC_Receive_Byte(u8 addr)
{
u8 c;
IIC_Start();//啟動總線
IIC_Write_Byte(addr+1); //發送器件地址,如果是讀則最低位為1即0x91
IIC_Ack();
c=IIC_Read_Byte(); //讀取數據
IIC_Ack(); //發送非就答位
IIC_Stop();//結束總線
return(c);
}
#include"AT24C04.h"
void Delay5us()
{
BYTE n = 4;
while (n--)
{
_nop_();
_nop_();
}
}
void Delay5ms()
{
WORD n = 2500;
while (n--)
{
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
}
void AT24C04_Start()
{
AT_SDA = 1; //拉高數據線
AT_SCL = 1; //拉高時鐘線
Delay5us(); //延時
AT_SDA = 0; //產生下降沿
Delay5us(); //延時
AT_SCL = 0; //拉低時鐘線
}
void AT24C04_Stop()
{
AT_SDA = 0; //拉低數據線
AT_SCL = 1; //拉高時鐘線
Delay5us(); //延時
AT_SDA = 1; //產生上升沿
Delay5us(); //延時
}
void AT24C04_SendACK(bit ack)
{
AT_SDA = ack; //寫應答信號
AT_SCL = 1; //拉高時鐘線
Delay5us(); //延時
AT_SCL = 0; //拉低時鐘線
Delay5us(); //延時
}
bit AT24C04_RecvACK()
{
AT_SCL = 1; //拉高時鐘線
Delay5us(); //延時
CY = AT_SDA; //讀應答信號
AT_SCL = 0; //拉低時鐘線
Delay5us(); //延時
return CY;
}
void AT24C04_SendByte(BYTE dat)
{
BYTE i;
for (i=0; i<8; i++) //8位計數器
{
dat <<= 1; //移出數據的最高位
AT_SDA = CY; //送數據口
AT_SCL = 1; //拉高時鐘線
Delay5us(); //延時
AT_SCL = 0; //拉低時鐘線
Delay5us(); //延時
}
AT24C04_RecvACK();
}
BYTE AT24C04_RecvByte()
{
BYTE i;
BYTE dat = 0;
AT_SDA = 1; //使能內部上拉,準備讀取數據
for (i=0; i<8; i++) //8位計數器
{
dat <<= 1;
AT_SCL = 1; //拉高時鐘線
Delay5us(); //延時
dat |= AT_SDA; //讀數據
AT_SCL = 0; //拉低時鐘線
Delay5us(); //延時
}
return dat;
}
|