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.

[参考译文] MSP430FR2673:当 TAxR 在连续模式下运行时、读取 TAxR

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1230463/msp430fr2673-reading-from-taxr-while-it-s-running-in-continous-mode

器件型号:MSP430FR2673

读者好!

我目前正在进行一个项目、我们在现场管理很多定时事件。  我们有一个固件版本、它在 PC 上运行以对其进行仿真、并且依赖于获取时间戳。  我要将其移植到我们的 MSP。  我想能够只是设置一个计时器持续计数,然后只是阅读 TAxR 在 forground ,但在家庭指南中有这一点让我犹豫。

这里引用了家庭指南 Slau445i (https://www.ti.com/lit/ug/slau445i/slau445i.pdf):)

"13.2.1 16位定时器计数器16位定时器/计数器寄存器、TAxR、随着时钟信号的每个上升沿增/减(由操作模式决定)。 TAxR 可以通过软件读取或写入。 此外、定时器溢出时、它可以生成一个中断。

注:访问 TAxR 时必须小心。 如果 CPU 在定时器运行期间访问(读取或写入) TAxR、则从 TAxR 读取的值或写入 TAxR 的值可能无法预测。 为了避免这种不确定性、应在访问 TAxR 之前向 MC 位写入0以使定时器停止工作。 对于读操作、可在定时器运行期间多次读取 TAxR、同时软件中会进行多数表决以确定正确读数。 "

我不想停止计时器,当我从它读取,所以我认为这让我多次读取计时器,并采取多数表决。  但这意味着什么?  是否读取多次并将值保存到数组中,然后从数组中选择最频繁的值?  或者、我可以如何使用捕获寄存器、然后从中读取数据吗?

感谢您抽出宝贵时间提供反馈。

此致、
扎卡里·安德森

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

    危险是、当您阅读计时器时、计时器可能正在递增。 它有一个通过位传播的进位。 读取、直到您得到两个匹配的顺序读取。

     我怀疑计时器计数器使用简单的纹波进位实现。 最好知道该值需要多长时间才能告诉您该值可以改变多长时间。

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

    David、您好!

    感谢您的答复。  我希望将 MCLK 同时用于 CPU 和计时器。  在本例中、计时器会在我每次读取时更改。  我可以减慢计时器时钟的速度、但我不希望这样做。  我们的 PC 仿真使用此分辨率、我想保持接近此分辨率。

    我已经设置了一个捕获寄存器来获取时间-我很快将进行测试并报告结果。

    u32 Get_Time (void)
    u32 u32TimeInMicroSeconds = 0

    //将计时器 A0捕获到捕获寄存器 TA0CCR0中
    //通过创建上升沿,然后重置
    //
    TA0CCTL0 &=(U32)~CCIFG//清除捕捉标志
    TA0CCTL0 =(U16) CCIS_VCC |(TA0CCTL0 &~((U16) CCIS));//设置为 VCC
    __ no_operation ();//给它一个周期来触发捕获
    TA0CCTL0 =(U16) CCIS_GND |(TA0CCTL0 &~((U16) CCIS));//设置为 GND

    //等待捕捉/比较中断标志(CCIFG)设置
    //再读取捕捉寄存器
    //
    while ((TA0CCTL0 & CCIFG));//等待捕捉/比较标志
    TA0CCTL0 &=(U32)~CCIFG//清除捕捉标志

    //将捕获寄存器和溢出计数器复制到中
    // TimeInMicrosecond
    //
    u32TimeInMicroSeconds =(U32) TA0CCR0//复制捕获寄存器
    u32TimeInMicroSeconds |=(u32) g_u16TimeInMicroSecondsOverflowCnt<< 16

    返回 u32TimeInMicrosec
    }



    此致、
    扎卡里·安德森

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

    您好!

    您的方法似乎可行。 请分享该解决方案的结果。 谢谢!

    此致、

    现金 Hao

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

    大家好!

    汇报。  将捕捉寄存器的输入设置为接地再设置到 VCC、确实可以捕捉上升沿。  我可以看到 SMCLK=MCLK 上的定时器在捕获寄存器中的值更新。

    接下来是使用该方法测量获得时间所需的时间、并验证我是否能够  准确地读取时间。  我打算每100个左右将值保存到一个数组中-我希望从计时器读取的值将由大约100个周期加上触发捕捉所需的周期分开。  我会报告所发现的情况。

    此致、
    扎卡里·安德森

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    以下是我的结果。  56uS、用于在1.016MHz 时通过 MCLK 读取计时器。
    对于如何加快这一进程的任何想法、我们都会表示赞赏。

    不完美  有时、在我捕获寄存器后、溢出计数器会递增、这会导致错误的时间。
    并且我通过翻转引脚得到的常规间隔是448uS、而不是我预期的416uS。

    //*****
    //
    // GetTimerCount -获取计时器的当前计数。
    //
    //参数:无
    //
    //返回- U32定时器的当前计数。
    //
    //注释
    //--
    //此计时器将在1h11分钟后回滚。
    //此函数需要56.14uS 才能完成
    //
    //*****

    u32 GetTimerCount ()
    u32 u32TimerCount = 0

    //将计时器 A0捕获到捕获寄存器 TA0CCR0中
    //通过创建上升沿,然后重置
    //
    //TA0CCTL0 &=(U16)~CCIFG;//清除捕捉标志
    TA0CCTL0 =(U16) CCIS_VCC |(TA0CCTL0 &~((U16) CCIS));//设置为 VCC
    __ no_operation ();//给它几个操作来触发捕获
    ___ no_operation();
    ___ no_operation();
    TA0CCTL0 =(U16) CCIS_GND |(TA0CCTL0 &~((U16) CCIS));//设置为 GND

    //等待捕捉/比较中断标志(CCIFG)设置
    //再读取捕捉寄存器
    //
    while ((TA0CCTL0 & CCIFG));//等待捕捉/比较标志
    TA0CCTL0 &=(U16)~CCIFG//清除捕捉标志

    //将捕获寄存器和溢出计数器复制到中
    //计时器计数
    //
    TA0CTL &=(U16)~TAIE//禁用溢出中断
    u32TimerCount =(U32) TA0CCR0//复制捕获寄存器
    u32TimerCount |=(U32)(((U32) g_u16TimerOverflowCount)<< 16)
    TA0CTL |= TAIE//启用溢出中断

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

    一个1MHz MCLK? 这真的很慢。 如果计时器以该速度运行、也会使您的问题更加困难。

    具有如此高分辨率的计时器用处不大。 而读取它所需的时间使得该分辨率用处更大。

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

    大家好!

    我只是检查一下。  我想知道如何确保不是在溢出的中间读。  我还发现有必要在禁用中断后添加一个 NOP、否则微控制器将进入某种故障状态。  我读取的时间现在具有从400uS 到12000uS 的大约20-40us 的一致偏移。

    //*****
    //
    // GetTimerCount -获取计时器的当前计数。
    //
    //参数:无
    //
    //返回- U32定时器的当前计数。
    //
    //注释
    //--
    //此计时器将在1h11分钟后回滚。
    //此函数需要56.14uS 才能完成
    //在禁用计时器后,需要使用 no_op。 通过找到此问题
    //详尽的测试。 如果没有它、g_u16TimerOverflow 会在什么时候导致锁定
    //正在读取。 参见 slau445i 第189页 DINT
    //发现 UC 在禁用后通常需要 no op
    //一个中断。 请参见以下链接:
    //
    //*****

    u32 GetTimerCount ()
    u32 u32TimerCount = 0
    u16 u16TimerOverflowCount

    捕获
    TA0CTL &=(U16)~TAIE//禁用溢出中断
    __ no_operation ();//必须确保禁用
    u16TimerOverflowCount = g_u16TimerOverflowCount
    TA0CTL |= TAIE//启用溢出中断

    //将计时器 A0捕获到捕获寄存器 TA0CCR0中
    //通过创建上升沿,然后重置
    //
    TA0CCTL0 &=(U16)~CCIFG//清除捕捉标志
    TA0CCTL0 ^= CCIS_1//切换到 VCC / GND

    //等待捕捉/比较中断标志(CCIFG)设置
    //再读取捕捉寄存器
    //
    while ((TA0CCTL0 & CCIFG));//等待捕捉/比较标志
    u32TimerCount =(U32) TA0CCR0//复制捕获寄存器

    TA0CTL &=(U16)~TAIE//禁用溢出中断
    __ no_operation ();//必须确保禁用
    如果(u16TimerOverflowCount!= g_u16TimerOverflowCount)转到捕获
    u32TimerCount |=(U32)(((U32) g_u16TimerOverflowCount)<< 16)
    TA0CTL |= TAIE//启用溢出中断

    返回 u32TimerCount
    }