久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

基于stc15單片機的只能藍牙溫控風扇程序

[復制鏈接]
跳轉到指定樓層
樓主
ID:944617 發表于 2021-6-25 15:46 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
  1. #include <stc15.h>
  2. #include <string.h>
  3. #include <stdio.h>
  4. #include <intrins.h>

  5. #define u8 unsigned char
  6. #define u16 unsigned int
  7. /*串口*/        
  8. #define FOSC 12000000L                         //系統頻率
  9. #define BAUD 9600                                 //串口波特率
  10. #define TM (65536 - (FOSC/4/BAUD))
  11. /*LCD1602*/
  12. #define LCD_Set 0x38                   //顯示初始化: 16*2顯示,5*7點陣,8位數
  13. #define LCD_Clear 0x01                //清屏
  14. #define LCD_Display 0x0C        //顯示功能設置:開顯示,不顯示光標,光標不閃爍
  15. #define LCD_Mode 0x06                //設置光標狀態:讀一個字符光標加1
  16. #define LCD_1 0x80                        //第一行起始地址
  17. #define LCD_2 (0x80+0x40)        //第二行起始地址
  18. /*EEPROM*/
  19. #define CMD_IDLE 0                 //空閑模式
  20. #define CMD_READ 1                 //IAP字節讀命令
  21. #define CMD_PROGRAM 2         //IAP字節編程命令
  22. #define CMD_ERASE 3         //IAP扇區擦除命令
  23. //#define ENABLE_IAP 0x80 //if SYSCLK<30MHz
  24. //#define ENABLE_IAP 0x81 //if SYSCLK<24MHz
  25. #define ENABLE_IAP 0x82 //if SYSCLK<20MHz
  26. //#define ENABLE_IAP 0x83 //if SYSCLK<12MHz
  27. //#define ENABLE_IAP 0x84 //if SYSCLK<6MHz
  28. //#define ENABLE_IAP 0x85 //if SYSCLK<3MHz
  29. //#define ENABLE_IAP 0x86 //if SYSCLK<2MHz
  30. //#define ENABLE_IAP 0x87 //if SYSCLK<1MHz
  31. #define ENABLE_IAP 0x82   
  32. #define  KEY1_PRES  1
  33. #define  KEY2_PRES  2
  34. #define  KEY3_PRES  3
  35. #define  KEY4_PRES  4
  36. sbit KEY1=P3^2;
  37. sbit KEY2=P3^3;
  38. sbit KEY3=P3^4;
  39. sbit KEY4=P3^5;
  40. u8 TEMP_String[10];
  41. u8 HUMI_String[10];
  42. u8 TH_String[4];
  43. u8 TL_String[4];
  44. sbit DHT11_Data=P1^0;
  45. sbit RS=P2^5;
  46. sbit RW=P2^6;
  47. sbit E=P2^7;
  48. sbit IN1=P1^1;
  49. sbit IN2=P1^2;
  50. sbit ENA=P1^3;
  51. sbit LED=P4^5;
  52. sbit Buzz=P5^5;
  53. u16 TH=30;
  54. u16 TL=15;
  55. u8 Flag=0;
  56. float temperature;
  57. void GPIO(void)
  58. {
  59.         P0M0=0;
  60.         P0M1=0;
  61.         P1M0=0;
  62.         P1M1=0;
  63.         P2M0=0;
  64.         P2M1=0;
  65.         P3M0=0;
  66.         P3M1=0;
  67.         P4M0=0;
  68.         P4M1=0;
  69.         P5M0=0;
  70.         P5M1=0;
  71. }

  72. void delay_ms(u16 ms)
  73. {
  74.         u16 i,j;
  75.         for(i=0;i<ms;i++)
  76.                 for(j=0;j<1147;j++);        //在12MHz時,1ms
  77. }
  78. void delay_30us(void)
  79. {
  80.         u16 i;
  81.         for(i=0;i<20;i++)
  82.                 _nop_();        
  83. }
  84. /*寫控制命令函數*LCD1602*/
  85. void Write_Command(u8 Comm)
  86. {
  87.         RS=0;
  88.         RW=0;
  89.         P0=Comm;
  90.         E=1;
  91.         delay_ms(1);
  92.         E=0;
  93. }

  94. /*寫數據函數*/
  95. void Write_Data(u8 Data)
  96. {
  97.         RS=1;
  98.         RW=0;
  99.         P0=Data;
  100.         E=1;
  101.         delay_ms(1);
  102.         E=0;
  103. }

  104. /*LCD1602初始化*/
  105. void LCD1602_Init(void)
  106. {
  107.         Write_Command(LCD_Set);
  108.         Write_Command(LCD_Display);
  109.         Write_Command(LCD_Mode);
  110.         Write_Command(LCD_Clear);
  111.         delay_ms(5);
  112.         
  113. }
  114. /*LCD1602在某行某列顯示一個字符*/
  115. void LCD1602_Print_Char(u8 line,u8 Addr,u8 Data)
  116. {
  117.         if(line)
  118.         {
  119.                 Write_Command(LCD_2+Addr);
  120.                 Write_Data(Data);
  121.                
  122.         }
  123.         else
  124.         {
  125.                 Write_Command(LCD_1+Addr);
  126.                 Write_Data(Data);
  127.                
  128.         }
  129. }
  130. /*LCD1602在某行顯示一串字符*/
  131. void LCD1602_Print_String(u8 line,u8 *table)
  132. {
  133.         u8 i;
  134.         if(line)
  135.         {
  136.                 Write_Command(LCD_2);
  137.         }
  138.         else
  139.         {
  140.                 Write_Command(LCD_1);
  141.         }
  142.         for(i=0;i<16;i++)
  143.         {
  144.                 Write_Data(table[i]);
  145.         }
  146. }
  147. //復位DHT11
  148. void DHT11_Rst(void)           
  149. {                 
  150.     DHT11_Data=0;         //拉低Data
  151.     delay_ms(20);            //至少18ms
  152.     DHT11_Data=1;         //Data=1
  153.          delay_30us();
  154. }
  155. //等待DHT11的回應
  156. //返回1:未檢測到DHT11的存在
  157. //返回0:存在
  158. u8 DHT11_Check(void)            
  159. {   
  160.         u8 retry=0;
  161.         while (DHT11_Data&&retry<100)//DHT11會拉低40~80us
  162.         {
  163.                 retry++;
  164.         }         
  165.         if(retry>=100)return 1;
  166.         else retry=0;
  167.     while (!DHT11_Data&&retry<100)//DHT11拉低后會再次提高40~80us
  168.         {
  169.                 retry++;
  170.         }
  171.         if(retry>=100)return 1;            
  172.         return 0;
  173. }
  174. //從DHT11讀取一個位
  175. //返回值:1/0
  176. u8 DHT11_Read_Bit(void)                          
  177. {
  178.          u8 retry=0;
  179.         while(DHT11_Data&&retry<100)//等待變成低電平
  180.         {
  181.                 retry++;
  182.         }
  183.         retry=0;
  184.         while(!DHT11_Data&&retry<100)//等待變成高電平
  185.         {
  186.                 retry++;
  187.         }
  188.         delay_30us();
  189.         if(DHT11_Data)return 1;
  190.         else return 0;                  
  191. }
  192. //從DHT11讀取一個字節
  193. //返回值:讀到的數據
  194. u8 DHT11_Read_Byte(void)   
  195. {        
  196.     u8 i,dat;
  197.     dat=0;
  198.         for (i=0;i<8;i++)
  199.         {
  200.                    dat<<=1;
  201.                      dat|=DHT11_Read_Bit();
  202.     }                                                   
  203.     return dat;
  204. }
  205. //從DHT11讀取一次數據
  206. //temp:溫度值(范圍:0~50°)
  207. //humi:濕度值(范圍:20%~90%)
  208. //返回值:0,正常;1,讀取失敗
  209. u8 DHT11_Read_Data(u8 *temp,u8 *humi)   
  210. {        
  211.          u8 buf[5];
  212.         u8 i;
  213.         DHT11_Rst();
  214.         if(DHT11_Check()==0)
  215.         {
  216.                 for(i=0;i<5;i++)//讀取40位數據
  217.                 {
  218.                         buf[i]=DHT11_Read_Byte();
  219.                 }
  220.                 if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
  221.                 {
  222.                         *humi=buf[0];
  223.                         *temp=buf[2];
  224.                 }
  225.         }
  226.         else return 1;
  227.         return 0;            
  228. }
  229. //初始化DHT11的IO口 DQ 同時檢測DHT11的存在
  230. //返回1:不存在
  231. //返回0:存在
  232. u8 DHT11_Init(void)
  233. {
  234.         DHT11_Rst();
  235.         return DHT11_Check();
  236. }
  237. void OtoC2(u8 value,u8 String[ ])
  238. {
  239.         String[0]=value/10+0x30;
  240.         String[1]=value%10+0x30;

  241. }
  242. void String_Join2bit(u8 Long_String [],u8 Short_String[],u8 Position)
  243. {
  244.          u8 i;
  245.         for(i=0;i<2;i++)
  246.                 Long_String[Position+i]=Short_String[i];        
  247. }
  248. /*按鍵掃描程序*/
  249. u8 KEY_Scan(u8 mode)
  250. {
  251.     static u8 key_up=1;//按鍵松開標志
  252.     if(mode)key_up=1; //支持連按
  253.     if(key_up&&(KEY1==0||KEY2==0||KEY3==0||KEY4==0))
  254.     {
  255.         delay_ms (10);//去抖動
  256.         key_up=0;
  257.         if(KEY1==0)
  258.                           return KEY1_PRES;
  259.         else if(KEY2==0)
  260.                           return KEY2_PRES;
  261.                                 else if(KEY3==0)
  262.                           return KEY3_PRES;
  263.                                 else if(KEY4==0)
  264.                           return KEY4_PRES;
  265.     }
  266.     else if(KEY1==1&&KEY2==1&&KEY3==1&&KEY4==1)
  267.         key_up=1;
  268.     return 0;// 無按鍵按下
  269. }
  270. /*----------------------------
  271.                         關閉IAP
  272. ----------------------------*/
  273. void IapIdle()
  274. {
  275.         IAP_CONTR = 0;         //關閉IAP功能
  276.         IAP_CMD = 0;                 //清除命令寄存器
  277.         IAP_TRIG = 0;                 //清除觸發寄存器
  278.         IAP_ADDRH = 0x80; //將地址設置到非IAP區域
  279.         IAP_ADDRL = 0;
  280. }
  281. /*----------------------------
  282. 從ISP/IAP/EEPROM區域讀取一字節
  283. ----------------------------*/
  284. u8 IapReadByte(u16 addr)
  285. {
  286.         u8 dat;                                                         //數據緩沖區
  287.         IAP_CONTR = ENABLE_IAP;         //使能IAP
  288.         IAP_CMD = CMD_READ;                         //設置IAP命令
  289.         IAP_ADDRL = addr;                         //設置IAP低地址
  290.         IAP_ADDRH = addr >> 8;                 //設置IAP高地址
  291.         IAP_TRIG = 0x5a;                                 //寫觸發命令(0x5a)
  292.         IAP_TRIG = 0xa5;                                 //寫觸發命令(0xa5)
  293.         _nop_();                                                 //等待ISP/IAP/EEPROM操作完成
  294.         dat = IAP_DATA;                                 //讀ISP/IAP/EEPROM數據
  295.         IapIdle();                                                 //關閉IAP功能
  296.         return dat;                                         //返回
  297. }
  298. /*----------------------------
  299. 寫一字節數據到ISP/IAP/EEPROM區域
  300. ----------------------------*/
  301. void IapProgramByte(u16 addr, u8 dat)
  302. {
  303.         IAP_CONTR = ENABLE_IAP;         //使能IAP
  304.         IAP_CMD = CMD_PROGRAM;                 //設置IAP命令
  305.         IAP_ADDRL = addr;                         //設置IAP低地址
  306.         IAP_ADDRH = addr >> 8;                 //設置IAP高地址
  307.         IAP_DATA = dat;                                 //寫ISP/IAP/EEPROM數據
  308.         IAP_TRIG = 0x5a;                                 //寫觸發命令(0x5a)
  309.         IAP_TRIG = 0xa5;                                 //寫觸發命令(0xa5)
  310.         _nop_();                                                 //等待ISP/IAP/EEPROM操作完成
  311.         IapIdle();
  312. }

  313. /*----------------------------
  314.                         扇區擦除
  315. ----------------------------*/
  316. void IapEraseSector(u16 addr)
  317. {
  318.         IAP_CONTR = ENABLE_IAP;         //使能IAP
  319.         IAP_CMD = CMD_ERASE;                 //設置IAP命令
  320.         IAP_ADDRL = addr;                         //設置IAP低地址
  321.         IAP_ADDRH = addr >> 8;                 //設置IAP高地址
  322.         IAP_TRIG = 0x5a;                                 //寫觸發命令(0x5a)
  323.         IAP_TRIG = 0xa5;                                 //寫觸發命令(0xa5)
  324.         _nop_();                                                 //等待ISP/IAP/EEPROM操作完成
  325.         IapIdle();
  326. }
  327. /*PWM初始化*/
  328. void PWM_Init(void)
  329. {
  330.         P_SW1 &= ~(1<<4|1<<5);         //在P1.0、P1.1輸出        
  331.         CCON = 0;         //初始化PCA寄存器
  332.         CL = 0;         //復位PCA寄存器
  333.         CH = 0;
  334.         CMOD = 0x02;                 //設置PCA時鐘源SYSCLK/2
  335.         PCA_PWM0  = 0x00;         //PCA模塊0工作于8位PWM
  336.         CCAP0H = CCAP0L = 0x00;         //PWM0的占空比為100%
  337.         CCAPM0 = 0x42;         //允許比較器功能、脈寬調節輸出
  338.         CR = 1;                 //PCA定時器開始工作
  339. }
  340. /*風扇轉動*/
  341. void zhuan(float temperature)
  342. {               
  343.                 u8 i;
  344.         if((temperature>TH)&&(Flag==0)) //如果溫度大于上限,則報警20次,并且使用全力風速
  345.                   
  346.         {//                IN1=1;
  347.                         IN2=0;
  348.                         
  349.                         for(i=0;i<20;i++)
  350.                         {
  351.                         LED=0;
  352.                         Buzz=0;
  353.                         delay_ms (100);
  354.                         LED=1;
  355.                         Buzz=1;
  356.                         delay_ms (100);
  357.                         }
  358.                         CCAP0H = CCAP0L = 0x00; //PWM0的占空比為100%
  359.                         Flag=1;
  360.                 }
  361.                
  362.          else if((TL<temperature)&&(temperature<TH))//大于下限,小于上限則為中速風力
  363.                 {
  364. //                IN1=~IN1;
  365.                         IN2=0;
  366.                         LED=1;
  367.                         Buzz=1;
  368.                         CCAP0H = CCAP0L = 0x80;//PWM0的占空比為50%
  369.       Flag=0;                        
  370.                 }
  371.                 else if((temperature<TL)&&(Flag==0))//小于下限則停止轉動
  372.                 {
  373. //                IN1=1;
  374.                         IN2=0;
  375.                         for(i=0;i<20;i++)
  376.                         {
  377.                         LED=0;
  378.                         Buzz=0;
  379.                         delay_ms (100);
  380.                         LED=1;
  381.                         Buzz=1;
  382.                         delay_ms (100);
  383.                         }
  384.                         CCAP0H = CCAP0L = 0xFF; //PWM0的占空比為0%
  385.                         Flag=1;
  386.                 }
  387. }
  388. /*串口中斷程序*/
  389. void Uart1_INT() interrupt 4 using 1//使用藍牙遙控;
  390. {
  391.         u8 Ch;
  392.         if (RI)
  393.         {
  394.                 RI = 0;         //清除RI位
  395.                 Ch= SBUF;         //將接收到的字符保存
  396.                 switch (Ch)        
  397.                 {
  398.                         case '1':
  399.                         {
  400.                                 TH++;
  401.                         IapEraseSector(0);
  402.                         IapProgramByte(0,TH);        //寫EEPROM上限
  403.                         IapProgramByte(1,TL);        //寫EEPROM下限
  404.                                 break;
  405.                         }
  406.                         case '2':
  407.                         {
  408.                                 TH--;
  409.                         IapEraseSector(0);
  410.                         IapProgramByte(0,TH);        //寫EEPROM上限
  411.                         IapProgramByte(1,TL);        //寫EEPROM下限
  412.                                 break;
  413.                         }
  414.                         case '3':
  415.                         {
  416.                                 TL++;
  417.                         IapEraseSector(0);
  418.                         IapProgramByte(0,TH);        //寫EEPROM上限
  419.                         IapProgramByte(1,TL);        //寫EEPROM下限
  420.                                 break;
  421.                         }
  422.                         case '4':
  423.                         {
  424.                                 TL--;
  425.                         IapEraseSector(0);
  426.                         IapProgramByte(0,TH);        //寫EEPROM上限
  427.                         IapProgramByte(1,TL);        //寫EEPROM下限
  428.                                 break;
  429.                         }
  430.                         case '5':
  431.                         {
  432.                                 IN2=0;
  433.                                 CCAP0H = CCAP0L = 0x00; //PWM0的占空比為100%
  434.                                 break;
  435.                         }
  436.                         case '6':
  437.                         {
  438.                                 IN1=1;
  439.                                 IN2=1;
  440.                                 break;
  441.                         }
  442.                         case 'G':
  443.                         {
  444.                                 IN2=0;
  445.                                 CCAP0H = CCAP0L = 0x40; //PWM0的占空比為75%
  446.                                 break;
  447.                         }
  448.                         case 'K':
  449.                         {
  450.                                 IN2=0;
  451.                                 CCAP0H = CCAP0L = 0xC0; //PWM0的占空比為25%
  452.                                 break;
  453.                         }
  454.                 }
  455.         }
  456. }
  457. /*串口初始化*/
  458. void UART1_Init(void)
  459. {
  460.         SCON = 0x50;        //方式1,8位UART,波特率可變
  461.         AUXR |= 1<<2|1<<0;         //定時器2為1T模式,UART1使用T2
  462. //        TMOD = 0x00;         //定時器1為模式0(16位自動重載)
  463.         T2L = TM; //設置波特率重裝值
  464.         T2H = TM>>8;
  465.         AUXR |= 1<<4; //定時器2啟動
  466.         ES = 1; //使能串口中斷
  467.         EA = 1;
  468. }

  469. int main(void)
  470. {
  471.         u8 t=0;
  472.         u8 temperature=0;              
  473.         u8 humidity=0;
  474. //        u8 TH_EEPROM_Value,TL_EEPROM_Value;        定義EEPROM溫度上下限變量  
  475.         u8 String1[]="T:   C  H:   %Rn ";               
  476.         u8 String2[]="TL:    ,TH:      ";
  477.         u8 Stirng_Error[ ]="  DHT11 Error!  ";
  478.         GPIO();
  479.         PWM_Init();
  480.         UART1_Init();
  481.         LCD1602_Init();
  482.         TH=IapReadByte(0);        //讀取EEPROM
  483.         TL=IapReadByte(1);
  484.                         IapProgramByte(0,TH);        //寫EEPROM上限
  485.                         IapProgramByte(1,TL);        //寫EEPROM下限
  486.         while(DHT11_Init())
  487.                 LCD1602_Print_String(0,Stirng_Error);
  488.         while(1)
  489.                 {        t=KEY_Scan(0);  //得到鍵值
  490.           switch(t)
  491.           {
  492.                  case KEY1_PRES:
  493.                  {
  494.                          TH++;
  495.                          IapEraseSector(0);
  496.                         IapProgramByte(0,TH);        //寫EEPROM上限
  497.                         IapProgramByte(1,TL);        //寫EEPROM下限
  498.                          break;
  499.                  }
  500.                  case KEY2_PRES:
  501.                  {
  502.                         TH--;
  503.                         IapEraseSector(0);
  504.                         IapProgramByte(0,TH);        //寫EEPROM上限
  505.                         IapProgramByte(1,TL);        //寫EEPROM下限
  506.                         break;
  507.                  }
  508.                  case KEY3_PRES:
  509.                  {
  510.                         TL++;
  511.                         IapEraseSector(0);
  512.                         IapProgramByte(0,TH);        //寫EEPROM上限
  513.                         IapProgramByte(1,TL);        //寫EEPROM下限
  514.                         break;
  515.                  }
  516.                  case KEY4_PRES:
  517.                  {
  518.                         TL--;
  519.                         IapEraseSector(0);
  520.                         IapProgramByte(0,TH);        //寫EEPROM上限
  521.                         IapProgramByte(1,TL);        //寫EEPROM下限
  522.                         break;
  523.                  }
  524.           }
  525.                         DHT11_Read_Data(&temperature,&humidity) ;
  526.                         OtoC2(temperature,TEMP_String);        
  527.                         String_Join2bit(String1,TEMP_String,2);        
  528.                         OtoC2(humidity,HUMI_String);                 
  529.                         String_Join2bit(String1,HUMI_String,10);
  530.                         OtoC2(TH,TH_String);        
  531.                         String_Join2bit(String2,TH_String,11);
  532.                         OtoC2(TL,TL_String);
  533.                         String_Join2bit(String2,TL_String,3);
  534.                         LCD1602_Print_String(0,String1);        
  535.                         LCD1602_Print_String(1,String2);
  536.                         zhuan(temperature);
  537.                 }
  538. }

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

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产美女在线观看 | 91精品国产91久久久久久密臀 | 97色伦网| 蜜桃官网| 国产成人免费视频网站高清观看视频 | 一级在线毛片 | 777zyz色资源站在线观看 | 中文二区 | 亚洲品质自拍视频网站 | 欧美日韩综合 | 美女爽到呻吟久久久久 | 亚洲精品99久久久久久 | 日韩一区二区三区四区五区六区 | 日韩视频一区二区三区 | 中文字幕乱码亚洲精品一区 | 成人免费视频在线观看 | 国产一区二区成人 | 欧美日韩一区二区在线 | 成人免费视频网站在线观看 | 国产精品久久久久久久久 | 免费美女网站 | 人人叉| 一区二区三区在线看 | 色综合久 | 美女拍拍拍网站 | 亚洲欧美日韩精品久久亚洲区 | 亚洲+变态+欧美+另类+精品 | 懂色av色香蕉一区二区蜜桃 | 色视频在线免费观看 | 国产精品久久久久久久久久免费看 | 中文字幕日韩一区 | 羞羞视频网站免费看 | 精品99久久久久久 | 亚洲国产精品日本 | 精品国产伦一区二区三区观看说明 | 美日韩免费 | 日韩美女在线看免费观看 | 亚洲视频免费在线 | 羞视频在线观看 | 精品欧美一区二区三区久久久 | 欧美成人激情 |