12864显示;
adc采集bandgap电压显示;
使用100K NTC测温显示;
家里的新房交付,自带简单装修,添置了些家具草草入住,同时考虑室外空气质量也比较差劲,更换了净化器的滤芯、添置了壁挂新风,考虑囊中羞涩,决定自己买传感器,拿51和12864来DIY个检测器;说在前面:
这个东西个人感觉没法定性也没必要,有个参考就可以了。
传感器: 淘宝找得基本最便宜的:国产达特WZ-S-K,带引脚的;PMS5003,不带温湿度、不带甲醛款;
其他配置:
玩萝丽控陆续攒的STC15w408AS、IIC接口的12864白色OLED屏;
原理:
两个传感器都是串口,均支持主动、被动通信;收发地一连,MCU接收传感器发来的数据,做个数据解析并给12864显示就完工了。
遇到的问题:
STC15W408AS自带1个串口,要与2个设备通信;
解决方法1:
按照网上的方法直连,经测试,估计引脚的输出能力偏弱,攀藤就被干掉了;失败;
解决方法2:
翻看STC的手册,这货可以分时的方式切换串口到第二、第三组引脚;16pin的stc15引脚比较少,但也有2组可用,满足要求。
程序主要思路:
通过设定flag的0、1状态,同时配合切换串口位置,分时发送命令给传感器,分时接收数据并做简单判断、解析并在12864上作出显示。
存在的问题:
未做数据的校验及错误情况的判断及软件重置。反正跑死了,手动重启就好啦。。。
补充说明:
1,PMS5003默认主动发送数据,掉电会自动恢复默认主动的发送情形,因此程序在每次上电时主动发送命令,使其工作在被动模式;
甲醛传感器貌似没啥影响,串口切到被动后,没注意掉电会不会恢复主动,测试显示数据没发现异常就没管它。发帖此时传感器没在手上,因此就不做测试,后续再议了。
2,PMS5003的官网手册,最后一些关于校验的协议,像是没写完,没有句号,也没明确2个校验字节的具体内容,因此通过官方要来了基本协议的解释,再次感谢热情的攀藤小姐姐。分享以下:
0x42 0x4D 0xE1 0x00 0x00 0x01 0x70 - passive mode return:42 4D 00 04 E1 00 01 74 0x42 0x4D 0xE1 0x00 0x01 0x01 0x71 - active mode. return:42 4D 00 04 E1 01 01 750x42 0x4D 0xE2 0x00 0x00 0x01 0x71 - Passive mode read instruction 0x42 0x4D 0xE4 0x00 0x00 0x01 0x73 - standby mode return::42 4D 00 04 E4 00 01 77 0x42 0x4D 0xE4 0x00 0x01 0x01 0x74 -Standby wakeup
传感器真身:
检测显示:
杂乱的全家福:
单片机源程序如下:
- #include <stc15.h>
- #include <12864.h>
- #include <delay.h>
- #include <character.h>
- unsigned char a[32],b[4];
- unsigned char n=0;
- unsigned char m=0;
- unsigned char numb=6;
- unsigned int numb2=0x2c;
- bit flag;
- unsigned int zong,pm10i,pm25i,pm100i;
- void UartInit(void) //9600bps@11.0592MHz
- {
- SCON = 0x50; //8位数据,可变波特率
- AUXR |= 0x01; //串口1选择定时器2为波特率发生器
- AUXR &= 0xFB; //定时器2时钟为Fosc/12,即12T
- T2L = 0xE8; //设定定时初值
- T2H = 0xFF; //设定定时初值
-
- AUXR |= 0x10; //启动定时器2
- EA=1;
- ES=1;
- }
- //发送一个byte;
- void sendonebyte(unsigned char udat)
- {
- SBUF=udat;
- while(!TI);
- TI=0;
- }
- //发送字符串;
- void sendstrings(unsigned char *upstr)
- {
- while(*upstr)
- {
- sendonebyte(*upstr++);
-
-
- }
- }
- void Delay05s()
- {
- Delay50ms();
- Delay50ms();
- Delay50ms();
- Delay50ms();
- Delay50ms();
- Delay50ms();
- Delay50ms();
- Delay50ms();
- Delay50ms();
- }
- unsigned char receivedat()
- {
- unsigned char redatbuf;
-
- if(RI == 1)
- {
-
- redatbuf=SBUF;
- RI=0;
- }
- return redatbuf;
- }
- void countnum(unsigned int num) //int 65536;
- {
- //b[4]=(num/10000)%10; //万位;
- b[3]=(num/1000)%10; //千位;
- b[2]=(num/100)%10; //百位;
- b[1]=(num/10)%10; //十位;
- b[0]=(num/1)%10; //个位;
- }
- void hcho_T() //flag=1,计算甲醛
- {
-
- Delay05s();
- AUXR1 |= 0x40; //串口切换到 P3.6Rxd P3.7Txd;
- Delay50ms();
- flag=1;
- sendonebyte(0xff); //FF 01 86 00 00 00 00 00 79 dart wz-s 请求数据命令;
- sendonebyte(0x01);
- sendonebyte(0x86);
- sendonebyte(0x00);
- sendonebyte(0x00);
- sendonebyte(0x00);
- sendonebyte(0x00);
- sendonebyte(0x00);
- sendonebyte(0x79);
- //
- }
- void pm25_T()
- {
-
- Delay05s();
- AUXR1 &= 0xbf; //串口切换到 P3.0Rxd P3.1Txd;
- Delay50ms();
- flag=0;
- sendonebyte(0x42);
- _nop_();
- sendonebyte(0x4d);
- _nop_();
- sendonebyte(0xe2);
- _nop_();
- sendonebyte(0x00);
- _nop_();
- sendonebyte(0x00);
- _nop_();
- sendonebyte(0x01);
- _nop_();
- sendonebyte(0x71);
- _nop_();
- }
- void pm25_init()
- {
-
- Delay05s();
- flag=0;
- sendonebyte(0x42);
- _nop_();
- sendonebyte(0x4d);
- _nop_();
- sendonebyte(0xe1);
- _nop_();
- sendonebyte(0x00);
- _nop_();
- sendonebyte(0x00);
- _nop_();
- sendonebyte(0x01);
- _nop_();
- sendonebyte(0x70);
- _nop_();
- }
-
- void hcho_R()
- {
- if((a[0]==0xff)&&(a[1]==0x86))
- {
- zong=((a[2]>>4)*16+(a[2]&0x0f))*256+a[3];
- countnum(zong);
- dxzm(b[3]+0x30,48,0);
- dxzm('.',56,0);
- dxzm(b[2]+0x30,64,0);
- dxzm(b[1]+0x30,72,0);
- dxzm(b[0]+0x30,80,0);
- dxzm('m',88,0);
- dxzm('g',96,0);
- dxzm('/',104,0);
- dxzm('m',112,0);
- location(120,0);
- dis_num86('3');
- }
- }
- void pm25_R()
- {
- if((a[0]==0x42)&&(a[1]==0x4d))
- {
-
- if(a[3]==0x1c)
- {
- pm10i=((a[10]>>4)*16+(a[10]&0x0f))*256+a[11];
- countnum(pm10i);
- if(b[3]==0)
- ;else
- dxzm(b[3]+0x30,48,2);
- if(b[2]==0)
- ;else
- dxzm(b[2]+0x30,56,2);
- if(b[1]==0)
- ;else
- dxzm(b[1]+0x30,64,2);
- dxzm(b[0]+0x30,72,2);
- dxzm('u',80,2);
- dxzm('g',88,2);
- dxzm('/',96,2);
- dxzm('m',104,2);
- location(112,2);
- dis_num86('3');
-
- pm25i=((a[12]>>4)*16+(a[12]&0x0f))*256+a[13];
- countnum(pm25i);
- if(b[3]==0)
- ;else
- dxzm(b[3]+0x30,48,4);
- if(b[2]==0)
- ;else
- dxzm(b[2]+0x30,56,4);
- if(b[1]==0)
- ;else
- dxzm(b[1]+0x30,64,4);
- dxzm(b[0]+0x30,72,4);
- dxzm('u',80,4);
- dxzm('g',88,4);
- dxzm('/',96,4);
- dxzm('m',104,4);
- location(112,4);
- dis_num86('3');
-
-
- pm100i=((a[14]>>4)*16+(a[14]&0x0f))*256+a[15];
- countnum(pm100i);
- if(b[3]==0)
- ;else
- dxzm(b[3]+0x30,48,6);
- if(b[2]==0)
- ;else
- dxzm(b[2]+0x30,56,6);
- if(b[1]==0)
- ;else
- dxzm(b[1]+0x30,64,6);
- dxzm(b[0]+0x30,72,6);
- dxzm('u',80,6);
- dxzm('g',88,6);
- dxzm('/',96,6);
- dxzm('m',104,6);
- location(112,6);
- dis_num86('3');
- }
- }
- }
- void dis_init()
- {
- dxzm('H',8,0);
- dxzm('C',16,0);
- dxzm('H',24,0);
- dxzm('O',32,0);
- dxzm(':',40,0);
-
- dxzm('P',0,2);
- dxzm('M',8,2);
- dxzm('1',16,2);
- dxzm('.',24,2);
- dxzm('0',32,2);
- dxzm(':',40,2);
-
- dxzm('P',0,4);
- dxzm('M',8,4);
- dxzm('2',16,4);
- dxzm('.',24,4);
- dxzm('5',32,4);
- dxzm(':',40,4);
-
-
- dxzm('P',0,6);
- dxzm('M',8,6);
- dxzm('1',16,6);
- dxzm('0',24,6);
- dxzm('.',32,6);
- dxzm(':',40,6);
- }
- void main()
- {
- u8 x;
- Initial_12864();
- clear_12864();
- UartInit();
- dis_init();
-
- Delay05s();
- Delay05s();
-
- pm25_init();
- Delay50ms();
- m=0;
-
-
- while(1)
- {
-
- hcho_T();
- Delay50ms();
- hcho_R();
-
- Delay05s();
-
- pm25_T();
- Delay50ms();
- pm25_R();
-
-
- }
- }
- void Serial_interrupt() interrupt 4
- {
- if((RI==1)&&(flag==1))
- {
- if(n==9)
- n=0;
- a[n]=SBUF; // a为事先定义的接收缓存,可以持续接收,直到你需要串口数据时来取为止
- RI=0;//接收中断信号清零,表示将继续接收
- n++;
- }
-
- if((RI==1)&&(flag==0))
- {
-
- a[m]=SBUF; // a为事先定义的接收缓存,可以持续接收,直到你需要串口数据时来取为止
- RI=0;//接收中断信号清零,表示将继续接收
- m++;
- if(m==32)
- m=0;
- }
-
- }
-
复制代码
所有资料51hei提供下载:
12864_ser2019pm.zip
(155.89 KB, 下载次数: 138)
|