找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

我用單片機pwm調制控制直流電機結果方波出來不均衡

[復制鏈接]
跳轉到指定樓層
樓主
ID:906008 發(fā)表于 2021-4-15 14:40 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
1黑幣
求大佬解惑 我設置的50%占空比結果出來波形不對


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

  2. #define lcd P0        //lcd1602數據接口
  3. sbit rs=P2^6;          //lcd1602傳輸控制接口
  4. sbit e=P2^7;                //         lcd1602傳輸控制接口
  5. sbit rw=P2^5;                  //  lcd1602傳輸控制接口
  6. sbit DQ=P3^7;//        溫度接口
  7. sbit key1=P3^0;//  上下限切換鍵/0檔
  8. sbit key2=P3^1;//        加/1檔
  9. sbit key3=P3^2;//         減/2檔
  10. sbit key4=P3^3;//         手動
  11. sbit key5=P3^4;//         自動
  12. sbit key6=P3^5;// 是否修改切換鍵
  13. sbit w0=P2^0;         //電機連接口


  14. int  iii=1;
  15. int count1;        //pwm所需變量
  16. int  dang1[16];//防止擋位錯誤中間變量
  17. int  dang2,dang3; // 防止擋位錯誤中間變量
  18. int temp1; //顯示函數所需變量
  19. int frequency;//顯示函數所需變量
  20. int b11;  //上下限增減中間變量
  21. int wen_du;        //溫度                                          
  22. int shang,xia; // 上限/下限
  23. int dang;//擋位
  24. bit p1=0; //  上下限修改參數
  25. bit p2=0;  // 是否修改切換鍵參數
  26. bit HM;        //自動手動切換參數

  27. void delay12 (int qq)//         延時函數
  28. {        int j;
  29.         for(j=0;j<qq;j++)   
  30.         {
  31. }
  32. }

  33. void cmd (unsigned char c)//lcd1602命令函數
  34. {         e=0;
  35.         rs=0;
  36.         rw=0;
  37.         lcd=c;
  38.         e=1;
  39.         delay12(8);
  40.         e=0;
  41. }
  42. void display (unsigned char c)        //lcd1602單個顯示函數
  43. {
  44.         e=0;
  45.         rs=1;
  46.         rw=0;
  47.         lcd=c;
  48.         e=1;
  49.         e=0;
  50. }
  51. void string (char *c)  //lcd1602  字符串顯示 函數
  52. {
  53.        
  54.         while(*c)
  55.         {display(*c++);}
  56. }

  57. void  display_frequency1(int frequency){        //lcd1602多個數字顯示模式1
  58.         if((frequency>=0) && (frequency<10)){  // 一位數顯示函數
  59.      string("0");  
  60.                 temp1=((frequency+48));
  61.                   display(temp1); }

  62. else if((frequency>=10) && (frequency<100))//  兩位數顯示函數
  63.       { temp1=((frequency/10)+48);
  64.                   display(temp1);
  65.                 temp1=((frequency%10)+48);
  66.                   display(temp1);       
  67.                 }
  68. else if((frequency>=100) && (frequency<1000))//        三位數顯示函數
  69.                 {        temp1=((frequency/100)+48);
  70.                   display(temp1);               
  71.                         temp1=(((frequency%100)/10)+48);
  72.                   display(temp1);
  73.                        
  74.                         temp1=((frequency%10)+48);
  75.                         display(temp1);}                       
  76.                  }
  77. void  display_frequency(int frequency){        ////lcd1602多個數字顯示模式0
  78.         if((frequency>=0) && (frequency<10)){
  79.       
  80.                 string("00");temp1=((frequency+48));  // 一位數顯示函數
  81.                   display(temp1); }

  82. else if((frequency>=10) && (frequency<100))                 //  兩位數顯示函數
  83.       { string("0");
  84.                                 temp1=((frequency/10)+48);
  85.                   display(temp1);
  86.                 temp1=((frequency%10)+48);
  87.                   display(temp1);       
  88.                 }
  89. else if((frequency>=100) && (frequency<1000))////        三位數顯示函數
  90.                 {        temp1=((frequency/100)+48);
  91.                   display(temp1);               
  92.                         temp1=(((frequency%100)/10)+48);
  93.                   display(temp1);
  94.                        
  95.                         temp1=((frequency%10)+48);
  96.                         display(temp1);}                       
  97.                  }

  98. void init (void)//lcd1602  初始化函數
  99. {
  100.         cmd(0x38);
  101.     cmd(0x0c);
  102.         cmd(0x06);
  103.        
  104. }
  105. void delay(int ms)                 //鍵盤掃描延遲函數
  106. {
  107.         unsigned char x;
  108.         for(ms;ms>0;ms--)
  109.                 for(x=10;x>0;x--);
  110. }


  111. void delay_18B20(int i)          //ds18b20延遲函數
  112. {
  113.         while(i--);
  114. }

  115. void Init_DS18B20()    //ds18b20初始化函數
  116. {
  117.          unsigned char x=0;
  118.          DQ=1;          //DQ復位
  119.          delay_18B20(8);  //稍作延時
  120.          DQ=0;          //單片機將DQ拉低
  121.          delay_18B20(80); //精確延時,大于480us
  122.          DQ=1;          //拉高總線
  123.          delay_18B20(14);
  124.          x=DQ;            //稍作延時后 如果x=0則初始化成功 x=1則初始化失敗
  125.          delay_18B20(20);
  126. }

  127. unsigned char ReadOneChar()        //ds18b20讀一個字節(jié)
  128. {
  129.         unsigned char i=0;
  130.         unsigned char dat=0;
  131.         for (i=8;i>0;i--)
  132.          {
  133.                   DQ=0; //給脈沖信號
  134.                   dat>>=1;
  135.                   DQ=1;//給脈沖信號
  136.                   if(DQ)
  137.                   dat|=0x80;
  138.                   delay_18B20(4);
  139.          }
  140.         return(dat);
  141. }

  142. void WriteOneChar(unsigned char dat)  //ds18b20寫一個字節(jié)
  143. {
  144.         unsigned char i=0;
  145.         for (i=8;i>0;i--)
  146.         {
  147.                   DQ=0;
  148.                 DQ=dat&0x01;
  149.             delay_18B20(5);
  150.                 DQ=1;
  151.             dat>>=1;
  152.         }
  153. }

  154. void ReadTemperature()                        //ds18b20讀取溫度
  155. {
  156.         unsigned char a=0;
  157.         unsigned char b=0;
  158.         unsigned char t=0;
  159.         Init_DS18B20();
  160.         WriteOneChar(0xCC);            // 跳過讀序號列號的操作
  161.         WriteOneChar(0x44);         // 啟動溫度轉換
  162.         delay_18B20(100);       //
  163.         Init_DS18B20();
  164.         WriteOneChar(0xCC);         //跳過讀序列號的操作
  165.         WriteOneChar(0xBE);         //讀取溫度寄存器等(共可讀9個寄存器)前兩個就是溫度
  166.         delay_18B20(100);
  167.         a=ReadOneChar();            //讀取溫度低值
  168.         b=ReadOneChar();                   //讀取溫度高值
  169.         wen_du=((b*256+a)>>4);    //當前采集溫度值除16得實際溫度值
  170.         if(wen_du>=100){wen_du=-1;}
  171. }

  172. void zi_keyscan()//        自動模式按鍵掃描函數
  173. {  

  174. if(HM==0 && p2==1){// 自動模式下按下是否修改切換鍵
  175. if(key1==0)//設置鍵按下
  176.         {
  177.                 delay(10);//按鍵去抖
  178.                 if(key1==0){p1=~p1;while(key1==0);}}//再次判斷按鍵;上下限切換鍵;松手檢測
  179. if(p1==0){b11=shang;}
  180. else{b11=xia;}
  181. if(key2==0)//加鍵按下
  182.         {
  183.                 delay(10);//按鍵去抖
  184.                 if(key2==0){b11++;}{while(key2==0);};//再次判斷按鍵;上限值加;松手檢測
  185.         }                       
  186. if(key3==0)//減鍵按下
  187.         {
  188.                 delay(10);//延時去抖
  189.                 if(key3==0){b11--;}{while(key3==0);};//再次判斷后上限減,松手檢測
  190.         }                       
  191. if(p1==0){shang=b11;
  192. }        else{xia=b11;}        }

  193. if(HM==1){                //手動鍵盤模式
  194. if(key1==0)
  195.         {
  196.                 delay(10);//延時去抖
  197.                 if(key1==0){dang=0;}}       
  198.        
  199. if(key2==0)
  200.         {
  201.                 delay(10);
  202.                 if(key2==0){dang=1;}}                       
  203. if(key3==0){delay(10);if(key3==0){dang=2;}}
  204. }       

  205.         if(key4==0)
  206.         {
  207.                 delay(10);
  208.                 if(key4==0){HM=1;}
  209.         }
  210.         if(key5==0)
  211.         {
  212.                 delay(10);
  213.                 if(key5==0){HM=0;}
  214.         }
  215. if(key6==0)
  216.         {
  217.                 delay(10);
  218.                 if(key6==0){p2=~p2;while(key6==0);}}
  219.        
  220.        
  221.        
  222. }
  223. void zi_dong()// 自動溫控模式
  224. {
  225.        
  226.                 if(wen_du<xia ){dang=0;}//
  227.                 if((wen_du>=xia)&&(wen_du<=shang))//
  228.                 {
  229.                         dang=1;
  230. }
  231.                 if(wen_du> shang ){dang=2;}//
  232. dang1[iii]=dang;   //穩(wěn)定擋數
  233.                 iii++;
  234. dang3=0;               
  235. if(iii==17){
  236. int r;       
  237. for(r=1;r<=16;r++)
  238. {dang3+=dang1[r];}
  239. dang2=dang3/16;
  240. iii=1;
  241. }               
  242. }



  243. void display_all(){        //整體顯示函數       
  244.    cmd(0x80);
  245. string("Tempn:")                ;       
  246. cmd(0x86);       
  247.         display_frequency(wen_du);       
  248. cmd(0x8b);       
  249. if(HM==0){display_frequency(dang2);} //自動模式擋位顯示
  250. if(HM==1){display_frequency(dang);}          //手動模式擋位顯示

  251. cmd(0xc1);
  252.         string("H:");
  253.         if(HM==0&& p1==0&&p2==1){//自動可修改上限部分
  254.   display(0xff);
  255.         display(0xff);        //顯示小方格
  256.                
  257.         delay12(1000);}
  258. cmd(0xc3);       
  259.         display_frequency1(shang);                //顯示上限
  260. cmd(0xc6);
  261.         string("L:");
  262. if(HM==0&&p1==1&&p2==1){   //自動可修改下限部分
  263.         display(0xff);
  264.         display(0xff);//顯示小方格
  265.   delay12(1000);}
  266. cmd(0xc8);
  267.         display_frequency1(xia); //顯示下限
  268. string(" ");       
  269. if(HM==1)        {string("Manu");} //手動顯示部分
  270.       else{string("Auto");}       
  271. if(shang<=25){shang=25;}                       
  272. if(shang>=60){shang=60;}                               
  273. if(xia<=5){xia=5;}                               
  274. if(xia>=23){shang=23;}                               
  275. }

  276. void  time0(){        //中斷初始化
  277.         TMOD=0x01;        
  278.         TH0=(65536-50000)/256;          
  279.         TL0=(65536-50000)%256;
  280.         EA=1;                                                       
  281.         ET0=1;                                                         
  282.         TR0=1;                                                                                         
  283. }

  284. void main()
  285. { shang=30;
  286.         xia=20;
  287.         ReadTemperature();        //讀取溫度
  288.         time0();//初始化中斷
  289.         init();//初始化lcd1602
  290.        
  291.         while(1)
  292.         {
  293.                 while(HM==1) //手動模式
  294.                                 {
  295.                                 ReadTemperature();        //讀取溫度
  296.                                 zi_keyscan();//掃描鍵盤
  297.                         display_all();        //lcd顯示       
  298.                         }
  299.         while(HM==0)//自動模式  
  300.                         {ReadTemperature();        //讀取溫度
  301.                                 zi_keyscan();//掃描鍵盤
  302.                                 zi_dong();// 自動模式下電機擋位選擇
  303. display_all();
  304.        
  305.         }
  306. }
  307. }
  308. void timer0() interrupt 1{         TH0=(65536-50000)/256;         
  309.         TL0=(65536-50000)%256;                  //設置中斷時間為50ms
  310. if(dang==0){w0=0;}                                  //  pwm電機控制
  311. if(dang==1){count1++;if(count1<=1){w0=1;}if(count1>1){w0=0;}if(count1==4){count1=0;}}  //  pwm電機控制
  312. if(dang==2){w0=1;}           //  pwm電機控制

  313. }
復制代碼

全部資料51hei下載地址:
風扇0.0.zip (141.37 KB, 下載次數: 4)

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

使用道具 舉報

沙發(fā)
ID:894154 發(fā)表于 2021-4-15 17:37 | 只看該作者
直流電機并一個104P的電容&&并一個反向的肖特基二極管
回復

使用道具 舉報

板凳
ID:160500 發(fā)表于 2021-4-15 17:55 | 只看該作者
你不加濾波電路自然不能行
回復

使用道具 舉報

地板
ID:160500 發(fā)表于 2021-4-15 17:56 | 只看該作者
不好意思看錯了
回復

使用道具 舉報

5#
ID:390416 發(fā)表于 2021-4-15 17:56 | 只看該作者
人人學會單片機,PWM程序 STC89單片機 定時器做 http://www.torrancerestoration.com/bbs/dpj-200820-1.html
回復

使用道具 舉報

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

本版積分規(guī)則

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

Powered by 單片機教程網

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