This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
你(们)好
我有另一个关于计时器的问题。
我将 CCR0设置为239、但计时器似乎会启动 223个时钟周期、有些时钟周期会启动240个时钟周期。
我如何才能在每次计时器启动时都保持一致的时钟周期。
(我还确保没有其他服务例程中断计时器)
谢谢
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector = TIMER0_B0_VECTOR __interrupt void TIMER0_B0_ISR(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(USCI_B0_VECTOR))) TIMER0_B0_ISR (void) #else #error Compiler not supported! #endif { delta[count] = RTCCNT - pre_rtc; pre_rtc = RTCCNT; count++; if (count>=120) { HWREG16(TIMER_B0_BASE + OFS_TBxCTL) &= ~MC; // process data HWREG16(TIMER_B0_BASE + OFS_TBxCTL) |= MC__UP; } }
您好、
那么、您似乎在按照设置 TimerB0的时间间隔读取 RTC 计数器-正确吗?
您能否提供 RTC 和 TimerB0的设置代码?
尊敬的 Dennis:
是的,它是 TimerB0和 RTC。
void RTCInit() { HWREG16(RTC_BASE + OFS_RTCCTL) &= ~(RTCSS_3 | RTCPS_7); HWREG16(RTC_BASE + OFS_RTCMOD) = 32767; RTC_start(RTC_BASE, RTCSS_1); } void InitTimer() { HWREG16(TIMER_B0_BASE + OFS_TBxCTL) = TBSSEL__SMCLK; HWREG16(TIMER_B0_BASE + OFS_TBxCCR0) = 239; HWREG16(TIMER_B0_BASE + OFS_TBxCCTL0) |= CCIE HWREG16(TIMER_B0_BASE + OFS_TBxCTL) |= MC__UP; }
您好、
好的、看起来不错、但我忘记问什么是 SMCLK 频率?
尊敬的 Dennis:
SMCLK 为24MHz
谢谢
您好、
好的、那么您使用以24MHz 运行的 SMCLK 为 RTC 和 TimerB 计时-到目前为止是正确的吗?
您没有提到 CPU 的运行速度、因此我假设采用相同的24MHz、在这种情况下、FRAM 等待状态是否为2?
下面是一些尝试帮助缩小问题范围的实验。
1.将代码从 delt[count]= RTCCNT - pre-RTC 更改为 delt[count]= RTCCNT - 239。 你看到什么?
2.保持 CPU 运行在24MHz、但将 SMCLK 分频至4MHz。 你看到什么?
尊敬的 Dennis:
是的、FRAM 被设定 为 NWAITS_2。
1>我更改为 deltation[count]= RTCCNT - 240
在大多数时间内,增量更改为 F0。
将结果附在以下位置。
这也是一个问题、只要指令不超过240个时钟周期、无论在两个定时器启动之间写入任何代码、结果都应该为240。 为什么 它只是通过更改一行代码就像这样工作? (实际上、我确实看到过类似的情况、这是最简单的例子)
2>4MHz 对我们来说并不是一个真正的选择、但是 、如果确实有必要、我可以稍后再试、看看结果。
谢谢
您好、
让我来看看这个。
您好、
好的、这里有一些不正确的地方。 我返回并再次查看您的 RTC 初始化。 根据您的初始化代码、您将清除 RTCSS 位、该位选择"无时钟"。 您打算将什么时钟源用于 RTC?
尊敬的 Dennis:
它对 RTC 使用 smclk。
它是 RTC_START()的库调用 ,用于设置时钟源
我在此附上代码。
谢谢
void RTC_start(uint16_t baseAddress, uint16_t clockSource) { HWREG16(baseAddress + OFS_RTCCTL) &= ~RTCSS_3; #ifdef RTCCKSEL HWREG16(SYS_BASE + OFS_SYSCFG2) &= ~RTCCKSEL; if(clockSource == RTC_CLOCKSOURCE_ACLK) { HWREG16(SYS_BASE + OFS_SYSCFG2) |= RTCCKSEL; HWREG16(baseAddress + OFS_RTCCTL) |= RTCSS_1; } else { HWREG16(baseAddress + OFS_RTCCTL) |= clockSource; } #else HWREG16(baseAddress + OFS_RTCCTL) |= clockSource; #endif HWREG16(baseAddress + OFS_RTCCTL) |= RTCSR; }
感谢 ming 对此进行了澄清。
那么、您以24MHz 运行 RTC、TimerB 和 CPU、对吧? 这意味着对于每个 SMCLK、RTC 和 TimerB 都将提前一个计数。 那么、在理论上、当 TimerB 计数首次匹配 CCR0时、RTCCNT 将等于 TimerB 计数、对吧?
然后 TimerB 生成一个中断并将计数复位为0。 与此同时、CPU 检测中断、入栈指针并执行几条指令来读取 RTCCNT 寄存器。 但是、从中断的那一刻起、直到 CPU 读取 RTCCNT 寄存器、SMCLK 继续增加 RTC 和 TimerB 计数。 因此、如果 CPU 花费20个时钟周期(作为一个示例)来执行导致读取 RTCCNT 寄存器的代码、RTCCNT 和 TimerB 将从中断发生时开始计数+20。 这意味着您不仅可以从 RTCCNT 中减去239、还需要考虑 CPU 时间、在本例中为 RTCCNT - 239 - 20。
我能否询问尝试使用 TimerB 读取 RTCCNT 的目的?
尊敬的 Dennis:
与我的理解只有一个不同之处。 只要指令小于240个周期、两次启动之间的定时器间隔应为240个周期。
电路板是从端口1接口读取/写入数据。
当计时器可以启动固定间隔240时、它会起作用。
我们从 TI 获得的参考板没有用于该流量的控制器。
谢谢
您好、
很遗憾、我前面没有 FR2155可用于编程和尝试代码、但您可以尝试快速实验吗?
在 ISR 中、修改代码以读取 TimerB 计数寄存器(TB0R)、并将这些值写入数组、然后向我展示您捕获的内容、而不是读取 RTCCNT 值并写入数组。
尊敬的 Dennis:
我用两种不同的情况进行测试。 一个具有 RTC 累积样式、另一个具有 RTC 增量样式编码。 请参考图像、并相应地显示两个结果。
第一种情况是 TB0R 计数器0x21、第二种情况是 TB0R 计数器值0x38。
第一种情况是 RTC 计数器240 、第二种情况是 RTC 计数器220。
指令未超过240个时钟周期、但 RTC 计数器应相同、对吧?
但是 、它具有 不同的 RTC 值、我们希望了解如何解决此问题。
谢谢
您好、
好的、TB0R 相当一致、这正是我所期望的。 我不确定 RTC 计数为何没有意义。 明天我将可以访问 FR2155、并运行您的代码以查看是否可以复制。
您好、
我使用您的原始代码设置了我的项目、它看起来工作正常。 每次在 ISR 中、我都会得到223的增量。
我已附上源代码供您尝试。 请注意、我必须使用具有相同外设的同一系列中的 FR2355。
#include <msp430.h> #include "driverlib/MSP430FR2xx_4xx/inc/hw_memmap.h" #include "stdint.h" #define RTC_CLOCKSOURCE_SMCLK RTCSS__SMCLK #define RTC_CLOCKSOURCE_ACLK RTCSS__XT1CLK void RTC_start(uint16_t, uint16_t); void RTCInit() { HWREG16(RTC_BASE + OFS_RTCCTL) &= ~(RTCSS_3 | RTCPS_7); HWREG16(RTC_BASE + OFS_RTCMOD) = 32767; RTC_start(RTC_BASE, RTCSS_1); } void InitTimer() { HWREG16(TIMER_B0_BASE + OFS_TBxCTL) = TBSSEL__SMCLK; HWREG16(TIMER_B0_BASE + OFS_TBxCCR0) = 239; HWREG16(TIMER_B0_BASE + OFS_TBxCCTL0) |= CCIE; HWREG16(TIMER_B0_BASE + OFS_TBxCTL) |= MC__UP; } void RTC_start(uint16_t baseAddress, uint16_t clockSource) { HWREG16(baseAddress + OFS_RTCCTL) &= ~RTCSS_3; #ifdef RTCCKSEL HWREG16(SYS_BASE + OFS_SYSCFG2) &= ~RTCCKSEL; if(clockSource == RTC_CLOCKSOURCE_ACLK) { HWREG16(SYS_BASE + OFS_SYSCFG2) |= RTCCKSEL; HWREG16(baseAddress + OFS_RTCCTL) |= RTCSS_1; } else { HWREG16(baseAddress + OFS_RTCCTL) |= clockSource; } #else HWREG16(baseAddress + OFS_RTCCTL) |= clockSource; #endif HWREG16(baseAddress + OFS_RTCCTL) |= RTCSR; } int main(void) { WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer // Configure two FRAM waitstate as required by the device datasheet for MCLK // operation at 24MHz(beyond 8MHz) _before_ configuring the clock system. FRCTL0 = FRCTLPW | NWAITS_2 ; 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 XT1 as FLL reference source CSCTL0 = 0; // clear DCO and MOD registers CSCTL1 |= DCORSEL_7; // Set DCO = 24MHz CSCTL2 = FLLD_0 + 731; // DCOCLKDIV = 24MHz __delay_cycles(3); __bic_SR_register(SCG0); // enable FLL while(CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1)); // FLL locked CSCTL4 = SELMS__DCOCLKDIV | SELA__XT1CLK; // set XT1 (~32768Hz) as ACLK source, ACLK = 32768Hz // default DCOCLKDIV as MCLK and SMCLK source P1DIR |= BIT0 | BIT1 | BIT2; // set ACLK SMCLK and LED pin as output P1SEL1 |= BIT0 | BIT1; // set ACLK and SMCLK pin as second function PM5CTL0 &= ~LOCKLPM5; // Disable the GPIO power-on default high-impedance mode // to activate previously configured port settings RTCInit(); InitTimer(); _enable_interrupts(); while(1) { LPM0; } } uint16_t delta[128]; uint16_t count, pre_rtc; #pragma vector = TIMER0_B0_VECTOR __interrupt void TIMER0_B0_ISR(void) { delta[count] = RTCCNT - pre_rtc; pre_rtc = RTCCNT; count++; if (count>=120) { HWREG16(TIMER_B0_BASE + OFS_TBxCTL) &= ~MC; /* set a break point on nop() */ _nop(); HWREG16(TIMER_B0_BASE + OFS_TBxCTL) |= MC__UP; } }