找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1771|回复: 4
打印 上一主题 下一主题
收起左侧

我用单片机pwm调制控制直流电机结果方波出来不均衡

[复制链接]
跳转到指定楼层
楼主
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读一个字节
  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写一个字节
  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;   //稳定挡数
  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空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:894154 发表于 2021-4-15 17:37 | 只看该作者
直流电机并一个104P的电容&&并一个反向的肖特基二极管
回复

使用道具 举报

板凳
ID:160500 发表于 2021-4-15 17:55 | 只看该作者
你不加滤波电路自然不能行
回复

使用道具 举报

地板
ID:160500 发表于 2021-4-15 17:56 | 只看该作者
不好意思看错了
回复

使用道具 举报

5#
ID:390416 发表于 2021-4-15 17:56 | 只看该作者
人人学会单片机,PWM程序 STC89单片机 定时器做 http://www.51hei.com/bbs/dpj-200820-1.html
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表