四段不同順序的程序會(huì)有如此巨大的差別!
程序段一:
__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;//低電平輸出結(jié)束,引腳輸出高電平
INPUT2=1;
}
if(num >= work)
{
INPUT1=0;//高電平輸出結(jié)束,引腳輸出低電平
INPUT2=0;
}
Tim_1S++;
if(Tim_1S==50000)
{
PWM_Flag=1;
}
}
if(PWM_Flag==1)
{
INPUT1=0;//高電平輸出結(jié)束,引腳輸出低電平
INPUT2=0;
Tim_1S--;
if(Tim_1S==0)
{
PWM_Flag=0;
num=0;
sum=0;
}
}
}
}
顯然這個(gè)程序的功能是引腳輸出一個(gè)可調(diào)的PWM波形,然后輸出一個(gè)低電平的波形,PWM的波形和這個(gè)低電平的波形持續(xù)的時(shí)間都是1S鐘,程序段一是正確的程序.
下面分析下面的三個(gè)程序的問題:
程序段二:
__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;//低電平輸出結(jié)束,引腳輸出高電平
INPUT2=1;
}
if(++num >= work)
{
INPUT1=0;//高電平輸出結(jié)束,引腳輸出低電平
INPUT2=0;
}
Tim_1S++;
if(Tim_1S==50000)
{
PWM_Flag=1;
}
}
if(PWM_Flag==1)
{
INPUT1=0;//高電平輸出結(jié)束,引腳輸出低電平
INPUT2=0;
Tim_1S--;
if(Tim_1S==0)
{
PWM_Flag=0;
num=0;
sum=0;
}
}
}
}
程序段二:
現(xiàn)在假設(shè)系統(tǒng)初始化,sum和num都是0,現(xiàn)在假設(shè)work=20,系統(tǒng)初始化后開始疊加運(yùn)算,等到num變?yōu)?0后會(huì)有高電平輸出結(jié)束,引腳輸出低電平,占空比為20%,系統(tǒng)正常運(yùn)行,但等到sum加到100后sum,num會(huì)置為0,然后num會(huì)加1變?yōu)?,此時(shí)下一個(gè)周期到來了,但是初始化卻和第一個(gè)周期不一樣了,這時(shí)num總會(huì)比sum大1,也就是最后輸出的占空比總是比設(shè)定的值會(huì)小1,比如設(shè)置work值為100,那么從起始狀態(tài)開始分析,起始狀態(tài)下num和sum都是0,等sum變?yōu)?00的時(shí)候會(huì)先將num置為0,然后num的值會(huì)做想應(yīng)的加1然后下一個(gè)周期來了,sum和num有了不同的初始值sum的初始值為0而num的初始值卻變?yōu)?,這樣話,時(shí)過境遷,num會(huì)首先變?yōu)?00,這時(shí)sum才是99,這時(shí)就會(huì)了出現(xiàn)一個(gè)短暫的低電平,這個(gè)低電平的持續(xù)時(shí)間剛好是一個(gè)周期,這樣就和我們的初衷相違背了,這時(shí)輸出的占空比不是100%,而是99%.同樣的道理這樣的問題不僅會(huì)出現(xiàn)有占空比為100%的情況,比如此里的占空比是設(shè)置的是20%,那么從初始狀態(tài)到sum變?yōu)?0,然后緊接著num又會(huì)加1變?yōu)?,那么從下一個(gè)周期開始兩個(gè)數(shù)據(jù)又會(huì)出現(xiàn)不同步的情況,從而直接導(dǎo)致下一次等到sum變?yōu)?9的候,num己經(jīng)是100了,從而又直接導(dǎo)致下一個(gè)周期的起始狀態(tài)又變成了sum=0,而num=1.周而復(fù)始,從而真正得到地占空比變?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;//高電平輸出結(jié)束,引腳輸出低電平
INPUT2=0;
}
if(sum >= 100) //2ms
{
num=0;
sum=0;
INPUT1=1;//低電平輸出結(jié)束,引腳輸出高電平
INPUT2=1;
}
Tim_1S++;
if(Tim_1S==50000)
{
PWM_Flag=1;
}
}
if(PWM_Flag==1)
{
INPUT1=0;//高電平輸出結(jié)束,引腳輸出低電平
INPUT2=0;
Tim_1S--;
if(Tim_1S==0)
{
PWM_Flag=0;
num=0;
sum=0;
}
}
}
}
關(guān)于第三種情況:
第三種情況倒不存在num和sum不同步的問題,但是有一個(gè)小問題就是當(dāng)work是100
的時(shí)候num會(huì)首先加到100輸出一個(gè)低電平,而這里的期望占空比是100%,也就是沒這里會(huì)有一個(gè)非常短暫的低電平,用示波器也是發(fā)現(xiàn)不了的,因?yàn)槭静ㄆ鞯姆直婺芰是沒有單片機(jī)執(zhí)行指令的速度快,所以說這個(gè)誤差可以忽略不計(jì),不過在邏輯是還是不完美的.
程序段四:
__interrupt interrupt_isr(void)
{
if(FTC0IRQ==1) //0.02ms
{
FTC0IRQ = 0;
if(PWM_Flag==0)
{
if(++num >= work)
{
INPUT1=0;//高電平輸出結(jié)束,引腳輸出低電平
INPUT2=0;
}
if(++sum >= 100) //2ms
{
num=0;
sum=0;
INPUT1=1;//低電平輸出結(jié)束,引腳輸出高電平
INPUT2=1;
}
Tim_1S++;
if(Tim_1S==50000)
{
PWM_Flag=1;
}
}
if(PWM_Flag==1)
{
INPUT1=0;//高電平輸出結(jié)束,引腳輸出低電平
INPUT2=0;
Tim_1S--;
if(Tim_1S==0)
{
PWM_Flag=0;
num=0;
sum=0;
}
}
}
}
關(guān)于第四種情況:
第四種情況和第三種情況累似,也不存在num和sum不同步的問題,同樣的問題也會(huì)出現(xiàn)一個(gè)非常短暫的低電平,同樣存在邏輯上的不完美.可以發(fā)現(xiàn)這兩個(gè)程序都有一個(gè)共同的特點(diǎn),就是num=0;和sum=0;都在程序的后面,就是這么一個(gè)小小的程序順序上的差別,都能直接導(dǎo)致num和sum的同步和不同步.這個(gè)問題雖然不是很嚴(yán)重,也就是說這個(gè)問題只會(huì)出現(xiàn)在work=100;的時(shí)候.也就是在其他的情況下沒有這個(gè)問題.不過我還是不想讓他出現(xiàn)這個(gè)問題.
關(guān)于這個(gè)程序的改進(jìn)
上面的程序可以進(jìn)行如下的改進(jìn),沒有必要使用兩個(gè)變量來分別對(duì)時(shí)間來進(jìn)先計(jì)數(shù),可以只用一個(gè)變量,這樣也可以將計(jì)數(shù)的不同步問題得到根本的上的解決,同時(shí)這個(gè)程序的PWM波的周期也不可調(diào)節(jié),改進(jìn)的程序應(yīng)增加對(duì)PWM波形的調(diào)節(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;//高電平輸出結(jié)束,引腳輸出低電平
INPUT2=0;
}
if(num>=sum)//周期為sum
{
num=0;//計(jì)數(shù)器清0,重新開始計(jì)數(shù),
INPUT1=1;//高電平輸出結(jié)束,引腳輸出高電平
INPUT2=1;
}
Tim_1S++;
if(Tim_1S==50000)
{
PWM_Flag=1;
}
}
if(PWM_Flag==1) //輸出低電平波形的狀態(tài)
{
INPUT1=0;//高電平輸出結(jié)束,引腳輸出低電平
INPUT2=0;
Tim_1S--;
if(Tim_1S==0)
{
PWM_Flag=0;
num=0;
sum=0;
}
}
}
}
這個(gè)改進(jìn)版的程序輸入有兩個(gè)有效的參數(shù),一個(gè)為work,一個(gè)為sum,sum用來控制PWM波形的周期,work用來控制PWM波形的占空比,簡單粗暴,異常性感.當(dāng)然可以把這個(gè)程序移殖到應(yīng)廣單片機(jī)上啊,這個(gè)是松瀚單片機(jī)的源程序,這個(gè)過程是很簡單的.
總而言之,這個(gè)改進(jìn)版的程序有以下三個(gè)方面的明顯提升:
1. 計(jì)數(shù)的變量由兩個(gè)變量變?yōu)榱艘粋(gè)變量.
2. 而且原來的程序的PWM波的周期不可調(diào),現(xiàn)在的程序的周期可調(diào).
3. 實(shí)現(xiàn)了模塊化的編程,就像函數(shù)的模式,有兩個(gè)輸入?yún)?shù),沒有輸出參數(shù).
還可以想一想如果用<=的方式能不能,構(gòu)建一個(gè)完美的程序,這個(gè)問題有時(shí)間再想.先想到這里吧.這個(gè)問題有想過,會(huì)有一點(diǎn)小小的不完美.具體細(xì)節(jié)以后再說.