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.

[参考译文] CC2652PSIP:用于计数的定时器边沿捕捉

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

https://e2e.ti.com/support/wireless-connectivity/other-wireless-group/other-wireless/f/other-wireless-technologies-forum/1471447/cc2652psip-timer-edge-capture-for-counting

器件型号:CC2652PSIP
Thread 中讨论的其他器件:SYSBIOS

工具与软件:

您好!  

我正在尝试 在 GPT_MODE_EDGE_TIME 中使用 GPTIMER 。  您知道可接受的最大频率是多少?  目前、如果我使用大于100kHz 的输入信号、并在 tirtos 中调用 Task_sleep 或在 FreeRTOS 中调用 vTaskDelay、程序将停止执行。  任何示例代码都很好。

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

    Chris、您好!

    GP 计时器源频率 来自主高频时钟频率(即48 MHz)、因此我预计边沿检测至少对12 MHz 是准确的(我留下一些错误空间)。  但是、必须确保器件未进入低功耗待机模式、因为这将禁用主时钟、从而禁用 GP 计时器的边沿检测能力。

    此致、
    Ryan

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

    是否有实现此功能的示例代码?   

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

    SimpleLink F2 SDK 中没有直接示例、但 GPTimerCC26XX.h 文件参考 确实介绍了必要的 GPTimerCC26XX_setCaptureEdge 和 GPTimerCC26XX_getValue API。  您还可以参考较低级别的 Timer.h driverlib 文档。

    Regtards、
    Ryan

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

    您好!

    我仍然无法从所需的计时器中获得性能。   

    这是我的初始代码。  如果我在大于100kHz 的频率下捕获脉冲、程序将不会执行超过 Task_sleep


    *==== timerled.c ====
    */

    #include

    /*驱动程序头文件*/
    #include
    #include

    /*板头文件*/
    #include "ti_drivers_config.h"

    /*测试*/
    #include
    #include
    #include
    void init_counter (void);
    /*回调用于切换 LED。 */
    void timerCallback (Timer_Handle myHandle、int_fast16_t status);


    易失性 uint32_t pulse_count = 0;
    volatile uint32_t wrong_interrupt = 0;
    GPTimerCC26XX_Handle hTimer;
    void timerCallback2 (GPTMERCC26XX_Handle handle、GPTimerCC26XX_IntMask interruptMask){
    //关键段
    if (interruptMask 和 GPT_INT_CAPTURE){
    PULSE_COUNT++;
    其他{
    wrong_interrupt ++;
    }

    }
    /*
    *==== mainThread ====
    */
    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);

    /*
    *在连续回调模式下设置计时器,以调用回调
    *以100,000微秒或1秒运行一次。
    */
    Timer_Params_(T&params);
    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){}
    }
    init_counter();
    while (1){
    GPTMERCC26XX_enableInterrupt (hTimer、GPT_INT_CAPTURE);
    Task_sleep (10000);
    GPTMERCC26XX_disableInterrupt (hTimer、GPT_INT_CAPTURE);
    PULSE_COUNT = 0;
    Task_sleep (10000);

    }
    返回(NULL);
    }

    /*
    *每1,000,000微秒或1秒调用一次该回调。 因为
    *每次调用该函数时都会切换 LED、LED 将以其闪烁
    *速率为每2秒一次。
    */
    void timerCallback (Timer_Handle myHandle、int_fast16_t 状态)

    GPIO_TOGGLE (CONFIG_GPIO_LED_0);
    }

    GPTimerCC26XX_Handle hTimer;

    void init_counter (void){
    //将 GPIO 路由到计时器的捕获事件
    IOCPortConfigureSet (IOID_2、
    IOC_PORT_MCU_PORT_EVENT1
    IOC_IOMODE_NORMAL | IOC_FALLING_EDGE | IOC_INPUT_ENABLE);

    //设置计时器参数
    GPTimerCC26XX_Params 参数;
    GPTimerCC26XX_PARAMS_INIT (&params);
    params.width = GPT_CONFIG_16BIT;
    params.mode = GPT_MODE_EDGE_TIME;
    params.direction = GPTimerCC26XX_DIRECTION_UP;
    params.debugStallMode = GPTimerCC26XX_DEBUG_STALL_OFF;

    //打开计时器
    hTimer = GPTimerCC26XX_OPEN (COUNTER_GPTIMER、&params);
    if (hTimer => NULL){
    while (1);//如果计时器无法打开、则会出现错误处理
    }
    //将捕捉边沿设置为上升沿
    GPTimerCC26XX_setCaptureEdge (hTimer、GPTimerCC26XX_NEG_EDGE);

    //寄存并启用中断
    GPTimerCC26XX_registerInterrupt (hTimer、timerCallback2、GPT_INT_CAPTURE);

    //启动计时器
    GPTimerCC26XX_START (hTimer);
    GPTMERCC26XX_enableInterrupt (hTimer、GPT_INT_CAPTURE);
    }

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

    使用 IOC_PORT_MCU_PORT_EVENT0、而不是 IOC_PORT_MCU_PORT_EVENT1  

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

    请记住:

    •  如果未及时处理重复的快速硬件中断、这些中断可能会重叠。  如果在微秒内调用它们、则最好不要使用它们。
    • 定时器边沿捕获模式是16位、因此任何超过0xFFFF 的值都将溢出回0。  如果输入信号非常频繁、则需要每隔几毫秒检查一次计时器值。

    #include <stddef.h>
    
    /* Driver Header files */
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/Timer.h>
    
    /* Board Header file */
    #include "ti_drivers_config.h"
    
    /* TEST */
    #include <ti/devices/cc13x2_cc26x2/driverlib/ioc.h>
    #include <ti/drivers/timer/GPTimerCC26XX.h>
    #include <ti/sysbios/knl/Task.h>
    void init_counter(void);
    /* Callback used for toggling the LED. */
    void timerCallback(Timer_Handle myHandle, int_fast16_t status);
    
    volatile uint32_t pulse_count = 0;
    volatile uint32_t previous_count = 0;
    volatile uint32_t wrong_interrupt = 0;
    GPTimerCC26XX_Handle hTimer;
    //void timerCallback2(GPTimerCC26XX_Handle handle, GPTimerCC26XX_IntMask interruptMask) {
    //// Critical section
    //    if (interruptMask & GPT_INT_CAPTURE){
    //        pulse_count++;
    //    }
    //    else {
    //        wrong_interrupt ++;
    //    }
    //}
    
    /*
    * ======== mainThread ========
    */
    void *mainThread(void *arg0)
    {
        Timer_Handle timer0;
        Timer_Params params;
    
        /* Call driver init functions */
        GPIO_init();
        Timer_init();
    
        /* Configure the LED pin */
        GPIO_setConfig(CONFIG_GPIO_LED_0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
    
        /* Turn off user LED */
        GPIO_write(CONFIG_GPIO_LED_0, CONFIG_GPIO_LED_OFF);
    
        /*
        * Setting up the timer in continuous callback mode that calls the callback
        * function every 1,000,000 microseconds, or 1 second.
        */
        Timer_Params_init(&params);
        params.period = 1000000;
        params.periodUnits = Timer_PERIOD_US;
        params.timerMode = Timer_FREE_RUNNING;
    //    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) {}
        }
        init_counter();
        while(1){
    //        GPTimerCC26XX_enableInterrupt(hTimer, GPT_INT_CAPTURE);
            previous_count = GPTimerCC26XX_getValue(hTimer);
            Task_sleep(5000);
    //        GPTimerCC26XX_disableInterrupt(hTimer, GPT_INT_CAPTURE);
    //        pulse_count = 0;
            pulse_count = GPTimerCC26XX_getValue(hTimer);
            if(previous_count > pulse_count)
            {
                pulse_count += (uint16_t)(0xFFFFF - previous_count);
            }
            else
            {
                pulse_count -= previous_count;
            }
            GPIO_toggle(CONFIG_GPIO_LED_0);
    //        Task_sleep(10000);
    
        }
        return (NULL);
    }
    
    /*
    * This callback is called every 1,000,000 microseconds, or 1 second. Because
    * the LED is toggled each time this function is called, the LED will blink at
    * a rate of once every 2 seconds.
    */
    void timerCallback(Timer_Handle myHandle, int_fast16_t status)
    {
        GPIO_toggle(CONFIG_GPIO_LED_0);
    }
    
    GPTimerCC26XX_Handle hTimer;
    
    void init_counter(void) {
        // Route GPIO to the timer's capture event
        IOCPortConfigureSet(26,
        IOC_PORT_MCU_PORT_EVENT0,
        IOC_IOMODE_NORMAL | IOC_FALLING_EDGE | IOC_INPUT_ENABLE);
    
        // Set up timer parameters
        GPTimerCC26XX_Params params;
        GPTimerCC26XX_Params_init(&params);
        params.width = GPT_CONFIG_16BIT;
        params.mode = GPT_MODE_EDGE_TIME;
        params.direction = GPTimerCC26XX_DIRECTION_UP;
        params.debugStallMode = GPTimerCC26XX_DEBUG_STALL_OFF;
    
        // Open timer
        hTimer = GPTimerCC26XX_open(COUNTER_GPTIMER, &params);
        if (hTimer == NULL) {
        while (1); // Error handling if timer cannot be opened
        }
        // Set capture edge to rising edge
        GPTimerCC26XX_setCaptureEdge(hTimer, GPTimerCC26XX_NEG_EDGE);
    
        // Register and enable interrupt
    //    GPTimerCC26XX_registerInterrupt(hTimer, timerCallback2, GPT_INT_CAPTURE);
    
        // Start the timer
        GPTimerCC26XX_start(hTimer);
    //    GPTimerCC26XX_enableInterrupt(hTimer, GPT_INT_CAPTURE);
    }
    

    上面的代码改进了结果。

    此致、
    Ryan