大学期间第一次经历小学期,真是痛苦.....老师还要求做一个PM2.5检测和处理的仿真,倒腾了两个星期,又参(chao)照(xi)了论坛内诸位大神的仿真图,总算给倒腾出来了,深感单片机学习真是不容易。给各位共享出来,加油学习,与诸君共勉......
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载):
单片机源程序如下:
- #include<reg51.h>
- #include<intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define LCD P0 //
- sbit PM2_5 = P2^1; //PM2.5模块PWM输入口
- sbit busy=P0^7; // "忙"标志位
- sbit add=P1^0;
- sbit jian=P1^1;
- sbit ledred=P1^2;
- sbit ledgreen=P1^3;
- sbit sanji=P2^2;
- sbit erji=P2^3;
- sbit yiji=P2^4;
- sbit guolvwang=P2^0;
- sbit warning=P1^7;
- uint ji=120;
- uint LowPulseTime_30s = 0; //30秒内低电平的时间,单位为ms
- uint LowPulseTime_3s = 0; //3秒内低电平的时间,单位为ms
- uint TotalTime_3s = 0;//总时间,3秒计数器
- uint TotalTime_30s = 0;//总时间,30秒计数器*
- uint LowperTotal = 0; //30秒内的低脉冲率,就是30秒内的低脉冲时间除以30秒的总时间,范围为5%~25%
- uint Concen = 0;//浓度值,整数
- uint pulseTime[10] = {0}; //每隔3秒的低电平时间数组,10项刚好就是30秒
- uchar Index = 0; //上述数组的索引
- bit bFreshDis = 0; //显示值刷新标志位,每隔3秒刷新一次显示
- bit bStartDis = 0; //开始显示浓度值标志位,因为上电后要等30秒的预热时间才能计算浓度值
- #define INT_CLOCK 1 //INT_CLOCK为定时值,单位为ms ,此处定义为1ms
- #define CRY_FREQUENCY 11059200 //CRY_FREQUENCY为晶振频率,单位为,Hz
- uchar TL0_temp; //暂存TL0的初值 中断值
- uchar TH0_temp; //暂存TH0的初值
- unsigned char fuhao;
- //代码表
- uchar dat=0x00;
- uchar CH;
- uchar dis[]={0x01,0x02,0x03,0x04};
- unsigned char code hutab[10]={"0123456789"};
- uchar code tablewe[]={0xfd,0xfb,0xf7,0xf0,0xdf,0xfe};
- unsigned char code TAB1[]={ 0x0c,0x12,0x12,0x0c,
- 0x00,0x00,0x00,0x00,
- };
- //字符表
- unsigned char code digit[20]={"0123456789"}; //定义字符数组显示数字
- /*************************
- LCD相关变量
- *************************/
- sbit RS=P2^5;
- sbit RW=P2^6;
- sbit EN=P2^7;
- //------------------------------------ 延时函数 -------------------------------------------
- void delay(unsigned int t) //延时若干微秒
- {
- while(t--);
- }
- //定时器
- void Timer0_init()
- {
- unsigned long T0_temp; //暂存T0的初始值
- T0_temp = 65536-((INT_CLOCK *CRY_FREQUENCY /1000)/12); //T0初始值计算公式,参考教科书
- TL0_temp = T0_temp & 0xff;
- TH0_temp = T0_temp >> 8;
- TL0 = TL0_temp;
- TH0 = TH0_temp;
- TMOD = 0x11;
- TR0 = 1;
- ET0 = 1;
- CH=0x00;
- }
- /************************************************
- 1602相关函数定义
- ************************************************/
- //----------------------------------
- void CHECK_BF() //判断是否忙碌
- {
- do
- {
- LCD=0xff;
- RS=0; // RS=0,选择指令寄存器
- RW=1; // RW=1,选择读模式
- EN=0; // 执行显示命令
- EN=1; // 允许读/写
- }
- while(busy); //busy为高电平表示忙,循环等待
- }
- void WR_COMM()//写指令//
- {
- RS=0;
- RW=0;
- EN=0;
- CHECK_BF();
- EN=1;
- }
- void WR_DATA()//写数据//
- {
- RS=1;
- RW=0;
- EN=0;
- CHECK_BF();
- EN=1;
- }
- //1602初始化
- void INIT_LCD()
- {
- unsigned char i=200;
- {
- while(--i);
- LCD=0x01; //清屏并光标复位
- WR_COMM(); //写入命令
- LCD=0x38; //设置显示模式:8位2行5x7点阵
- WR_COMM();
- LCD=0x0c; //开显示屏
- WR_COMM();
- LCD=0x06; //文字不动,光标自动右移
- WR_COMM(); //写入命令
- }
- }
- //显示模块
- void DISP_YUJING()//显示浓度
- {
- LCD=0xc0;
- WR_COMM();
- LCD=('P');
- WR_DATA();
- LCD=0xc1;
- WR_COMM();
- LCD=('M');
- WR_DATA();
- LCD=0xc2;
- WR_COMM();
- LCD=('2');
- WR_DATA();
- LCD=0xc3;
- WR_COMM();
- LCD=('.');
- WR_DATA();
- LCD=0xc4;
- WR_COMM();
- LCD=('5');
- WR_DATA();
- LCD=0xc5;
- WR_COMM();
- LCD=('y');
- WR_DATA();
- LCD=0xc6;
- WR_COMM();
- LCD=('u');
- WR_DATA();
-
- LCD=0xc7;
- WR_COMM();
- LCD=('j');
- WR_DATA();
- LCD=0xc8;
- WR_COMM();
- LCD=('i');
- WR_DATA();
- LCD=0xc9;
- WR_COMM();
- LCD=('n');
- WR_DATA();
-
- LCD=0xca;
- WR_COMM();
- LCD=('g');
- WR_DATA();
- LCD=0xcb;
- WR_COMM();
- LCD=(':');
- WR_DATA();
- LCD=0xcc;
- WR_COMM();
- LCD=ji/100+0x30;
- WR_DATA();
- LCD=0xcd;
- WR_COMM();
- LCD=(ji%100)/10+0x30;
- WR_DATA();
- LCD=0xce;
- WR_COMM();
- LCD=(ji%10)+0x30;
- WR_DATA();
-
-
- }
- void DISP_CONCE()//显示浓度
- {
- LCD=0x80;
- WR_COMM();
- LCD=('P');
- WR_DATA();
- LCD=0x81;
- WR_COMM();
- LCD=('M');
- WR_DATA();
- LCD=0x82;
- WR_COMM();
- LCD=('2');
- WR_DATA();
- LCD=0x83;
- WR_COMM();
- LCD=('.');
- WR_DATA();
- LCD=0x84;
- WR_COMM();
- LCD=('5');
- WR_DATA();
- LCD=0x85;
- WR_COMM();
- LCD=('j');
- WR_DATA();
- LCD=0x86;
- WR_COMM();
- LCD=('i');
- WR_DATA();
-
- LCD=0x87;
- WR_COMM();
- LCD=('a');
- WR_DATA();
- LCD=0x88;
- WR_COMM();
- LCD=('n');
- WR_DATA();
- LCD=0x89;
- WR_COMM();
- LCD=('c');
- WR_DATA();
-
- LCD=0x8a;
- WR_COMM();
- LCD=('e');
- WR_DATA();
- LCD=0x8b;
- WR_COMM();
- LCD=(':');
- WR_DATA();
- LCD=0x8c;
- WR_COMM();
- LCD=Concen/100+0x30;
- WR_DATA();
- LCD=0x8d;
- WR_COMM();
- LCD=(Concen%100)/10+0x30;
- WR_DATA();
- LCD=0x8e;
- WR_COMM();
- LCD=(Concen%10)+0x30;
- WR_DATA();
-
- }
- void DISP_WAIT()//显示等待
- {
- LCD=0x80;
- WR_COMM();
- LCD=('P');
- WR_DATA();
- LCD=0x81;
- WR_COMM();
- LCD=('M');
- WR_DATA();
- LCD=0x82;
- WR_COMM();
- LCD=('2');
- WR_DATA();
- LCD=0x83;
- WR_COMM();
- LCD=('.');
- WR_DATA();
- LCD=0x84;
- WR_COMM();
- LCD=('5');
- WR_DATA();
- LCD=0x85;
- WR_COMM();
- LCD=('j');
- WR_DATA();
- LCD=0x86;
- WR_COMM();
- LCD=('i');
- WR_DATA();
-
- LCD=0x87;
- WR_COMM();
- LCD=('a');
- WR_DATA();
- LCD=0x88;
- WR_COMM();
- LCD=('n');
- WR_DATA();
- LCD=0x89;
- WR_COMM();
- LCD=('c');
- WR_DATA();
-
- LCD=0x8a;
- WR_COMM();
- LCD=('e');
- WR_DATA();
- LCD=0x8b;
- WR_COMM();
- LCD=('w');
- WR_DATA();
- LCD=0x8c;
- WR_COMM();
- LCD=('a');
- WR_DATA();
- LCD=0x8d;
- WR_COMM();
- LCD=('i');
- WR_DATA();
- LCD=0x8e;
- WR_COMM();
- LCD=('t');
- WR_DATA();
-
-
- }
- void PM2_5SHUAXIN()
- {
- uchar i;
- if(bStartDis)
- {
- if(bFreshDis) /*开始刷新*/
- {
- bFreshDis = 0;
- LowPulseTime_30s = 0;
- for(i = 0;i < 10;i++)
- LowPulseTime_30s += pulseTime[i]; /**统计30秒内的低电平时间**/
- }
- LowperTotal = LowPulseTime_30s/30; //低脉冲率本来是小数,但这里将其变成整数,便于单片机处理,假如脉冲率为25%,那么经过此公式计算得到的值为25
- Concen = (LowperTotal*10)/2; //浓度值 = 低脉冲率/2 ;将浓度值放大十倍,变整数方便显示*/
- DISP_CONCE(); //显示
-
- }
- else /*预热过程*/
- {
- DISP_WAIT(); /*显示预热*/
- } }
- /*************************************
- 主程序
- **************************************/
- //main
- void main()
- {
- uint ji2;
- uint ji3;
- Timer0_init(); //中断初始化
- INIT_LCD(); //1602初始化
- EA = 1; //开中断
- delay(100);
-
- while(1)
- {
- ji2=ji+50;
- ji3=ji+100;
- if(guolvwang==1)
- warning=1;
- else
- warning=0;
- if(add==0)
- {
- delay(20000);
- ji++;
- }
- if(jian==0)
- {
- delay(20000);
- ji--;
- }
- if(Concen>=ji)
- {
- ledgreen=0;
- ledred=1;
- }
- else
- {
- ledred=0;
- ledgreen=1;
- }
- //报警部分
- if(Concen>=ji3)
- sanji=1;
- else
- sanji=0;
- if(Concen>=ji2)
- {
- if(Concen<ji3)
- erji=1;
- else
- erji=0;
- }
- else
- erji=0;
- if(Concen>=ji)
- {
- if(Concen<ji2)
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
雾霾检测及处理仿真.zip
(103.03 KB, 下载次数: 303)
|