|
這是一個(gè)用51單片機(jī)做的酒精濃度檢測(cè)儀
原理圖:
0.png (113.8 KB, 下載次數(shù): 161)
下載附件
2017-5-10 15:32 上傳
pcb圖:
0.png (123.17 KB, 下載次數(shù): 121)
下載附件
2017-5-10 15:30 上傳
酒精濃度檢測(cè)仿真:
0.png (28.95 KB, 下載次數(shù): 123)
下載附件
2017-5-10 15:33 上傳
0.png (70.73 KB, 下載次數(shù): 109)
下載附件
2017-5-10 15:30 上傳
DXP格式用 Altium designer Summer 軟件打開(kāi)
protel99格式用 protel99SE 軟件打開(kāi)
PDF格式用 PDF 軟件打開(kāi)
Word格式用 Word 或用WPS 軟件打開(kāi)
4種格式的原理圖都內(nèi)容是一樣的 只是打開(kāi)方式不同
請(qǐng)看原理圖焊接,不要看仿真圖焊接。
wrod格式里面的原理圖是復(fù)制出來(lái)的,有一點(diǎn)點(diǎn)變行變形,麻煩大家注意一下,盡量看其他三種格式的圖焊接,
如果論文里面的原理圖和原理圖文件夾內(nèi)的圖不一樣的話(huà),請(qǐng)大家以原理圖文件夾內(nèi)的為準(zhǔn),原理圖文件夾的圖是和實(shí)物配套的,可以自己截圖或復(fù)制,然后粘貼到論文里面去。
單片機(jī)源程序:
- #include <reg52.h> //調(diào)用單片機(jī)頭文件
- #define uchar unsigned char //無(wú)符號(hào)字符型 宏定義 變量范圍0~255
- #define uint unsigned int //無(wú)符號(hào)整型 宏定義 變量范圍0~65535
- uchar a_a;
- #include <intrins.h>
- //數(shù)碼管段選定義 0 1 2 3 4 5 6 7 8 9
- uchar code smg_du[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x04,0x14,
- 0x0c,0xa4,0x27,0xc4,0x26,0x2e,0xff}; //斷碼
- //數(shù)碼管位選定義
- uchar code smg_we[]={0x7f,0xbf,0xdf,0xef};
- uchar dis_smg[8] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8};
- uchar smg_i = 4; //顯示數(shù)碼管的個(gè)位數(shù)
- sbit CS=P3^2; //CS定義為P1口的第4位腳,連接ADC0832CS腳
- sbit SCL=P3^3; //SCL定義為P1口的第3位腳,連接ADC0832SCL腳
- sbit DO=P3^4; //DO定義為P1口的第4位腳,連接ADC0832DO腳
- sbit beep = P3^6; //蜂鳴器IO口定義
- long dengji,s_dengji = 50; //酒精等級(jí)
- bit flag_300ms = 1;
- uchar menu_1; //菜單設(shè)計(jì)的變量
- #define RdCommand 0x01 //定義ISP的操作命令
- #define PrgCommand 0x02
- #define EraseCommand 0x03
- #define Error 1
- #define Ok 0
- #define WaitTime 0x01 //定義CPU的等待時(shí)間
- sfr ISP_DATA=0xe2; //寄存器申明
- sfr ISP_ADDRH=0xe3;
- sfr ISP_ADDRL=0xe4;
- sfr ISP_CMD=0xe7;
- sfr ISP_TRIG=0xe6;
- sfr ISP_CONTR=0xe5;
- /* ================ 打開(kāi) ISP,IAP 功能 ================= */
- void ISP_IAP_enable(void)
- {
- EA = 0; /* 關(guān)中斷 */
- ISP_CONTR = ISP_CONTR & 0x18; /* 0001,1000 */
- ISP_CONTR = ISP_CONTR | WaitTime; /* 寫(xiě)入硬件延時(shí) */
- ISP_CONTR = ISP_CONTR | 0x80; /* ISPEN=1 */
- }
- /* =============== 關(guān)閉 ISP,IAP 功能 ================== */
- void ISP_IAP_disable(void)
- {
- ISP_CONTR = ISP_CONTR & 0x7f; /* ISPEN = 0 */
- ISP_TRIG = 0x00;
- EA = 1; /* 開(kāi)中斷 */
- }
- /* ================ 公用的觸發(fā)代碼 ==================== */
- void ISPgoon(void)
- {
- ISP_IAP_enable(); /* 打開(kāi) ISP,IAP 功能 */
- ISP_TRIG = 0x46; /* 觸發(fā)ISP_IAP命令字節(jié)1 */
- ISP_TRIG = 0xb9; /* 觸發(fā)ISP_IAP命令字節(jié)2 */
- _nop_();
- }
- /* ==================== 字節(jié)讀 ======================== */
- unsigned char byte_read(unsigned int byte_addr)
- {
- EA = 0;
- ISP_ADDRH = (unsigned char)(byte_addr >> 8);/* 地址賦值 */
- ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);
- ISP_CMD = ISP_CMD & 0xf8; /* 清除低3位 */
- ISP_CMD = ISP_CMD | RdCommand; /* 寫(xiě)入讀命令 */
- ISPgoon(); /* 觸發(fā)執(zhí)行 */
- ISP_IAP_disable(); /* 關(guān)閉ISP,IAP功能 */
- EA = 1;
- return (ISP_DATA); /* 返回讀到的數(shù)據(jù) */
- }
- /* ================== 扇區(qū)擦除 ======================== */
- void SectorErase(unsigned int sector_addr)
- {
- unsigned int iSectorAddr;
- iSectorAddr = (sector_addr & 0xfe00); /* 取扇區(qū)地址 */
- ISP_ADDRH = (unsigned char)(iSectorAddr >> 8);
- ISP_ADDRL = 0x00;
- ISP_CMD = ISP_CMD & 0xf8; /* 清空低3位 */
- ISP_CMD = ISP_CMD | EraseCommand; /* 擦除命令3 */
- ISPgoon(); /* 觸發(fā)執(zhí)行 */
- ISP_IAP_disable(); /* 關(guān)閉ISP,IAP功能 */
- }
- /* ==================== 字節(jié)寫(xiě) ======================== */
- void byte_write(unsigned int byte_addr, unsigned char original_data)
- {
- EA = 0;
- SectorErase(byte_addr);
- ISP_ADDRH = (unsigned char)(byte_addr >> 8); /* 取地址 */
- ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);
- ISP_CMD = ISP_CMD | PrgCommand; /* 寫(xiě)命令2 */
- ISP_DATA = original_data; /* 寫(xiě)入數(shù)據(jù)準(zhǔn)備 */
- ISPgoon(); /* 觸發(fā)執(zhí)行 */
- ISP_IAP_disable(); /* 關(guān)閉IAP功能 */
- EA =1;
- }
- /***********************1ms延時(shí)函數(shù)*****************************/
- void delay_1ms(uint q)
- {
- uint i,j;
- for(i=0;i<q;i++)
- for(j=0;j<120;j++);
- }
- /******************把數(shù)據(jù)從單片機(jī)內(nèi)部eeprom中讀出來(lái)*****************/
- void read_eeprom() //讀出保存數(shù)據(jù)
- {
- s_dengji = byte_read(0x2001);
- s_dengji <<= 8;
- s_dengji |= byte_read(0x2000);
- a_a = byte_read(0x2058);
- }
- /******************把數(shù)據(jù)保存到單片機(jī)內(nèi)部eeprom中******************/
- void write_eeprom() //保存數(shù)據(jù)
- {
- SectorErase(0x2000);
- byte_write(0x2000, s_dengji % 256);
- byte_write(0x2001, s_dengji / 256);
- byte_write(0x2058,a_a);
- }
- /**************開(kāi)機(jī)自檢eeprom初始化*****************/
- void init_eeprom() ////開(kāi)始初始化保存的數(shù)據(jù)
- {
- read_eeprom(); //讀出保存數(shù)據(jù)
- if(a_a != 33)
- {
- a_a = 33;
- s_dengji = 80;
- write_eeprom(); //保存數(shù)據(jù)
- }
- }
- /***********讀數(shù)模轉(zhuǎn)換數(shù)據(jù)********************************************************/
- //請(qǐng)先了解ADC0832模數(shù)轉(zhuǎn)換的串行協(xié)議,再來(lái)讀本函數(shù),主要是對(duì)應(yīng)時(shí)序圖來(lái)理解,本函數(shù)是模擬0832的串行協(xié)議進(jìn)行的
- // 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; //開(kāi)始
- SCL=0; //第一個(gè)上升沿
- SCL=1;
- DO=SGL;
- SCL=1; //第二個(gè)上升沿
- SCL=0;
- DO=ODD;
- SCL=1; //第三個(gè)上升沿
- SCL=0; //第三個(gè)下降沿
- DO=1;
- for(i=0;i<8;i++)
- {
- SCL=0;
- SCL=1; //開(kāi)始從第四個(gè)下降沿接收數(shù)據(jù)
- value<<=1;
- if(DO)
- value++;
- }
- for(i=0;i<8;i++)
- { //接收校驗(yàn)數(shù)據(jù)
- value1>>=1;
- if(DO)
- value1+=0x80;
- SCL=0;
- SCL=1;
- }
- CS=1;
- SCL=1;
- if(value==value1) //與校驗(yàn)數(shù)據(jù)比較,正確就返回?cái)?shù)據(jù),否則返回0
- return value;
- return 0;
- }
- /********************獨(dú)立按鍵程序*****************/
- uchar key_can; //按鍵值
- void key() //獨(dú)立按鍵程序
- {
- static uchar key_new;
- key_can = 20; //按鍵值還原
- P2 |= 0x0f; //把按鍵的IO口輸出為高電平
- if((P2 & 0x0f) != 0x0f) //按鍵按下
- {
- delay_1ms(1); //按鍵消抖動(dòng)
- if(((P2 & 0x0f) != 0x0f) && (key_new == 1))
- { //確認(rèn)是按鍵按下
- key_new = 0;
- switch(P2 & 0x0f)
- {
- case 0x0e: key_can = 3; break; //得到k1鍵值
- case 0x0d: key_can = 2; break; //得到k2鍵值
- case 0x0b: key_can = 1; break; //得到k3鍵值
- // case 0x07: key_can = 1; break; //得到k4鍵值
- }
- }
- }
- else
- key_new = 1;
- }
- /****************按鍵處理數(shù)碼管顯示函數(shù)***************/
- void key_with()
- {
- if(key_can == 1) //設(shè)置鍵
- {
- menu_1 ++;
- if(menu_1 >= 2)
- {
- menu_1 = 0;
- }
- }
- if(menu_1 == 1) //設(shè)置酒精報(bào)警值
- {
- smg_i = 4; //顯示4位數(shù)碼管
- if(key_can == 2)
- {
- s_dengji ++ ; //加1
- if(s_dengji > 500)
- s_dengji = 500;
- }
- if(key_can == 3)
- {
- s_dengji -- ; //減1
- if(s_dengji <= 1)
- s_dengji = 1;
- }
- dis_smg[0] = smg_du[s_dengji % 10]; //取個(gè)位顯示
- dis_smg[1] = smg_du[s_dengji / 10 % 10] ; //取十位顯示
- dis_smg[2] = smg_du[s_dengji / 100 % 10] ; //
- dis_smg[3] = 0x0c; //a
- write_eeprom(); //保存數(shù)據(jù)
- }
- }
- /***********************數(shù)碼顯示函數(shù)*****************************/
- void display()
- {
- static uchar i;
- P1 = 0xff; //消隱
- P2 = smg_we[i]; //位選
- P1 = dis_smg[i]; //段選
- i ++;
- if(i >= smg_i)
- i = 0;
- }
- /*************定時(shí)器0初始化程序***************/
- void time_init()
- {
- EA = 1; //開(kāi)總中斷
- TMOD = 0X01; //定時(shí)器0、定時(shí)器1工作方式1
- ET0 = 1; //開(kāi)定時(shí)器0中斷
- TR0 = 1; //允許定時(shí)器0定時(shí)
- }
- /****************報(bào)警函數(shù)***************/
- void clock_h_l()
- {
- static uchar value;
- if((dengji >= s_dengji)) //報(bào)警
- {
- value ++;
- if(value >= 2)
- {
- value = 10;
- beep = ~beep; //蜂鳴器報(bào)警
- }
- }else
- {
- if((dengji < s_dengji)) //取消報(bào)警
- {
- value = 0;
- beep = 1;
- }
- }
- }
- /****************主函數(shù)***************/
- void main()
- {
- beep = 0; //開(kāi)機(jī)叫一聲
- delay_1ms(150);
- P0 = P1 = P2 = P3 = 0xff; //單片機(jī)IO口初始化為1
- time_init(); //初始化定時(shí)器
- init_eeprom(); //開(kāi)始初始化保存的數(shù)據(jù)
- while(1)
- {
- key(); //獨(dú)立按鍵程序
- if(key_can < 10)
- {
- key_with(); //按鍵按下要執(zhí)行的程序
- }
- if(flag_300ms == 1)
- {
- flag_300ms = 0;
- clock_h_l();
- dengji = ad0832read(1,0);
- dengji = dengji * 450 / 255.0;
- dengji = dengji - 100; //首先減去零點(diǎn)漂移,一般是100mV
- if(dengji < 0)
- dengji = 0;
- dengji = dengji * 2; //將mV轉(zhuǎn)變成mg/L,系數(shù)需要校準(zhǔn)
- //電壓每升高0.1V,實(shí)際被測(cè)氣體的濃度增加20ppm
- //1ppm=1mg/kg=1mg/L=1×10-6 常用來(lái)表示氣體濃度,或者溶液濃度。
- if(menu_1 == 0)
- {
- if(dengji >= 1000)
- smg_i = 4;
- else
- smg_i = 3;
- dis_smg[3]=smg_du[dengji/1000%10]; //千位
- dis_smg[2]=smg_du[dengji/100%10]; //百位
- dis_smg[1]=smg_du[dengji/10%10]; //十位
- dis_smg[0]=smg_du[dengji%10]; //個(gè)位 ADC0832為8位ADC,數(shù)值為0~255,我們將其分開(kāi)放入l_tmpdate數(shù)組中顯示
- }
- }
- }
- }
- /*************定時(shí)器0中斷服務(wù)程序***************/
- void time0_int() interrupt 1
- {
- static uchar value;
- …………限于本文篇幅 余下代碼請(qǐng)從51黑下載附件…………
復(fù)制代碼
全部資料下載:
單片機(jī)酒精檢測(cè)儀.rar
(244.6 KB, 下載次數(shù): 324)
2017-5-10 09:22 上傳
點(diǎn)擊文件名下載附件
|
評(píng)分
-
查看全部評(píng)分
|