專注電子技術學習與研究
當前位置:單片機教程網(wǎng) >> MCU設計實例 >> 瀏覽文章

一個程序順序引發(fā)的血案(關于軟件PWM編程)

作者:huqin   來源:本站原創(chuàng)   點擊數(shù):  更新時間:2014年04月15日   【字體:

四段不同順序的程序會有如此巨大的差別!

程序段一:

__interrupt  interrupt_isr(void)

{      

         if(FTC0IRQ==1)                                     //0.02ms

         {

                   FTC0IRQ  = 0;          

                   if(PWM_Flag==0)

                   {      

                            num++;

                            sum++;                                                 

                            if(sum >= 100)                    //2ms

                            {

                                     num=0;

                                     sum=0;

                                     INPUT1=1;//低電平輸出結束,引腳輸出高電平

                                     INPUT2=1;

                            }

                            if(num >= work)               

                            {

                                     INPUT1=0;//高電平輸出結束,引腳輸出低電平

                                     INPUT2=0;

                            }

                            Tim_1S++;

                            if(Tim_1S==50000)

                            {

                                     PWM_Flag=1;

                            }               

                   }

                   if(PWM_Flag==1)

                   {      

                            INPUT1=0;//高電平輸出結束,引腳輸出低電平

                            INPUT2=0;               

                            Tim_1S--;

                            if(Tim_1S==0)

                            {

                                     PWM_Flag=0;

                                     num=0;

                                     sum=0;

                            }               

                   }                                                                                                                      

         }

}

顯然這個程序的功能是引腳輸出一個可調的PWM波形,然后輸出一個低電平的波形,PWM的波形和這個低電平的波形持續(xù)的時間都是1S鐘,程序段一是正確的程序.

下面分析下面的三個程序的問題:

程序段二:

__interrupt  interrupt_isr(void)

{      

         if(FTC0IRQ==1)                                     //0.02ms

         {

                   FTC0IRQ  = 0;          

                   if(PWM_Flag==0)

                   {                                                              

                            if(++sum >= 100)               //2ms

                            {

                                     num=0;

                                     sum=0;

                                     INPUT1=1;//低電平輸出結束,引腳輸出高電平

                                     INPUT2=1;

                            }

                            if(++num >= work)           

                            {               

                                     INPUT1=0;//高電平輸出結束,引腳輸出低電平

                                     INPUT2=0;

                            }

                            Tim_1S++;

                            if(Tim_1S==50000)

                            {

                                     PWM_Flag=1;

                            }               

                   }

                   if(PWM_Flag==1)

                   {      

                            INPUT1=0;//高電平輸出結束,引腳輸出低電平

                            INPUT2=0;               

                            Tim_1S--;

                            if(Tim_1S==0)

                            {

                                     PWM_Flag=0;

                                     num=0;

                                     sum=0;

                            }               

                   }                                                                                                                      

         }

}

 

程序段二:

現(xiàn)在假設系統(tǒng)初始化,sum和num都是0,現(xiàn)在假設work=20,系統(tǒng)初始化后開始疊加運算,等到num變?yōu)?0后會有高電平輸出結束,引腳輸出低電平,占空比為20%,系統(tǒng)正常運行,但等到sum加到100后sum,num會置為0,然后num會加1變?yōu)?,此時下一個周期到來了,但是初始化卻和第一個周期不一樣了,這時num總會比sum大1,也就是最后輸出的占空比總是比設定的值會小1,比如設置work值為100,那么從起始狀態(tài)開始分析,起始狀態(tài)下num和sum都是0,等sum變?yōu)?00的時候會先將num置為0,然后num的值會做想應的加1然后下一個周期來了,sum和num有了不同的初始值sum的初始值為0而num的初始值卻變?yōu)?,這樣話,時過境遷,num會首先變?yōu)?00,這時sum才是99,這時就會了出現(xiàn)一個短暫的低電平,這個低電平的持續(xù)時間剛好是一個周期,這樣就和我們的初衷相違背了,這時輸出的占空比不是100%,而是99%.同樣的道理這樣的問題不僅會出現(xiàn)有占空比為100%的情況,比如此里的占空比是設置的是20%,那么從初始狀態(tài)到sum變?yōu)?0,然后緊接著num又會加1變?yōu)?,那么從下一個周期開始兩個數(shù)據(jù)又會出現(xiàn)不同步的情況,從而直接導致下一次等到sum變?yōu)?9的候,num己經(jīng)是100了,從而又直接導致下一個周期的起始狀態(tài)又變成了sum=0,而num=1.周而復始,從而真正得到地占空比變?yōu)?9%.

 

程序段三:

__interrupt  interrupt_isr(void)

{      

         if(FTC0IRQ==1)                                     //0.02ms

         {

                   FTC0IRQ  = 0;          

                   if(PWM_Flag==0)

                   {      

                            num++;

                            sum++;                                                                    

                            if(num >= work)               

                            {               

                                     INPUT1=0;//高電平輸出結束,引腳輸出低電平

                                     INPUT2=0;

                            }

                            if(sum >= 100)           //2ms

                            {

                                     num=0;

                                     sum=0;

                                     INPUT1=1;//低電平輸出結束,引腳輸出高電平

                                     INPUT2=1;

                            }

                            Tim_1S++;

                            if(Tim_1S==50000)

                            {

                                     PWM_Flag=1;

                            }               

                   }

                   if(PWM_Flag==1)

                   {      

                            INPUT1=0;//高電平輸出結束,引腳輸出低電平

                            INPUT2=0;               

                            Tim_1S--;

                            if(Tim_1S==0)

                            {

                                     PWM_Flag=0;

                                     num=0;

                                     sum=0;

                            }               

                   }                                                                                                                      

         }

}

關于第三種情況:

第三種情況倒不存在num和sum不同步的問題,但是有一個小問題就是當work是100

的時候num會首先加到100輸出一個低電平,而這里的期望占空比是100%,也就是沒這里會有一個非常短暫的低電平,用示波器也是發(fā)現(xiàn)不了的,因為示波器的分辨能力還是沒有單片機執(zhí)行指令的速度快,所以說這個誤差可以忽略不計,不過在邏輯是還是不完美的.

程序段四:

__interrupt  interrupt_isr(void)

{      

         if(FTC0IRQ==1)                                     //0.02ms

         {

                   FTC0IRQ  = 0;          

                   if(PWM_Flag==0)

                   {                                                                       

                            if(++num >= work)           

                            {               

                                     INPUT1=0;//高電平輸出結束,引腳輸出低電平

                                     INPUT2=0;

                            }

                            if(++sum >= 100)               //2ms

                            {

                                     num=0;

                                     sum=0;

                                     INPUT1=1;//低電平輸出結束,引腳輸出高電平

                                     INPUT2=1;

                            }

                            Tim_1S++;

                            if(Tim_1S==50000)

                            {

                                     PWM_Flag=1;

                            }               

                   }

                   if(PWM_Flag==1)

                   {      

                            INPUT1=0;//高電平輸出結束,引腳輸出低電平

                            INPUT2=0;               

                            Tim_1S--;

                            if(Tim_1S==0)

                            {

                                     PWM_Flag=0;

                                     num=0;

                                     sum=0;

                            }               

                   }                                                                                                                      

         }

}

關于第四種情況:

         第四種情況和第三種情況累似,也不存在num和sum不同步的問題,同樣的問題也會出現(xiàn)一個非常短暫的低電平,同樣存在邏輯上的不完美.可以發(fā)現(xiàn)這兩個程序都有一個共同的特點,就是num=0;和sum=0;都在程序的后面,就是這么一個小小的程序順序上的差別,都能直接導致num和sum的同步和不同步.這個問題雖然不是很嚴重,也就是說這個問題只會出現(xiàn)在work=100;的時候.也就是在其他的情況下沒有這個問題.不過我還是不想讓他出現(xiàn)這個問題.

關于這個程序的改進

         上面的程序可以進行如下的改進,沒有必要使用兩個變量來分別對時間來進先計數(shù),可以只用一個變量,這樣也可以將計數(shù)的不同步問題得到根本的上的解決,同時這個程序的PWM波的周期也不可調節(jié),改進的程序應增加對PWM波形的調節(jié)能力,廢話不多話直接上程序.

__interrupt  interrupt_isr(void)

{

         if(FTC0IRQ==1)                                     //0.02ms

         {

                   FTC0IRQ  = 0;

                   if(PWM_Flag==0)                        //輸出PWM波形的狀態(tài)

                   {

                            num++;

                            if(num >= work)

                            {

                                     INPUT1=0;//高電平輸出結束,引腳輸出低電平

INPUT2=0;

                            }

                            if(num>=sum)//周期為sum

            {

                 num=0;//計數(shù)器清0,重新開始計數(shù),

                 INPUT1=1;//高電平輸出結束,引腳輸出高電平

INPUT2=1;

            }

                            Tim_1S++;

                            if(Tim_1S==50000)

                            {

                                     PWM_Flag=1;

                            }

                   }

                   if(PWM_Flag==1)                        //輸出低電平波形的狀態(tài)

                   {

                            INPUT1=0;//高電平輸出結束,引腳輸出低電平

                            INPUT2=0;

                            Tim_1S--;

                            if(Tim_1S==0)

                            {

                                     PWM_Flag=0;

                                     num=0;

                                     sum=0;

                            }

                   }

         }

}

         這個改進版的程序輸入有兩個有效的參數(shù),一個為work,一個為sum,sum用來控制PWM波形的周期,work用來控制PWM波形的占空比,簡單粗暴,異常性感.當然可以把這個程序移殖到應廣單片機上啊,這個是松瀚單片機的源程序,這個過程是很簡單的.

         總而言之,這個改進版的程序有以下三個方面的明顯提升:

1.      計數(shù)的變量由兩個變量變?yōu)榱艘粋變量.

2.      而且原來的程序的PWM波的周期不可調,現(xiàn)在的程序的周期可調.

3.      實現(xiàn)了模塊化的編程,就像函數(shù)的模式,有兩個輸入?yún)?shù),沒有輸出參數(shù).
         還可以想一想如果用<=的方式能不能,構建一個完美的程序,這個問題有時間再想.先想到這里吧.這個問題有想過,會有一點小小的不完美.具體細節(jié)以后再說.

關閉窗口

相關文章