|
设计的是一种以酒精浓度传感器、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);
- }
- }
- }
复制代码
|
评分
-
查看全部评分
|