利用MSP430調(diào)采集脈沖程序(疑問+解答)
在調(diào)試過程中利用CPU端口模擬周期為1.25S,脈沖寬度為20ms 40ms 60ms ,時采集數(shù)據(jù),采集數(shù)據(jù)時的
本文引用地址:http://www.ex-cimer.com/article/201608/295564.htm問題:究竟采集多少個數(shù)據(jù)能夠把一個周期的信號都采集到,
方法是:利用大數(shù)組來采集根據(jù)實際讀出的數(shù)據(jù)來計算一個周期需要采集的點數(shù)。
根據(jù)DATASHEET利用SHT_0--15 來選擇采樣周期,再加上完成AD轉(zhuǎn)換需13個ADC12CLK,依據(jù)此來計算與實際采到的數(shù)不符合,不知為什么,
問題2:當時為得到2.4s 周期的脈沖,脈沖寬度為300ms ,按道理采集的數(shù)據(jù)應(yīng)該多才對,但實際測試一個周期
采集的數(shù)據(jù)確減少。(說明:當時模擬周期信號時用是ACLK,但當模擬2.4ms的周期信號時,把ACLK進
行了2分頻,但我感覺,因為AD采樣采用不同的時鐘,因些應(yīng)該與分頻沒關(guān)系,但實際確不是這樣,
為什么?希望日后能發(fā)現(xiàn)這個問題)
終于找到問題所在了: :::::::::::::::::
msp430---------最大特色在于低功耗,然而低功耗確在于靈活時鐘的應(yīng)用。
MCU的靈魂在于----------CLK
而造成上面出現(xiàn)問題的原因----------------------------就在于對基礎(chǔ)時鐘應(yīng)用不當 ,下面具體解說:
涉及的代碼如下:
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
P6SEL |= 0x08; // Enable A/D channel inputs
BCSCTL1 &= ~XT2OFF;
BCSCTL2 = SELM_2; //select XT2;
ADC12CTL0 = ADC12ON+MSC+SHT0_8+REFON+REF2_5V;
// Turn on ADC12, extend sampling time
ADC12CTL1 = SHP+CONSEQ_2 +ADC12DIV_7+ ADC12SSEL_2;
// Use sampling timer, repeated sequence+ ADC12DIV_7
ADC12MCTL0 = SREF_1+INCH_3;
ADC12IE = 0X01;
ADC12CTL0 |= ENC; // Enable conversions
ADC12CTL0 |= ADC12SC; // Start conversion
TACCTL0 |= CCIE ;
TACCTL1 |= CCIE ;
/*
//按周期是1.25S來寫的脈沖程序SH0_8 +ADC12DIV_7
//TACCR1 = 0X9D70; //20mS 14/863/870 = 0.0162 20/1250=0.016
//TACCR1 = 0X9AE0;//40mS 28/863/870=0.0324 40/1250=0.032
//TACCR1 = 0x9851; //60mS 56/870
//TACCR0 = 0XA000;
*/
//為了寫出周期為2.4S,脈沖為300MS的程序,需要修改的地方為
BCSCTL1 = DIVA_1; //對ACLK進行2分頻;
//TACCR1 = 0x7334; //PULSE 600MS
TACCR1 = 0x8667; //PULSE 300MS
TACCR0 = 0X999A; //周斯2.4S
/*
//并且調(diào)試中發(fā)現(xiàn),
//如果采用SHT0_8+8分頻的話,周斯為124, 300ms時,為15或16/124=0.125
// 600ms時,31/124=0.25
//如果采用SHT0_6+8分頻的話,周斯為236, 300ms時,為29或30/235或236=0.125
// 600ms時,59/236 = 0.25
針對1.25S來寫的脈沖程序SH0_8 +ADC12DIV_7
計算:由于采用DCO = 800K , 且進行了8 分頻,所以周期為10us.
轉(zhuǎn)換一個數(shù)需要的時間為:(SHT0_8)256+16個ADC12CLK , 也即為272*10=2.72ms
所以對于周期為1.25S, 將會采集到1250/2.72=459.5 而實測為459,理論與實際符合,
采樣定時器占256個ADC12CLK
同步占 3個ADC12CLK
轉(zhuǎn)換占13個ADC12CLK
從上面程序可以看到執(zhí)行下面兩句目的是:打開外部晶振,并讓主時鐘選用外部晶體,然后讓ADC選用主時鐘,并進行8分頻。
BCSCTL1 &= ~XT2OFF;
BCSCTL2 = SELM_2+DIVM_3; //select XT2;
雖然寫了上面的語句,但實際上上面的語句完全不起作用,
After a PUC, the internal resistor is selected for the DC generator, RSELx =4, and DCOx = 3, allowing the DCO to start at a mid-range frequency. MCLK and SMCLK are sourced from DCOCLK.
The basic clock module incorporates an oscillator-fault detection fail-safe feature. The oscillator fault detector is an analog circuit that monitors the LFXT1CLK (in HF mode) and the XT2CLK. An oscillator fault is detected when either clock signal is not present for approximately 50 µs. When an oscillator fault is detected, and when MCLK is sourced from either LFXT1 in HF mode or XT2, MCLK is automatically switched to the DCO for its clock source. This allows code execution to continue, even though the crystal oscillator has stopped
從以上兩段話可知及實際實驗可知:
正因為程序?qū)懙氖怯猛獠繒r鐘,從而按外部時鐘來計算時間,而程序執(zhí)行時由于小于晶振起動時間,因些外部晶體沒有起動,從而自動轉(zhuǎn)入DCO來執(zhí)行程序,從而造成假象。
對程序中周期為2.4S的脈沖采樣時,采到的數(shù)據(jù)反而小的解釋如下:
由于定時用ACLK,所以當定時超過2秒時,我對ACLK進行了2分頻,從而程序先后執(zhí)行了下面兩條語句:
BCSCTL1 &= ~XT2OFF;
BCSCTL1 = DIVA_1; //對ACLK進行2分頻;
執(zhí)行以上兩句確實實現(xiàn)了2.4s的準確定時,但同時引入問題是:執(zhí)行第二句時,是對其賦值0X10, 以至于把默認的RSELX = 4改為0,從而DCO由800K降為50K左右,從而采集到的數(shù)據(jù)大大減少,
而正確的語句應(yīng)為:BCSCTL1 | = DIVA_1; //對ACLK進行2分頻;
從實際測試數(shù)據(jù)反推:(((2400/124)/272)/8) 其倒數(shù)再乘以1000得114526,即114K,
從DATASHEET圖可以看出當DCOX=3 RSELX=4時,選取的是近110K的時鐘,從而上面的奇怪現(xiàn)象得以解釋。
并且要使外部晶體正確起振:
After a PUC, the basic clock module uses DCOCLK for MCLK. If required,
MCLK may be sourced from LFXT1 or XT2.
The sequence to switch the MCLK source from the DCO clock to the crystal
clock (LFXT1CLK or XT2CLK) is:
1) Switch on the crystal oscillator
2) Clear the OFIFG flag
3) Wait at least 50 µs
4) Test OFIFG, and repeat steps 1-4 until OFIFG remains cleared.
; Select LFXT1 (HF mode) for MCLK
BIC #OSCOFF,SR ; Turn on osc.
BIS.B #XTS,&BCSCTL1 ; HF mode
L1 BIC.B #OFIFG,&IFG1 ; Clear OFIFG
MOV #0FFh,R15 ; Delay
L2 DEC R15 ;
JNZ L2 ;
BIT.B #OFIFG,&IFG1 ; Re?test OFIFG
JNZ L1 ; Repeat test if needed
BIS.B #SELM1+SELM0,&BCSCTL2 ; Select LFXT1CLK
其C語言為:
Do
{
IFG1 &= ~OFIFG; //清除晶振失敗標志
for (i = 0xFF; i > 0; i--); // 等待8MHz晶體起振
}
while ((IFG1 & OFIFG)); // 晶振失效標志仍然存在?
在調(diào)試程序中加入以上判別語句后,一切都下常起來。
結(jié)論:一切不合理的現(xiàn)象皆是有原因的,發(fā)現(xiàn)它,找到它,掌握它。
評論