#include <reg52.h> //调用单片机头文件 #define uchar unsigned char //无符号字符型 宏定义 变量范围0~255 #define uint unsigned int //无符号整型 宏定义 变量范围0~65535 #include <intrins.h> //#include "lcd1602.h" sbit CS=P2^4; //CS定义为P2口的第4位脚,连接ADC0832CS脚 sbit SCL=P2^3; //SCL定义为P2口的第3位脚,连接ADC0832SCL脚 sbit DO=P2^2; //DO定义为P2口的第4位脚,连接ADC0832DO脚 sbit beep = P3^2; //蜂鸣器IO口定义 long dengji,s_dengji = 50; //酒精等级 bit flag_300ms ; uchar key_can; //按键值的变量 uchar menu_1; //菜单设计的变量 uchar flag_clock; #include "eeprom52.h" #include "lcd1602.h" /***********************1ms延时函数*****************************/ void delay_1ms(uint q) { uint i,j; for(i=0;i<q;i++) for(j=0;j<120;j++); } /******************把数据保存到单片机内部eeprom中******************/ void write_eeprom() { SectorErase(0x2000); // byte_write(0x2000, s_dengji); byte_write(0x2001, s_dengji); byte_write(0x2060, a_a); } /******************把数据从单片机内部eeprom中读出来*****************/ void read_eeprom() { // s_dengji = byte_read(0x2000); s_dengji = byte_read(0x2001); a_a = byte_read(0x2060); } /**************开机自检eeprom初始化*****************/ void init_eeprom() { read_eeprom(); //先读 if(a_a != 2) //新的单片机初始单片机内问eeprom { s_dengji = 80; a_a = 2; write_eeprom(); } } /***********读数模转换数据********************************************************/ //请先了解ADC0832模数转换的串行协议,再来读本函数,主要是对应时序图来理解,本函数是模拟0832的串行协议进行的 // 1 0 0 通道 // 1 1 1 通道 unsigned char ad0832read(bit SGL,bit ODD) { unsigned char i=0,value=0,value1=0; SCL=0; DO=1; CS=0; //开始 SCL=1; //第一个上升沿 SCL=0; DO=SGL; SCL=1; //第二个上升沿 SCL=0; DO=ODD; SCL=1; //第三个上升沿 SCL=0; //第三个下降沿 DO=1; for(i=0;i<8;i++) { SCL=1; SCL=0; //开始从第四个下降沿接收数据 value<<=1; if(DO) value++; } for(i=0;i<8;i++) { //接收校验数据 value1>>=1; if(DO) value1+=0x80; SCL=1; SCL=0; } CS=1; SCL=1; if(value==value1) //与校验数据比较,正确就返回数据,否则返回0 return value; return 0; } /*************定时器0初始化程序***************/ void time_init() { EA = 1; //开总中断 TMOD = 0X01; //定时器0、定时器1工作方式1 ET0 = 1; //开定时器0中断 TR0 = 1; //允许定时器0定时 } /****************按键处理显示函数***************/ void key_with() { if(key_can == 1) { s_dengji ++ ; //酒精浓度设置数加1 if(s_dengji > 999) s_dengji = 999; } if(key_can == 2) { s_dengji -= 1; //酒精浓度设置数减1 if(s_dengji <= 1) s_dengji = 1 ; } write_sfm2(2,9,s_dengji); //显示酒精等级 write_eeprom(); //保存数据 } /********************独立按键程序*****************/ uchar key_can; //按键值 void key() //独立按键程序 { static uchar key_new; key_can = 20; //按键值还原 P1 |= 0x0f; if((P1 & 0x0f) != 0x0f) //按键按下 { delay_1ms(1); //按键消抖动 if(((P1 & 0x0f) != 0x0f) && (key_new == 1)) { //确认是按键按下 key_new = 0; switch(P1 & 0x0f) { case 0x0b: key_can = 2; break; //得到k3键值 case 0x07: key_can = 1; break; //得到k4键值 } } } else key_new = 1; } /****************报警函数***************/ void clock_h_l() { static uchar value; if(dengji >= s_dengji ) //报警 { value ++; if(value >= 2) { value = 10; beep = ~beep; //蜂鸣器报警 } }else { if(dengji < s_dengji) //取消报警 { value = 0; beep = 1; } } } /***************主函数*****************/ void main() { beep = 0; //开机叫一声 delay_1ms(150); P0 = P1 = P2 = P3 = 0xff; //单片机IO口初始化为1 init_eeprom(); //读eeprom数据 time_init(); //初始化定时器 init_1602(); while(1) { key(); //独立按键程序 if(key_can < 10) { key_with(); //按键按下要执行的程序 } if(flag_300ms == 1) { flag_300ms = 0; clock_h_l(); //报警函数 dengji = ad0832read(1,0); dengji = dengji * 450 / 255.0; dengji = dengji - 130; //首先减去零点漂移,一般是1V if(dengji < 0) dengji = 0; dengji = dengji * 2; //将mV转变成mg/L,系数需要校准 //电压每升高0.1V,实际被测气体的浓度增加20ppm //1ppm=1mg/kg=1mg/L=1×10-6 常用来表示气体浓度,或者溶液浓度。 write_sfm2(1,9,dengji); //显示酒精浓度 } } } /*************定时器0中断服务程序***************/ void time0_int() interrupt 1 { static uchar value; TH0 = 0x3c; TL0 = 0xb0; // 50ms value ++; if(value % 6 == 0) { flag_300ms = 1; //300ms value = 0; } } 这是所用程序 |