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.

[参考译文] MSP430FR2311:MSP430新手需要了解计时器 B 功能的帮助。

Guru**** 2390160 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/909112/msp430fr2311-new-to-msp430-need-help-understanding-timer-b-functionality

器件型号:MSP430FR2311

大家好、

我不熟悉 MSP430平台、我正在从事一个项目、在这个项目中、需要在两个上升沿之间以200us 的延迟生成一个双脉冲(请见所附图片)。 我目前正在尝试使用 Timer B 来生成这些信号。 当前使用标准1MHz SMCLK 作为计时器 B 的输入

下面的代码是我当前的代码、我不知道 TBxCCRn 寄存器是如何工作的。 我想知道是否有人可以帮忙? 还是提供更好的说明来说明数据表/系列用户手册中的内容? 令我感到困惑的是放在 TB1CCR1和 TB1CCR2寄存器中的值

感谢您提前提供的所有帮助。

#include 

int main (void)
{
WDTCTL = WDTPW | WDTHOLD;//停止看门狗计时器。




//触发输入(P1.0)
P1DIR &=~BIT0;
P1REN |= BIT0;//启用内部上拉/下拉电阻器
P1OUT |= BIT0;//为 P1.0选择上拉模式
P1IE |= BIT0;//启用中断
P1IES |= BIT0;//HIGH -> LOW 设置标志
P1IFG &=~BIT0;//清除中断标志寄存器


p1.1上的//输出(init_q_drive)
P1DIR |= BIT1;//在特定引脚上设置方向
P1OUT &=~BIT1;//将初始输出设置为0


PM5CTL0 &=~LOCKLPM5;//禁用 GPIO 加电默认值以激活先前配置的设置

//TB1CCTL1 |=(OUTMOD_7 | CCIE);// Timer B1捕获/比较控制寄存器1设置为设置/复位
TB1CCTL1 |= CCIE;//Timer B1捕获/比较控制寄存器1为中断启用

//TB1CCTL2 |=(OUTMOD_7 | CCIE);// Timer B1捕获/比较控制寄存器1设置/复位
TB1CCTL2 |= CCIE;//Timer B1捕获/比较控制寄存器1为中断启用

TB1CCR1 = 10;
TB1CCR2 = 20;

while (1){
_bis_SR_register (LPM3_bits | GIE);//进入低功耗模式并启用中断
}
}

// I/O 端口上的中断(引脚 P1.0)
#pragma vector = Port1_vector
__interrupt void Port_1_ISR (void)
{

P1IE &=~BIT0;//禁用中断,因此在此例程中不会发生任何中断
P1IFG &=~BIT0;//清除 p1.0上发生的中断标志

//低于需要设置不同的延迟时间(200、400、800、1000us)
//检查输入引脚以查看所选内容。 根据旋转开关检查

TB1CCR0 = 208;//200us 延迟(此硬编码是临时的)

//启动计时器
TB1CTL = TBSSEL_2 | MC_1 | TBCLR | TBIE;//启动计时器 SMCLK (1MHz)、向上计数模式、清除 TBR、启用中断
}

//计时器 b 中断服务例程当计时器 b 导致中断时,此例程称为
#pragma vector = Timer1_B1_vector
__interrupt void Timer1_b1_ISR (void)

switch (__event_in_range (TB1IV、TB1IV_TBIFG))
{
TB1IV_NONE 案例:
中断;//无中断

案例 TB1IV_TBCCR1:
P1OUT ^= BIT1;//输出...两个波形的上升沿
中断;

案例 TB1IV_TBCCR2:
P1OUT ^= BIT1;//输出...两个波形的下降沿
中断;

案例 TB1IV_TBIFG:
P1IE |= BIT0;//中断被启用
P1IFG &=~BIT0;//清除中断标志... 计时器停止时
TB1CTL = TBSSEL_2 | MC_0 | TBCLR | TBIE;//停止计时器
中断;

默认值:
中断;
}
} 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Matt、

    SMCLK 为1MHz 且 TB1CCR1 = 10 &  TB1CCR2 = 20, you were expecting a pulse width of 10 us while you are seeing a pulse width of about 35 us. Is that the query? I think with the default DCO clock of 2 MHz, 10 us is 20 cycles. I think the interrupt handling in the code above would be taking more than 20 cycles. I think this is the reason, why the values used in TB1CCR1 & TB1CCR2 do not match the pulse width. 

    您可以将时钟增加到16MHz、这样就可以使用 TB1CCR1和 TB1CCR2中编程的值更好地控制脉冲宽度。

    Srinivas

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    是的、这是我的问题之一、因为我认为 TB1CCR1和 TB1CCR2控制的是脉冲宽度、但在我的测试中、情况并非如此。 我会更改这些值、脉宽将保持不变。 但现在它更有意义,因为我甚至没有考虑 ISR 所消耗的周期。 此外、您是否有更好的方法来处理这一问题? 抱歉最后一个问题。 为什么 TB1IV_TBIFG 标志只抛出一次? 我不确定我提供的代码是如何生成双脉冲的。 感谢你的所有帮助
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    中断(TAIV)优先级产生双脉冲(和单个 TAIFG)、TAIFG 为最低。 TAIFG、CCR1和 CCR2中断都在10us 内发生、因此、通过第一次读取 TAIV、(较旧的) TAIFG 和(较新的) CCR1中断都存在、并且 CCR1首先出现。 到那时、另一个10us 已经过去、CCR2首先进入。 该序列会生成第二个脉冲。 只有在这之后、TAIFG 才会被呈现为关闭计时器。  

    这可以实现双脉冲,尽管仅对脉冲进行计数可能更可靠-- CCR2始终会结束脉冲,因此它可以计数到2并关闭计时器(根本没有 TAIFG)。

    ----

    您是否可以选择用于输出的引脚(init_q_drive)? 如果您可以使用 P2.0 (TB1.1)等、则可以使用 OUTMOD=7 (复位/设置)并在 CCR1中设置脉冲宽度和在 CCR0中设置脉冲周期。 (CCR2未使用。) 硬件将精确地生成脉冲、而无需担心软件需要多长时间。 [编辑:您还需要根据数据表(SLASE58E)表6-44]设置 PSEL 位

    这将是答案的大部分。 (1)您仍然需要在第二个脉冲之后停止脉冲序列。 为此、我建议使用 CCR1 CCIE 并计数到2。 在发生中断时、信号将为低电平、因此您可以停止计时器。 (2)初始脉冲需要一个小的舞蹈、因为它是触发它的计数的顶部。 为此、在启动定时器(无 TBCLR)之前、将 TB1R 加载到(CCR0-1)中。 会有一滴延迟、但在您所做的其他所有事情中、这一点并不明显。

    [编辑:更正了拼写错误。]

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    遗憾的是、我无法更改输出引脚、因为其余所有引脚都用于电路板上的其他功能。 我在数据表中读过有关 OUTMOD 位的内容、我想走那个路、但后来意识到我无法在我需要的引脚上输出。  

    我很喜欢您对脉冲进行计数、然后在到达第二个脉冲时停止计时器的想法、我的当前解决方案是将时钟速度提高到16MHz、这样就不会同时发生中断。 使用16MHz 时钟的结果可预测性要高得多。  

    那么、现在我的 ISR 看起来是这样的。 在这里、我在停止计时器之前使用 volatile int 计数到2、这与您的解决方案类似、但我的可能效率较低。  

    感谢您的回复、它确实帮助我了解了实际发生的情况。 现在、我的下一项工作是使 MSP430与外部晶体振荡器配合使用!

    #pragma vector = Timer1_B1_vector
    __interrupt void Timer1_B1_ISR (void)
    {
    switch (__event_in_range (TB1IV、TB1IV_TBIFG))
    {
    TB1IV_NONE 案例:
    中断;//无中断
    
    案例 TB1IV_TBCCR1:
    P1OUT ^= BIT1;//输出...两个波形的上升沿
    中断;
    
    案例 TB1IV_TBCCR2:
    P1OUT ^= BIT1;//输出...两个波形的下降沿
    中断;
    
    案例 TB1IV_TBIFG:
    if (i = 0){
    i = 1;
    }
    否则{
    I = 0;
    P1IE |= BIT0;//中断被启用
    P1IFG &=~BIT0;//清除中断标志... 计时器停止时
    TB1CTL = TBSSEL_2 | MC_0 | TBCLR | TBIE;//停止计时
    器}
    中断;
    
    默认值:
    中断;
    }
    }