![]() |
#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; } } 這是所用程序 |