大家好、
我在使用计时器 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