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.

[参考译文] CC1311R3:使用外部输入触发 GPTimer

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

https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz-group/sub-1-ghz/f/sub-1-ghz-forum/1633288/cc1311r3-trigger-gptimer-with-external-input

部件号: CC1311R3

我正在尝试将 GPTimer 配置为由外部事件(即 DIO 输入上的边沿或电平)启动的延迟计时器(例如 1us 分辨率)。 这是 MCU 计时器的常见用例之一、但该问题上没有 TI 驱动程序和 Driverlib 文档。

TRM 的第 15.4.1 节指示我“将 GPT:TnMR TnSNAPS、TnWOT、TnMTE 和 TnCDIR 寄存器位配置为...使用外部触发器开始计数、配置额外的触发器或中断...“、但 TnWOT 似乎只是从菊花链中先前位置的计时器设置触发器、并且 GPTMT.HW 寄存器中没有进一步提及

或者、当配置为单触发计时器 (GPT_MODE_OneShot_up) 时、由 hwAttrs->pinMux 定义的引脚是否用作启动触发器。

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

    尊敬的 Roger:

    这里有一个误解。 没有要设置的寄存器可以启用在发生外部事件时启动的计时器。 您将需要在某种事件处理程序/ISR 中实现此目的。  
    我认为 1us 分辨率并不现实。  您最多可以捕获外部事件发生的时间、然后将其添加到计时器中。  
    谢谢、
    Marie H
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    实际上、所有 Chipcon TRMS 中都提到了“TnMTE 寄存器位“、但我想它们永远不存在或不起作用。 我最终为外部触发使用了传统的 INT_AON_GPIO_EDGE 中断。 然后、为了 尽可能减少启动延迟计时器所需的时间、我设置其 TAWOT 位以使其停止计数、直到 GPIO_EDGE 回调清除了  TAWOT 并允许延迟计时器开始计数。 测量的延迟为~8us±2us。

    GPTimerCC26XX_Handle delay_timer;
    
    /* This ISR is called by dly_timer timeout.
       It starts the delayed process. */
    void delay_callback(GPTimerCC26XX_Handle handle,
    		    GPTimerCC26XX_IntMask interruptMask)
    {
    	/* Trigger process from delayed external input */
    }
    
    /* This ISR is called by falling edge of TRIG_IN.
       It starts the one-shot dly_timer. */
    void trigger_callback()
    {
    	uint32_t gpt_base = delay_timer->hwAttrs->baseAddr;
    	
    	/* Start delay_timer by clearing GPTMn[TAWOT] bit */
    	TimerWaitOnTriggerControl(gpt_base, TIMER_A, false);
    	
    	// Disable GPIO interrupt
    	IntDisable(INT_AON_GPIO_EDGE);
    }
    
    /* Latency (in addition to the loaded timer value)
       between TRIG_IN edge and delay_callback was
       determined empirically to be 8 +/-2 us. */
    #define DLY_LATENCY 8
    
    /* This ISR is called by falling edge of TRIG_IN.
       It starts the one-shot dly_timer. */
    int setup_delay_timer()
    {
    	/* Set up GPT as one-shot delay */
    	GPTimerCC26XX_Params params;
    	GPTimerCC26XX_Params_init(&params);
    	
    	params.width          = GPT_CONFIG_16BIT;
    	params.mode           = GPT_MODE_ONESHOT;
    	params.direction      = GPTimerCC26XX_DIRECTION_UP;
    	params.debugStallMode = GPTimerCC26XX_DEBUG_STALL_ON;
    	
    	delay_timer = GPTimerCC26XX_open(DELAY_GPT, &params);
    	if (delay_timer == NULL) {
    		return ENXIO;
    	}
    	/* Register interrupt at GPT timeout */
    	GPTimerCC26XX_registerInterrupt(delay_timer,
    					delay_callback,
    					GPT_INT_TIMEOUT);
    
    	/* Enable input on TRIG_IN */
    	IOCIOInputSet(TRIG_IN, IOC_INPUT_ENABLE);
    
    	/* Set up falling GPIO edge as interrupt */
    	IOCIOIntSet(TRIG_IN, IOC_INT_ENABLE, IOC_FALLING_EDGE);
    	IOCIntEnable(TRIG_IN);
    
    	/* Register GPIO_EDGE handler in dynamic vector table */
    	IntRegister(INT_AON_GPIO_EDGE, trigger_callback);
    	
    	/* Disable for now */
    	IntDisable(INT_AON_GPIO_EDGE);
    
    	return 0;
    }
    
    void arm_trigger(uint32_t delay)
    {
    	uint32_t gpt_base = delay_timer->hwAttrs->baseAddr;
    	
    	/* Load timer with specified microsecond delay */
    	uint32_t dly_load_value = 48UL * (delay - DLY_LATENCY);
    	GPTimerCC26XX_setLoadValue(delay_timer, dly_load_value);
    
    	/* Set GPTMn[TAWOT] bit (wait-for-trigger mode) to
    	   temporarily block delay_timer from counting. */
    	TimerWaitOnTriggerControl(gpt_base, TIMER_A, true);
    	
    	/* Start delay_timer */
    	GPTimerCC26XX_start(delay_timer);
    
    	/* Clear interrupt for TRIG_IN pin */
    	IOCIntClear(TRIG_IN);
    	
    	/* Clear any pending GPIO_EDGE interrupts */
    	IntPendClear(INT_AON_GPIO_EDGE);
    	
    	/* Enable GPIO_EDGE interrupts */
    	IntEnable(INT_AON_GPIO_EDGE);
    }