找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 1669|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

才入門的單片機(jī)新手請(qǐng)教大家關(guān)于直流電機(jī)調(diào)速的問(wèn)題

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:461851 發(fā)表于 2019-12-31 19:32 | 只看該作者 |只看大圖 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
不是一般的pwm控制,就是幾個(gè)AD/DA的轉(zhuǎn)換,用三極管放大控制電樞電流..........第一次寫這種幾百行的大程序感覺好難啊

問(wèn)題是在proteus上調(diào)試發(fā)現(xiàn)速度只能加,設(shè)置速度比實(shí)際速度小的時(shí)候就不能降速了,代碼也不能發(fā)現(xiàn)問(wèn)題,來(lái)求助大家

仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)


以下是單片機(jī)代碼
  1. #include <reg52.h>
  2. #define  digital P0                 //DAC0832 數(shù)據(jù)管腳
  3. #define  leddat  P1                   //數(shù)碼管數(shù)據(jù)管腳
  4. #define   en    1    //電機(jī)一圈的脈沖數(shù) 根據(jù)電機(jī)實(shí)際參數(shù)設(shè)定
  5. #define uint unsigned int
  6. #define uchar unsigned char
  7. #define ufloat unsigned float
  8. sbit scl=P3^5;
  9. sbit sda=P3^7;
  10. sbit Y3 = P3^0;              //數(shù)碼管段選腳定義
  11. sbit Y2 = P3^1;
  12. sbit Y1 = P3^2;
  13. sbit Y0 = P3^3;
  14. sbit Y7 = P2^0;              //數(shù)碼管段選腳定義
  15. sbit Y6 = P2^1;
  16. sbit Y5 = P2^2;
  17. sbit Y4 = P2^3;
  18. sbit LSA = P2^4;             //138譯碼器管腳定義
  19. sbit LSB = P2^5;
  20. sbit LSC = P2^6;
  21. sbit  LSG1 = P2^7;
  22. char code Led_dat[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};       //共陰數(shù)碼管段碼 0123456789
  23. long double speed=0;
  24. long int count=0;  //記錄脈沖數(shù)量
  25. void Delay10us()
  26. {
  27.         unsigned char a,b;
  28.         for(b=1;b>0;b--)
  29.                 for(a=2;a>0;a--);

  30. }

  31. void delay()  //延時(shí)幾微秒。延時(shí)函數(shù)在很多函數(shù)里都要用它。至少要大于4.7us
  32. {;;}          //當(dāng)你把這個(gè)函數(shù)寫在用它這個(gè)函數(shù)的前面就不用聲明了

  33. void init()  //初始化總線。將總線都拉高以釋放
  34. {
  35.         scl=1;
  36.         delay();  //I2C總線使用時(shí)一般都要延時(shí)5us左右
  37.         sda=1;
  38.         delay();
  39. }

  40. void start() //啟始信號(hào)。 時(shí)鐘信號(hào)為高電平期間,數(shù)據(jù)總線產(chǎn)生下降沿。
  41. {            //為什么要下降沿,且sda先要為1。因?yàn)橄纫WC數(shù)據(jù)線為空才能工作
  42.         sda=1;   //先釋放數(shù)據(jù)總線。高電平釋放
  43.         delay();
  44.         scl=1;
  45.         delay();
  46.         sda=0;
  47.         delay();
  48. }

  49. void stop()
  50. {
  51.         sda=0;  //先要有工作狀態(tài)才能釋放,sda=0時(shí)在工作狀態(tài)
  52.         delay();
  53.         scl=1;
  54.         delay();
  55.         sda=1;  //釋放數(shù)據(jù)總線
  56.         delay();
  57. }

  58. void respons()  //應(yīng)答函數(shù)
  59. {
  60.         uchar i=0;
  61.         scl=1;  //每個(gè)字節(jié)發(fā)送完后的第九個(gè)時(shí)鐘信號(hào)的開始
  62.         delay();
  63.         while((sda==1)&&(i<255))   //此處i的定義使用了uchar.只要填一個(gè)小于255的就行
  64.         i++;                       //此處的sda是從機(jī)的
  65.         scl=0; //表示主器件默認(rèn)從器件已經(jīng)收到而不再等待。不再等待之后,時(shí)鐘的高電平過(guò)了就是低電平,所以scl=0
  66.                //此時(shí)第酒個(gè)時(shí)鐘信號(hào)結(jié)束
  67. }

  68. void writebyte(uchar d)  //寫一字節(jié),每次左移一位
  69. {
  70.         uchar i,temp;
  71.         temp=d;
  72.         for(i=0;i<8;i++)
  73.         {
  74.                 temp=temp<<1;
  75.                 scl=0;        //數(shù)據(jù)傳輸期間要想sda可變,先把時(shí)鐘拉低。此處要給sda賦值
  76.                 delay();
  77.                 sda=CY;       //CY為左移移入PSW寄存器中的的CY位。
  78.                 delay();
  79.                 scl=1;        //sda有數(shù)據(jù)了。保持?jǐn)?shù)據(jù)穩(wěn)定
  80.                 delay();
  81.         }
  82.         scl=0;            //此處是寫數(shù)據(jù),是屬于數(shù)據(jù)傳輸過(guò)程中。只有在時(shí)鐘信號(hào)為低電平期間
  83.         delay();          //數(shù)據(jù)總線才可以變化。
  84.         sda=1;            //所以要想釋放數(shù)據(jù)總線,就必須先把時(shí)鐘拉低
  85.         delay();         
  86.         /*此處釋放總線寫在末尾是因?yàn)檎{(diào)用它時(shí),前面有起始函數(shù)釋放了總線*/
  87. }

  88. uchar readbyte()
  89. {
  90.         uchar i,k;
  91.         scl=0;
  92.         delay();
  93.         sda=1;
  94.         delay();
  95.         /*此處釋放總線放在前面是因?yàn)橐话愣际窍葘懞笞x,保險(xiǎn)起見,釋放一下總線*/
  96.         for(i=0;i<8;i++)
  97.         {
  98.                 scl=1;     //一個(gè)時(shí)鐘信號(hào)的開始
  99.                 delay();
  100.                 k=(k<<1)|sda;    //實(shí)質(zhì)是把sda的數(shù)據(jù),最先傳來(lái)的放在最高位,依次往下排
  101.                 scl=0;    //一個(gè)時(shí)鐘信號(hào)結(jié)束
  102.                 delay();
  103.         }
  104.         return k;
  105. }
  106. void write(uchar addr,uchar dat)
  107. {
  108.         start();          //初始化
  109.         writebyte(0x90);      //調(diào)用寫一字節(jié)函數(shù).PCF8591為1001。此處是給從機(jī)發(fā)送寫信號(hào)(最低位是0)
  110.         respons();            //調(diào)用應(yīng)答函數(shù)讓從機(jī)應(yīng)答
  111.         writebyte(addr);      //寫入地址
  112.         respons();            //每寫一字節(jié)都要應(yīng)答
  113.         writebyte(dat);
  114.         respons();
  115.         stop();
  116. }

  117. uchar read(uchar addr)
  118. {
  119.         uchar dat;
  120.         start();
  121.         writebyte(0x90);      //從此處的發(fā)送地址和方向位0到從機(jī)
  122.         respons();            //此處的從機(jī)產(chǎn)生應(yīng)答。屬于“偽寫”。用于確定和哪臺(tái)機(jī)子通信
  123.         writebyte(addr);
  124.         respons();
  125.         start();
  126.         writebyte(0x91);      //從此處開始,從機(jī)向主機(jī)寫數(shù)據(jù)。讀的方向位為1
  127.         respons();
  128.         dat=readbyte();
  129.         stop();
  130.         return dat;           //讀得的數(shù)據(jù)要返回
  131. }


  132. void delay1(int i)           //延時(shí)函數(shù)
  133. {
  134.                 while(i--);
  135. }

  136. void display(int x,int y)           //數(shù)碼管操作函數(shù)
  137. {

  138.         delay1(100);
  139.         leddat = ~0x00;                       //清屏消隱
  140.         Y0=0;Y1=1;Y2=1;Y3=1;Y4=1;Y5=1;Y6=1;Y7=1;                     //段選1
  141.         leddat = ~Led_dat[x%10];               //取余數(shù) 取出個(gè)位數(shù)
  142.         
  143.         delay1(100);
  144.         leddat = ~0x00;
  145.         Y0=1;Y1=0;Y2=1;Y3=1;Y4=1;Y5=1;Y6=1;Y7=1;                  //段選2
  146.                 leddat = ~Led_dat[x/10%10];         //取出十位數(shù)
  147.         
  148.         delay1(100);
  149.         leddat = ~0x00;
  150.    Y0=1;Y1=1;Y2=0;Y3=1;Y4=1;Y5=1;Y6=1;Y7=1;                  //段選3
  151.                 leddat = ~Led_dat[x/100%10];         //取出百位數(shù)
  152.         
  153.         delay1(100);
  154.         leddat = ~0x00;
  155.    Y0=1;Y1=1;Y2=1;Y3=0;Y4=1;Y5=1;Y6=1;Y7=1;                    //段選4
  156.                  leddat = ~Led_dat[x/1000];            //取出千位數(shù)
  157.         
  158.         delay1(100);
  159.         leddat = ~0x00;                       //清屏消隱
  160.         Y0=1;Y1=1;Y2=1;Y3=1;Y4=0;Y5=1;Y6=1;Y7=1;                     //段選5
  161.         leddat = ~Led_dat[y%10];               //取余數(shù) 取出個(gè)位數(shù)
  162.         
  163.         delay1(100);
  164.         leddat = ~0x00;
  165.         Y0=1;Y1=1;Y2=1;Y3=1;Y4=1;Y5=0;Y6=1;Y7=1;                  //段選6
  166.                 leddat = ~Led_dat[y/10%10];         //取出十位數(shù)
  167.         
  168.         delay1(100);
  169.         leddat = ~0x00;
  170.    Y0=1;Y1=1;Y2=1;Y3=1;Y4=1;Y5=1;Y6=0;Y7=1;                  //段選7
  171.                 leddat = ~Led_dat[y/100%10];         //取出百位數(shù)
  172.         
  173.         delay1(100);
  174.         leddat = ~0x00;
  175.    Y0=1;Y1=1;Y2=1;Y3=1;Y4=1;Y5=1;Y6=1;Y7=0;                    //段選8
  176.                  leddat = ~Led_dat[y/1000];            //取出千位數(shù)
  177. }

  178. void timerInit()
  179. {

  180.         TMOD=0x15;                 //模式設(shè)置,00000001
  181.         TR0=1;                         //打開計(jì)數(shù)器
  182.         ET0=1;                         //開計(jì)數(shù)器0中斷
  183.         
  184.         TR1=1;                         //打開計(jì)數(shù)器
  185.         ET1=1;                         //開計(jì)數(shù)器0中斷
  186.         TH1=(65536-45872)/256;         //50ms
  187.         TL1=(65536-45872)%256;
  188.         TH0=0;
  189.         TL0=0;
  190.         
  191.         EA=1;                         //開總中斷
  192. }

  193. uint T0_read()
  194. {
  195.         uchar tl,th1,th2;
  196.         uint val;
  197.         while(1)
  198.         {
  199.                 th1=TH0;
  200.                 tl=TL0;
  201.                 th2=TH0;
  202.                 if(th1==th2)
  203.                         break;
  204.         }
  205.         val=th1*256+tl;
  206.         return val;
  207. }



  208. void main()
  209. {
  210.     double dat = 0;
  211.                 int dig=0;
  212.           int i;
  213.         int  x_speed=150;   //速度增量
  214.         
  215.          LSA = 0;                //138譯碼器 YC2輸出低
  216.         LSB = 1;
  217.         LSC = 0;
  218.         LSG1 = 1;
  219.         WR = 0;                  //打開dac0830轉(zhuǎn)換 WR輸出低
  220.   timerInit();
  221.                 while(1)
  222.                 {
  223.                         dat=read(0x00);
  224.                         dat = (dat*67)/255 + 17;    //設(shè)定的每秒轉(zhuǎn)速    17~84r/s  對(duì)應(yīng) 1020~5040r/min
  225.                                 
  226.                           speed = count/en;   //當(dāng)前速度
  227.                                 
  228.                         if(speed < dat) x_speed+=1;    //如果實(shí)際速度小于設(shè)定速度 速度增量加
  229.                         else x_speed-=1;               //反之則減
  230.                         if(x_speed > 255)x_speed = 255;             //速度增量最大255 最小0
  231.                         if(x_speed < 0) x_speed = 0;
  232.                         digital =x_speed;  //電機(jī)輸出速度為 設(shè)定速度加上速度增量
  233.                         
  234.                         i=10;
  235.                         while(i--)
  236.                         {
  237.                                 i--;
  238.                          display(speed*60,dat*60);     //顯示當(dāng)前速度 每分鐘轉(zhuǎn)速  
  239.             }
  240.                         
  241.                 }
  242. }

  243. void timer_T1() interrupt 3      //定時(shí)器中斷
  244. {
  245.         static int i = 0;               
  246.         TH1=(65536-45872)/256;         //50ms
  247.         TL1=(65536-45872)%256;
  248.         i++;
  249.     if(i>=20)         //20*50=1000ms  定時(shí)1s
  250.                 {     
  251.                         TR0=0;                       //關(guān)閉計(jì)數(shù)器 記錄脈沖數(shù)量
  252.                         count=T0_read();
  253.                   TH0=0;
  254.                         TL0=0;
  255.                         i=0;                //脈沖清零 重新開始計(jì)數(shù)
  256.                         TR0=1;
  257.                 }

  258. }
復(fù)制代碼
全部資料51hei下載地址:
調(diào)速.zip (115.21 KB, 下載次數(shù): 14)

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

使用道具 舉報(bào)

本版積分規(guī)則

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

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表