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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

關于51單片機輸出頻率和占空比可調的PWM波程序問題

  [復制鏈接]
跳轉到指定樓層
樓主
前日看到一篇很好的代碼。有好代碼就要拿出來與壇友分享嘛
程序可以利用51單片機輸出頻率和占空比可調的PWM波程序。作者寫的很詳細,程序寫的很漂亮!!!但我還是有地方不明白
現在咱們大家來探討探討吧!!!


我有三個問題,懇求網友不吝賜教。
1.  頻率計算函數,當頻率變化,計算出定時器0初值;      
2.  脈寬計算函數,脈寬變化時,計算出定時器1初值;
3.  關定時器1,一定要這一步,因為定時器1的定時短于定時器0;


  1. <div>//------------------------------------------------------------------------------------
  2. //程序功能簡介:本程序產生15HZ~~~50KHZ的方波,并且實現頻率和脈寬的獨立調制,即可
  3. //在改變頻率的同時不改變脈寬,再改變脈寬的同時不改變頻率;同時設置
  4. //兩個調節步長------在KEY鍵按下時,粗調,沒有按下時,細調;
  5. //程序思路: 本程序用到兩個定時器------定時器0和定時器1,其中定時器0工作在定時方式下,
  6. //決定方波的頻率;定時器1,同樣工作在定時方式下,用于設定脈寬;
  7. //------------------------------------------------------------------------------------ </div><div>
  8. </div><div> #include <reg52.h>
  9. #include <math.h></div><div>
  10. </div><div> #define  uchar unsigned char
  11. #define  uint unsigned int
  12. #define  ALL  65536                              //定時器工作方式1時,最大基數長度 65536;
  13. #define  F_osc 12000000                       //晶振頻率12M;</div><div>
  14. </div><div> sbit KEY_F_UP=P0^2;                       //頻率上調按鈕;
  15. sbit KEY_F_DOWN=P0^3;                  //頻率下調按鈕;
  16. sbit KEY_W_UP=P0^4;                     //脈寬上調按鈕;
  17. sbit KEY_W_DOWN=P0^5;                //脈寬下調按鈕;
  18. sbit KEY=P0^6;                               //粗細調節按鈕-----按下為粗調,否則為細調;
  19. sbit OUTPUT=P1^0;                         //波形輸出;</div><div>
  20. </div><div> uchar TIMER0_H,TIMER0_L,TIMER1_H,TIMER1_L;         //定時器0和定時器1的初值設置;
  21. uchar PERCENT=50;                                                    //初始占空比;
  22. uchar FLAG_F=0,FLAG_W=0;                                      //頻率調節標志和脈寬調制標志;
  23. uint  FREQ=50000;                                                     //初始頻率;
  24. float temp;                                                                 //臨時全局變量,用于數據傳遞;</div><div>
  25. </div><div> void delay(uchar t);         //延時函數,用于按鍵去抖;
  26. void init();                      //初始化函數,用于定時器的初始化;
  27. void calculate_F();          //<font style="background-color: red;">頻率計算函數,當頻率變化,計算出定時器0初值;</font>
  28. void calculate_W();         //<font style="background-color: red;">脈寬計算函數,脈寬變化時,計算出定時器1初值;</font>
  29. void key_scan();             //按鍵掃描函數;
  30. void timer0();                //定時器0中斷函數;
  31. void timer1();                //定時器1中斷函數;</div><div>
  32. </div><div> void delay(uchar t)
  33. {
  34.     uchar i,j;</div><div>
  35. </div><div>    while(t--)             //每個脈沖為1us
  36.      {
  37.       for(i=0;i<100;i++)
  38.        for(j=0;j<100;j++);
  39.      }
  40.   }</div><div>
  41. </div><div> void calculate_F()
  42. {
  43.    <font color="red"> temp = ALL - F_osc/12.0/FREQ;</font></div><div>
  44. </div><div>    TIMER0_H = (uint)temp/256;
  45.     TIMER0_L = (uint)temp%256;
  46. }</div><div>
  47. </div><div> void calculate_W()
  48. {
  49.     float TEMP;</div><div>
  50. </div><div>    <font color="red">TEMP = (1 - PERCENT/100.0)*ALL + temp*PERCENT/100.0;</font></div><div>
  51. </div><div>    TIMER1_H = (uint)TEMP/256;
  52.     TIMER1_L = (uint)TEMP%256;
  53.   }</div><div>
  54. </div><div>  void key_scan()
  55.   {
  56.     delay(4);</div><div>
  57. </div><div>    if(!KEY_F_UP)     //頻率上調鍵按下;
  58.     {
  59.       FLAG_F=1;    //置標志位;</div><div>
  60. </div><div>      if(!KEY)
  61.         FREQ+=10;</div><div>
  62. </div><div>      else
  63.         FREQ++;</div><div>
  64. </div><div>      if(FREQ>50000)
  65.         FREQ=1;
  66.     }</div><div>
  67. </div><div>    else if(!KEY_F_DOWN)   //頻率下調鍵按下;
  68.     {
  69.       FLAG_F=1;    //置標志位;</div><div>
  70. </div><div>      if(!KEY)
  71.         FREQ-=10;</div><div>
  72. </div><div>      else
  73.         FREQ--;</div><div>
  74. </div><div>      if(FREQ<1)
  75.         FREQ=50000;
  76.      }</div><div>
  77. </div><div>     else if(!KEY_W_UP)    //脈寬上調鍵按下;
  78.      {
  79.        FLAG_W=1;    //置標志位;</div><div>
  80. </div><div>       if(!KEY)
  81.          PERCENT+=5;</div><div>
  82. </div><div>       else
  83.          PERCENT++;</div><div>
  84. </div><div>       if(PERCENT>49)
  85.          PERCENT=1;
  86.       }</div><div>
  87. </div><div>     else if(!KEY_W_DOWN)   //脈寬下調鍵按下;
  88.      {
  89.        FLAG_W=1;    //置標志位;</div><div>
  90. </div><div>       if(!KEY)
  91.          PERCENT-=5;</div><div>
  92. </div><div>       else
  93.          PERCENT--;</div><div>
  94. </div><div>       if(PERCENT<1)
  95.          PERCENT=49;
  96.       } </div><div>
  97. </div><div>      else ;</div><div>
  98. </div><div>      }</div><div>
  99. </div><div>  void timer0() interrupt 1      //決定頻率
  100.    {
  101.      TH0=TIMER0_H;
  102.      TL0=TIMER0_L;
  103.      TR1=1;           //開定時器1;
  104.      OUTPUT=1;
  105.    }</div><div>
  106. </div><div>   void timer1() interrupt 3     //決定脈寬
  107.    {
  108.      TH1=TIMER1_H;
  109.      TL1=TIMER1_L;
  110.      TR1=0;         <font style="background-color: red;"> //關定時器1,一定要這一步,因為定時器1的定時短于定時器0;</font>
  111.      OUTPUT=0;
  112.    }</div><div>
  113. </div><div>   void init()
  114.    {
  115.      TMOD=0x11;      //定時器0和定時器1都工作在方式1,16位計數器;
  116.      calculate_F();  //初始為1KHZ,占空比為50%;
  117.      calculate_W();</div><div>
  118. </div><div>     TH0=TIMER0_H;
  119.      TL0=TIMER0_L;</div><div>
  120. </div><div>     TH1=TIMER1_H;
  121.      TL1=TIMER1_L;</div><div>
  122. </div><div>     ET0=1;
  123.      ET1=1;</div><div>
  124. </div><div>     EA=1;</div><div>
  125. </div><div>     TR0=1;
  126.      TR1=1;
  127.      
  128.    }</div><div>
  129. </div><div> main()
  130. {
  131.     init();</div><div>
  132. </div><div>    while(1)
  133.     {
  134.        key_scan();
  135.        if(FLAG_F)     //改變頻率時要注意要進行脈寬的重新設置;
  136.        {
  137.          calculate_F();
  138.          calculate_W();
  139.          FLAG_F=0;
  140.        }</div><div>
  141. </div><div>       if(FLAG_W)     // 脈寬改變,頻率不改變;
  142.        {
  143.          calculate_W();
  144.          FLAG_W=0;
  145.        }
  146.      }
  147. }
  148. </div>
復制代碼



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

使用道具 舉報

沙發
ID:140769 發表于 2016-10-26 22:01 | 只看該作者
不知為什么顯示的這么亂呢?
回復

使用道具 舉報

板凳
ID:39386 發表于 2016-10-29 07:39 | 只看該作者
請重新上傳吧。想看看!
回復

使用道具 舉報

地板
ID:88606 發表于 2017-5-5 15:21 | 只看該作者
//------------------------------------------------------------------------------------
//程序功能簡介:本程序產生15HZ~~~50KHZ的方波,并且實現頻率和脈寬的獨立調制,即可
//在改變頻率的同時不改變脈寬,再改變脈寬的同時不改變頻率;同時設置
//兩個調節步長------在KEY鍵按下時,粗調,沒有按下時,細調;
//程序思路: 本程序用到兩個定時器------定時器0和定時器1,其中定時器0工作在定時方式下,
//決定方波的頻率;定時器1,同樣工作在定時方式下,用于設定脈寬;
//------------------------------------------------------------------------------------
  #include <reg52.h>
#include <math.h>
#define  uchar unsigned char
#define  uint unsigned int
#define  ALL  65536             //定時器工作方式1時,最大基數長度 65536;
#define  F_osc 12000000         //晶振頻率12M;

sbit KEY_F_UP=P0^2;             //頻率上調按鈕;
sbit KEY_F_DOWN=P0^3;           //頻率下調按鈕;
sbit KEY_W_UP=P0^4;             //脈寬上調按鈕;
sbit KEY_W_DOWN=P0^5;           //脈寬下調按鈕;
sbit KEY=P0^6;                  //粗細調節按鈕-----按下為粗調,否則為細調;
sbit OUTPUT=P1^0;               //波形輸出;

uchar TIMER0_H,TIMER0_L,TIMER1_H,TIMER1_L;//定時器0和定時器1的初值設置;
uchar PERCENT=50;               //初始占空比;
uchar FLAG_F=0,FLAG_W=0;//頻率調節標志和脈寬調制標志;
uint  FREQ=50000;               //初始頻率;
float temp;                     //臨時全局變量,用于數據傳遞;
void delay(uchar t);           //延時函數,用于按鍵去抖;
void init();                      //初始化函數,用于定時器的初始化;
void calculate_F();     
//頻率計算函數,當頻率變化,計算出定時器0初值;
void calculate_W();     
//脈寬計算函數,脈寬變化時,計算出定時器1初值;
void key_scan();             //按鍵掃描函數;
void timer0();                //定時器0中斷函數;
void timer1();                //定時器1中斷函數;
void delay(uchar t)
{
    uchar i,j;
    while(t--)             //每個脈沖為1us
     {
      for(i=0;i<100;i++)
       for(j=0;j<100;j++);
     }
  }
void calculate_F()
{
    TIMER0_H = (uint)temp/256;
    TIMER0_L = (uint)temp%256;
}
void calculate_W()
{
    float TEMP;
    TEMP = (1 - PERCENT/100.0)*ALL + temp*PERCENT/100.0;
    TIMER1_H = (uint)TEMP/256;
    TIMER1_L = (uint)TEMP%256;
  }
  void key_scan()
  {
    delay(4);
    if(!KEY_F_UP)     //頻率上調鍵按下;
    {
      FLAG_F=1;    //置標志位;
      if(!KEY)
        FREQ+=10;
      else
        FREQ++;
      if(FREQ>50000)
        FREQ=1;
    }
    else if(!KEY_F_DOWN)   //頻率下調鍵按下;
    {
      FLAG_F=1;    //置標志位;
      if(!KEY)
        FREQ-=10;
      else
        FREQ--;
      if(FREQ<1)
        FREQ=50000;
     }
     else if(!KEY_W_UP)    //脈寬上調鍵按下;
     {
       FLAG_W=1;    //置標志位;
       if(!KEY)
         PERCENT+=5;
       else
         PERCENT++;
       if(PERCENT>49)
         PERCENT=1;
      }
     else if(!KEY_W_DOWN)   //脈寬下調鍵按下;
     {
       FLAG_W=1;    //置標志位;
       if(!KEY)
         PERCENT-=5;
       else
         PERCENT--;
       if(PERCENT<1)
         PERCENT=49;
      }
      else ;
      }
  void timer0() interrupt 1      //決定頻率
   {
     TH0=TIMER0_H;
     TL0=TIMER0_L;
     TR1=1;           //開定時器1;
     OUTPUT=1;
   }
   void timer1() interrupt 3     //決定脈寬
   {
     TH1=TIMER1_H;
     TL1=TIMER1_L;
     TR1=0; //關定時器1,一定要這一步,因為定時器1的定時短于定時器0;
     OUTPUT=0;
   }
   void init()
   {
     TMOD=0x11;      //定時器0和定時器1都工作在方式1,16位計數器;
     calculate_F();  //初始為1KHZ,占空比為50%;
     calculate_W();
     TH0=TIMER0_H;
     TL0=TIMER0_L;
     TH1=TIMER1_H;
     TL1=TIMER1_L;
     ET0=1;
     ET1=1;
     EA=1;
     TR0=1;
     TR1=1;
     
   }
main()
{
    init();
    while(1)
    {
       key_scan();
       if(FLAG_F)     //改變頻率時要注意要進行脈寬的重新設置;
       {
         calculate_F();
         calculate_W();
         FLAG_F=0;
       }
       if(FLAG_W)     // 脈寬改變,頻率不改變;
       {
         calculate_W();
         FLAG_W=0;
       }
     }
}
回復

使用道具 舉報

5#
ID:203412 發表于 2017-5-22 11:30 | 只看該作者
有proteus 仿真圖嗎
回復

使用道具 舉報

6#
ID:153136 發表于 2018-4-14 20:16 | 只看該作者
我試了一下,沒辦法實現頻率的改變
回復

使用道具 舉報

7#
ID:153136 發表于 2018-4-14 20:48 | 只看該作者
對比截圖中兩個函數,我自己測試了,頻率無法改變,可能跟程序中根據頻率計算計時器初始值的函數沒寫好有關。

QQ截圖20180414204620.png (11.55 KB, 下載次數: 121)

QQ截圖20180414204620.png

QQ截圖20180414204631.png (20.19 KB, 下載次數: 102)

QQ截圖20180414204631.png
回復

使用道具 舉報

8#
ID:300215 發表于 2018-4-14 21:23 | 只看該作者
//------------------------------------------------------------------------------------ //程序功能簡介:本程序產生15HZ~~~50KHZ的方波,并且實現頻率和脈寬的獨立調制,即可 //在改變頻率的同時不改變脈寬,再改變脈寬的同時不改變頻率;同時設置 //兩個調節步長------在KEY鍵按下時,粗調,沒有按下時,細調; //程序思路: 本程序用到兩個定時器------定時器0和定時器1,其中定時器0工作在定時方式下, //決定方波的頻率;定時器1,同樣工作在定時方式下,用于設定脈寬; //------------------------------------------------------------------------------------    #include <reg52.h> #include <math.h> #define  uchar unsigned char #define  uint unsigned int #define  ALL  65536             //定時器工作方式1時,最大基數長度 65536; #define  F_osc 12000000         //晶振頻率12M;  sbit KEY_F_UP=P0^2;             //頻率上調按鈕; sbit KEY_F_DOWN=P0^3;           //頻率下調按鈕; sbit KEY_W_UP=P0^4;             //脈寬上調按鈕; sbit KEY_W_DOWN=P0^5;           //脈寬下調按鈕; sbit KEY=P0^6;                  //粗細調節按鈕-----按下為粗調,否則為細調; sbit OUTPUT=P1^0;               //波形輸出;  uchar TIMER0_H,TIMER0_L,TIMER1_H,TIMER1_L;//定時器0和定時器1的初值設置; uchar PERCENT=50;               //初始占空比; uchar FLAG_F=0,FLAG_W=0;//頻率調節標志和脈寬調制標志; uint  FREQ=50000;               //初始頻率; float temp;                     //臨時全局變量,用于數據傳遞; void delay(uchar t);           //延時函數,用于按鍵去抖; void init();                      //初始化函數,用于定時器的初始化; void calculate_F();      //頻率計算函數,當頻率變化,計算出定時器0初值; void calculate_W();      //脈寬計算函數,脈寬變化時,計算出定時器1初值; void key_scan();             //按鍵掃描函數; void timer0();                //定時器0中斷函數; void timer1();                //定時器1中斷函數; void delay(uchar t) {     uchar i,j;     while(t--)             //每個脈沖為1us      {       for(i=0;i<100;i++)        for(j=0;j<100;j++);      }   } void calculate_F() {     TIMER0_H = (uint)temp/256;     TIMER0_L = (uint)temp%256; } void calculate_W() {     float TEMP;     TEMP = (1 - PERCENT/100.0)*ALL + temp*PERCENT/100.0;     TIMER1_H = (uint)TEMP/256;     TIMER1_L = (uint)TEMP%256;   }   void key_scan()   {     delay(4);     if(!KEY_F_UP)     //頻率上調鍵按下;     {       FLAG_F=1;    //置標志位;       if(!KEY)         FREQ+=10;       else         FREQ++;       if(FREQ>50000)         FREQ=1;     }     else if(!KEY_F_DOWN)   //頻率下調鍵按下;     {       FLAG_F=1;    //置標志位;       if(!KEY)         FREQ-=10;       else         FREQ--;       if(FREQ<1)         FREQ=50000;      }      else if(!KEY_W_UP)    //脈寬上調鍵按下;      {        FLAG_W=1;    //置標志位;        if(!KEY)          PERCENT+=5;        else          PERCENT++;        if(PERCENT>49)          PERCENT=1;       }      else if(!KEY_W_DOWN)   //脈寬下調鍵按下;      {        FLAG_W=1;    //置標志位;        if(!KEY)          PERCENT-=5;        else          PERCENT--;        if(PERCENT<1)          PERCENT=49;       }        else ;       }   void timer0() interrupt 1      //決定頻率    {      TH0=TIMER0_H;      TL0=TIMER0_L;      TR1=1;           //開定時器1;      OUTPUT=1;    }    void timer1() interrupt 3     //決定脈寬    {      TH1=TIMER1_H;      TL1=TIMER1_L;      TR1=0; //關定時器1,一定要這一步,因為定時器1的定時短于定時器0;      OUTPUT=0;    }    void init()    {      TMOD=0x11;      //定時器0和定時器1都工作在方式1,16位計數器;      calculate_F();  //初始為1KHZ,占空比為50%;      calculate_W();      TH0=TIMER0_H;      TL0=TIMER0_L;      TH1=TIMER1_H;      TL1=TIMER1_L;      ET0=1;      ET1=1;      EA=1;      TR0=1;      TR1=1;          } main() {     init();     while(1)     {        key_scan();        if(FLAG_F)     //改變頻率時要注意要進行脈寬的重新設置;        {          calculate_F();          calculate_W();          FLAG_F=0;        }        if(FLAG_W)     // 脈寬改變,頻率不改變;        {          calculate_W();          FLAG_W=0;        }      } }
回復

使用道具 舉報

9#
ID:153136 發表于 2018-4-18 09:56 | 只看該作者
林木 發表于 2018-4-14 20:48
對比截圖中兩個函數,我自己測試了,頻率無法改變,可能跟程序中根據頻率計算計時器初始值的函數沒寫好有關 ...

若想實現頻率改變,調頻代碼應這樣修改

QQ截圖20180418095602.jpg (22.11 KB, 下載次數: 114)

QQ截圖20180418095602.jpg
回復

使用道具 舉報

10#
ID:242952 發表于 2018-4-24 12:26 | 只看該作者
樓主解決了嗎
回復

使用道具 舉報

11#
ID:372402 發表于 2018-9-1 13:06 | 只看該作者
林木 發表于 2018-4-18 09:56
若想實現頻率改變,調頻代碼應這樣修改

試了你這個也不行啊~
回復

使用道具 舉報

12#
ID:470545 發表于 2019-1-19 15:27 | 只看該作者
林木 發表于 2018-4-14 20:48
對比截圖中兩個函數,我自己測試了,頻率無法改變,可能跟程序中根據頻率計算計時器初始值的函數沒寫好有關 ...

把 P0^6 腳接地,頻率可以實現增加,但是占空比和頻率都無法減
回復

使用道具 舉報

13#
ID:837631 發表于 2021-9-6 13:46 | 只看該作者
有大俠解決了頻率改變的問題嗎?
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 亚洲一区二区欧美 | 久久大陆 | 一级做a爰片性色毛片 | 日韩欧美国产综合 | 中文字幕av网址 | 成人国产精品久久 | 久久亚洲综合 | 国产精品久久久久9999鸭 | 久久精品国产亚洲 | 97精品国产一区二区三区 | 成人精品一区二区三区 | 国产亚洲精品久久久久久豆腐 | 日韩高清中文字幕 | 91热在线| 国产精品久久久久久久久久久久久 | 全免费a级毛片免费看视频免 | 精品久久久久久中文字幕 | 精品一区二区三区四区五区 | 亚洲综合成人网 | 国产精品网址 | 精品国产一区二区三区在线观看 | 国产免费一区二区 | www.788.com色淫免费 | 国产久视频 | 欧美国产日韩在线观看成人 | 99在线免费观看 | 国产日韩欧美激情 | 国产精品高清在线 | 亚洲男女视频在线观看 | 国产日韩精品一区 | 亚洲网站免费看 | 久久com| 成人亚洲精品久久久久软件 | 久久99精品久久久久蜜桃tv | 一区二区三区回区在观看免费视频 | 亚洲视频在线看 | 日韩免费高清视频 | 成人av播放 | 中文字幕1区2区3区 日韩在线视频免费观看 | 久久99精品久久久97夜夜嗨 | 午夜一区二区三区 |