使用输出比较在低状态下创建脉冲,默认情况下必须为高电平+定时器在需要时不启用
此问题的产生源于my other question。我决定创建一个新的,因为这是我无法在任何地方找到的一件非常特别的事情。使用输出比较在低状态下创建脉冲,默认情况下必须为高电平+定时器在需要时不启用
在STM32F415中,我希望定时器的输出比较默认为高电平,而我告诉他的时钟周期数量低。我的目标是禁用一个计时器使用另一个计时器。在Reference Manual第620页中,上有一个示例,使用一个定时器启用另一个定时器。
就我而言,我希望TIM3控制TIM2和TIM4来控制TIM5。 TIM2和TIM5正在触发对DMA的DAC请求,并且它们工作正常。
这是我如何初始化TIM3(此功能被无限循环调用之前在主要):
void TIM3_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitBaseStructure;
TIM_DeInit(TIM3);
// TIM3 Periph clock enable
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
// Time base configuration
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = 0x46; //ARR = 70 (cycles low will be 0-63)
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
// TIM3 Output Compare configuration
TIM_OCStructInit(&TIM_OCInitBaseStructure);
TIM_OCInitBaseStructure.TIM_OCMode=TIM_OCMode_Active;
TIM_OCInitBaseStructure.TIM_Pulse=0x3C; //CCR
TIM_OCInitBaseStructure.TIM_OutputState=TIM_OutputState_Enable;
TIM_OC1Init(TIM3,&TIM_OCInitBaseStructure);
TIM3->CCMR1 &= 0xFFF7; // OC1PE: Output compare 1 preload disabled
TIM3->CCMR1 &= 0xFFFC; // CC1S[1:0]=00 CC1 channel is configured as output.
TIM3->CR1 |= 0x8;
TIM3->CR2 |= 0x40;
TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_OC1Ref); // MSM[2:0] = 100 OC1REF as TIM3 TRGO
TIM_Cmd(TIM3, ENABLE);
}
然后,在相应的DMA IRQ处理程序:
void DMA1_Stream6_IRQHandler(void) /* DAC2 */
{
if (DMA_GetITStatus(DMA1_Stream6,DMA_IT_HTIF6) == SET)
{
DMA_ClearITPendingBit(DMA1_Stream6,DMA_IT_HTIF6);
TIM3->CNT = 0x0; // Reset timer
TIM3->CR1 |= 0x1; // Enable timer
}
/* Some code for the Transfer Complete case */
}
在另一程序的一点我根据我希望从机定时器(TIM2或TIM5)被禁用的周期数更改CCR。
我的主要问题是它根本不起作用,而且在调试过程中,我发现TIM3和TIM4使指令看起来没有任何作用:启用位(TIMx CR1寄存器中的CEN)保持'0'而不是更改为'1'。 TIM2和TIM5初始化几乎完全相同,没有输出比较和门控输入配置到相应的定时器TRGO,并且可以正常启用和禁用它们。
我还没有发现任何条件或限制,我应该如何启用一个计时器,可能会影响我的程序,所以我有点失落了。
任何帮助将不胜感激,谢谢!
当OPM
位被置位时,CEN
位在计数器结束时立即复位为0,因此可能所有内容都工作正常,但由于发生得太快,所以看不到它。如果您想用调试器检查定时器,请在您的情况下设置APB冻结寄存器中的一些位,DBGMCU->APB1_FZ
。或者放慢速度,抓取所有内容,使用预分频器并在没有PLL的内部HSI时钟上运行内核。然而,我只能同意这里似乎是大多数人的观点,对计时器使用SPL或HAL只是浪费了各种资源(程序员和控制器)。使用寄存器产生更短,更简单的代码,并且它也非常便于携带。我已经在STM32L1上测试了这个,但我确定它也可以在F415上运行。
#define PRESCALER 0xFFFFU
#define TDELAY 8U
void gatedtimer(void) {
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN | RCC_APB1ENR_TIM3EN;
RCC->APB1RSTR = RCC_APB1RSTR_TIM2RST | RCC_APB1RSTR_TIM3RST;
RCC->APB1RSTR = 0;
TIM2->PSC = PRESCALER; // a BIG prescaler to slow things down to observable speed
TIM2->EGR = TIM_EGR_UG; // force prescaler update
TIM3->PSC = PRESCALER; // same prescaler to all timers
TIM3->EGR = TIM_EGR_UG; // force prescaler update
// of course you should omit the above in production code
TIM2->SMCR = (0b010U << TIM_SMCR_TS_Pos) // Trigger selection ITR2 = TIM3
| (0b101U << TIM_SMCR_SMS_Pos); // Gated Mode
TIM2->CR1 = TIM_CR1_CEN; // start the slave
TIM3->CR2 = (0b100U << TIM_CR2_MMS_Pos); // "100: Compare - OC1REF signal is used as trigger output (TRGO)"
TIM3->CCMR1 = (0b110U << TIM_CCMR1_OC1M_Pos); // "110: PWM mode 1 - In upcounting, channel 1 is active as long as TIMx_CNT < TIMx_CCR1 else inactive."
TIM3->CCR1 = TDELAY; // "some delay" is required for the timer hw to start a pulse
while(TIM2->CNT < 20U)
printf("TIM2->CNT=%lu TIM3->CNT=%lu\n", TIM2->CNT, TIM3->CNT); // slave runs normally
TIM3->ARR = TDELAY + 30; // set delay length
TIM3->CR1 = TIM_CR1_CEN | TIM_CR1_OPM; // start the master in one pulse mode
while(TIM3->CR1 & TIM_CR1_CEN) // CEN bit will be reset
printf("TIM2->CNT=%lu TIM3->CNT=%lu\n", TIM2->CNT, TIM3->CNT); // slave stops when master CNT reaches TDELAY
while(TIM2->CNT < 40)
printf("TIM2->CNT=%lu TIM3->CNT=%lu\n", TIM2->CNT, TIM3->CNT); // slave resumes counting
}
TL; DR,但:不要使用那个英国媒体报道STlib /“HAL”。它不会让你的代码更便于携带,但会增加不必要的开销,从而降低代码的可移植性。 – Olaf