文件共享,文件分享。
综合项目,花了很久时间精细研究得到的成果,可以完美运行。
酒精测试仪以STC12C5A60S2单片机作为主控芯片,采用高精度MQ-3乙醇气体传感器对空气中的乙醇浓度进行检测,主控芯片对检测信号进行A/D转换和处理(不需要外接A/D转换,芯片自带该功能,),最后通过LCD1602液晶显示屏显示出来。酒精浓度测试仪具有醉酒阈值设定功能,可以根用户需要设定修改醉酒阈值。当检测到的酒精浓度超过设定阀值时会发出声光警报。
硬件电路十分简单,方便学习。
代码原理图数据手册见附件。
单片机源程序如下:
- #include "STC12C5A60S2.h"
- #include "intrins.h"
- #define uchar unsigned char
- #define uint unsigned int
-
- sbit RS = P2^7;
- sbit RW = P2^6;
- sbit EN = P2^5;
- sbit k0 = P3^3;
- sbit k1 = P3^4;
- sbit tm = P2^0;
- sbit in = P1^1;
- sbit led0= P1^5;
- sbit led1= P1^3;
- uchar shi=2,fen,miao;
- uchar num=0,n=0;
- uchar da1=0,add=0;
- double Data,c;
- char ac,bc,dc;
- char a[5]="";
- char b[4]="2.00";
- void key();
- void jian_ce();
- /************************************
- 延时函数
- *************************************/
- //一个机械周期
- void DelayUs2x(uchar t)
- {
- while(--t);
- }
- //自定义延时,单位微秒us
- void DelayMs(uchar t)
- {
- while(t--)
- {
- DelayUs2x(245);
- DelayUs2x(245);
- }
- }
- /************************************
- 判忙函数
- *************************************/
- bit LCD_Check_Busy(void)
- {
- P0= 0xFF;
- RS=0;
- RW=1;
- EN=0;
- _nop_();
- EN=1;
- return (bit)(P0 & 0x80);
- }
- /************************************
- 写指令函数
- *************************************/
- void LCD_Write_Com(uchar com)
- {
- while(LCD_Check_Busy()); //忙则等待
- RS=0;
- RW=0;
- EN=1;
- P0= com;
- _nop_();
- EN=0;
- }
- /************************************
- 写数据函数
- *************************************/
- void LCD_Write_Data(uchar Data)
- {
- while(LCD_Check_Busy()); //忙则等待
- RS=1;
- RW=0;
- EN=1;
- P0= Data;
- _nop_();
- EN=0;
- }
- /************************************
- 清屏函数
- *************************************/
- void LCD_Clear(void)
- {
- LCD_Write_Com(0x01);
- DelayMs(5);
- }
- /************************************
- 写字符串函数
- *************************************/
- void LCD_Write_String(uchar x,uchar y,uchar *s)
- {
- if (y == 0)
- {
- LCD_Write_Com(0x80 + x); //表示第一行
- }
- else
- {
- LCD_Write_Com(0xC0 + x); //表示第二行
- }
- while (*s)
- {
- LCD_Write_Data( *s);
- s ++;
- }
- }
- /************************************
- LCD初始化函数
- *************************************/
- void LCD_Init(void)
- {
- LCD_Write_Com(0x38);
- DelayMs(5);
- LCD_Write_Com(0x38);
- DelayMs(5);
- LCD_Write_Com(0x38);
- DelayMs(5);
- LCD_Write_Com(0x38);
- LCD_Write_Com(0x08);
- LCD_Write_Com(0x01);
- LCD_Write_Com(0x06);
- DelayMs(5);
- LCD_Write_Com(0x0C);
- }
-
- /************************************
- ADC函数
- *************************************/
- void InitADC() //初始AD寄存器
- {
- P1ASF=0X00; //P1.0脚作为模拟量输入端
- ADC_RES=0X00; //清除高8位缓冲数据
- //ADC_CONTR为ADC控制寄存器
- ADC_CONTR=0xF0; //AD转换控制寄存器
- _nop_(); //低三位 000 为P1.0口作为A/D输入
- _nop_();
- _nop_(); //必须经过4个空操作延时后执行
- _nop_();
- ADC_CONTR=0xE8; //1110.1000 第三位置一
- }
- void timer0() interrupt 1 //定时器0
- {
- TH0=(65536-20000)/256;
- TL0=(65536-20000)%256;
- InitADC();
- }
- void adc_isr() interrupt 5 //ADC中断
- {
- da1=ADC_RES; //获取转换结果
- c=((double)da1/256)*5; //取八位计算基准电压
-
- a[0]=((int)c%10+0x30); //个位
- a[1]='.'; //小数点
- a[2]=((int)(c*10)%10+0x30); //十分位
- a[3]=((int)(c*100)%10+0x30); //百分位
- a[4]='\0';
- LCD_Write_String(8,0,a); //LCD显示测量值
- ADC_CONTR&=0xEF; //标志位清零
- num++;
- if(num==252)num=0;
- }
- /************************************
- LCD显示函数
- *************************************/
- void LCDXS()
- {
- LCD_Init();
- LCD_Clear();
- LCD_Write_String(0,0,"nong du:");
- LCD_Write_String(12,0,"mg/L");
- LCD_Write_String(0,1,"fen jie:");
- LCD_Write_String(8,1,b);
- LCD_Write_String(12,1,"mg/L");
- }
- /************************************
- 中断初始化函数
- *************************************/
- void Init_zd()
- {
- TH0=(65536-20000)/256;
- TL0=(65536-20000)%256;
- IE=0xA2; //打开EA(总中断)
- //EADC(ADC中断允许位)
- //ET0(定时器0中断允许位)
- TR0=1;
- }
- /************************************
- 按键控制
- *************************************/
- void key()
- {
- if(!k0)//按键选位
- {
- DelayMs(30);
- if(!k0)
- {add++;
- while(!k0);
- switch (add)
- {
- case 1: EA=0;n=1;DelayMs(5);
- LCD_Write_Com(0xc0+8);
- LCD_Write_Com(0x0f);
- break;
-
- case 2: LCD_Write_Com(0xc0+10);
- break;
-
- case 3: LCD_Write_Com(0xc0+11);
- break;
-
- case 4: LCD_Write_Com(0x0c);
- add=0;DelayMs(5);n=0;EA=1;
- break;
- } //switch(add)
- }
- }//if(!k0);
- if(add!=0)//按键加
- {
- switch (add)
- {
- case 1:if(!k1)
- {
- DelayMs(30);
- if(!k1)
- {shi++;
- while(!k1);
- if(shi==5)shi=0;
- }
- }
- LCD_Write_Com(0xc0+8);
- LCD_Write_Data(0x30+shi);
- LCD_Write_Com(0xc0+8);
- break;
- case 2:if(!k1)
- {
- DelayMs(30);
- if(!k1)
- {fen++;
- while(!k1);
- if(fen==10)fen=0;
- }
- }
- LCD_Write_Com(0xc0+10);
- LCD_Write_Data(0x30+fen);
- LCD_Write_Com(0xc0+10);
- break;
- case 3:if(!k1)
- {
- DelayMs(30);
- if(!k1)
- {miao++;
- while(!k1);
- if(miao==10)miao=0;
- }
- }
- LCD_Write_Com(0xc0+11);
- LCD_Write_Data(0x30+miao);
- LCD_Write_Com(0xc0+11);
- break;
- }//switch()
- }//if(add!=0)
- }//key()
- /************************************
- 主函数
- *************************************/
- void main()
- {
- LCDXS();
- DelayMs(255);
- Init_zd();
-
- while(1)
- {
- ac=(int)c%10;
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
酒精测试仪—程序.rar
(43.71 KB, 下载次数: 57)
AD原理图.rar
(15.72 KB, 下载次数: 36)
|