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 RT106x Re: 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 中断标志后,您可以读取捕获寄存器:
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: 请参阅我之前的帖子。
致以最崇高的敬意
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,这样我就不用再使用级联模式了。不过,为了帮助其他可能看到此问题的人,我会尽量花一点时间找出错误,更新本帖。
記事全体を表示