新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > MSP430G2553捕獲程序案例與經(jīng)驗(yàn)分享

MSP430G2553捕獲程序案例與經(jīng)驗(yàn)分享

作者: 時(shí)間:2017-10-14 來源:網(wǎng)絡(luò) 收藏

  單片機(jī)定時(shí)器A有3個(gè)捕獲比較寄存器CCR0,CCR1,CCR2.。捕獲程序應(yīng)用很廣泛,電子工程師可以多加了解。

本文引用地址:http://m.butianyuan.cn/article/201710/366352.htm

  所謂捕獲,就是我們來檢測外圍的信號(hào)跳變時(shí)刻(此時(shí)信號(hào)理解為數(shù)字信號(hào),即脈沖),此信號(hào)乃為我們捕獲的對象,可以測量信號(hào)的脈沖寬度,即頻率等。

  捕獲首先需要考慮的初始化工作

  1.設(shè)置BCS模塊,確定系統(tǒng)時(shí)鐘MCLK子系統(tǒng)時(shí)鐘SMCLK

  把MCLK設(shè)置為8MHZ,SMCLK設(shè)置為1MHZ。

  2.捕獲輸入引腳的選擇

  選擇IO引腳時(shí)應(yīng)查閱器件的手冊,能夠快速的查閱PDF資料找到正確的答案是一個(gè)程序員的基本素質(zhì)。

  3.程序設(shè)計(jì)思路

  根據(jù)測頻的原理,需要2次捕獲才能測量一次輸入信號(hào)的頻率。因此要定義2個(gè)變量保存2次捕獲結(jié)果。變量是無符號(hào)的整數(shù)型變量(與捕獲寄存器的字長匹配)。

  輸入信號(hào)與CPU的工作是異步的,所以設(shè)計(jì)程序的時(shí)候是不知道什么時(shí)候才有捕獲輸入。

  程序處理何時(shí)發(fā)生了捕獲的方法有2種

  一是查詢的方法,定時(shí)器硬件在發(fā)生捕獲事件后會(huì)置捕獲中斷表示CCIF為1,程序在主循環(huán)里不斷的查詢這個(gè)標(biāo)志即可判斷是否有捕獲事件發(fā)生。

  二是定時(shí)器中斷法,當(dāng)發(fā)生捕獲事件時(shí)必產(chǎn)生定時(shí)器中斷,在中斷中讀取捕獲寄存器即可。

  查詢的方法不是好的程序設(shè)計(jì)方法,因?yàn)椴樵儠r(shí)要占用CPU,使得CPU不能再做其他任務(wù)。中斷的方法對初學(xué)者有一定的困難。即中斷程序如何與主程序通信(交換信息)。理解中斷及設(shè)計(jì)中斷服務(wù)程序要困難一些。

  捕獲模式

  捕獲外部輸入的信號(hào)的上升沿或下降沿或上升沿下降沿都捕捉,當(dāng)捕捉發(fā)生時(shí),把TAR的值裝載到TACCRx中,同時(shí)也可以進(jìn)入中斷,執(zhí)行相應(yīng)的操作。這樣利用捕捉上升沿或下降沿就可以計(jì)算外部輸入信號(hào)的周期,得出頻率。利用捕捉上升沿和下降沿可以得出輸入信號(hào)的高電平或低電平的持續(xù)時(shí)間。也可以算出占空比。下面是一個(gè)例子,是Timer_A捕獲初始化的程序:

  void timer_init() //使用Timer1_A時(shí)要特別注意各個(gè)寄存器的寫法,因?yàn)門imer0_A的寄存器都簡寫了,所以在寫

  //Timer1_A的寄存器時(shí),要特別注意與Timer0_A的不同

  {

  P1SEL |= BIT2; //選擇P12作為捕捉的輸入端子 Timer0_A

  //TACCTL1 |=CM_3+SCS+CAP+CCIE; //上下沿都觸發(fā)捕捉,用于測脈寬,同步模式、時(shí)能中斷 CCI1A

  TACCTL1 |=CM_1+SCS+CAP+CCIE; //上升沿觸發(fā)捕捉,同步模式、時(shí)能中斷 CCI1A

  TACTL |= TASSEL1+MC_2; //選擇SMCLK時(shí)鐘作為計(jì)數(shù)時(shí)鐘源,不分頻 增計(jì)數(shù)模式不行,必須連續(xù)計(jì)數(shù)模式

  P2SEL |= BIT1; //選擇P21作為捕捉的輸入端子 Timer1_A

  //TA1CCTL1 |=CM_3+SCS+CAP+CCIE; //上下沿都觸發(fā)捕捉,用于測脈寬,同步模式、時(shí)能中斷 CCI1A

  TA1CCTL1 |=CM_1+SCS+CAP+CCIE; //上升沿觸發(fā)捕捉,同步模式、時(shí)能中斷 CCI1A

  TA1CTL |= TASSEL1+MC_2; //選擇SMCLK時(shí)鐘作為計(jì)數(shù)時(shí)鐘源,不分頻 增計(jì)數(shù)模式不行,必須連續(xù)計(jì)數(shù)模式

  }

  相對應(yīng)的中斷函數(shù)如下:

  #pragma vector=TIMER0_A1_VECTOR //Timer0_A CC1 的中斷向量

  __interrupt void Timer_A(void)

  {

  // CCI0A 使用的捕捉比較寄存器是TA0CCR0,TA0CCR0單獨(dú)分配給一個(gè)

  //中斷向量TIMER1_A0_VECTOR,所以進(jìn)入中斷后直接就是Timer0_A CC0產(chǎn)生的中斷,不用經(jīng)過類似

  //下面的方法判斷中斷源了 。

  //Timer0_A CC1-4, TA0公用一個(gè)中斷向量 TIMER0_A1_VECTOR,所以進(jìn)入了中斷后還要用下面

  //的方法進(jìn)行判斷是哪一個(gè)中斷源產(chǎn)生的中斷

  switch(TAIV) //如果是Timer0_A CC1產(chǎn)生的中斷

  {

  case 2:

  {

  flag=1;

  LPM1_EXIT; //退出低功耗模式

  // _BIC_SR_IRQ(LPM1_bits);

  //_bic_SR_register_on_exit(LPM1_bits);

  break;

  }

  case 4: break;

  case 10:break;

  }

  }

  #pragma vector=TIMER1_A1_VECTOR //Timer1_A CC1 的中斷向量

  __interrupt void Timer_A1(void)

  {

  // P1OUT|=BIT0; //led調(diào)試用的

  // LPM1_EXIT; //退出低功耗模式 因?yàn)槭褂玫氖荂CI0A 使用的捕捉比較寄存器是TA1CCR0,TA1CCR0單獨(dú)分配給一個(gè)

  //中斷向量TIMER1_A0_VECTOR,所以進(jìn)入中斷后直接就是Timer1_A CC0產(chǎn)生的中斷,不用經(jīng)過類似

  //下面注釋掉的方法判斷 。

  //而Timer1_A CC1-4, TA1則公用一個(gè)中斷向量 TIMER1_A1_VECTOR,所以進(jìn)入了中斷后還要用下面

  //的方法進(jìn)行判斷是哪一個(gè)中斷源產(chǎn)生的中斷

  switch(TA1IV) //如果是Timer1_A CC1產(chǎn)生的中斷

  {

  case 2:

  {

  flag=2;

  LPM1_EXIT; //退出低功耗模式

  // _BIC_SR_IRQ(LPM1_bits);

  //_bic_SR_register_on_exit(LPM1_bits);

  break;

  }

  case 4:break;

  case 10:break;

  }

  }

  //如果要測量更低頻率的信號(hào)的話,可以在中斷中判斷溢出中斷發(fā)生的次數(shù),這樣就可以得到溢出的次數(shù),從而可以測量更

  //低頻率的信號(hào)

  程序例子---利用捕獲功能測一個(gè)正弦波信號(hào)的頻率

  1.在進(jìn)行測量之前,你需要對正弦波進(jìn)行轉(zhuǎn)換,把它變?yōu)榉讲?。這個(gè)很簡單的電路。

  2.測頻率,下面的代碼是我自己寫的,可以測到100K。精確度0.01HZ??偟膩碚f,用TIEMEA產(chǎn)生一個(gè)2S的中斷,2S后去去讀計(jì)算頻率。TIMERA0是對脈沖寬度的測量,TIMERA1是對定時(shí)器timerA中斷的處理

  void Init_Capture(void)

  {

  P1DIR=~BIT1;

  P1SEL|=BIT1;

  BCSCTL2 |= SELS; // SMCLK=XT2=16M

  BCSCTL2 |= DIVS_1; //SMCLK 2分頻,即SMCL=8MHZ

  TACTL |=TASSEL_1+TAIE+TACLR; //8分頻,選擇ACLK為timerA的時(shí)鐘源(ACLK),開中斷,增計(jì)數(shù)模式

  TACCTL0 |=CM_1+SCS+CAP+CCIS_0+CCIE; //上升沿捕獲+同步捕獲+開捕獲+timerA為捕獲+打開捕獲中斷

  TACTL |=MC_2;

  }

  int main()

  {

  Init_Capture();

  while(1)

  {

  if(global_a.Conver==1)//捕獲頻率

  {

  _DINT();

  global_a.Conver=0;

  global_a.CapCount=(float)((32768.0*global_a.pulse)/global_a.time);//計(jì)算頻率,注意理解!

  Print_Fre();//顯示頻率

  _EINT();

  }

  }

  }

  #pragma vector=TIMERA0_VECTOR

  __interrupt void timer_A(void)

  {

  if(global_a.Cap_Tar==0)

  {

  global_a.Cap_First = TACCR0;

  global_a.Cap_Tar++;

  }

  else

  {

  global_a.Cap_Last = TACCR0;

  global_a.Cap_Tar++;

  }

  }

  #pragma vector=TIMERA1_VECTOR

  __interrupt void timeA1(void)

  {

  switch(TAIV)

  {case 2:

  break;

  case 4:

  break;

  case 10: if(global_a.Cap_Tar==0)

  global_a.pulse=0;

  else

  {

  global_a.pulse=global_a.Cap_Tar-1;

  global_a.time = global_a.Cap_Last-global_a.Cap_First;

  global_a.Cap_Tar=0;

  TACTL =~BIT0;

  // BIC_SR_IRQ(LPM3_bits);

  global_a.Conver=1;

  _DINT();

  }

  break;

  }

  }



關(guān)鍵詞: MSP430G2553

評論


相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉