找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

單片機垂直起降控制程序 PWM輸出,PCF8591讀取角度

[復制鏈接]
跳轉到指定樓層
樓主
ID:849756 發(fā)表于 2020-12-13 09:09 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
垂直起降懸臂控制,代碼可以實現指定角度懸停,采用PWM輸出,PCF8591讀取角度,八位數碼管顯示設定角度與實時角度。

單片機源程序如下:
  1. #include<reg52.h>
  2. #include<intrins.h>
  3. #define DataPort P0
  4. #define CYCLE 10
  5. typedef unsigned char uint8;
  6. typedef unsigned int uint16;
  7. typedef unsigned long uint32;
  8. void Display(unsigned char FirstBit,unsigned char Num);
  9. void PWMOUT();
  10. void wucha();
  11. void scan();
  12. void xianshi();
  13. void DelayUs2x(unsigned char t);//us級延時函數聲明
  14. void DelayMs(unsigned char t); //ms級延時
  15. void Init_Timer0(void);
  16. bit flag_300ms = 0;
  17. sbit LATCH1=P2^2;
  18. sbit LATCH2=P2^3;
  19. sbit K1 = P3^0;
  20. sbit K2 = P3^1;
  21. sbit PWM = P1^3;
  22. sbit I2C_SDA = P2^1;
  23. sbit I2C_SCL = P2^0;//I2C通信的兩個引腳
  24. uint8 AD_value = 0;//AD值
  25. key=0;
  26. TempData[8];
  27. angle=0;
  28. sangle=0;
  29. Proportion=1.5;
  30. Integral=0;
  31. Derivative=0;
  32. Error;
  33. LastError;
  34. PrevError;
  35. out=20;
  36. count=0;
  37. uint8 get_ADC_vaule(uint8 chn);
  38. code dofly_DuanMa[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};// 顯示段碼值0~9
  39. code dofly_WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//分別對應相應的數碼管點亮,即位碼
  40. void main()
  41. {
  42. Init_Timer0();
  43.          while(1)
  44.          {
  45.                   xianshi();
  46.                  scan();
  47.                  wucha();
  48.                  xianshi();
  49.          }
  50. }
  51. void DelayUs2x(unsigned char t)
  52. {   
  53. while(--t);
  54. }
  55. void DelayMs(unsigned char t)
  56. {

  57. while(t--)
  58. {
  59.      //大致延時1mS
  60.      DelayUs2x(245);
  61.          DelayUs2x(245);
  62. }
  63. }
  64. void scan()
  65. {
  66.         P3 = 0xff;
  67.         
  68.         if (P3==0xfe) key=1;
  69. if (P3==0xfd) key=2;
  70. if (P3==0xfb) key=3;
  71. if (P3==0xf7) key=4;
  72. if (P3==0xef) key=5;
  73. if (P3==0xdf) key=6;
  74. if (P3==0xbf) key=7;
  75. if (P3==0x7f) key=8;
  76.                 switch (key)
  77.                 {
  78.                 case 1:
  79.                         {
  80.                  sangle=0;
  81.                                         Proportion=3;
  82. Integral=0;
  83. Derivative=0;
  84.                         }
  85.                 break;
  86.                 case 2:
  87.                 {                        
  88.          sangle=35;
  89.                         Proportion=1.7;
  90. Integral=0.1;
  91. Derivative=0.1;
  92.                 }
  93.                 break;
  94.                 case 3:
  95.                         {
  96.                  sangle=45;
  97.                         Proportion=1.85;
  98. Integral=0;
  99. Derivative=0;}
  100.                 break;
  101.                 case 4:
  102.                 {                        
  103.          sangle=45;
  104.                         Proportion=1.85;
  105. Integral=0.2;
  106. Derivative=0;
  107.                 }
  108.                 break;
  109.                 case 5:
  110.                         {
  111.                  sangle=45;
  112.                         Proportion=1.85;
  113. Integral=0.3;
  114. Derivative=0.1;}
  115.                 break;
  116.                 case 6:
  117.                 {                        
  118.          sangle=50;
  119.                         Proportion=1.5;
  120. Integral=0;
  121. Derivative=0;
  122.                 }
  123.                 break;
  124.                 case 7:
  125.                         {
  126.                  sangle=55;
  127.                         Proportion=1.8;
  128. Integral=0.01;
  129. Derivative=0;}
  130.                 break;
  131.                 case 8:
  132.                 {                        
  133.          sangle=60;
  134.                         Proportion=1.5;
  135. Integral=0;
  136. Derivative=0;
  137.                 }
  138.         }
  139. }
  140.         void xianshi()
  141.         {DelayMs(1);
  142.                         AD_value = get_ADC_vaule(0);//讀取通道0的AD值
  143.         
  144.         angle=(float)AD_value*1.41-21;
  145.         TempData[3]=dofly_DuanMa[angle%10];
  146.   TempData[2]=dofly_DuanMa[angle/10%10];
  147.         TempData[1]=dofly_DuanMa[angle/100];
  148.   TempData[7]=dofly_DuanMa[sangle%10];
  149.         TempData[6]=dofly_DuanMa[sangle/10%10];
  150.   TempData[5]=dofly_DuanMa[sangle/100];
  151. }
  152. void wucha()
  153.          {
  154.                  angle=(float)AD_value*1.41-21;
  155.                 Error=sangle-angle;
  156.   PrevError+=Error;
  157.                  out=out+Proportion*Error+Integral*PrevError+Derivative*(LastError-Error);
  158.                  //out=out+Proportion*(Error-LastError)+Integral*Error+Derivative*(Error+PrevError-2*LastError);
  159.    LastError=Error;
  160.                  //out=50;
  161.                  //out=out+Proportion*Error+Integral*Error*0.02+Derivative*Error/0.02;
  162. if(out<0)
  163.    out=0;
  164.    if(out>100)
  165.    out=100;        
  166.         }

  167. void I2C_delay()//I2C延時函數
  168. {
  169.         _nop_();
  170.         _nop_();
  171.         _nop_();
  172.         _nop_();
  173. }

  174. void I2C_start()//I2C起始信號
  175. {
  176.         I2C_SDA = 1;
  177.         I2C_SCL = 1;
  178.         I2C_delay();
  179.         I2C_SDA = 0;
  180.         I2C_delay();
  181.         I2C_SCL = 0;
  182.         I2C_delay();
  183. }

  184. void I2C_stop()//I2C停止信號
  185. {
  186.         I2C_SDA = 0;
  187.         I2C_SCL = 0;
  188.         I2C_delay();
  189.         I2C_SCL = 1;
  190.         I2C_delay();
  191.         I2C_SDA = 1;
  192.         I2C_delay();
  193. }

  194. bit I2C_write(uint8 dat)//I2C寫一個字節(jié)
  195. {
  196.         bit ack = 0;
  197.         uint8 mask = 0;
  198.         for(mask=0x80;mask!=0;mask>>=1)
  199.         {
  200.                 if((mask&dat) == 0)
  201.                         I2C_SDA = 0;
  202.                 else
  203.                         I2C_SDA = 1;
  204.                 I2C_delay();
  205.                 I2C_SCL = 1;
  206.                 I2C_delay();
  207.                 I2C_SCL = 0;
  208.                 I2C_delay();
  209.         }
  210.         I2C_SDA = 1;
  211.         I2C_delay();
  212.         I2C_SCL = 1;
  213.         I2C_delay();
  214.         ack = I2C_SDA;
  215.         I2C_delay();
  216.         I2C_SCL = 0;
  217.         I2C_delay();
  218.         
  219.         return (~ack);        
  220. }

  221. uint8 I2C_read_ACK()//I2C讀一個字節(jié),并發(fā)送應答位
  222. {
  223.         uint8 dat = 0;
  224.         uint8 mask = 0;
  225.         I2C_SDA = 1;
  226.         for(mask=0x80;mask!=0;mask>>=1)
  227.         {
  228.                 if(I2C_SDA == 0)
  229.                         dat = dat & (~mask);
  230.                 else
  231.                         dat = dat | mask;
  232.                 I2C_delay();
  233.                 I2C_SCL = 1;
  234.                 I2C_delay();
  235.                 I2C_SCL = 0;
  236.                 I2C_delay();
  237.         }
  238.         I2C_SDA = 0;
  239.         I2C_delay();
  240.         I2C_SCL = 1;
  241.         I2C_delay();
  242.         I2C_SCL = 0;
  243.         I2C_delay();

  244.         return dat;
  245. }

  246. uint8 I2C_read_NACK()//I2C讀一個字節(jié),并發(fā)送非應答位
  247. {
  248.         uint8 dat = 0;
  249.         uint8 mask = 0;
  250.         I2C_SDA = 1;
  251.         for(mask=0x80;mask!=0;mask>>=1)
  252.         {
  253.                 if(I2C_SDA == 0)
  254.                         dat = dat & (~mask);
  255.                 else
  256.                         dat = dat | mask;
  257.                 I2C_delay();
  258.                 I2C_SCL = 1;
  259.                 I2C_delay();
  260.                 I2C_SCL = 0;
  261.                 I2C_delay();
  262.         }
  263.         I2C_SDA = 1;
  264.         I2C_delay();
  265.         I2C_SCL = 1;
  266.         I2C_delay();
  267.         I2C_SCL = 0;
  268.         I2C_delay();
  269.         return dat;
  270. }

  271. uint8 get_ADC_vaule(uint8 chn)//獲取AD值
  272. {
  273.         uint8 value;
  274.         I2C_start();//I2C起始信號
  275.         if(!I2C_write(0X90))//寫入PCF8591地址及讀寫選擇位為寫
  276.         {
  277.                 I2C_stop();
  278.                 return 0;
  279.         }
  280.         I2C_write(0X40 | chn);//寫入PCF8591通道0
  281.         I2C_write(0x00 | chn);//寫入PCF8591通道0
  282.         I2C_start();//I2C起始信號
  283.         I2C_write(0x48<<1 | 0x01);
  284.         I2C_read_ACK();//提供轉換所需的時鐘信號
  285.         value = I2C_read_NACK();//讀取上一次轉換的結果
  286.         I2C_stop();//I2C結束信號

  287.         return value;
  288. }
  289. void Init_Timer0(void)
  290. {
  291. TMOD |= 0x01;          //使用模式1,16位定時器,使用"|"符號可以在使用多個定時器時不受影響                     
  292. TH0=0x00;              //給定初值
  293. TL0=0x00;
  294. EA=1;            //總中斷打開
  295. ET0=1;           //定時器中斷打開
  296. TR0=1;           //定時器開關打開
  297. }
  298. void Timer0_isr(void) interrupt 1
  299. {
  300. static unsigned char count;
  301. TH0=(65536-10)/256;                  //重新賦值 2ms
  302. TL0=(65536-10)%256;

  303. Display(0,8);                // 調用數碼管掃描
  304.   count++;
  305. if (count<out)
  306. PWM= 1;
  307. else
  308. PWM=0;
  309. if(count==100)
  310.                 count= 0;
  311.     }
  312. void Display(unsigned char FirstBit,unsigned char Num)
  313. {
  314.       static unsigned char i=0;
  315.          

  316.            DataPort=0;   //清空數據,防止有交替重影
  317.        LATCH1=1;     //段鎖存
  318.        LATCH1=0;

  319.        DataPort=dofly_WeiMa[i+FirstBit]; //取位碼
  320.        LATCH2=1;     //位鎖存
  321.        LATCH2=0;

  322.        DataPort=TempData[i]; //取顯示數據,段碼
  323.        LATCH1=1;     //段鎖存
  324.        LATCH1=0;
  325.            i++;
  326.        if(i==Num)
  327.               i=0;
  328. }
復制代碼

全部程序51hei下載地址:
第四次.rar (40.58 KB, 下載次數: 16)
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復

使用道具 舉報

沙發(fā)
ID:328014 發(fā)表于 2020-12-13 16:52 | 只看該作者
沒有原理圖 樓主能分享一下嗎?
回復

使用道具 舉報

板凳
ID:230742 發(fā)表于 2020-12-13 19:37 | 只看該作者
我是小白,看過很多設計?戳四愕脑O計,我沒明白的是用讀取電位器角度。沒搞錯吧。你設計的是一個飛機啊。難道你要在飛機的電位器上掛個重錘?來讀取電位器的角度?
回復

使用道具 舉報

地板
ID:849756 發(fā)表于 2020-12-16 20:57 | 只看該作者
啤酒瓶子老大 發(fā)表于 2020-12-13 19:37
我是小白,看過很多設計?戳四愕脑O計,我沒明白的是用讀取電位器角度。沒搞錯吧。你設計的是一個飛機啊。 ...

阿。這就是一個小diy作品,就控制了單個懸臂
回復

使用道具 舉報

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

本版積分規(guī)則

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

Powered by 單片機教程網

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