|
設計的是一種以酒精濃度傳感器、AT89C51單片機和A/D轉換器為主的,檢測駕駛員呼出氣體的酒精濃度的,而且還帶有聲光報警功能的酒精濃度檢測儀。這種檢測儀不僅可以檢測出空氣環境中酒精濃度值,還可以由不同的環境來設定不同的閾值,當空氣中酒精濃度超過設定的閾值時進行聲光報警。系統主要為兩部分:硬件設計部分和軟件設計部分。硬件設計部分是利用MQ3氣敏傳感器先測量空氣中的酒精濃度,然后轉換為電壓信號,再通過A/D轉換器轉換成數字信號后再傳給單片機系統,最后由單片機系統和相應外圍電路進行信號處理,并由LCD顯示酒精濃度值并且對超過的閾值進行報警。軟件設計部分的程序采用的是模塊化設計思想,各個子程序的功能相對獨立,便于調試和修改。電路可分為單片機小系統電路、A/D轉換電路、聲光報警電路、LCD顯示電路,按鍵電路。
在硬件設計的時候,考慮到傳感器可以把酒精濃度這種非電量轉換為電量,可以輸出0-5V的電壓值并且電壓值比較穩定,外部干擾較小等特點。所以,可以直接把傳感器輸出的電壓值經過ADC0832采集數據送入單片機內進行處理。酒精濃度檢測儀的硬件電路設計主要包括:傳感器測量電路、AT89C51單片機系統、A/D轉換電路、LCD顯示電路、鍵盤電路、聲光報警電路。
單片機源程序如下:
- #include<reg51.H>
- #include<intrins.h>
- #include<stdio.h>
- #define uintunsigned int
- #define ucharunsigned char
- /**********************定義全局變量***************/
- //unsigned chardat=0x00 ; //AD值
- unsigned charcount = 0x00; //定時器計數
- unsigned charchannel; //通道變量
- //ADC0832的引腳
- sbit ADCS=P1^2; //ADC0832 chip seclect
- sbit ADDI=P1^1; //ADC0832 k in
- sbit ADDO=P1^1; //ADC0832 k out
- sbit ADCLK=P1^0; //ADC0832 clock signal
- unsigned chardispbuf[3];
- uint temp;
- uint alc;//酒精濃度
- uchar dat; //獲取ADC轉換回來的值
- uchar*aa="M=T.TTmg/L";
- uchar*cc="alarm";
- uchar *dd="";
- uint sheding=60;
- ucharbb[16]={'A','l','c','o','h','o','l','=',' ','.',' ',' ','m','g','/','L'};
- sbit RS =P2^0; //定義端口
- sbit RW = P2^1;
- sbit EN = P2^2;
- sbit beep=P3^7;
- sbit k1=P1^3;//+鍵
- sbit k2=P1^4;//-鍵
- #define RS_CLRRS=0
- #define RS_SETRS=1
- #define RW_CLRRW=0
- #define RW_SETRW=1
- #define EN_CLREN=0
- #define EN_SETEN=1
- voidDelayUs2x(unsigned char t);
- voidDelayMs(unsigned char t);
- voidLCD_Write_String(unsigned char x,unsigned char y,unsigned char *s);
- voidLCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data);
- void init();
- voidwrite_com(unsigned char com);
- voidwrite_data(unsigned char date);
- voidDelayUs2x(unsigned char t)
- {
- while(--t);
- }
- voidDelayMs(unsigned char t)
- {
- while(t--)
- {
- //大致延時1mS
- DelayUs2x(245);
- DelayUs2x(245);
- }
- }
- /*********************************lcd1602各子函數**************************************/
- voidwrite_com(unsigned char com) //寫命令
- {
- RS_CLR;
- RW_CLR;
- P0=com;
- DelayMs(5);
- EN_SET;
- DelayMs(5);
- EN_CLR;
- }
- voidwrite_data(unsigned char date) //寫一個字符
- {
- RS_SET;
- RW_CLR;
- P0=date;
- DelayMs(5);
- EN_SET;
- DelayMs(5);
- EN_CLR;
- }
- void initlcd() //初始化
- {
- write_com(0x38);
- write_com(0x0c);
- write_com(0x06);
- write_com(0x01);
- }
- /*------------------------------------------------
- 寫入字符串函數
- ------------------------------------------------*/
- void LCD_Write_String(unsigned char x,unsignedchar y,unsigned char *s)
- {
- if (y == 0)
- {
- write_com(0x80 + x);
- }
- else
- {
- write_com(0xC0+ x);
- }
- while (*s)
- {
- write_data( *s);
- s ++;
- }
- }
- /*------------------------------------------------
- 寫入字符函數
- ------------------------------------------------*/
- void LCD_Write_Char(unsigned char x,unsignedchar y,unsigned char Data)
- {
- if (y == 0)
- {
- write_com(0x80+ x);
- }
- else
- {
- write_com(0xC0+ x);
- }
- write_data(Data);
- }
- /****************************************************************************
- 函數功能:AD轉換子程序
- 入口參數:CH
- 出口參數:dat
- ****************************************************************************/
- //采集并返回
- unsigned charAdc0832(unsigned char channel) //AD轉換,返回結果
- {
- uchar i=0;
- uchar j;
- uchar dat=0;
- uchar ndat=0;
- if(channel==0)channel=2;
- if(channel==1)channel=3;
- ADDI=1;
- _nop_();
- _nop_();
- ADCS=0;//拉低CS端
- _nop_();
- _nop_();
- ADCLK=1;//拉高CLK端
- _nop_();
- _nop_();
- ADCLK=0;//拉低CLK端,形成下降沿1
- _nop_();
- _nop_();
- ADCLK=1;//拉高CLK端
- ADDI=channel&0x1;
- _nop_();
- _nop_();
- ADCLK=0;//拉低CLK端,形成下降沿2
- _nop_();
- _nop_();
- ADCLK=1;//拉高CLK端
- ADDI=(channel>>1)&0x1;
- _nop_();
- _nop_();
- ADCLK=0;//拉低CLK端,形成下降沿3
- ADDI=1;//控制命令結束
- _nop_();
- _nop_();
- dat=0;
- for(i=0;i<8;i++)
- {
- dat|=ADDO;//收數據
- ADCLK=1;
- _nop_();
- _nop_();
- ADCLK=0;//形成一次時鐘脈沖
- _nop_();
- _nop_();
- dat<<=1;
- if(i==7)dat|=ADDO;
- }
- for(i=0;i<8;i++)
- {
- j=0;
- j=j|ADDO;//收數據
- ADCLK=1;
- _nop_();
- _nop_();
- ADCLK=0;//形成一次時鐘脈沖
- _nop_();
- _nop_();
- j=j<<7;
- ndat=ndat|j;
- if(i<7)ndat>>=1;
- }
- ADCS=1;//拉低CS端
- ADCLK=0;//拉低CLK端
- ADDO=1;//拉高數據端,回到初始狀態
- dat<<=8;
- dat|=ndat;
- return(dat);//returnad k
- }
- /****************************************************************************
- 函數功能:定時器中斷延時程序 這一段的作用時隔一段時間抽樣一次 否側顯示的最后一位會不穩定
- 入口參數:
- 出口參數:
- ****************************************************************************/
- voidtimer0(void) interrupt 1
- {
- TMOD = 0x01;
- TH0 = 0x00;
- TL0 = 0x00;
- IE = 0x82;
- TR0 = 01;
- count++;
- if (count == 0x0A)
- {
- count = 0x00;
- dat= Adc0832(channel);
- }
- }
- /*voidformat_data(uint dat)
- {
- uint change_dat=dat;
- uchar ptr[3];
- change_dat=(change_dat<<8)+(change_dat<<7)+(change_dat<<6)+(change_dat<<5)+(change_dat<<4)+(change_dat<<2);//乘500
- change_dat=change_dat>>8;//除以256
- ptr[0]=change_dat/100; //得到個位數字
- ptr[1]=(change_dat-(100*ptr[0]))/10; //得到十分位數字
- ptr[2]=change_dat-(100*ptr[0])-(10*ptr[1]);//得到百分位數字
- }*/
- void keyscan()
- {
-
- if(!k1)
- {
- DelayMs(5);
- if(!k1)
- {
- while(!k1);
- sheding+=5;
- LCD_Write_Char(2,1,sheding/100+'0');
- LCD_Write_Char(4,1,sheding%100/10+'0');
- LCD_Write_Char(5,1,sheding%10+'0');
- }
- }
- if(!k2)
- {
- DelayMs(5);
- if(!k2)
- {
- while(!k2);
- sheding-=5;
- LCD_Write_Char(2,1,sheding/100+'0');
- LCD_Write_Char(4,1,sheding%100/10+'0');
- LCD_Write_Char(5,1,sheding%10+'0');
- }
- }
- }
- /****************************************
- 函數功能:主程序
- 入口參數:
- 出口參數:
- ****************************************/
- void main(void)
- {
- uchar i;
- P2=0xff; //端口初始化
- P0=0xff;
- P3=0xff;
- channel=0x00; //channel=0
- TMOD = 0x01;
- TH0 = 0x00;
- TL0 = 0x00;
- IE = 0x82;
- TR0 = 01;
- initlcd();
- LCD_Write_String(0,0,bb);
- LCD_Write_String(0,1,aa);
- //LCD_Write_String(11,1,cc);
- LCD_Write_Char(2,1,sheding/100+'0');
- LCD_Write_Char(4,1,sheding%100/10+'0');
- LCD_Write_Char(5,1,sheding%10+'0');
- while(1)
- {
- temp=dat*1.0/255*500; //電壓值轉換,5V做為參考電壓,分成256份。
-
- if(temp<187)
- {
- alc=100*(temp-8)/895;
- }
- else
- {
- alc=100*(temp-133)/272;
- }
- dispbuf[0]=alc%10+'0'; //個位
- dispbuf[1]=alc/10%10+'0'; //十位
- dispbuf[2]=alc/100%10+'0'; //百位
-
- //dispbuf[0]=temp%10+'0'; //個位
- //dispbuf[1]=temp/10%10+'0'; //十位
- //dispbuf[2]=temp/100%10+'0'; //百位
-
- LCD_Write_Char(8,0,dispbuf[2]);
- LCD_Write_Char(10,0,dispbuf[1]);
- LCD_Write_Char(11,0,dispbuf[0]);
- keyscan();
- if(alc>sheding)
- {
- //beep=0;
- for(i=0;i<10;i--)
- {
- beep=0;
- DelayMs(1);
- beep=1;
- }
-
-
- LCD_Write_String(11,1,cc);
- }
- else
- {
- LCD_Write_String(11,1,dd);
- }
- }
- }
復制代碼
|
-
原理圖
評分
-
查看全部評分
|