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.

[参考译文] LP-CC1352P7:复位计时器计数

Guru**** 2416110 points
Other Parts Discussed in Thread: SYSCONFIG

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

https://e2e.ti.com/support/wireless-connectivity/zigbee-thread-group/zigbee-and-thread/f/zigbee-thread-forum/1269670/lp-cc1352p7-reset-timer-count

器件型号:LP-CC1352P7
主题中讨论的其他器件:SysConfig

您好!

我使用两个计时器、如快照中所示。

Timer_close() API 似乎没有正确地重置计时器计数。 因此,使用新的周期值调用 Timer_start()似乎不会生效(回调函数未被调用)。

例如、以下是用于初始化计时器1的代码:

void timer_1_init (uint32_t period_us)
{
   int32_t STATUS = 0;

   Timer_1_flag = 0;

   Timer_Params_(&TIMER_1_PARAMS);
   Timer_1_params.periodUns = Timer_period_US;
   Timer_1_params.period = period_us;
   Timer_1_params.timerMode = Timer_OneShot 回调;
   Timer_1_params.timerCallback = timer_1_callbackfunction;

   Timer_init();

   Timer_1_Handle = Timer_open (CONFIG_TIMER_1、&TIMER_1_PARAMS);

   if (timer_1_handle == NULL){
       // Timer_open()失败
       while (1);
   }

下面是使用新周期值关闭和重新启动计时器(在状态机内)的代码片段:

Timer_1_flag = 0;
Timer_close (timer_1_handle);
Timer_1_init (TIMESTAMP_START_TX);
Timer_start (timer_1_handle);

(1)请检查代码片段,并告诉我是否有任何问题。

(2)如何通过硬件寄存器地址访问计时器1以复位计数器?

谢谢

卡尔蒂克

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

    您好 Karthik、

    如果您配置了  timer_1_params.timerMode = Timer_Oneshot_callback、则在触发计时器中断前调用 timer_stop()或 timer_close ()时不会调用回调。 这似乎就是问题所在、因为设置看起来不错。

    请查看 以下项目中计时器模式的定义: https://dev.ti.com/tirex/explore/content/simplelink_cc13xx_cc26xx_sdk_7_10_01_24/docs/drivers/doxygen/html/_timer_8h.html#ab0e86a066b5c68c55183cd680090a9b7

    调用 Timer_close()时,计时器始终复位。 然而,您可以通过 GPTimerCC26xx_resetHw ()函数调用手动重置计时器,但这不是必要的,因为 Timer_close ()已经调用了这一函数。

    此致
    曼努埃尔

     

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

    您好、Manuel:

    非常清楚的解释!

    我将相应地审核我的代码。

    使用 TIMER_STOP 有什么作用? 这是否意味着、我们可以立即调用 timer_start、并且计数器从其先前停止的位置继续计数?

    此外,如果在触发计时器中断(回调)之前将 timer_1_init()调用"再次",会发生什么情况?

    谢谢

    卡尔蒂克

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

    Karthik、您好、

    是的 timer_stop ()将停止当前计数中的定时器,而不复位寄存器。 因此调用 timer_start()将从最后一个值开始计数。

    当定时器运行时,在中断前调用 timer_1_init ()时,你需要再次运行 timer_start()以使定时器重新启动。
    然而,我认为使用 Timer_setPeriod ()来更改计时器的周期会更有用。 即使在计时器运行期间也可以调用此函数。 但值将异步更新。
    有关更多信息、请参阅以下内容:  
    https://dev.ti.com/tirex/explore/content/simplelink_cc13xx_cc26xx_sdk_7_10_01_24/docs/drivers/doxygen/html/_timer_8h.html#aee385432bc15af4d7ae919e941341a4c

    此致
    曼努埃尔

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

    您好、Manuel:

    我已经使用 timer_1_init ()初始化了定时器,其中调用了 Timer_open。

    我希望 TIMER_1在3ms (在 TIMESTAMP_START_TX 宏中定义)之后生成中断、但没有发生这种情况。

    如下代码片段用于验证计时器计数是否设置正确。 无法根据打印的值理解它:t1[0]、t1[1]和 t1[2]。

    请评论,并告诉我,如果我错过了什么。

    让我感到困惑的另一件事是 timer_setperiod 的预条件建议在调用 setperiod API 之前使用 timer_stop。 这似乎与描述在"Timer_Oneshot_callback "下的内容相矛盾,即在定时器中断前 调用 timer_stop 将防止调用指定的回调。 如果我误解了它、请告诉我。

    #define TIMESTAMP_START_TX 3000
    
    timer_1_count[0] = Timer_getCount(timer_1_handle);
    uart_printf("t1[0] %d\r\n",timer_1_count[0]);
    Timer_stop(timer_1_handle); // Karts[13-09-2023]: use this when timer setperiod is used
    timer_1_count[1] = Timer_getCount(timer_1_handle);
    uart_printf("t1[1] %d\r\n",timer_1_count[1]);
    timer_1_status = Timer_setPeriod(timer_1_handle,Timer_PERIOD_US,TIMESTAMP_START_TX);
    if(timer_1_status == 0)
    {
        Timer_start(timer_1_handle);
        timer_1_count[2] = Timer_getCount(timer_1_handle);
        uart_printf("t1[2] %d\r\n",timer_1_count[2]);
        while(1);
    }
                
                
    Result:
    t1[0] 4935
    t1[1] 58317
    t1[2] 58461

    谢谢

    卡尔蒂克

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

    您好 Karthik、

    您可以在第3行之前分享初始化计时器的初始周期吗?  
    这将帮助我了解您将获得的输出。

    计时器需要到达其末尾并触发回调或在回调之前停止、以便重置周期。

    您能否尝试测试以下示例代码、看看这是否起作用:

    Timer_Params_init(&params);
        params.period        = 1000000;
        params.periodUnits   = Timer_PERIOD_US;
        params.timerMode     = Timer_ONESHOT_CALLBACK;
        params.timerCallback = timerCallback;
    
        timer0 = Timer_open(CONFIG_TIMER_0, &params);
    
        if (timer0 == NULL)
        {
            /* Failed to initialized timer */
            while (1) {}
        }
    
        if (Timer_start(timer0) == Timer_STATUS_ERROR)
        {
            /* Failed to start timer */
            while (1) {}
        }
    
        while(gwaitForCallback == 0)
        {
            // do nothing
        }
    
        Timer_setPeriod(timer0, Timer_PERIOD_US, 2000000);
    
        if (Timer_start(timer0) == Timer_STATUS_ERROR)
        {
          /* Failed to start timer */
          while (1) {}
        }
    
        Timer_stop(timer0); //cancelling after starting
    
        //CHECK THAT CALLBACK HAS NOT BEEN CALLED
        //If you comment out the timer stop, the callback will be called twice
    
    
        return (NULL);
    }
    
    void timerCallback(Timer_Handle myHandle, int_fast16_t status)
    {
        if (status == Timer_STATUS_SUCCESS)
        {
            GPIO_toggle(CONFIG_GPIO_LED_0); //optional GPIO toggle
            gwaitForCallback++;
        }
    
    }

    此致
    曼努埃尔

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

    手动、初始周期为65534微秒、中断可能还未产生。

     在我分享的片段中、我在设置新的周期值(小于初始值的3000微秒)之前停止了计时器。

    只是为了更新你,我也尝试在 Timer_continuous_callback 模式. 不起作用。

    已尝试代码。代码卡在"初始化计时器失败"。

    谢谢

    卡尔蒂克

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

    您好 Karthik、

    您是否仍将计时器配置为16位? 您是否可以尝试在将相应的定时器配置为标准32位模式时再次运行该程序?

    您是否已经尝试了 SDK 中包含的"timerled"示例? 这也使用 Timer_continuous_callback 模式、应该开箱即可使用。

    此致
    曼努埃尔

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

    您好、Manuel:

    定时器类型为16位。

    尝试了示例。 它似乎起作用了。首先、LED 每1秒切换一次。 然后切换到每5秒切换一次。

    下面是代码:

    void *mainThread (void *arg0)
    {
       Timer_Handle timer0;
       Timer_Params 参数;

       /*调用驱动程序初始化函数*/
       GPIO_init ();
       Timer_init();

       /*配置 LED 引脚*/
       GPIO_setConfig (CONFIG_GPIO_LED_0、GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);

       /*关闭用户 LED */
       GPIO_WRITE (CONFIG_GPIO_LED_0、CONFIG_GPIO_LED_OFF);

       /*
        *在连续回调模式下设置计时器,以调用回调
        *函数、每1,000,000微秒或1秒运行一次。
        */
       Timer_Params_(参数(&P);
       params.period       = 1000000;
       params.periodUnits  = Timer_period_US;
       params.timerMode    = Timer_continuous_callback;
       params.timerCallback = timerCallback;

       timer0 = Timer_open (CONFIG_TIMER_0、&params);

       if (timer0 == NULL)
       {
           /*初始化计时器失败*/
           while (1){}
       }

       if (Timer_start (timer0)== Timer_STATUS_ERROR)
       {
           /*启动计时器失败*/
           while (1){}
       }

       while (1)
       {
           if (timer_0_flag == 1)
           {
               Timer_0_flag = 0;
               Timer_0_COUNT++;
           }

           if (timer_0_count == 10)
           {
               Timer_stop (timer0);
               Timer_0_count = 0;
               Timer_0_flag = 0;
               Timer_setPeriod (timer0、Timer_period_US、5000000);
               if (Timer_start (timer0)== Timer_STATUS_ERROR)
               {
                   /*启动计时器失败*/
                   while (1){}
               }
           }
       }

       返回(NULL);


    /*
     *该回调每1,000,000微秒或1秒调用一次。 因为
     *每次调用此函数时、LED 都会进行切换、LED 将以
     *每2秒一次的速率。
     */
    void timerCallback (Timer_Handle myHandle、int_fast16_t status)
    {
       Timer_0_flag = 1;
       GPIO_TOGGLE (CONFIG_GPIO_LED_0);

    我遇到问题的背景是、我将使用两个计时器实例。 将不得不在这个例子中尝试该方案。您能否确认 即使在使用多个计时器实例时也是否应该只调用一次 Timer_init()? 因为、我在初始化 timer0和 Timer1时、在两个子例程中调用该函数。

    作为参考,我已经复制了上面这个线程中的 timer_1_init()例程。 类似地、还写入了 TIMER_0_INIT 例程。

    在边注中、每当我暂停调试会话时、控制就会进入未知状态(下面的快照)。 这是预期结果吗? 如何知道控件是否在有效位置停止?

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

    您好 Karthik、

    Timer_init()只能在任何计时器打开前调用一次。
    但必须为两个具有所需参数的计时器实例调用 Timer_open()。

    您在这里看到的调试问题可能是由于在1或5秒长的计数周期内处于睡眠模式所致(请参阅 PowerCC26xx_standbyPolicy ())。 因此、在睡眠期间停止调试将导致该状态。

    此致
    曼努埃尔

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

    您好、Manuel:

    我想我设法重现了这个问题。

    请查看快照。 计时器1计数器卡在1。 理想情况下、它应该得到一个大于计时器0计数的数字。

    还连接了源代码(在单次触发模式下为定时器0、在连续模式下为定时器1)。

    最初、定时器1配置为65ms、定时器0配置为10ms。随后、定时器1配置为3ms。

    预计定时器1的计数器的增量为定时器0的增量三倍。 但是、计数一直停留在1。

    请评论,并告诉我,如果我错过了任何东西.

    e2e.ti.com/.../timerled.zip

    谢谢

    卡尔蒂克

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

    您好 Karthik、

    我已经对您的代码进行了测试、遇到了同样的问题。
    驱动程序中似乎存在错误、设置新的加载值时计数寄存器不会复位。 这就是为什么在重新启动计时器时、它会最终溢出并重新启动的原因。  

    目前、您必须在寄存器级别手动复位计数器值寄存器。
    请使用以下命令进行该操作:

    Timer_stop();
    Timer_setPeriod();
    
    HWREG(0xTAV_Address) = 0xFFFFFFFF;
    HWREG(0xTBV_Address) = 0xFFFFFFFF;
    
    Timer_start();

    对于"TAV_Address"和"TBV_Address"、请在 CCS 中查看寄存器视图、并查找您各自使用的计时器(GPTx)、并找到该 GPTx 的 TAV/TBV 寄存器的地址。

    希望这将解决您身边的问题。

    此致
    曼努埃尔

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

    您好、Manuel:

    试过、但似乎不起作用。 定时器1的计数器不递增。

    您能否查看并确认硬件地址(对应于 GPT1的计时器1)是否正确?

    更新:

    我暂停了代码执行并多次运行、然后让执行暂停。

    一段时间后、恢复执行。 有趣的是、计时器1计数器递增。

    我不理解这种行为。 我接下来应该怎么做?

    谢谢

    卡尔蒂克

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

    您好 Karthik、

    在暂停后计时器递增可能与计时器溢出然后重新启动有关。 我观察到类似的行为。

    我需要更好地了解您正在尝试做什么。
    据我所见、您希望两个计时器都独立运行、但以65ms 的间隔启动计时器1、该间隔从未完成、但在计数器0首次计数到0后重新配置为3ms。
    是这样吗?

    如果您希望两个计时器持续运行、则应将它们配置为连续回调、并添加:

    while(timer_0_flag == 0)
                {
    
                }

    然后再重新配置计时器1。 这种方式、它仅在计时器0一次达到0时完成。
    您需要删除重新配置部件周围的 while 循环。

    您能否告诉我、您是否打算这样做以及该解决方案是否有效?

    此致
    曼努埃尔

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

    您好、Manuel:

    我希望计时器0在单次触发模式下以10ms 的持续时间运行。 将其搁置一边。

    我希望在整个应用中对计时器1进行配置和重新配置。

    例如(以及在我发送的样本中)、我已经将计时器1初始化为65ms、在这段时间结束之前、我需要将其重新配置为3ms 并超时。

    作为建议的硬件地址被写入复位计数器(分配为0xFFFFFFFF)。 不过、计时器似乎没有立即启动。 它为什么应该溢出然后开始? 那么、写入 TAV 和 TBV 寄存器的要点是什么? 驱动程序中可能还有其他错误?

    如果您可以快速解决问题、我愿意直接与您联系。

    我已经延迟了此帖子、如果能快速回复以关闭此帖子、我将不胜感激。

    谢谢

    卡尔蒂克

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

    您好 Karthik、  

    我现在完全像您一样修改了我的代码。
    计时器0作为 Oneshot_callback、计时器1作为连续回调、而 GPT1作为计时器外设。

    当我运行以下代码(根据您发送的代码改编)时、一切都按预期运行:e2e.ti.com/.../timerled_5F00_092723.c

    您可以检验一下吗?

    此致
    曼努埃尔

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

    您好、Manuel:

    我想您已经假设一次性模式下的计时器0仅在应用中使用一次。 如果是、则不是。

    每当设置定时器0的中断标志以执行其他一些事件时、我都会再次启动该定时器0。 这种情况发生时、我需要使用 Timer1启动其他一些操作。

    我想了解为什么我们应该等待 TIMER_0_FLAG 置位、然后再重新配置计时器1? 定时器是具有独立寄存器的独立对象(固件角度)。

    我尝试了您分享的逻辑。 它没有工作。

    请查看快照。 计时器0标志置1。 然而、TIMER_1_COUNT 仍为0。

    它仅在经过长时间的暂停和执行后有效。 现在看看当我暂停代码执行时控制权在哪里。

    这里还缺少什么?

    谢谢

    卡尔蒂克

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

    您好 Karthik、

    等待 timer_0_flag 的 while 循环仅在本例中用于提供一个示例、在该示例中、当计时器0达到回调时、实际重新配置计时器1。 就像您在本周早些时候给我发送的代码片段中一样。
    对于最终应用、我建议使用信标、而不是 while 循环。

    e2e.ti.com/.../timerled_5F00_example.zip

    我现已附上我使用的整个项目、以确保 SysConfig 设置一致。

    我将 Code Composer Studio 12.4.0.0007与 SimpleLink_CC13xx_C26xx_SDK_7_10_01_24配合使用。
    LaunchPad 是 LP-CC1352P7-1。

    请确认您使用的版本、软件和硬件与我相同。  

    这是我测试过的确切代码、它在我旁边的工作方式如下:

    配置了两个计时器。 我已经检查了寄存器值、是否在重新加载寄存器中加载了正确的间隔。
    计时器0回调并将 TIMER_0_FLAG 设置为1。 这会导致要重新配置计时器1重载值、也可以通过 GPT1_TAILR 寄存器中的值进行验证。
    然后、计时器1在所需的3ms 间隔内进行计数。

    请确保此代码也适用于您。

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

    您好、Manuel:

    你的项目很适合我。

    使用的 SDK:C:/ti/simplelink_cc13xx_cc26xx_sdk_7_10_00_98/source

    CCS 版本:12.4.0.00007  

    它在示例项目中也起作用。 区别在于、示例项目中的定时器1尝试使用任何 GPTM0而不是 GPTM1 (发生冲突)。

    会返回到我的实际应用并尝试。

    谢谢

    卡尔蒂克