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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

在進行PWM控制步進電機時為何將全局變量改成程序的局部變量會導致波形失真?

[復制鏈接]
跳轉到指定樓層
樓主
本帖最后由 ceiwei 于 2015-5-23 19:12 編輯

做了一個用PWM控制步進電機輸出的實驗,我設定了一個溢出步數int step_number_over;//溢出步數和實時累加計算的步數 int step_number,如果溢出步數設定為全局變量輸出一開始沒有問題,但如果溢出步數設定為局部變量,也就是調用子程序的參數就會導致輸出波形在運行一段時間后改變,而且全部變量那個方法的輸出也會在經過十多分鐘后改變。具體對比可以看兩張圖,失真的那張圖的波形上升和下降沿都跳到格子中間了。
以下是程序可能導致波形失真的地方我已經用黑字描述出來。
原始程序
# include<reg51.h>                                           //頭文件
sbit pulse=P1^0;//脈沖輸出口
sbit pulse2=P1^1;
sbit pwm_manual_button=P2^0;//手動輸出一步
sbit pwm_auto_button=P2^1;         //自動連續輸出
  sbit pwm_increase_button=P2^2;
   sbit pwm_decrease_button=P2^3;
   int pwm_hz=1000;//預設脈沖頻率為1000         //默認步進電機頻率為1000,即1ms
int pwm1=(65536-1000)/256;  //             不可以直接把pwm_hz放進去,這是全局變量定義,除非是系統自設的變量,如P1等,否則就不能放進去計算,只能用數字計算
int pwm2=(65536-1000)%256; //
int pwm3=(65536-500)/256;  
int pwm4=(65536-500)%256;
char out1_4[4]={0x03,0x06,0x0c,0x09};//雙四拍輸出
char out1_8[8]={0x02,0x06,0x04,0x0c,0x08,0x09,0x01,0x03};                                         //等待輸入八拍數據        ,為何模擬的時候會后退半步?         把0x01,0x03這兩個拍從最開始兩位放到最后兩位,然后輸出,否則一開始是0x01會導致后退一步,0x03會原地不動一步
char out_loop=0;
int step_number_over;//溢出步數
int step_number;        //總步數
bit shep_one_yes; //是否走了一步
void t0sss() interrupt 1        //定時器中斷0為確定輸出頻率
{

          TH0=pwm1;//重新賦值,就代表高低電平的半周期,TH和TL中的是計數器初值,中斷則是計數器從初值到溢出之后發生的,輸出一個信號,如果要產生脈寬,則設置第二個定時器中斷,輸出相反信號
    TL0=pwm2;
   P1=out1_8[out_loop];

   if(out_loop<=6)            //判斷是否到數組3號元素,到了以后就回零,重復循環
   {
   out_loop++;
   }
   else
   {
   out_loop=0;
   }                                        //啟動定時器中斷1,類似于嵌套結構
           step_number++;

}
void t1sss() interrupt 3        //定時器中斷1,輸出特定脈寬        采用了2個定時器后,原本定時器0設定的周期要再度減半。所以原本如果定時器0設定為500還想保持1kHz,就要增加
{

      TH1=pwm3;//重新賦值,
    TL1=pwm4;
   pulse=~pulse;
   TR1=0;                         //必須要加上這一句,防止重復中斷


}

void pwm_auto()         //自動輸出模式
{
   TMOD=0x11;//使用模式1
   TH0=pwm1;//重新賦值,這里是
   TL0=pwm2;
   ET0=1; //允許定時器1中斷
   TR0=1; //允許定時器1工作
   while(1)
   {
   //進行增減速計算,如果不按下就直接以默認頻率運行
   if(pwm_increase_button==0)        //按下增速按鈕
   {
   pwm_hz=pwm_hz-10;        //通過減小數值來增大每秒脈沖。來增加速度的目的
   }
      if(pwm_decrease_button==0)   //按下減速按鈕
   {
   pwm_hz=pwm_hz+10;   //通過增大數值來增大脈沖的周期,達到減速的目的
   }
pwm1=(65536-pwm_hz)/256;  //          實驗已經證明如果需要更改脈沖頻率可以從這里改變
pwm2=(65536-pwm_hz)%256; //
if(pwm_auto_button==1)break;         //如果自動PWM按鈕復位,跳出
if(step_number>=step_number_over)break;//總步數的大于上限,跳出
   }          //如果這里有有{}則不要加;
}

void pwm_manual() //手動輸出,單步模式
{
   int step_number_plus=step_number+1;         //預設下一步的步數

   ET0=0; //允許定時器1中斷
   TR0=0; //允許定時器1工作
   TH0=pwm1;//重新賦值,這里是
   TL0=pwm2;
   ET0=1; //允許定時器1中斷
   TR0=1; //允許定時器1工作

   P1=out1_8[out_loop];  //輸出P1口狀態給步進電機放大芯片
      if(out_loop<=6)            //判斷是否到數組3號元素,到了以后就回零,重復循環
   {
   out_loop++;
   }
      else
   {
   out_loop=0;
   }                                        //啟動定時器中斷1,類似于嵌套結構

   step_number++;        //總步數加1
   shep_one_yes=(step_number_plus==step_number);                //確認是否走了一步后      
   while(shep_one_yes)break;  //走了一步后跳出
}

main()
{
char out_loop_plus=out_loop+1;
//這里可以更改總步數上限
EA=1; //允許總中斷
while(1)
{
   TR0=0;//預先關閉定時器中斷
   //自動模式的啟動和復位
  if((pwm_auto_button==0)&&(pwm_manual_button==1)&&(step_number<step_number_over))         //自動輸出打開而手動輸出關閉同時總步數小于上限的時候啟動自動輸出
   {
   pwm_auto();

   }
   if(step_number>=step_number_over)   //總步數大于上限,關閉中斷,等待復位
   {
   TR0=0;
   if(pwm_auto_button==1)        //自動輸出按鍵彈起來的時候,總步數復位,也可以是其他情況
     {
         step_number=0;
     }
   }
   //手動模式的啟動和復位
   if((pwm_auto_button==1)&&(pwm_manual_button==0)&&(~shep_one_yes))          //手動輸出打開而自動輸出關閉同時還沒有走步的時候啟動手動輸出
      {
   pwm_manual();
}
   if((pwm_manual_button==1)&&(shep_one_yes))                //手動輸出關閉同時走了一步
        {
        shep_one_yes=0;
        }
}
}


程序第二次改變
# include<reg51.h>                                           //頭文件
sbit pulse=P1^0;//脈沖輸出口
sbit pulse2=P1^1;
sbit pwm_manual_button=P2^0;//手動輸出一步
sbit pwm_auto_button=P2^1;         //自動連續輸出
  sbit pwm_increase_button=P2^2;
   sbit pwm_decrease_button=P2^3;
   int pwm_hz=1000;//預設脈沖頻率為1000         //默認步進電機頻率為1000,即1ms
int pwm1=(65536-1000)/256;  //             不可以直接把pwm_hz放進去,這是全局變量定義,除非是系統自設的變量,如P1等,否則就不能放進去計算,只能用數字計算
int pwm2=(65536-1000)%256; //
int pwm3=(65536-500)/256;  
int pwm4=(65536-500)%256;
char out1_4[4]={0x03,0x06,0x0c,0x09};//雙四拍輸出
char out1_8[8]={0x02,0x06,0x04,0x0c,0x08,0x09,0x01,0x03};                                         //等待輸入八拍數據        ,為何模擬的時候會后退半步?         把0x01,0x03這兩個拍從最開始兩位放到最后兩位,然后輸出,否則一開始是0x01會導致后退一步,0x03會原地不動一步
char out_loop=0;

int step_number;        //總步數
int step_number_over_max=10000;//總步數上限 ,設為10000,用作主程序判斷與 int step_number_over不是一個變量
bit shep_one_yes; //是否走了一步
void t0sss() interrupt 1        //定時器中斷0為確定輸出頻率
{

          TH0=pwm1;//重新賦值,就代表高低電平的半周期,TH和TL中的是計數器初值,中斷則是計數器從初值到溢出之后發生的,輸出一個信號,如果要產生脈寬,則設置第二個定時器中斷,輸出相反信號
    TL0=pwm2;
   P1=out1_8[out_loop];

   if(out_loop<=6)            //判斷是否到數組3號元素,到了以后就回零,重復循環
   {
   out_loop++;
   }
   else
   {
   out_loop=0;
   }                                        //啟動定時器中斷1,類似于嵌套結構
           step_number++;

}
void t1sss() interrupt 3        //定時器中斷1,輸出特定脈寬        采用了2個定時器后,原本定時器0設定的周期要再度減半。所以原本如果定時器0設定為500還想保持1kHz,就要增加
{

      TH1=pwm3;//重新賦值,
    TL1=pwm4;
   pulse=~pulse;
   TR1=0;                         //必須要加上這一句,防止重復中斷


}

void pwm_auto(int step_number_over)         //自動輸出模式         ,本次自動輸出步數上限,step_number_over從開始到這里了
{
   TMOD=0x11;//使用模式1
   TH0=pwm1;//重新賦值,這里是
   TL0=pwm2;
   ET0=1; //允許定時器1中斷
   TR0=1; //允許定時器1工作
   while(1)
   {
   //進行增減速計算,如果不按下就直接以默認頻率運行
   if(pwm_increase_button==0)        //按下增速按鈕
   {
   pwm_hz=pwm_hz-10;        //通過減小數值來增大每秒脈沖。來增加速度的目的
   }
      if(pwm_decrease_button==0)   //按下減速按鈕
   {
   pwm_hz=pwm_hz+10;   //通過增大數值來增大脈沖的周期,達到減速的目的
   }
pwm1=(65536-pwm_hz)/256;  //          實驗已經證明如果需要更改脈沖頻率可以從這里改變
pwm2=(65536-pwm_hz)%256; //
if(pwm_auto_button==1)break;         //如果自動PWM按鈕復位,跳出
if(step_number>=step_number_over)break;//總步數的大于上限,跳出
   }          //如果這里有有{}則不要加;
}

void pwm_manual() //手動輸出,單步模式
{
   int step_number_plus=step_number+1;         //預設下一步的步數

   ET0=0; //允許定時器1中斷
   TR0=0; //允許定時器1工作
   TH0=pwm1;//重新賦值,這里是
   TL0=pwm2;
   ET0=1; //允許定時器1中斷
   TR0=1; //允許定時器1工作

   P1=out1_8[out_loop];  //輸出P1口狀態給步進電機放大芯片
      if(out_loop<=6)            //判斷是否到數組3號元素,到了以后就回零,重復循環
   {
   out_loop++;
   }
      else
   {
   out_loop=0;
   }                                        //啟動定時器中斷1,類似于嵌套結構

   step_number++;        //總步數加1
   shep_one_yes=(step_number_plus==step_number);                //確認是否走了一步后      
   while(shep_one_yes)break;  //走了一步后跳出
}

main()
{
char out_loop_plus=out_loop+1;
//這里可以更改總步數上限
EA=1; //允許總中斷
while(1)
{
   TR0=0;//預先關閉定時器中斷
   //自動模式的啟動和復位
   if((pwm_auto_button==0)&&(pwm_manual_button==1)&&(step_number<step_number_over_max))         //自動輸出打開而手動輸出關閉同時總步數小于上限的時候啟動自動輸出
   {
   pwm_auto(100);

   }
   if(step_number>=step_number_over_max)   //總步數大于上限,關閉中斷,等待復位
   {
   TR0=0;
   if(pwm_auto_button==1)        //自動輸出按鍵彈起來的時候,總步數復位,也可以是其他情況
     {
         step_number=0;
     }
   }
   //手動模式的啟動和復位
   if((pwm_auto_button==1)&&(pwm_manual_button==0)&&(~shep_one_yes))          //手動輸出打開而自動輸出關閉同時還沒有走步的時候啟動手動輸出
      {
   pwm_manual();
}
   if((pwm_manual_button==1)&&(shep_one_yes))                //手動輸出關閉同時走了一步
        {
        shep_one_yes=0;
        }
}
}

為何把總步數上限從全局變量改成局部變量后就會發生失真,并且CPU使用量大增?



實驗3失真照片.JPG (263.18 KB, 下載次數: 133)

實驗3失真照片.JPG

正常情況輸出波形.JPG (262.19 KB, 下載次數: 123)

正常情況輸出波形.JPG
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:79077 發表于 2015-5-19 15:14 | 只看該作者
是我描述的方式不對嗎,沒有人回答
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: aaaa一级毛片| 91精品国产91久久久久久三级 | 国产精品天堂 | 欧美在线综合 | 亚洲乱码一区二区三区在线观看 | 久久中文字幕一区 | 九九九国产| 亚洲精品视频一区 | 国产成人免费视频网站高清观看视频 | 久久久久久亚洲精品 | 欧美区日韩区 | 亚洲精品中文字幕在线观看 | 久久久性 | 精品国产精品国产偷麻豆 | 性高湖久久久久久久久3小时 | 国产精品久久久久久久久久久免费看 | 激情毛片| 日韩精品久久久 | 天天综合网永久 | 免费日韩av网站 | 欧美日韩一区在线播放 | 精品国产乱码久久久久久图片 | www网站在线观看 | 久操国产 | 国产在线麻豆精品入口 | 99精品99 | 日韩电影免费在线观看中文字幕 | 成人看片在线观看 | 一级黄色片网站 | 国产欧美一区二区三区在线看蜜臀 | 欧美精产国品一二三区 | 久久久久国产 | 日韩和的一区二区 | 久久精品久久久 | 欧美激情一区二区三区 | 精品亚洲一区二区三区 | 成人av电影在线 | 国产农村妇女毛片精品久久麻豆 | 久久色视频 | 久久99视频这里只有精品 | 可以在线看的黄色网址 |