我想将我的 MCU 与具有特定通信方式的模块连接。模块发送可变字符数的消息,其中两个字符之间的周期也是可变的。我的想法是使用计时器来克服这个问题。假设模块发送 5 个字符。接收到第一个字符后,计时器将被激活。假设第二个字符在第一个字符之后不久发送,之后它的接收计时器将被重置并再次启动。其余 3 个角色的原理相同。由于没有更多数据要接收,定时器将达到其预定义的、实验定义的值并生成中断,因此通知 MCU 已接收到完整的消息。
简而言之,计时器将在接收到每个字符后重置。
我想在STM32G070上以正常模式配置TIM7。我的主要问题是如何重置计时器。我接触互联网的方式有多种:
CEN
寄存器中的
CR1
位 - 计时器停止计数并 保持当前值(无复位,无中断)。这个方法 要求将计时器设置为初始值(我仍然不确定如何),因此 花时间
EGR
寄存器中设置UG位 - 定时器被重新加载但全局中断 通过设置
SR
寄存器中的 UIF 位来触发(中断应该是 仅在接收到最后一个字符时激活)。
TIM7 -> ARR = 0;
TIM7 -> CR1 &= ~TIM_CR1_UDIS;
TIM7 -> EGR = TIM_EGR_UG;
TIM7 -> CR1 |= TIM_CR1_UDIS;
在这种情况下,似乎您需要在中断事件(收到完整消息)后禁用计时器,并在再次接收第一个数据(新消息的开始)后重新启用它(并重新启用中断) 。正如您所说,这是通过
CEN
寄存器的
CR1
位和
UIE
寄存器的
CR2
位来完成的。这样,当没有数据传输时,定时器就不会产生不必要的中断。要重新启动定时器,您只需在接收到每个字节后向计数器寄存器写入 0 即可。所以:
// after receiving first byte
TIM7->CR1 |= 0x01; // set the CEN
TIM7->CR2 |= 0x01; // set the UIE bit for interrupt generation
// after receiving each byte
timerValue = TIM7->CNT; // save the time
TIM7->CNT &= 0x0; // restart the timer
// in the timer interrupt callback routine (after receiving last byte)
TIM7->CR2 &= ~(0x01); // disable the interrupt
TIM7->CR1 &= ~(0x01); // disable the counter, this won't be necessary
TIM7 -> ARR = 0;
TIM7 -> CR1 |= TIM_CR1_UDIS;
TIM7 -> EGR = TIM_EGR_UG;
TIM7 -> CR1 &= ~TIM_CR1_UDIS;
就我而言,我只需要重置计数器 CNT。
URS
寄存器进行操作。根据[此链接]https://www.rotr.info/ electronics/mcu/stm32f100/stm32_tim1/registers.htm(抱歉,但我找不到关于STM的英文如此全面的文档,只有一些[像这个]https://www.st.com/resource/en/application_note/an4013-stm32-crossseries-timer-overview-stmicro electronics.pdf(在本文档中搜索“URS”)),需要编写代码像这样的东西
TIM1->CR1 |= TIM_CR1_URS;
在 UG
位设置上禁用中断生成。