2289832_zh-CN

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

2289832_zh-CN

2289832_zh-CN

i.MX RT1060 QTMR 级联模式,带输入捕获-无上限

当级联两个 TMR 通道用于 32 位计数器时,我似乎无法正常进行输入捕获。仅使用一个通道时,输入捕获可以正常工作,但当我尝试级联通道时却无法正常工作。

1.定义了 TMR1 ch0 和 ch1 结构。TMR1 ch0 时钟源为 kQTMR_ClockDivide_1,TMR2 ch1 时钟源为 kQTMR_ClockCounter0,输出
2. qtmr_begin 初始化通道。它们被设置为自由运行。TMR1 IRQ 已启用。为输入捕获启用 TMR1 中断。计时器启动。

当我调用 getCount 时,上层计数(通道 1)只能得到 0。否则,如果我忽略上面的计数,下面的计数总是正确的。

const qtmr_config_t QuadTimer_1_Channel_0_config = {
	.primarySource = kQTMR_ClockDivide_1,
	.secondarySource = kQTMR_Counter0InputPin,
	.enableMasterMode = false,
	.enableExternalForce = false,
	.faultFilterCount = 0,
	.faultFilterPeriod = 0,
	.debugMode = kQTMR_RunNormalInDebug
};

const qtmr_config_t QuadTimer_1_Channel_1_config = {
	.primarySource = kQTMR_ClockCounter0Output,
	.secondarySource = kQTMR_Counter0InputPin,
	.enableMasterMode = false,
	.enableExternalForce = false,
	.faultFilterCount = 0,
	.faultFilterPeriod = 0,
	.debugMode = kQTMR_RunNormalInDebug
};

void qtmr_begin()
{
	QTMR_Init(TMR1, kQTMR_Channel_0, &QuadTimer_1_Channel_0_config);
	QTMR_Init(TMR1, kQTMR_Channel_1, &QuadTimer_1_Channel_1_config);

	/* Ensure free-running (no stop at compare) */
	TMR1->CHANNEL[kQTMR_Channel_0].CTRL &= ~TMR_CTRL_LENGTH_MASK;
	TMR1->CHANNEL[kQTMR_Channel_1].CTRL &= ~TMR_CTRL_LENGTH_MASK;

	/* Setup the input capture */
	QTMR_SetupInputCapture(TMR1, kQTMR_Channel_0, QTMR_CounterInputPin, false, true, kQTMR_RisingEdge);

	/* Enable at the NVIC */
	EnableIRQ(TMR1_IRQn);

	/* Enable timer compare interrupt */
	QTMR_EnableInterrupts(TMR1, kQTMR_Channel_0, kQTMR_EdgeInterruptEnable);

	QTMR_StartTimer(TMR1, kQTMR_Channel_0, kQTMR_PriSrcRiseEdge);
	QTMR_StartTimer(TMR1, kQTMR_Channel_1, kQTMR_CascadeCount);
}

void TMR1_IRQHandler(void)
{
    QTMR_ClearStatusFlags(TMR1, kQTMR_Channel_0, kQTMR_EdgeFlag);
    qtmrIsrFlag = true;
}

void getCount(void)
{
    // Discard the first capture
    for (int i = 0; i < 2; i++)
    {
        while (!qtmrIsrFlag)
        {
        }
        qtmrIsrFlag = false;

        uint16_t lowerCount = TMR1->CHANNEL[kQTMR_Channel_0].CAPT;
        uint16_t upperCount = TMR1->CHANNEL[kQTMR_Channel_1].HOLD;
        uint32_t counterValue = ((uint32_t)upperCount << 16) | lowerCount;
    }
}

i.MX RT106xRe: i.MX RT1060 QTMR Cascade mode w/ Input Capture - No Upper Count

我在某种程度上已经明白了这一点。我使用了错误的寄存器来读取上部(通道 1)的计数。HOLD 寄存器不保存级联通道的计数,它用于存储特定事件期间的计数器值,无论是硬件还是软件,通常用于同步事件或保存先前的值等。

我应该只是读取 CNTR 寄存器。我可以在 IRQ 处理程序中或之后立即读取,然后同步到低 16 位。

不过,我发现还有一个问题不明白。如果我将频道 1 计时器 RESET 为 0,则计数始终从 1 开始,而不是 0。因此,(通道 1)上限计数的捕获时间总是偏差 1。为了补偿,我必须将通道 1 计数器 RESET 为 0xFFFF 才能获得正确的计数。为什么?

const qtmr_config_t QuadTimer_1_Channel_0_config = {
	.primarySource = kQTMR_ClockDivide_1,
	.secondarySource = kQTMR_Counter0InputPin,
	.enableMasterMode = false,
	.enableExternalForce = false,
	.faultFilterCount = 0,
	.faultFilterPeriod = 0,
	.debugMode = kQTMR_RunNormalInDebug
};

const qtmr_config_t QuadTimer_1_Channel_1_config = {
	.primarySource = kQTMR_ClockCounter0Output,
	.secondarySource = kQTMR_Counter0InputPin,
	.enableMasterMode = false,
	.enableExternalForce = false,
	.faultFilterCount = 0,
	.faultFilterPeriod = 0,
	.debugMode = kQTMR_RunNormalInDebug
};

void qtmr_begin()
{
	QTMR_Init(TMR1, kQTMR_Channel_0, &QuadTimer_1_Channel_0_config);
	QTMR_Init(TMR1, kQTMR_Channel_1, &QuadTimer_1_Channel_1_config);

	/* Ensure free-running (no stop at compare) */
	TMR1->CHANNEL[kQTMR_Channel_0].CTRL &= ~TMR_CTRL_LENGTH_MASK;
	TMR1->CHANNEL[kQTMR_Channel_1].CTRL &= ~TMR_CTRL_LENGTH_MASK;

	/* Setup the input capture */
	QTMR_SetupInputCapture(TMR1, kQTMR_Channel_0, QTMR_CounterInputPin, false, true, kQTMR_RisingEdge);

	/* Enable at the NVIC */
	EnableIRQ(TMR1_IRQn);

	/* Enable timer compare interrupt */
	QTMR_EnableInterrupts(TMR1, kQTMR_Channel_0, kQTMR_EdgeInterruptEnable);

	QTMR_StartTimer(TMR1, kQTMR_Channel_1, kQTMR_CascadeCount);
	QTMR_StartTimer(TMR1, kQTMR_Channel_0, kQTMR_PriSrcRiseEdge);
}

void TMR1_IRQHandler(void)
{
    QTMR_ClearStatusFlags(TMR1, kQTMR_Channel_0, kQTMR_EdgeFlag);
    qtmrIsrFlag = true;
}

void getCount(void)
{
	// Discard the first capture
	uint16_t lowerCount;
	uint16_t upperCount;
	uint32_t counterValue;

	for (int i = 0; i < 2; i++)
	{
		/* Reset channel 1 count to 0 - for some reason we have to reset to one value before or the count is off by 1...so we reset to 0xFFFF */
		TMR1->CHANNEL[kQTMR_Channel_1].CNTR = 0xFFFF;
		
		while (!qtmrIsrFlag)
		{
		}
		qtmrIsrFlag = false;

		lowerCount = TMR1->CHANNEL[kQTMR_Channel_0].CAPT;
		upperCount = TMR1->CHANNEL[kQTMR_Channel_1].CNTR;
		counterValue = ((uint32_t)upperCount << 16) | lowerCount;
	}
}


Re: i.MX RT1060 QTMR Cascade mode w/ Input Capture - No Upper Count

@azone

非常感谢您关注我们的产品并使用我们的社区。

我根据你关于使用QTMR Cascade模式和输入捕获的问题进行了验证测试。

硬件:MIMXRT1060-EVKB , 将输入信号连接至 J33-6。
软件:QTMR3 通道 0 和通道 1 配置为级联模式

使用此设置,当计数器级联时,输入捕获可以正常工作。

设置 Edge 中断标志后,您可以读取捕获寄存器:

mayliu1_0-1768206759574.png

board_qtmr_baseaddr->channel[board_qtmr_input_capture_channel0].capt;

和 BOARD_QTMR_BASEADDR->CHANNEL[BOARD_QTMR_INPUT_CAPTURE_CHANNEL1].CAPT;

顺祝商祺!

MayLiu

Re: i.MX RT1060 QTMR Cascade mode w/ Input Capture - No Upper Count

你好@azone

感谢您提供的最新信息。

关于你的新问题,我也为你做了一个测试。 输入频率为 1kHz 的信号和频率为 150MHz 的 TMR 时钟,可以得到正确的数值。

硬件:MIMXRT1060-EVKB,我向 J33-6 输入 1KHZ 信号。

SW: 请参阅我之前的帖子。

mayliu1_2-1768290894570.png


mayliu1_1-1768290710042.png

致以最崇高的敬意

MayLiu

Re: i.MX RT1060 QTMR Cascade mode w/ Input Capture - No Upper Count

嗨,谢谢您的答复。我从你的配置中看出,获得级联通道 1 计数的最佳方法是同时为该通道设置输入捕获并读取 CAPT 寄存器,而不是依赖读取 CNTR 寄存器。

这招管用。但对于通道 1 来说,它仍然算出了一个过高的值。我使用的是 SDK 的应用程序接口,而不是直接操作寄存器,但我的配置似乎与您的相同。

举例说明,当我输入频率为 1kHz 的信号,TMR 时钟为 150MHz 时,我预计计数将为 150,000。这意味着高 16 位计数为 "2",低 16 位计数为 "18928"=150,000。但是,我得到的上限计数是 "3"。在测量任何频率时,它总是偏差+1。为什么会这样?

const qtmr_config_t QuadTimer_1_Channel_0_config = {
	.primarySource = kQTMR_ClockDivide_1,
	.secondarySource = kQTMR_Counter0InputPin,
	.enableMasterMode = false,
	.enableExternalForce = false,
	.faultFilterCount = 0,
	.faultFilterPeriod = 0,
	.debugMode = kQTMR_RunNormalInDebug
};

const qtmr_config_t QuadTimer_1_Channel_1_config = {
	.primarySource = kQTMR_ClockCounter0Output,
	.secondarySource = kQTMR_Counter0InputPin,
	.enableMasterMode = false,
	.enableExternalForce = false,
	.faultFilterCount = 0,
	.faultFilterPeriod = 0,
	.debugMode = kQTMR_RunNormalInDebug
};

void qtmr_begin()
{
	CLOCK_EnableClock(kCLOCK_Timer1);

	QTMR_Init(TMR1, kQTMR_Channel_0, &QuadTimer_1_Channel_0_config);
	QTMR_Init(TMR1, kQTMR_Channel_1, &QuadTimer_1_Channel_1_config);

	/* Explicitly disable secondary source - not supported in API and not necessary but doing it anyways */
	TMR1->CHANNEL[kQTMR_Channel_0].CTRL &= ~TMR_CTRL_SCS_MASK;
	TMR1->CHANNEL[kQTMR_Channel_1].CTRL &= ~TMR_CTRL_SCS_MASK;

	/* Ensure free-running (no stop at compare) */
	TMR1->CHANNEL[kQTMR_Channel_0].CTRL &= ~TMR_CTRL_LENGTH_MASK;

	/* Setup the input capture */
	QTMR_SetupInputCapture(TMR1, kQTMR_Channel_0, kQTMR_Counter0InputPin, false, true, kQTMR_RisingEdge);
	QTMR_SetupInputCapture(TMR1, kQTMR_Channel_1, kQTMR_Counter0InputPin, false, true, kQTMR_RisingEdge);

	/* Enable at the NVIC */
	EnableIRQ(TMR1_IRQn);

	/* Enable timer compare interrupt */
	QTMR_EnableInterrupts(TMR1, kQTMR_Channel_0, kQTMR_EdgeInterruptEnable);
}

void TMR1_IRQHandler(void)
{
	uint16_t lowerCount;
	uint16_t upperCount;
	
	QTMR_ClearStatusFlags(TMR1, kQTMR_Channel_0, kQTMR_EdgeFlag);
	qtmrIsrFlag = true;
	
	lowerCount = TMR1->CHANNEL[kQTMR_Channel_0].CAPT;
	upperCount = TMR1->CHANNEL[kQTMR_Channel_1].CAPT; // UPPER COUNT IS ALWAYS OFF BY +1
}

void getCount(void)
{
	uint32_t counterValue;

	while (!qtmrIsrFlag)
	{
	}
	qtmrIsrFlag = false;

	counterValue = ((uint32_t)upperCount << 16) | lowerCount;
	}
}
Re: i.MX RT1060 QTMR Cascade mode w/ Input Capture - No Upper Count

好的,感谢您的测试。一定是我的配置出错了。我们可以修改硬件,使用 32 位 GPT 代替 16 位 QTMR,这样我就不用再使用级联模式了。不过,为了帮助其他可能看到此问题的人,我会尽量花一点时间找出错误,更新本帖。

Tags (1)
No ratings
Version history
Last update:
‎01-16-2026 02:26 AM
Updated by: