目录
前言:
结构:
大概框架:
关于烟雾报警器的相关代码:mian.c有其它模块的相关部分代码会有点多
前言:
这是大三做的一个课程设计-基于51单片机的课程设计。当时觉得只是做一个烟雾报警器比较简单,所以自己又添加了烟雾、温度、电子时钟、闹钟、pwm电机功能。因为程序是自己写的,所以比较长,程序十分繁琐。导致了蜂鸣器会间断的响,也影响了DS18B20温度传感器的时序(我猜测的,因为温度不准确,而18b20是单线,所以对时间要求很严)。其它功能正常。这儿我想到的办法解决是用多线程来提高程序的可行性,等到后面有时间了做修改。我把课程设计的贴在下面,需要仿真和程序的朋友请联系。
结构:
大概框架:
防真:
程序文件:用的的模块比较多,就没有全部都写在主
函数了
关于烟雾报警器的相关代码:mian.c有其它模块的相关部分代码会有点多
MQ2.c
#include "reg51.h"#include "intrins.h"#include "MQ2.h"typedef unsigned char ;typedef unsigned int ;sbit Clk=P1^1;sbit CS=P1^0;sbit DATI=P1^2; //DATI和DATO是分开作用的,所以可以公用一条线sbit DATO=P1^2;/*函数功能:AD模数转换 输入参数:CHtest和adval为测验值和实值输出参数:dat*/unsigned char adc0832(unsigned char CH){unsigned char i,test,adval,dat;adval = 0x00;test = 0x00;Clk = 0;DATI = 1;_nop_();CS = 0; //开启AD转换_nop_(); //延时,保持低电平Clk = 1;_nop_();if ( CH == 0x00 ) //通道0{Clk = 0;DATI = 1; //1位_nop_();Clk = 1;_nop_();Clk = 0;DATI = 0; //2位_nop_();Clk = 1;_nop_();} else //通道1{Clk = 0;DATI = 1; //1位_nop_();Clk = 1;_nop_();Clk = 0;DATI = 1; //2位_nop_();Clk = 1;_nop_();}Clk = 0;DATI = 1;for( i = 0;i < 8;i++ ) //读取前8位{_nop_();adval <<= 1;Clk = 1;_nop_();Clk = 0;if (DATO)adval |= 0x01;elseadval |= 0x00;}for (i = 0; i < 8; i++) //读取后8位{test >>= 1;if (DATO)test |= 0x80;else test |= 0x00;_nop_();Clk = 1;_nop_();Clk = 0;}if (adval == test) //检验dat = test;nop_();CS = 1;DATO = 1;Clk = 1;return dat;}/*函数功能:得到的AD值转化位烟雾浓度Value是我们得到的烟雾浓度*/unsigned char GetYanWuValue(void){unsigned int sum=0;unsigned int m,value=0;for(m=0;m<50;m++)//累计50次AD值sum = adc0832(0)+sum;value=(unsigned char)(sum/50);//所得AD值平均/*if(value > ADC_Zero) value = value - ADC_Zero; //去掉零点漂移 elsevalue = 0;*/ return value;}
MQ2.h
#ifndef __MQ2_H#define __MQ2_Hunsigned char adc0832(unsigned char CH);unsigned char GetYanWuValue(void);#endif
LCD.c
#include "string.h"#include "reg51.h"#include "lcd.h"typedef unsigned char ;typedef unsigned int ;sbit RS = P2^3;sbit RW = P2^1;sbit EN = P2^2;//延迟函数.void delay_ms(t){ int i,j;for(i=0;i<t;i++)for(j=0;j<123;j++);}//判断1602是否忙,忙则处理1602CPU的命令/*void Read_Busy(){ uchar sta; P0 = 0xff; RS = 0; RW = 1; do {EN = 1;sta = P0;EN = 0; }while(sta & 0x80); // 对液晶状态最高位判断。结果为1忙、禁止,0允许读写}*///对LCD1602写指令void Write_Cmd(char cmd) { //Read_Busy(); RS = 0; RW = 0;EN = 1;P3 = cmd; delay_ms(5); EN = 0; }//写入字节数据void Write_Dat(char dat) { //Read_Busy(); RS = 1; RW = 0;EN = 1; P3 = dat; delay_ms(5); EN = 0; }//设置坐标位置void LCD1602_XY(unsigned char x,unsigned char y){switch(y){case 0:Write_Cmd(0x80+x);break; //1行x列case 1:Write_Cmd(0xc0+x);break; //2行x列}}//用空格符代替清屏功能(可以清屏指定位置)//从x清除到x1void LCD1602_Clear(unsigned char x,unsigned char y,unsigned char x1){for(;x<x1;x++){ LCD1602_XY(x,y); Write_Dat(0x20); //0x20无字符}}//显示指定字符void LCD1602_ShowChar(unsigned char x,unsigned char y,unsigned char dat){LCD1602_XY(x,y);Write_Dat(dat);}//显示指定字符串void LCD1602_ShowStr(unsigned char x,unsigned char y,unsigned char *String){ LCD1602_XY(x,y); while(*String) {Write_Dat(*String);String++; }}//显示整数void LCD1602_ShowNumber(unsigned char x,unsigned char y,unsigned int Number,unsigned char Count){unsigned char NumbArray[6]={0};NumbArray[0]=(Number/10000)+0x30; NumbArray[1]=(Number/1000) +0x30; NumbArray[2]=(Number/100) +0x30; NumbArray[3]=(Number/10) +0x30; NumbArray[4]=(Number/1) +0x30; NumbArray[5]= 0; LCD1602_ShowStr(x,y,&NumbArray[5-Count]);}//显示浮点数//Count1整数个数,Count2小数个数(程序被改的是保留3位小数)void LCD1602_ShowNum_Float(unsigned char x,unsigned char y,float Number, unsigned char Count1, unsigned char Count2){ unsigned char NumberArray[10]={0}; unsigned int Number_Integer = 0; unsigned int Number_Decimal = 0; float Number_Temp; Number_Temp = Number; if(Number_Temp < 0) {Number_Temp= 0 - Number_Temp; } Number_Integer = (unsigned int)(Number_Temp); Number_Decimal = (unsigned short)((Number_Temp - Number_Integer + 0.0005) * 1e3); //NumberArray[ 1] = '+'; NumberArray[ 0] = Number_Integer/10000 % 10 + 0x30; NumberArray[ 1] = Number_Integer/ 1000 % 10 + 0x30; NumberArray[ 2] = Number_Integer/ 100 % 10 + 0x30; NumberArray[ 3] = Number_Integer/ 10 % 10 + 0x30; NumberArray[ 4] = Number_Integer/ 1 % 10 + 0x30; NumberArray[ 5] ='.'; NumberArray[ 6] = Number_Decimal/ 100 % 10 + 0x30; NumberArray[ 7] = Number_Decimal/ 10 % 10 + 0x30; NumberArray[ 8] = Number_Decimal/ 1 % 10 + 0x30; NumberArray[ 9] = 0; /*if(Number>0) { NumberArray[5-Count1] = '+'; } else {NumberArray[5-Count1] = '-'; }*/ NumberArray[7+Count2] = 0;LCD1602_ShowStr(x, y, &NumberArray[5-Count1]);}//光标位置void SetCurPosition(unsigned char X,unsigned char Y){Y &= 0x01;X &= 0x0F; if (Y){X |= 0x0c; //第二行}X |= 0x08; //第一行Write_Cmd(X); // 显示位置Write_Cmd(0x02); //光标Write_Cmd(0x0d); //关闭光标}//LCD1602void LCD1602_Init(){ Write_Cmd(0x38); //设置16*2(16列,2行) Write_Cmd(0x0c); //关闭光标Write_Cmd(0x06); //文字左移右移无效 Write_Cmd(0x01); //清屏}
lcd.h
#ifndef __LCD_H#define __LCD_Hvoid delay_ms(t);//void Read_Busy();void Write_Cmd(char cmd);void Write_Dat(char dat);void LCD1602_XY(unsigned char x,unsigned char y);void LCD1602_ShowChar(unsigned char x,unsigned char y,unsigned char dat);void LCD1602_ShowStr(unsigned char x,unsigned char y,unsigned char *String);void LCD1602_ShowNum_Float(unsigned char x,unsigned char y,float Number, unsigned char Count1, unsigned char Count2);void LCD1602_ShowNumber(unsigned char x,unsigned char y,unsigned int Number,unsigned char Count);void LCD1602_Clear(unsigned char x,unsigned char y,unsigned char num);void SetCurPosition(unsigned char X,unsigned char Y);void LCD1602_Init();#endif
main.c
#include "reg51.h"#include "lcd.h"#include "MQ2.h"#include "buzzer.h"#include "motor.h"#include "time.h"//#include "time1.h"#include "button.h"#include "definction.h"#include "DS18B20.h"#include "music.h"extern unsigned int ack;unsigned char code *str[]={"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"};void main(){unsigned char i=0x40;//buzzer=0; //初始化P1^7,P1^6,buzzer=1;relay=1; //初始化P0^3管脚//music_start();Init_DS18B20(); //初始化,温度的初始化要在定时器前面,定时器溢出会对温度的时序产生影响 LCD1602_Init(); time0_init();while(1){button_init(); buzzer_init();relay_motor();if(t==0 && n==0) //开机显示{i++; LCD1602_ShowStr(0,0,"Hello,Mr.");LCD1602_ShowChar(14,0,i); LCD1602_ShowStr(0,1,"Good luck to you.");}if(s==8 && m==0 && t==0) //8秒无动作,强制切换到菜单{Write_Cmd(0x01); //清屏t=5; //默认是最后一个模式m=1; //防止程序再一次运行进入该if语句(程序运行的时间以us为标准,定时的时间是1ms)LCD1602_ShowStr(0,0,">>");}if(t==1){ LCD1602_ShowStr(2,0,"Smoke Mode"); LCD1602_ShowStr(2,1,"Temp Mode");}if(t==2){ LCD1602_ShowStr(2,0,"Temp Mode");LCD1602_ShowStr(2,1,"Clock Mode");}if(t==3){LCD1602_ShowStr(2,0,"Clock Mode");LCD1602_ShowStr(2,1,"Fan Mode");}if(t == 4){LCD1602_ShowStr(2,0,"Fan Mode");LCD1602_ShowStr(2,1,"Alarm Mode");}if(t == 5){LCD1602_ShowStr(2,0,"Alarm Mode");LCD1602_ShowStr(2,1,"Smoke Mode");}if(n == 1 ){LCD1602_ShowStr(0,0,"Value:");LCD1602_ShowNumber(7,0,Value,3);if(Value>=Valuemax){LCD1602_ShowChar(10,1,0x20);LCD1602_ShowChar(14,1,0x20);LCD1602_ShowChar(15,1,0x20);LCD1602_ShowChar(14,0,0x20);LCD1602_ShowChar(15,0,0x20);LCD1602_ShowStr(0,1,"ERROR:OVER MAX");}else{ LCD1602_ShowChar(10,1,0x20); LCD1602_ShowStr(4,1,"/");LCD1602_ShowStr(7,1,"/");LCD1602_ShowNumber(0,1,year,4);LCD1602_ShowNumber(5,1,month,2);LCD1602_ShowNumber(8,1,day,2);LCD1602_ShowNumber(11,1,h,2);LCD1602_ShowChar(13,1,':');LCD1602_ShowNumber(14,1,min,2);}}if(n == 2 && Temp_flag==1){LCD1602_ShowStr(0,0,"Temp:");LCD1602_ShowNumber(6,0,Temp,2);LCD1602_ShowStr(8,0,"℃");LCD1602_ShowStr(4,1,"/");LCD1602_ShowStr(7,1,"/");LCD1602_ShowNumber(0,1,year,4);LCD1602_ShowNumber(5,1,month,2);LCD1602_ShowNumber(8,1,day,2);LCD1602_ShowNumber(11,1,h,2);LCD1602_ShowChar(13,1,':');LCD1602_ShowNumber(14,1,min,2);}if(n == 3 ){LCD1602_ShowStr(0,0,str[fewone-1]);LCD1602_ShowStr(4,1,"/");LCD1602_ShowStr(7,1,"/");LCD1602_ShowNumber(0,1,year,4);LCD1602_ShowNumber(5,1,month,2);LCD1602_ShowNumber(8,1,day,2);LCD1602_ShowNumber(11,1,h,2);LCD1602_ShowChar(13,1,':');LCD1602_ShowNumber(14,1,min,2);LCD1602_ShowNumber(14,0,s,2);if(Clock_flag == 1){TR0 = 0;Write_Cmd(0x0e); //开,显示,不闪烁Write_Cmd(y+x);delay_ms(10); //必须延时Write_Cmd(0x0c); //一定要关闭,否则光标会跳动}else{x=0;TR0 = 1;Write_Cmd(0x0c);}}if(n == 4 && flag%2 == 1 && Fan_flag==1){PWM_flag=1;LCD1602_ShowStr(4,1,"/");LCD1602_ShowStr(7,1,"/");LCD1602_ShowNumber(0,1,year,4);LCD1602_ShowNumber(5,1,month,2);LCD1602_ShowNumber(8,1,day,2);LCD1602_ShowNumber(11,1,h,2);LCD1602_ShowChar(13,1,':');LCD1602_ShowNumber(14,1,min,2);}if(n == 4 && flag%2 == 0 && Fan_flag==1){PWM_flag=0;LCD1602_ShowStr(0,0,"0 Gear");LCD1602_ShowStr(0,1,"/12/");LCD1602_ShowNumber(8,1,day,2);LCD1602_ShowNumber(11,1,h,2);LCD1602_ShowChar(13,1,':');LCD1602_ShowNumber(14,1,min,2);}if(n == 5){LCD1602_ShowNumber(0,1,h1,2);LCD1602_ShowChar(2,1,':');LCD1602_ShowNumber(3,1,min1,2);if(Alarm_flag == 1){LCD1602_ShowStr(0,0,"Alarm OK!"); Write_Cmd(0x0e); //开,显示,不闪烁 Write_Cmd(0xc0+x); delay_ms(10); //必须延时 Write_Cmd(0x0c); //一定要关闭,否则光标会跳动}else{x=0;LCD1602_ShowStr(0,0,"Alarm Cancel!");Write_Cmd(0x0c);}}}}
如果觉得《基于51单片机多功能烟雾报警器——菜单栏有烟雾 温度 电子时钟 闹钟 pwm电机功能》对你有帮助,请点赞、收藏,并留下你的观点哦!