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.

[参考译文] TM4C123GH6PGE:使用输入捕捉模式的 TimerValueGet ()在 OS 任务延迟下是不准确的。

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1106012/tm4c123gh6pge-timervalueget-using-input-capture-mode-is-not-accurate-with-os-task-delay

器件型号:TM4C123GH6PGE

您好!

我正在使用 FreeRTOS 开发 TM4C123GH launchpad。

我在50Hz 至400Hz 之间有一个方波输入进入 PC7。 我已将计时器计数配置为递减、根据以下代码捕获每个上升沿的计时器:

/* Enable the Timer
	 * Note that the GP Timer module clock must be enabled before the registers can be programmed
	 * (see page 338 or page 357). There must be a delay of 3 system clocks after the Timer module clock
	 * is enabled before any Timer module registers are accessed.
	 */
	MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_WTIMER1);

	// Set the IO pin to be an input for wide timer
	// Use PC7 which is input 8, which is an ODD input (i.e. TIMER B)
	GPIOPinConfigure(GPIO_PC7_WT1CCP1);
	MAP_GPIOPinTypeTimer(GPIO_PORTC_BASE, GPIO_PIN_7);

	// Configure the timer
	// Capture the time value at each event edge
	MAP_TimerConfigure(WTIMER1_BASE, (TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PERIODIC | TIMER_CFG_B_CAP_TIME));

	// Count on Positive Edges
	MAP_TimerControlEvent(WTIMER1_BASE, TIMER_B, TIMER_EVENT_POS_EDGE);

	// The timer starts at 0xFFFFFFFF and counts down.
	MAP_TimerLoadSet(WTIMER1_BASE, TIMER_B, 0x00FFFFFF);
	MAP_TimerMatchSet(WTIMER1_BASE, TIMER_B, 0x00FFFFFE);

	// Configure the prescaler
	// Note: I can not see when this is operating in our split timer mode
	MAP_TimerPrescaleSet(WTIMER1_BASE, TIMER_B, 0xFF);
	MAP_TimerPrescaleMatchSet(WTIMER1_BASE, TIMER_B, 0xFE);

	// Configure the update mode
	TimerUpdateMode(WTIMER1_BASE, TIMER_B, TIMER_UP_LOAD_IMMEDIATE);

	// Clear the interrupt for TIMER_B capture event
	MAP_TimerIntClear(WTIMER1_BASE, TIMER_CAPB_EVENT);

	// Start the timer
	MAP_TimerEnable(WTIMER1_BASE, TIMER_B);

我还有一个主要任务、在该任务中、我检查是否发生了捕获事件、读取计时器并计算差异、如下所示:

while(1)
	{

		// Check if we have status
		/* Poll the CnERIS bit in the GPTMRIS register or wait for the interrupt to be generated (if enabled).
		 * In both cases, the status flags are cleared by writing a 1 to the CnECINT bit of the GPTM
		 * Interrupt Clear (GPTMICR) register. The time at which the event happened can be obtained
		 * by reading the GPTM Timer n (GPTMTnR) register.
		 */
		u32Status = MAP_TimerIntStatus(WTIMER1_BASE, 0);
		if((u32Status & TIMER_CAPB_EVENT) == TIMER_CAPB_EVENT)
		{
			// Count of timer ticks between pulses
			m_u32RawCount = (Luint32)TimerValueGet(WTIMER1_BASE, TIMER_B);

			// As we are counting down do the difference
			// It may be that the variant of the CPU we use does not have an up-counter function?
			u32Diff = (0xFFFFFFFF - m_u32RawCount);

			// Work out the difference
			m_u32TimerCount = u32Diff - u32TempPrev;

			// Save the prev value
			u32TempPrev = u32Diff;

			// Clear the flag again for next time
			MAP_TimerIntClear(WTIMER1_BASE, TIMER_CAPB_EVENT);

		}

		vTaskDelay(pdMS_TO_TICKS(1));
	}

我们注意到、如果频率为50Hz、则计时器值始终是合理的、但是一旦我们开始超过100Hz、对操作系统任务延迟值的任何更改(例如从1ms 到10ms)都会影响我们从计时器读取的值。 这种影响是半随机的、但是定时器值似乎 在正确的值和大约1/2的预期值之间交替。

我的理解 是发生捕获事件、自由运行定时器的值被传输到定时器值寄存器中、我们随后在未来的某个时候读取该寄存器。

有人能推测我们调用 TimerValueGet ()的速度为何会影响计时器值的准确性?

谢谢。

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

    在100Hz 时、每10ms 发生一次事件。 如果你停止寻找10ms、很有可能在那个时间发生两个事件、你将错过第一个事件;在这种情况下、算术将指示一个周期的长度是时间的两倍(速度的一半)。

    我建议使用 ISR 来馈送队列。 这样、您就不必猜测投票的频率。

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

    您好!

    在编写本文档时、我认为我看到了逻辑、如果我错过了一个计时器事件、那么上一个事件和下一个采样事件之间的差异将是时间的两倍。

    谢谢!