欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 7902|回復: 6
打印 上一主題 下一主題
收起左側

單片機PM2.5檢測儀的PCB+原理圖+程序設計資料

  [復制鏈接]
跳轉到指定樓層
樓主
很高興來到這里。
Altium Designer畫的原理圖和PCB圖如下:(51hei附件中可下載工程文件)



元件清單:
單片機STC89C52    1片
單片機座    1個
晶振11.0592M    1個
獨石電容30pF    2個
電解電容10uF    1個
電解電容220uF    1個
電阻10K    1個
排阻10K(103)    1片
按鍵    2個
1602液晶    1個
1602液晶座    1個
電位器10K(103)    1個
PM2.5傳感器 GP2Y1051AU0F    1個
有源蜂鳴器    1個
S8550(PNP)三極管    1個
洞洞板9*15cm    1張
電源座    1個
電源開關    1個
電源線    1根


      為什么會有兩個原理圖呢?                                      
                                                                                                           
      1、兩個原理圖本質是一樣的,只不過連接方式不同而已。                                                     
      2、原理圖1是以模塊化的形式展現,模塊和模塊之間通過網絡編號                                                  
         關聯起來,這樣連接的好處是整個原理圖看起來非常簡潔明了。   
                                                      
                                                                    
      3、原理圖2中,各個元件都通過導線連接起來,好處是看起來比較                                                         
         直觀,缺點是整個圖給人的感覺比較亂。                       
                                                                     
                                                                    
      4、建議,最好是采用原理圖1的連接方式,這種修改和查看都         
         都比較方便的。之所以還給了一個原理圖2,是滿足部分有強迫   
         癥的同學,他們沒看到有導線相連,總覺得不對。其實原理圖1                                                         
         這種網絡編號連接才是規范的。                              
                                                                    
         以后出去工作接觸的項目,要么一個芯片上百個引腳,要么一個   
         原理圖上百個元件,要是都通過線來連接,可以想象整個原理圖   
         將是多么的亂,已經失去了原理圖的意義了,所以還是建議采用   
         模塊化的思想來畫原理圖。


     一、程序用什么軟件查看?                                                                             
      打開程序的軟件是Keil,我們提供了相關的安裝包,放在資料包                                                                        
      《24、軟件--Keil 安裝包》里面。                              
                                                                                                                       
     二、如何復制到word?                                          
                                                                    
      1、進入“程序(Keil版)”這個文件夾;                                                                                       
      2、找到“main.c”這個文件,程序源碼就在這個文件里面;                                                         
      3、用電腦自帶的記事本軟件可以打開這個“main.c”文件;                                                                    
      4、用記事本打開之后,自己復制到word就可以了;                                                                              
                                                                    
     三、如何下載程序到板子上?                                    
                                                                    
      我們提供了下載程序的視頻教程,放在資料包《19、如何下載                              
      單片機程序》。

單片機源程序如下:
  1. #include <reg52.h>
  2. #include <intrins.h>

  3. #define uchar unsigned char                // 以后unsigned char就可以用uchar代替
  4. #define uint  unsigned int                // 以后unsigned int 就可以用uint 代替

  5. sfr ISP_DATA  = 0xe2;                        // 數據寄存器
  6. sfr ISP_ADDRH = 0xe3;                        // 地址寄存器高八位
  7. sfr ISP_ADDRL = 0xe4;                        // 地址寄存器低八位
  8. sfr ISP_CMD   = 0xe5;                        // 命令寄存器
  9. sfr ISP_TRIG  = 0xe6;                        // 命令觸發寄存器
  10. sfr ISP_CONTR = 0xe7;                        // 命令寄存器

  11. sbit LcdRs_P  = P2^7;     // 1602液晶的RS管腳      
  12. sbit LcdRw_P  = P2^6;     // 1602液晶的RW管腳
  13. sbit LcdEn_P  = P2^5;     // 1602液晶的EN管腳
  14. sbit Key1_P   = P3^2;                        // 減按鍵
  15. sbit Key2_P   = P3^3;                        // 加按鍵
  16. sbit Buzzer_P = P1^0;                        // 蜂鳴器


  17. uint  gAlarm ;                                                // 報警值
  18. uchar gIndex=0;                                                // 串口接收索引
  19. uint  Value[20]={0};                        // 串口數據緩存區


  20. /*********************************************************/
  21. // 單片機內部EEPROM不使能
  22. /*********************************************************/
  23. void ISP_Disable()
  24. {
  25.         ISP_CONTR = 0;
  26.         ISP_ADDRH = 0;
  27.         ISP_ADDRL = 0;
  28. }


  29. /*********************************************************/
  30. // 從單片機內部EEPROM讀一個字節,從0x2000地址開始
  31. /*********************************************************/
  32. unsigned char EEPROM_Read(unsigned int add)
  33. {
  34.         ISP_DATA  = 0x00;
  35.         ISP_CONTR = 0x83;
  36.         ISP_CMD   = 0x01;
  37.         ISP_ADDRH = (unsigned char)(add>>8);
  38.         ISP_ADDRL = (unsigned char)(add&0xff);
  39.         // 對STC89C51系列來說,每次要寫入0x46,再寫入0xB9,ISP/IAP才會生效
  40.         ISP_TRIG  = 0x46;          
  41.         ISP_TRIG  = 0xB9;
  42.         _nop_();
  43.         ISP_Disable();
  44.         return (ISP_DATA);
  45. }


  46. /*********************************************************/
  47. // 往單片機內部EEPROM寫一個字節,從0x2000地址開始
  48. /*********************************************************/
  49. void EEPROM_Write(unsigned int add,unsigned char ch)
  50. {
  51.         ISP_CONTR = 0x83;
  52.         ISP_CMD   = 0x02;
  53.         ISP_ADDRH = (unsigned char)(add>>8);
  54.         ISP_ADDRL = (unsigned char)(add&0xff);
  55.         ISP_DATA  = ch;
  56.         ISP_TRIG  = 0x46;
  57.         ISP_TRIG  = 0xB9;
  58.         _nop_();
  59.         ISP_Disable();
  60. }


  61. /*********************************************************/
  62. // 擦除單片機內部EEPROM的一個扇區
  63. // 寫8個扇區中隨便一個的地址,便擦除該扇區,寫入前要先擦除
  64. /*********************************************************/
  65. void Sector_Erase(unsigned int add)          
  66. {
  67.         ISP_CONTR = 0x83;
  68.         ISP_CMD   = 0x03;
  69.         ISP_ADDRH = (unsigned char)(add>>8);
  70.         ISP_ADDRL = (unsigned char)(add&0xff);
  71.         ISP_TRIG  = 0x46;
  72.         ISP_TRIG  = 0xB9;
  73.         _nop_();
  74.         ISP_Disable();
  75. }


  76. /*********************************************************/
  77. // 毫秒級的延時函數,time是要延時的毫秒數
  78. /*********************************************************/
  79. void DelayMs(uint time)
  80. {
  81.         uint i,j;
  82.         for(i=0;i<time;i++)
  83.                 for(j=0;j<112;j++);
  84. }


  85. /*********************************************************/
  86. // 1602液晶寫命令函數,cmd就是要寫入的命令
  87. /*********************************************************/
  88. void LcdWriteCmd(uchar cmd)
  89. {
  90.         LcdRs_P = 0;
  91.         LcdRw_P = 0;
  92.         LcdEn_P = 0;
  93.         P0=cmd;
  94.         DelayMs(2);
  95.         LcdEn_P = 1;   
  96.         DelayMs(2);
  97.         LcdEn_P = 0;       
  98. }


  99. /*********************************************************/
  100. // 1602液晶寫數據函數,dat就是要寫入的數據
  101. /*********************************************************/
  102. void LcdWriteData(uchar dat)
  103. {
  104.         LcdRs_P = 1;
  105.         LcdRw_P = 0;
  106.         LcdEn_P = 0;
  107.         P0=dat;
  108.         DelayMs(2);
  109.         LcdEn_P = 1;   
  110.         DelayMs(2);
  111.         LcdEn_P = 0;
  112. }


  113. /*********************************************************/
  114. // 1602液晶初始化函數
  115. /*********************************************************/
  116. void LcdInit()
  117. {
  118.         LcdWriteCmd(0x38);        // 16*2顯示,5*7點陣,8位數據口
  119.         LcdWriteCmd(0x0C);        // 開顯示,不顯示光標
  120.         LcdWriteCmd(0x06);        // 地址加1,當寫入數據后光標右移
  121.         LcdWriteCmd(0x01);        // 清屏
  122. }


  123. /*********************************************************/
  124. // 液晶光標定位函數
  125. /*********************************************************/
  126. void LcdGotoXY(uchar line,uchar column)
  127. {
  128.         // 第一行
  129.         if(line==0)        
  130.                 LcdWriteCmd(0x80+column);
  131.          // 第二行
  132.         if(line==1)        
  133.                 LcdWriteCmd(0x80+0x40+column);
  134. }


  135. /*********************************************************/
  136. // 液晶輸出數字
  137. /*********************************************************/
  138. void LcdPrintNum(uint num)
  139. {
  140.         if(num>999)
  141.         {
  142.                 LcdWriteData(num/1000+48);                        // 如果有千位,則輸出千位
  143.         }
  144.         else                                                                                                                        // 如果沒有千位,則輸出空格
  145.         {
  146.                 LcdWriteData(' ');
  147.         }
  148.         LcdWriteData(num%1000/100+48);                // 百位
  149.         LcdWriteData(num%100/10+48);                        // 十位
  150.         LcdWriteData(num%10+48);                                         // 個位
  151. }


  152. /*********************************************************/
  153. // 液晶輸出字符串函數
  154. /*********************************************************/
  155. void LcdPrintStr(uchar *str)
  156. {
  157.         while(*str!='\0')
  158.                 LcdWriteData(*str++);
  159. }


  160. /*********************************************************/
  161. // 液晶顯示內容初始化
  162. /*********************************************************/
  163. void LcdShowInit()
  164. {
  165.         LcdGotoXY(0,0);                                // 液晶光標定位到第0行第0列
  166.         LcdPrintStr("PM2.5:     ug/m3");
  167.         LcdGotoXY(1,0);                                // 液晶光標定位到第1行第0列
  168.         LcdPrintStr("Alarm:     ug/m3");
  169. }



  170. /*********************************************************/
  171. // 串口初始化
  172. /*********************************************************/
  173. void UartInit()
  174. {
  175.         TMOD = 0x20;
  176.         SCON = 0x50;
  177.         TH1  = 0xf4;
  178.         TL1  = 0xf4;
  179.         TR1  = 1;
  180.         REN  = 1;
  181.         EA   = 1;
  182.         ES   = 1;
  183. }


  184. /*********************************************************/
  185. // 按鍵掃描
  186. /*********************************************************/
  187. void KeyScanf()
  188. {
  189.         /* 減按鍵被按下 */
  190.         if(Key1_P==0)               
  191.         {
  192.                 if(gAlarm>1)                                                                                                // 只有報警值大于1,才能完成減操作
  193.                 {
  194.                         gAlarm--;                                                                                                        // 報警值減1
  195.                         LcdGotoXY(1,6);                                                                                // 液晶定位到第1行第6列
  196.                         LcdPrintNum(gAlarm);                                                        // 顯示報警濃度值
  197.                         Sector_Erase(0x2000);                                                         // 存儲之前必須先擦除
  198.                         EEPROM_Write(0x2000,gAlarm/100);        // 存儲新的報警值
  199.                         EEPROM_Write(0x2001,gAlarm%100);       
  200.                 }
  201.         }
  202.        
  203.         /* 減按鍵被按下 */
  204.         if(Key2_P==0)
  205.         {
  206.                 if(gAlarm<1300)                                                                                        // 只有報警值小于1300,才能完成加操作
  207.                 {
  208.                         gAlarm++;                                                                                                        // 報警值加1
  209.                         LcdGotoXY(1,6);                                                                                // 液晶定位到第1行第6列
  210.                         LcdPrintNum(gAlarm);                                                        // 顯示報警濃度值
  211.                         Sector_Erase(0x2000);                                                         // 存儲之前必須先擦除
  212.                         EEPROM_Write(0x2000,gAlarm/100);        // 存儲新的報警值
  213.                         EEPROM_Write(0x2001,gAlarm%100);       
  214.                 }
  215.         }
  216. }


  217. /*********************************************************/
  218. // 報警判斷
  219. /*********************************************************/
  220. void AlarmJudge(uint num)
  221. {
  222.         if(num>gAlarm)       
  223.                 Buzzer_P=0;                // 開啟蜂鳴器報警
  224.         else
  225.                 Buzzer_P=1;                // 停止蜂鳴器報警
  226. }


  227. /*********************************************************/
  228. // 主函數
  229. /*********************************************************/
  230. void main(void)
  231. {
  232.         uchar i;                                // 循環變量
  233.         uint ret;                                // 保存測量結果
  234.        
  235.         gAlarm=EEPROM_Read(0x2000)*100+EEPROM_Read(0x2001);                // 上電時,先讀取報警值
  236.         if((gAlarm==0)||(gAlarm>999))                                                                                                        // 如果讀取到的報警值異常,則重新賦值
  237.                 gAlarm=200;
  238.                
  239.        
  240.         LcdInit();                                            // 液晶功能初始化
  241.         LcdShowInit();                                        // 液晶顯示初始化
  242.         UartInit();                                                        // 串口初始化

  243.         LcdGotoXY(1,6);                                        // 液晶定位到第1行第6列
  244.         LcdPrintNum(gAlarm);                // 顯示報警濃度值
  245.        
  246.         while(1)
  247.         {
  248.                 ret=0;                                                                                        // 清零測量結果
  249.                 for(i=0;i<20;i++)                                                // 將最新的20個測量結果求和
  250.                 {
  251.                         ret=ret+Value[i];
  252.                 }
  253.                 ret=ret/20;                                                                        // 再除以20求得平均值
  254.                
  255.                 ret=((ret*5)/1024.0)*380;                // 將讀取到的電壓值轉換為灰塵濃度值       
  256.                
  257.                 LcdGotoXY(0,6);                                                        // 液晶定位到第0行第6列
  258.                 LcdPrintNum(ret);                                                // 顯示測量結果
  259.                
  260.                 AlarmJudge(ret);                                                // 判斷是否需要報警
  261.                
  262.                 KeyScanf();                                                                        // 進行按鍵掃描,判斷是否有按鍵按下
  263. ……………………

  264. …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼


全部資料51hei下載地址:
10、元件清單.rar (2.97 KB, 下載次數: 82)
07、單片機程序.rar (39.13 KB, 下載次數: 117)
08、電路圖(原理圖和PCB圖).rar (514.6 KB, 下載次數: 129)


評分

參與人數 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏7 分享淘帖 頂1 踩
回復

使用道具 舉報

沙發
ID:585455 發表于 2019-7-22 22:15 | 只看該作者
感謝分享
回復

使用道具 舉報

板凳
ID:689272 發表于 2020-2-1 18:05 | 只看該作者
感謝分享
回復

使用道具 舉報

地板
ID:441206 發表于 2020-2-14 16:30 來自觸屏版 | 只看該作者
怎么下載啊
回復

使用道具 舉報

5#
ID:692917 發表于 2020-2-15 19:04 | 只看該作者
感謝資料分享
回復

使用道具 舉報

6#
無效樓層,該帖已經被刪除
7#
ID:741640 發表于 2020-5-1 14:32 | 只看該作者
怎末沒有仿真啊
回復

使用道具 舉報

8#
無效樓層,該帖已經被刪除
9#
無效樓層,該帖已經被刪除
10#
ID:47293 發表于 2021-8-29 11:58 | 只看該作者
你的PM2.5傳感器輸出是模擬信號,為何直接送給了單片機?不需要AD轉換?
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表