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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4645|回復: 4
收起左側

51單片機風扇驅動源程序

[復制鏈接]
ID:396717 發表于 2019-6-3 19:31 | 顯示全部樓層 |閱讀模式
自己寫的一個有關51單片機控制電機風扇的程序,有LCD1602、ds18b20、紅外遙控,還有E2PROM保存按鍵值的程序,整體的程序結構有點亂,大家可以取一些需要的內容參考,歡迎大家指出不足!

單片機源程序如下:
  1. #include<reg51.h>
  2. #include<intrins.h>                         //包含頭文件
  3. #define uchar unsigned char
  4. #define uint unsigned int                 //宏定義
  5. #include "eeprom52.h"
  6. #define LCD1602_DB         P0
  7. sbit LCD1602_RS = P2^6;//“RD”接單片機P2.6, 0=輸入指令,1=輸入數據         
  8. sbit LCD1602_RW = P2^5;//“WR”接單片機P2.5,0=向LCD寫入指令或數據,1=從LCD讀取信息
  9. sbit LCD1602_E  = P2^7;//“LCDE”接單片機P2.7,下降沿有效的使能信號
  10. sbit IO_18B20=P3^7;
  11. sbit IN1=P1^0;
  12. sbit IN2=P1^1;
  13. sbit ENA=P1^2;
  14. sbit key1=P2^1;//設置溫度
  15. sbit key2=P2^2;//溫度加
  16. sbit key3=P2^3;//溫度減
  17. bit flag1s=0;//1s定時標志
  18. unsigned char T0RH=0;
  19. unsigned char T0RL=0;

  20. int temp;//讀取到的當前溫度值
  21. unsigned char len;
  22. int intT,decT;//溫度值的整數和小數部分
  23. unsigned char str[12];
  24. unsigned char d1,d2,d3;//顯示數據暫存變量
  25. unsigned char flag;
  26. unsigned int shang,xia; //對比溫度暫存變量
  27. void Compare();
  28. void GetTemp();
  29. void ConfigTimer0(unsigned int ms);
  30. unsigned char IntToString(unsigned char *str,int dat);
  31. extern bit Start18B20();
  32. extern bit Get18B20Temp(int *temp);
  33. extern void InitLcd1602();
  34. extern void LcdShowStr(unsigned char x,unsigned char y,unsigned char *str);
  35. /******************把數據保存到單片機內部eeprom中******************/
  36. void write_eeprom()
  37. {
  38.         SectorErase(0x2000);                //清除扇區
  39.         byte_write(0x2000, shang);        //寫上限數值到扇區
  40.         byte_write(0x2001, xia);        //寫下限數值到扇區
  41.         byte_write(0x2060, a_a);        //寫初始變量到扇區指定位置
  42. }

  43. /******************把數據從單片機內部eeprom中讀出來*****************/
  44. void read_eeprom()
  45. {
  46.         shang   = byte_read(0x2000);                 //從扇區讀取上限數據
  47.         xia = byte_read(0x2001);                         //從扇區讀取下限數據
  48.         a_a      = byte_read(0x2060);                 //從扇區讀取初始變量
  49. }

  50. /**************開機自檢eeprom初始化*****************/
  51. void init_eeprom()
  52. {
  53.         read_eeprom();                //先讀扇區的數據
  54.         if(a_a != 1)                //判斷是否是新單片機(原理:新的單片機扇區里的數據都是0,這里判斷是否不等于1。如果是不等于1,就是等于0,那就是新單片機了,就會執行下面的上下限值初始化數值的語句,并讓a_a變成1,下次開機就會知道是用過的單片機了就會讀取EEPROM里的上下限數據了)
  55.         {
  56.                 shang   = 30;        //上限數值初始為30
  57.                 xia = 20;                //下限數值初始為20
  58.                 a_a = 1;                //初始值變量賦值1,下次開機就會直接讀取EEPROM內的上下限數據
  59.                 write_eeprom();           //將初始的數據保存進單片機的EEPROM
  60.         }       
  61. }

  62. /**************LCD1602*****************/
  63. /* 等待液晶準備好 */
  64. void LcdWaitReady()
  65. {
  66.     unsigned char sta;
  67.    
  68.     LCD1602_DB = 0xFF;                         //DB0~DB8為11111111
  69.     LCD1602_RS = 0;                                 //數據和指令選擇控制端
  70.     LCD1602_RW = 1;                                 //讀操作
  71.     do {
  72.         LCD1602_E = 1;
  73.         sta = LCD1602_DB; //讀取狀態字
  74.         LCD1602_E = 0;
  75.     } while (sta & 0x80); //bit7等于1表示液晶正忙,重復檢測直到其等于0為止
  76. }
  77. /* 向LCD1602液晶寫入一字節命令,cmd-待寫入命令值 */
  78. void LcdWriteCmd(unsigned char cmd)
  79. {
  80.     LcdWaitReady();
  81.     LCD1602_RS = 0;
  82.     LCD1602_RW = 0;
  83.     LCD1602_DB = cmd;
  84.     LCD1602_E  = 1;
  85.     LCD1602_E  = 0;
  86. }
  87. /* 向LCD1602液晶寫入一字節數據,dat-待寫入數據值 */
  88. void LcdWriteDat(unsigned char dat)
  89. {
  90.     LcdWaitReady();
  91.     LCD1602_RS = 1;
  92.     LCD1602_RW = 0;
  93.     LCD1602_DB = dat;
  94.     LCD1602_E  = 1;
  95.     LCD1602_E  = 0;
  96. }
  97. /* 設置顯示RAM起始地址,亦即光標位置,(x,y)-對應屏幕上的字符坐標 */
  98. void LcdSetCursor(unsigned char x, unsigned char y)
  99. {
  100.     unsigned char addr;
  101.    
  102.     if (y == 0)  //由輸入的屏幕坐標計算顯示RAM的地址
  103.         addr = 0x00 + x;  //第一行字符地址從0x00起始
  104.     else
  105.         addr = 0x40 + x;  //第二行字符地址從0x40起始
  106.     LcdWriteCmd(addr | 0x80);  //設置RAM地址
  107. }
  108. /* 在液晶上顯示字符串,(x,y)-對應屏幕上的起始坐標,str-字符串指針 */
  109. void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str)
  110. {
  111.     LcdSetCursor(x, y);   //設置起始地址
  112.     while (*str != '\0')  //連續寫入字符串數據,直到檢測到結束符
  113.     {
  114.         LcdWriteDat(*str++);
  115.     }
  116. }
  117. /* 初始化1602液晶 */
  118. void InitLcd1602()
  119. {
  120.     LcdWriteCmd(0x38);  //16*2顯示,5*7點陣,8位數據接口
  121.     LcdWriteCmd(0x0C);  //顯示器開,光標關閉
  122.     LcdWriteCmd(0x06);  //文字不動,地址自動+1
  123.     LcdWriteCmd(0x01);  //清屏
  124. }
  125. //sbit IO_18B20=P3^2;

  126. /*軟件延時函數,延時時間(t*10)us*/
  127. void DelayX10us(unsigned char t)
  128. {
  129.         do{
  130.                 _nop_();
  131.                 _nop_();
  132.                 _nop_();
  133.                 _nop_();
  134.                 _nop_();
  135.                 _nop_();
  136.                 _nop_();
  137.                 _nop_();
  138.         }while(--t);
  139. }
  140. /*復位總線,獲取存在脈沖,以啟動一次讀寫操作*/
  141. bit Get18B20Ack()
  142. {
  143.         bit ack;
  144.        
  145.         EA=0;                                   //禁止總中斷
  146.         IO_18B20=0;                        //產生500us復位脈沖
  147.         DelayX10us(50);
  148.         IO_18B20=1;
  149.         DelayX10us(6);                //延時60us
  150.         ack=IO_18B20;                //讀取存在脈沖
  151.         while(!IO_18B20);   //等待存在脈沖結束
  152.         EA=1;                                //重新使能總中斷
  153.         return ack;
  154. }
  155. /*向DS18B20寫入一個字節,dat-待寫入字節*/
  156. void Write18B20(unsigned char dat)
  157. {
  158.         unsigned char mask;
  159.         EA=0;
  160.         for(mask=0x01;mask!=0;mask<<=1)//低位在先,依次移出8個bit
  161.         {
  162.                 IO_18B20=0;//產生2us低電平脈沖
  163.                 _nop_();
  164.                 _nop_();
  165.                 if((mask&dat)==0)//輸出該bit值
  166.                         IO_18B20=0;
  167.                 else
  168.                         IO_18B20=1;
  169.                 DelayX10us(6);//延時60us
  170.                 IO_18B20=1;//拉高通信引腳
  171.         }
  172.         EA=1;
  173. }
  174. /*從DS18B20讀取一個字節,返回值-讀到的字節*/
  175. unsigned char Read18B20()
  176. {
  177.         unsigned char dat;
  178.         unsigned char mask;

  179.         EA=0;
  180.         for(mask=0x01;mask!=0;mask<<=1)//低位在先,依次采集8個bit
  181.         {
  182.                 IO_18B20=0;//產生2us低電平脈沖
  183.                 _nop_();
  184.                 _nop_();
  185.                 IO_18B20=1;//結束低電平脈沖,等待18B20輸出數據
  186.                 _nop_(); //延時2us
  187.                 _nop_();
  188.                 if(!IO_18B20)//讀取通信引腳上的值
  189.                         dat &= ~mask;
  190.                 else
  191.                         dat |= mask;
  192.                 DelayX10us(6);//再延時60us
  193.         }
  194.         EA=1;
  195.         return dat;
  196. }
  197. /*啟動一次18B20溫度轉換,返回值-表示是否啟動成功*/
  198. bit Start18B20()
  199. {
  200.         bit ack;
  201.         ack=Get18B20Ack();//執行總線復位,并獲取18B20應答
  202.         if(ack==0)
  203.         {
  204.                 Write18B20(0xCC);
  205.                 Write18B20(0x44);
  206.         }
  207.         return ~ack;
  208. }
  209. /*讀取DS18B20轉換的溫度值,返回值-表示是否讀取成功*/
  210. bit Get18B20Temp(int *temp)
  211. {
  212.         bit ack;
  213.         unsigned char LSB,MSB;//16bit溫度值的低字節和高字節

  214.         ack=Get18B20Ack();//執行總線復位,并獲取18B20應答
  215.         if(ack==0)
  216.         {
  217.                 Write18B20(0xCC);//跳過ROM操作
  218.                 Write18B20(0xBE);//發送讀命令
  219.                 LSB=Read18B20();//讀溫度值的低字節
  220.                 MSB=Read18B20();//讀溫度值的高字節
  221.                 *temp=((int)MSB<<8)+LSB;//合成為16bit整型數
  222.         }
  223.         return ~ack;
  224. }
  225. void main()
  226. {
  227.         bit res;

  228.         EA=1;
  229.         ConfigTimer0(10);//T0定時10ms
  230.         Start18B20();//啟動DS18B20
  231.         InitLcd1602();//初始化液晶

  232.         while(1)
  233.         {               
  234.                 if(flag1s)//每秒更新一次溫度
  235.                 {
  236.                         flag1s=0;
  237.                         res=Get18B20Temp(&temp);//讀取當前溫度
  238.                         if(res)//讀取成功時,刷新當前溫度顯示
  239.                         {
  240.                                 GetTemp();
  241.                        
  242.                                 LcdShowStr(0,0,(unsigned char *)"Welcome to use");//顯示字符及溫度值
  243.                                 LcdShowStr(0,1,"Current T:");
  244.                                 LcdShowStr(10,1,str);
  245.                                         Compare();
  246.                         }
  247.                         else //讀取失敗時,提示錯誤信息
  248.                         {
  249.                                 LcdShowStr(0,0,"error!");

  250.                         }
  251.                         Start18B20();//重新啟動下一次轉換                                         
  252.                 }
  253.         }
  254. }
  255. /*溫度獲取函數,獲取當前環境溫度值并保存在str數組中*/
  256. void GetTemp()
  257. {
  258.         intT=temp>>4;//分離出溫度值整數部分
  259.         decT=temp &0x0F;//分離出溫度值小數部分
  260.                        
  261.         len=IntToString(str,intT);//整數部分轉換成字符串
  262.                        
  263.         str[len++]='.';
  264.         decT=(decT%10)/16;//二進制的小數部分轉換為1位十進制位
  265.         str[len++]=decT+'0';//十進制小數位再轉換為ASCII字符
  266.         while(len<6)//用空格補齊到6個字符長度
  267.         {
  268.                 str[len++]=' ';
  269.         }
  270.         str[len++]='\0';
  271. }
  272. /*延時函數,用于PWM控制*/
  273. void delay(unsigned int z)
  274. {
  275.         unsigned int x,y;
  276.         for(x=z;x>0;x--)
  277.                 for(y=110;y>0;y--);
  278. }
  279. /*比較函數,通過溫度值的比較設置電機的轉速*/
  280. void Compare()
  281. {
  282.         unsigned int i=0;
  283.         unsigned char j;

  284.         if((intT>= 24) && (intT<26))   //以兩度為一個溫差范圍,并設溫度范圍索引
  285.         {
  286.                 j=0;       
  287.         }
  288.         else if((intT>=26) &&(intT<28))
  289.         {
  290.                 j=1;
  291.         }
  292.         else if((intT>=28) &&(intT<30))
  293.         {
  294.                 j=2;
  295.         }
  296.         else if(intT>=30)
  297.         {
  298.                 j=3;
  299.         }
  300.         switch(j)                  //根據溫度索引設置電機轉速
  301.         {
  302.                 case 0:        IN1=1;
  303.                                 IN2=0;
  304.                                   for(i=0;i<200;i++)
  305.                               {
  306.                                         ENA=1;
  307.                                      delay(20);
  308.                                   ENA=0;
  309.                                         delay(30);
  310.                                 }
  311.                                 break;
  312.        
  313.                 case 1:        IN1=1;
  314.                                 IN2=0;
  315.                                   for(i=0;i<200;i++)
  316.                               {
  317.                                         ENA=1;
  318.                                      delay(30);
  319.                                   ENA=0;
  320.                                         delay(30);
  321.                                 }
  322.                                 break;         
  323.        
  324.                 case 2:        IN1=1;
  325.                                 IN2=0;
  326.                                   for(i=0;i<200;i++)
  327.                               {
  328.                                         ENA=1;
  329.                                      delay(55);                         
  330.                                   ENA=0;
  331.                                         delay(30);
  332.                                 }
  333.                                 break;         
  334.                                                        
  335.                 case 3:        IN1=1;
  336.                                 IN2=0;
  337.                               ENA=1;
  338.                                 break;

  339.                 default:break;                  
  340.         }
  341. }  

  342. /*整型數轉換為字符串,str-字符串指針,dat-待轉換數,返回值-字符串長度*/
  343. unsigned char IntToString(unsigned char *str,int dat)
  344. {
  345.         signed char i=0;
  346.         unsigned char len=0;
  347.         unsigned char buf[6];

  348.         if(dat<0)//如果為負數,首先取絕對值,并在指針上添加負號
  349.         {
  350.                  dat=-dat;
  351.                 *str++='-';
  352.                 len++;
  353.         }
  354.         do{           //先轉換為低位在前的十進制數組
  355.                 buf[i++]=dat%10;
  356.                 dat /=10;
  357.         }while(dat>0);
  358.         len += i;//i最后的值就是有效字符的個數
  359.         while(i-->0)//將數組值轉換為ASCII碼反向拷貝到接收指針上
  360.         {
  361.                 *str++=buf[i]+'0';
  362.         }
  363.         *str='\0';
  364.         return len;
  365. }
  366. void ConfigTimer0(unsigned int ms)
  367. {
  368.         unsigned long tmp;

  369.         tmp=11059200/12;
  370.         tmp=(tmp*ms)/1000;
  371.         tmp=65536-tmp;
  372.         tmp=tmp+12;
  373.         T0RH=(unsigned char)(tmp>>8);
  374.         T0RL=(unsigned char)tmp;
  375.         TMOD &= 0xF0;
  376.         TMOD |= 0x01;
  377.         TH0=T0RH;
  378.         TL0=T0RL;
  379.         ET0=1;
  380.         TR0=1;
  381. }
  382. void InterruptTimer0() interrupt 1
  383. {
  384.         static unsigned char tmr1s=0;

  385.         TH0=T0RH;
  386.         TL0=T0RL;
  387.         tmr1s++;
  388.         if(tmr1s>=100)
  389.         {
  390.                 tmr1s=0;
  391.                 flag1s=1;
  392.         }                 

  393. }
  394. void zi_keyscan()//自動模式按鍵掃描函數
  395. {
  396.         if(key1==0)                                                          //設置鍵按下
  397.         {
  398.                 delay(80);                                                  //延時去抖
  399.                 if(key1==0)
  400.                 {
  401.                         flag=1;                                  //再次判斷按鍵,按下的話進入設置狀態
  402.                         while(key1==0);//松手檢測                  //按鍵釋放
  403.                 }
  404.         }
  405.         while(flag==1)                                                  //進入設置上限狀態
  406.         {
  407.                 d1=18;d2=shang/10;d3=shang%10;          //顯示字母H 和上限溫度值
  408.                 if(key1==0)                                                  //判斷設置鍵是否按下
  409.                 {
  410.                         delay(80);                                          //延時去抖
  411.                         if(key1==0)
  412.                         {
  413.                                 flag=2;                          //按鍵按下,進入設置下限模式
  414.                                 while(key1==0);//松手檢測
  415.                         }
  416.                 }
  417.                 if(key2==0)                                                  //加鍵按下
  418.                 {
  419.                         delay(80);                                          //延時去抖
  420.                         if(key2==0)                                          //加鍵按下
  421.                         {
  422.                                 shang+=1;                                  //上限加1
  423.                                 if(shang>=100)shang=100;  //上限最大加到100
  424.                                 while(key2==0);//松手檢測
  425.                         }
  426.                 }
  427.                 if(key3==0)                                                  //減鍵按下
  428.                 {
  429.                         delay(80);                                          //延時去抖
  430.                         if(key3==0)                                          //減鍵按下
  431.                         {
  432.                                 shang-=1;                                  //上限減1
  433.                                 if(shang<=10)shang=10;          //上限最小減到10
  434.                                 while(key3==0);//松手檢測
  435.                         }
  436.                 }               
  437.         }
  438.         while(flag==2)                                                  //設置下限
  439.         {
  440.                 d1=17;d2=xia/10;d3=xia%10;                  //顯示字母L 顯示下限溫度值
  441.                 if(key1==0)
  442.                 {
  443.                         delay(80);
  444.                         if(key1==0)
  445.                         {
  446.                                 flag=0;
  447.                                 while(key1==0);//松手檢測
  448.                                 write_eeprom();                           //保存數據       
  449.                         }
  450.                 }
  451.                 if(key2==0)
  452.                 {
  453.                         delay(80);
  454.                         if(key2==0)
  455.                         {
  456.                                 xia+=1;
  457.                                 if(xia>=99)xia=99;
  458.                                 while(key2==0);//松手檢測
  459.                         }
  460.                 }
  461.                 if(key3==0)
  462.                 {
  463.                         delay(80);
  464.                         if(key3==0)
  465.                         {
  466.                                 xia-=1;
  467.                                 if(xia<=0)xia=0;
  468.                                 while(key3==0);//松手檢測
  469.                         }
  470.                 }               
  471.         }
  472. }                                                                                                                       
復制代碼

所有資料51hei提供下載:
51單片機風扇.rar (57.84 KB, 下載次數: 37)


評分

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

查看全部評分

回復

使用道具 舉報

ID:396717 發表于 2019-6-7 20:56 | 顯示全部樓層
啊呀!!!發錯程序了,發成了修改之前的程序,這個程序是不對的,大家在看的時候注意了!!!!!!!!!
回復

使用道具 舉報

ID:698943 發表于 2020-2-27 12:17 | 顯示全部樓層
賺錢買八爪魚 發表于 2019-6-7 20:56
啊呀!!!發錯程序了,發成了修改之前的程序,這個程序是不對的,大家在看的時候注意了!!!!!!!!!

哪里錯了
回復

使用道具 舉報

ID:592703 發表于 2020-2-28 18:05 | 顯示全部樓層
學習一下!!謝謝大佬!
回復

使用道具 舉報

ID:432653 發表于 2020-3-1 14:13 | 顯示全部樓層
第5行和39行顯示錯誤
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 久久久久久久久久久高潮一区二区 | 久久国产精品久久久久久 | 在线观看成人 | 一区二区中文字幕 | 色综合久久伊人 | 久久天堂 | 久久久久一区二区三区四区 | 亚洲一区二区 | 亚洲一区二区三区视频免费观看 | 国产91久久精品一区二区 | 欧美13videosex性极品 | 国产真实乱对白精彩久久小说 | 一区二区高清 | 欧美色综合一区二区三区 | 亚洲乱码一区二区三区在线观看 | 亚洲精久久久 | 日韩一区二区三区在线观看 | 久久99精品久久久久久 | 成人av网站在线观看 | 亚洲三级国产 | 日韩国产欧美视频 | 亚洲欧美中文日韩在线 | 亚洲国产一区二区三区 | 国产亚洲精品久久久久动 | 欧美在线视频观看 | 久久这里只有精品首页 | 少妇一区二区三区 | 久久人人爽人人爽人人片av免费 | 亚洲成人精品久久 | 99re在线视频观看 | 欧美久久久久久 | 狠狠色狠狠色综合日日92 | 久久国产综合 | 国产精品一区二 | 久久精品国产精品青草 | 日韩中文字幕一区二区 | 日本在线一二 | 国产精品高潮呻吟久久久久 | 91精品亚洲 | 精品久久久久久久久久 | 精品中文字幕一区二区三区 |