大家好、
我在使用计时器 B 进行频率输入捕获时偶然发现了一个问题。
定时器 B0配置为捕获/比较连续模式。 MCLK = SMCLK = 24MHz。
我正在使用 eComp 0进行外部应用频率捕获。
代码在定制硬件和 EXP-MSP430FR2355 Launchpad 上进行测试:
#include <msp430.h> #include <stdint.h> #include <stdbool.h> #include <intrinsics.h> static inline void init_clk(void); static inline void init_ecomp(void); static inline void init_timer(void); static inline void timer_start(void); static inline void callback_period_finished(const uint16_t t); volatile uint32_t captureTrace[100] = { 0 }; volatile uint_fast8_t cntPeriods = 0; volatile uint_fast8_t cntOverflow = 0; static inline void init_clk(void) { WDTCTL = WDTPW | WDTHOLD;// stop watchdog timer PM5CTL0 &= ~LOCKLPM5; // Disable the GPIO power-on default high-impedance // mode to activate previously configured port settings // Configure reference PMMCTL0_H = PMMPW_H; // Unlock the PMM registers PMMCTL2 |= INTREFEN; // Enable internal reference while (!(PMMCTL2 & REFGENRDY)) ;// Poll till internal reference settles FRCTL0 = FRCTLPW | NWAITS_2;// FRAM waitstate for usage with 24MHz P2SEL1 |= BIT6 | BIT7; // P2.6~P2.7: crystal pins do { CSCTL7 &= ~(XT1OFFG | DCOFFG);// Clear XT1 and DCO fault flag SFRIFG1 &= ~OFIFG; } while (SFRIFG1 & OFIFG);// Test oscillator fault flag __bis_SR_register(SCG0); // disable FLL CSCTL3 |= SELREF__XT1CLK;// Set XT1CLK as FLL reference source CSCTL1 = DCORSEL_7; // DCO Range = 24MHz CSCTL2 = FLLD_0 + 731;// DCOCLKDIV = 32768Hz*(n+1) = SMCLK __delay_cycles(3); __bic_SR_register(SCG0); // enable FLL CSCTL4 = SELMS__DCOCLKDIV | SELA__XT1CLK;// Set ACLK = XT1CLK = 32768Hz // DCOCLK = MCLK and SMCLK source CSCTL5 |= DIVM_0 | DIVS_0; // MCLK = DCOCLK // SMCLK = MCLK __delay_cycles(1000);// Allow clock system to settle } static inline void init_ecomp(void) { // Select eCOMP input function on P1.0 P1SEL0 |= BIT0; P1SEL1 |= BIT0; CP0CTL0 = CPPSEL_0; // Select C0 as input for V+ terminal CP0CTL0 |= CPNSEL1 | CPNSEL2;// Select DAC as input for V- terminal CP0CTL0 |= CPPEN | CPNEN; // Enable eCOMP input CP0DACCTL |= CPDACEN; // Select VCC as ref and enable DAC CP0DACDATA |= CPDACBUF1_31; // CPDACBUF1=On-chip VREF(1V5) *31/64 CP0CTL1 |= CPEN | CPMSEL_1; // Turn on eCOMP, in low power mode } static inline void init_timer(void) { // Timer0_B1 Setup TB0CCTL1 = CM_1 | CCIS__CCIB | SCS | CAP | CCIE; // Capture rising edge, // Use CCI1B=internal, // Synchronous capture, // Enable capture mode, // Enable capture interrupt } static inline void timer_start(void) { TB0CTL = TBCLR; TB0CTL &= ~TBIFG; TB0CCR1 = 0; TB0CTL &= ~COV | ~CCIFG; TB0CTL = TBSSEL__SMCLK | MC__CONTINUOUS | TBIE | ID_0 | CNTL__16;// Start timer in continuous mode, enable interrupt } static inline void callback_period_finished(const uint16_t t) { captureTrace[cntPeriods] = (uint32_t)(cntOverflow * 65535 + t); cntOverflow = 0; } int main(void) { init_clk(); init_ecomp(); init_timer(); __bis_SR_register(GIE); timer_start(); while (1) ; } #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector = TIMER0_B1_VECTOR __interrupt void Timer0_B1_ISR(void) #elif defined(__GNUC__) void __attribute__((interrupt(TIMER0_B1_VECTOR))) Timer0_B1_ISR(void) #else #error Compiler not supported! #endif { switch (__even_in_range(TB0IV, TB0IV_TBIFG)) { case TB0IV_TB0CCR1: { //period finished const uint16_t t = TB0CCR1; TB0R = 0; TB0CTL &= ~CCIFG; callback_period_finished(t); ++cntPeriods; } break; case TB0IV_TB0CCR2: break; case TB0IV_TB0IFG: //overflow occured ++cntOverflow; break; default: break; } if (cntPeriods > 99) { //for Debug _nop(); cntPeriods = 0; } }
在这两种情况下都观察到相同的行为:当应用外部频率366Hz 时、即捕获寄存器应保持值65535 (24MHz/65535 ~= 366Hz)时、TB0CCR1寄存器中的值存在很大差异。
我注意到、当调试中断标志时、CCIFG 在读取 TB0CCR1时被复位(行109)、并在写入0到 TB0R 时(行110)直接被置位。
旗不应该保持复位? 计时器可能会出现问题吗?
期待任何建议,并提前感谢!
Br、
Jonathan