|
一款以DSL-08PM2.5/10檢測模塊為主的檢測裝置,控制器為STC89C52RC,顯示屏為LCD1602。主要可顯示PM2.5和PM10濃度,有報警功能,且報警閾值可通過按鍵設(shè)置。硬件包含DS1302,可按鍵切換顯示時間。附件包含傳感器資料、源程序、PCB工程文件及操作說明供參考。
制作出來的實物圖如下:
IMG_20200317_122410.jpg (3.46 MB, 下載次數(shù): 82)
下載附件
2020-3-18 13:52 上傳
IMG_20200315_135359.jpg (4.91 MB, 下載次數(shù): 93)
下載附件
2020-3-18 13:51 上傳
1. 模塊上電默認(rèn)顯示PM2.5/10數(shù)據(jù),按一下“顯示切換”鍵可切換至PM2.5/10報警值設(shè)置界面;再按一次則進(jìn)入時間顯示界面,顯示北京時間;再按可返回初始界面。
2. 在PM2.5/10報警值設(shè)置界面時,按“M“鍵開始設(shè)置數(shù)據(jù)。按下“M”鍵后首位數(shù)據(jù)光標(biāo)閃爍,此時可以按“▲”修改數(shù)值,該位可在0~9內(nèi)遞增變換。“ ”鍵可切換數(shù)據(jù)位,切換到哪一位,該位的光標(biāo)閃爍。
3. 在設(shè)置過程中(即光標(biāo)閃爍時)“顯示切換”鍵不可用,所有數(shù)據(jù)設(shè)置完后再按一次“M“鍵可確認(rèn)數(shù)據(jù),此時“顯示切換”鍵恢復(fù)功能。
4. 在設(shè)置過程中(即光標(biāo)閃爍時)報警功能暫停,所有數(shù)據(jù)設(shè)置完后再按一次“M“鍵可確認(rèn)數(shù)據(jù),此時報警功能恢復(fù)。
Altium Designer畫的原理圖和PCB圖如下:(51hei附件中可下載工程文件)
0.jpg (435.66 KB, 下載次數(shù): 80)
下載附件
2020-3-18 19:09 上傳
單片機(jī)源程序如下:
- #include<reg52.h>
- #include<intrins.h>
- #define uint unsigned int
- #define uchar unsigned char
- #define FOSC 11059200L
- #define T1MS (65536 - FOSC / 12 / 500)
- sbit DS1302_CLK = P3 ^ 7; //實時時鐘時鐘線引腳
- sbit DS1302_IO = P3 ^ 6; //實時時鐘數(shù)據(jù)線引腳
- sbit DS1302_RST = P3 ^ 5; //實時時鐘復(fù)位線引腳
- sbit ACC0 = ACC^0;
- sbit ACC7 = ACC^7;
- unsigned char t0,t1,t2,t3,t4,t5;
- unsigned char d0,d1,d2,d3,d4,d5;
- typedef struct __SYSTEMTIME__
- {
- unsigned char Second;
- unsigned char Minute;
- unsigned char Hour;
- unsigned char Week;
- unsigned char Day;
- unsigned char Month;
- unsigned char Year;
- unsigned char DateString[9];
- unsigned char TimeString[9];
- }SYSTEMTIME; //定義的時間類型
- #define AM(X) X
- #define PM(X) (X+12) // 轉(zhuǎn)成24小時制
- #define DS1302_SECOND 0x80
- #define DS1302_MINUTE 0x82
- #define DS1302_HOUR 0x84
- #define DS1302_WEEK 0x8A
- #define DS1302_DAY 0x86
- #define DS1302_MONTH 0x88
- #define DS1302_YEAR 0x8C
- #define DS1302_RAM(X) (0xC0+(X)*2) //用于計算 DS1302_RAM 地址的宏
- uchar cnt_PM25 = 0;//數(shù)碼管PM2.5循環(huán)計數(shù)
- uchar R_data = 0;//讀數(shù)據(jù)標(biāo)志
- uchar USART_RX_STB = 0;
- uchar complete_flag = 0;
- uchar USART_RX_BUF[32];//接收緩沖,最大32個字節(jié).
- uchar time_js = 0;//判斷串口一幀數(shù)據(jù)是否接收完成的計數(shù)變量
- uchar PM25_data[2] = {0};
- uchar PM10_data[2] = {0};
- uchar PM_ASC[8];//數(shù)據(jù)分解后的存儲數(shù)組
- uint PM25_1, PM25_2, PM10_1, PM10_2;
- sbit RS = P2 ^ 5; //定義端口
- sbit RW = P2 ^ 6;
- sbit EN = P2 ^ 7;
- #define RS_CLR RS = 0
- #define RS_SET RS = 1
- #define RW_CLR RW = 0
- #define RW_SET RW = 1
- #define EN_CLR EN = 0
- #define EN_SET EN = 1
- #define DataPort P0
- uchar key_temp, key_num, display_num = 0, KKK = 0;
- uchar mode_flag = 0;
- uchar bit_select_counter;
- uchar PM_data_buf[8] = {0, 2, 0, 0, 0, 2, 0, 0};
- //-------開機(jī)、讀數(shù)據(jù)、關(guān)機(jī)指令----------------------------------
- uchar code open[9] = {0xAA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x66, 0xBB};
- uchar code autodata[9] = {0xAA, 0x06, 0x00, 0x00, 0x00, 0x00, 0x01, 0x6B, 0xBB};
- //void Delay500ms( ) //@11.0592MHz
- //{
- // unsigned char i, j, k;
- // _nop_( );
- // i = 4;
- // j = 129;
- // k = 119;
- // do
- // {
- // do
- // {
- // while (--k);
- // } while (--j);
- // } while (--i);
- //}
- /*------------------------------------------------
- uS延時函數(shù),含有輸入?yún)?shù) unsigned char t,無返回值
- unsigned char 是定義無符號字符變量,其值的范圍是
- 0~255 這里使用晶振12M,精確延時請使用匯編,大致延時
- 長度如下 T=tx2+5 uS
- ------------------------------------------------*/
- void DelayUs2x(unsigned int t)
- {
- while(-- t);
- }
- /*------------------------------------------------
- mS延時函數(shù),含有輸入?yún)?shù) unsigned char t,無返回值
- unsigned char 是定義無符號字符變量,其值的范圍是
- 0~255 這里使用晶振12M,精確延時請使用匯編
- ------------------------------------------------*/
- void DelayMs(unsigned char t)
- {
- while(t --)
- {
- //大致延時1mS
- DelayUs2x(245);
- DelayUs2x(245);
- }
- }
- /*------------------------------------------------
- 判忙函數(shù)
- ------------------------------------------------*/
- bit LCD_Check_Busy(void)
- {
- DataPort= 0xFF;
- RS_CLR;
- RW_SET;
- EN_CLR;
- _nop_( );
- EN_SET;
- return (bit)(DataPort & 0x80);
- }
- /*------------------------------------------------
- 寫入命令函數(shù)
- ------------------------------------------------*/
- void LCD_Write_Com(unsigned char com)
- {
- while(LCD_Check_Busy( )); //忙則等待
- RS_CLR;
- RW_CLR;
- EN_SET;
- DataPort = com;
- _nop_( );
- EN_CLR;
- }
- //=======數(shù)據(jù)解析===========
- void shuju_jiexi(void)
- {
- uint PM25, PM10;
- uint sss;
- PM25 = (((uint)PM25_data[0]) << 8) + PM25_data[1];
- PM10 = (((uint)PM10_data[0]) << 8) + PM10_data[1];
- //------------------------
- if(PM25 > 999)
- PM25 = 999;
- if(PM10 > 1500)
- PM10 = 1500;
-
- PM25_1 = PM25;
- PM10_1 = PM10;
- //===========分解PM2.5的值=========================
- sss = PM25;
- PM_ASC[0] = sss / 1000;
- sss = sss % 1000;
- PM_ASC[1] = sss / 100;
- sss = sss % 100;
- PM_ASC[2] = sss / 10;
- PM_ASC[3] = sss % 10;
- //
- //============分解PM10的值=========================
- sss = PM10;
- PM_ASC[4] = sss / 1000;
- sss = sss % 1000;
- PM_ASC[5] = sss / 100;
- sss = sss % 100;
- PM_ASC[6] = sss / 10;
- PM_ASC[7] = sss % 10;
- }
- void Display_cal( )//顯示切換
- {
- if(P45 == 0)
- {
- Delay_1ms(100);
- if(P45 == 0 && mode_flag == 0)
- {
- LCD_Clear( );//清屏
- display_num ++;
-
- if(display_num > 2)
- {
- display_num = 0;
- }
- }
- }
- else
- {
- display_num = display_num;
- }
- }
- uchar Key_Drive( )//鍵值讀取
- {
- if(P20 == 0)
- {
- Delay_1ms(100);
- if(P20 == 0)
- {
- key_temp = 1;
- }
- }
- if(P21 == 0)
- {
- Delay_1ms(100);
- if(P21 == 0)
- {
- key_temp = 2;
- }
- }
- if(P22 == 0)
- {
- Delay_1ms(100);
- if(P22 == 0)
- {
- key_temp = 3;
- }
- }
- return key_temp;
- }
- void Set_Drive( )//設(shè)置數(shù)值
- {
- uchar temp;
- temp = Key_Drive( );
- key_temp = 0;
-
- if(temp == 2)//選擇修改位置
- {
- if(mode_flag != 0)
- {
- bit_select_counter ++;
- if(bit_select_counter > 7)
- {
- bit_select_counter = 0;
- }
- }
- }
-
- if(temp == 3)//修改數(shù)據(jù)值按鍵
- {
- if(mode_flag != 0)
- {
- PM_data_buf[bit_select_counter] += 1;
- if(PM_data_buf[bit_select_counter] > 9)
- {
- PM_data_buf[bit_select_counter] = 0;
- }
- }
- }
-
- if(temp == 1)//M
- {
- bit_select_counter = 0;
- mode_flag ++;
-
- if(mode_flag > 1)
- {
- mode_flag = 0;
- }
- }
- }
- //定時器T2,用于顯示, 70ms刷新一次
- /******定時器2初始化函數(shù)******/
- void Timer2_Init( ) //初始化子函數(shù)
- {
- T2MOD = 0;//T2定時器,16位自動重裝
- T2CON = 0;
- TL2 = 0x00;
- TH2 = 0x04;
- RCAP2L = 0x00;
- RCAP2H = 0x04;
- TR2 = 1;
- EA = 1;
- ET2 = 1;
- }
- void DS1302InputByte(unsigned char d) //實時時鐘寫入一字節(jié)(內(nèi)部函數(shù))
- {
- unsigned char i;
- ACC = d;
- for(i=8; i>0; i--)
- {
- DS1302_IO = ACC0; //相當(dāng)于匯編中的 RRC
- DS1302_CLK = 1;
- DS1302_CLK = 0;
- ACC = ACC >> 1;
- }
- }
- unsigned char DS1302OutputByte(void) //實時時鐘讀取一字節(jié)(內(nèi)部函數(shù))
- {
- unsigned char i;
- for(i=8; i>0; i--)
- {
- ACC = ACC >>1; //相當(dāng)于匯編中的 RRC
- ACC7 = DS1302_IO;
- DS1302_CLK = 1;
- DS1302_CLK = 0;
- }
- return(ACC);
- }
- void Write1302(unsigned char ucAddr, unsigned char ucDa) //ucAddr: DS1302地址, ucData: 要寫的數(shù)據(jù)
- {
- DS1302_RST = 0;
- DS1302_CLK = 0;
- DS1302_RST = 1;
- DS1302InputByte(ucAddr); // 地址,命令
- DS1302InputByte(ucDa); // 寫1Byte數(shù)據(jù)
- // DS1302_CLK = 1;
- DS1302_RST = 0;
- }
- unsigned char Read1302(unsigned char ucAddr) //讀取DS1302某地址的數(shù)據(jù)
- {
- unsigned char ucData;
- DS1302_RST = 0;
- DS1302_CLK = 0;
- DS1302_RST = 1;
- DS1302InputByte(ucAddr|0x01); // 地址,命令
- ucData = DS1302OutputByte(); // 讀1Byte數(shù)據(jù)
- // DS1302_CLK = 1;
- DS1302_RST = 0;
- return(ucData);
- }
- void DS1302_SetProtect(bit flag) //是否寫保護(hù)
- {
- if(flag)
- Write1302(0x8E,0x10);
- else
- Write1302(0x8E,0x00);
- }
- void DS1302_SetTime(unsigned char Address, unsigned char Value) // 設(shè)置時間函數(shù)
- {
- DS1302_SetProtect(0);
- Write1302(Address, ((Value/10)<<4 | (Value%10)));
- }
- void DS1302_GetTime(SYSTEMTIME *Time)
- {
- unsigned char ReadValue;
- ReadValue = Read1302(DS1302_SECOND);
- Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //八進(jìn)制轉(zhuǎn)換成十進(jìn)制
- ReadValue = Read1302(DS1302_MINUTE);
- Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
- ReadValue = Read1302(DS1302_HOUR);
- Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
- ReadValue = Read1302(DS1302_DAY);
- Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
- ReadValue = Read1302(DS1302_WEEK);
- Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
- ReadValue = Read1302(DS1302_MONTH);
- Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
- ReadValue = Read1302(DS1302_YEAR);
- Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
- }
- void DateToStr(SYSTEMTIME *Time) //
- {
- Time->DateString[0] = Time->Year/10 ; //分離出個位和十位
- Time->DateString[1] = Time->Year%10 ;
- Time->DateString[2] = '-';
- Time->DateString[3] = Time->Month/10;
- Time->DateString[4] = Time->Month%10 ;
- Time->DateString[5] = '-';
- Time->DateString[6] = Time->Day/10 ;
- Time->DateString[7] = Time->Day%10 ;
- Time->DateString[8] = '\0';
- }
- void TimeToStr(SYSTEMTIME *Time)
- {
- Time->TimeString[0] = Time->Hour/10 ;
- Time->TimeString[1] = Time->Hour%10 ;
- Time->TimeString[2] = ':';
- Time->TimeString[3] = Time->Minute/10 ;
- Time->TimeString[4] = Time->Minute%10 ;
- Time->TimeString[5] = ':';
- Time->TimeString[6] = Time->Second/10;
- Time->TimeString[7] = Time->Second%10 ;
- Time->DateString[8] = '\0';
- }
- void Initial_DS1302(void)
- {
- unsigned char Second=Read1302(DS1302_SECOND);
- if(Second&0x80)
- DS1302_SetTime(DS1302_SECOND,0);
- }
- void main( )
- {
- uchar i;
- uint HR_crc = 0;
- uint check = 0;
-
- SYSTEMTIME CurrentTime;
-
- P44 = 0;
- display_num = 0;
- mode_flag = 0;
- Serial_Init( ); //串口初始化
- Timer0_Init( ); //T0 初始化
- LCD_Init( );
- LCD_Clear( );//清屏
- Initial_DS1302( );
- Timer2_Init( );
-
- // DS1302_SetTime(DS1302_YEAR, 20); //設(shè)置時間
- // DS1302_SetTime(DS1302_MONTH, 03);
- // DS1302_SetTime(DS1302_DAY, 15);
- // DS1302_SetTime(DS1302_HOUR, 18); //設(shè)置時間
- // DS1302_SetTime(DS1302_MINUTE, 42);
- // DS1302_SetTime(DS1302_SECOND, 30);
-
- Delay_1ms(100);
- //---------開機(jī)指令--------------------
- for(i = 0; i < 9; i ++)
- {
- Serial_send(open[i]);
- Delay_1ms(1);
- }
- Delay_1ms(10);
- //---------將傳感器改為自動發(fā)送模式--------
- for(i = 0; i < 9; i ++)
- {
- Serial_send(autodata[i]);
- Delay_1ms(1);
- }
- Delay_1ms(10);
-
- while(1)
- {
- Display_cal( );
-
- DS1302_GetTime(&CurrentTime);
- DateToStr(&CurrentTime);
- TimeToStr(&CurrentTime);
-
- d0=CurrentTime.DateString[0];
- d1=CurrentTime.DateString[1];
- d2=CurrentTime.DateString[3];
- d3=CurrentTime.DateString[4];
- d4=CurrentTime.DateString[6];
- d5=CurrentTime.DateString[7];
-
- t0=CurrentTime.TimeString[0];
- t1=CurrentTime.TimeString[1];
- t2=CurrentTime.TimeString[3];
- t3=CurrentTime.TimeString[4];
- t4=CurrentTime.TimeString[6];
- t5=CurrentTime.TimeString[7];
-
- R_data = 1;
- /*------------------------------------------------
- // 在接收一幀數(shù)據(jù)后,首先檢驗接收數(shù)據(jù)是否正確
- // 若正確,將數(shù)據(jù)分解,然后顯示 */
- if(complete_flag == 1)
- {
- //--------------計算校驗和-------------------
- HR_crc = 0;
- check = 0;
- for(i = 0; i < 30; i ++)
- {
- HR_crc += USART_RX_BUF[i];
- }
- check = (((uint)USART_RX_BUF[30]) << 8) + USART_RX_BUF[31];
- //---------------------------------------------
- if((HR_crc == check)) //判斷接收的數(shù)據(jù)是否正確
- {
- //------------數(shù)據(jù)解析-------------------
- PM10_data[0] = USART_RX_BUF[8];
- PM10_data[1] = USART_RX_BUF[9];
- PM25_data[0] = USART_RX_BUF[6];
- PM25_data[1] = USART_RX_BUF[7];
- shuju_jiexi( ); //將檢測數(shù)值由十六進(jìn)制轉(zhuǎn)成ASCII碼
- }
- complete_flag = 0;
- }
-
- if(display_num == 0)
- {
- LCD_Write_String(0, 0, "PM2.5:");
- LCD_Write_Char(6, 0, PM_ASC[0] + '0');
- LCD_Write_Char(7, 0, PM_ASC[1] + '0');
- LCD_Write_Char(8, 0, PM_ASC[2] + '0');
- LCD_Write_Char(9, 0, PM_ASC[3] + '0');
- LCD_Write_String(10, 0, "ug/m3");
-
- LCD_Write_String(0, 1, "PM10:");
- LCD_Write_Char(5, 1, PM_ASC[4] + '0');
- LCD_Write_Char(6, 1, PM_ASC[5] + '0');
- LCD_Write_Char(7, 1, PM_ASC[6] + '0');
- LCD_Write_Char(8, 1, PM_ASC[7] + '0');
- LCD_Write_String(9, 1, "ug/m3");
- }
- else if(display_num == 1)
- {
- Set_Drive( );
-
- LCD_Write_String(0, 0, "SET PM2.5:");
- LCD_Write_String(5, 1, "PM10:");
-
- LCD_Write_Char(11, 0, PM_data_buf[0] + '0');
- LCD_Write_Char(12, 0, PM_data_buf[1] + '0');
- LCD_Write_Char(13, 0, PM_data_buf[2] + '0');
- LCD_Write_Char(14, 0, PM_data_buf[3] + '0');
-
- LCD_Write_Char(10, 1, PM_data_buf[4] + '0');
- LCD_Write_Char(11, 1, PM_data_buf[5] + '0');
- LCD_Write_Char(12, 1, PM_data_buf[6] + '0');
- LCD_Write_Char(13, 1, PM_data_buf[7] + '0');
- }
- else
- {
- LCD_Write_String(3, 0, "20");
- LCD_Write_Char(5, 0, d0 + '0');
- LCD_Write_Char(6, 0, d1 + '0');
- LCD_Write_Char(7, 0, '-');
- LCD_Write_Char(8, 0, d2 + '0');
- LCD_Write_Char(9, 0, d3 + '0');
- LCD_Write_Char(10, 0, '-');
- LCD_Write_Char(11, 0, d4 + '0');
- LCD_Write_Char(12, 0, d5 + '0');
-
- LCD_Write_Char(4, 1, t0 + '0');
- LCD_Write_Char(5, 1, t1 + '0');
- LCD_Write_Char(6, 1, ':');
- LCD_Write_Char(7, 1, t2 + '0');
- LCD_Write_Char(8, 1, t3 + '0');
- LCD_Write_Char(9, 1, ':');
- LCD_Write_Char(10, 1, t4 + '0');
- LCD_Write_Char(11, 1, t5 + '0');
- }
-
- if(mode_flag == 1)//光標(biāo)閃爍
- {
- switch(bit_select_counter)
- {
- case 0:
- LCD_Write_Com(0x80 + 11);
- LCD_Write_Com(0x0f);
- break;
- case 1:
- LCD_Write_Com(0x80 + 12);
- LCD_Write_Com(0x0f);
- break;
- case 2:
- LCD_Write_Com(0x80 + 13);
- LCD_Write_Com(0x0f);
- break;
- case 3:
- LCD_Write_Com(0x80 + 14);
- LCD_Write_Com(0x0f);
- break;
- case 4:
- LCD_Write_Com(0xC0 + 10);
- LCD_Write_Com(0x0f);
- break;
- case 5:
- LCD_Write_Com(0xC0 + 11);
- LCD_Write_Com(0x0f);
- break;
- case 6:
- LCD_Write_Com(0xC0 + 12);
- LCD_Write_Com(0x0f);
- break;
- case 7:
- LCD_Write_Com(0xC0 + 13);
- LCD_Write_Com(0x0f);
- break;
- }
- }
- if(mode_flag == 0)
- {
- LCD_Write_Com(0x0C); /*顯示開及光標(biāo)設(shè)置*/
-
- PM25_2 = PM_data_buf[0] * 1000 + PM_data_buf[1] * 100 + PM_data_buf[2] * 10 + PM_data_buf[3];
- PM10_2 = PM_data_buf[4] * 1000 + PM_data_buf[5] * 100 + PM_data_buf[6] * 10 + PM_data_buf[7];
-
- if(PM25_1 >= PM25_2 || PM10_1 >= PM10_2)
- {
- P44 = 1;
- KKK = 1;
- }
- else
- {
- P44 = 0;
- KKK = 0;
- }
- if(KKK == 1)
- {
- if(PM25_1 >= PM25_2)
- {
- P24 = 0;
- Delay_1ms(20);
- P24 = 1;
- Delay_1ms(20);
- }
- else
- {
- P24 = 1;
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復(fù)制代碼
所有資料51hei提供下載:
pcb+源程序.7z
(1.71 MB, 下載次數(shù): 48)
2020-3-18 15:34 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|
評分
-
查看全部評分
|