STM32F4一个主定时器触发两个从属时间

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STM32F4一个主定时器触发两个从属时间相关的知识,希望对你有一定的参考价值。

我对STM32F446RE的定时器同步感到有些困惑。

我想使用1个定时器作为主设备,使用两个定时器作为从设备。主定时器(即TIM2)具有5秒的周期并同时启动另外两个定时器。

从属计时器具有自己的周期(第一个从站的周期为4秒,第二个从站的周期为最长3秒)。第二从定时器(即TIM1)将产生单脉冲输出。两个奴隶都应跑1次并停下来。如果主计时器发送触发器,它们只应再次激活。我想使用1. slave来调整第二个从器件的周期,调用一个中断处理程序,我写入寄存器ARR和PSC以及CCR1(一个脉冲)。

我试图用HAL做到这一点,但它变得越来越混乱。有没有人有一个很好的想法如何编写这个(小代码片段将是非常好的)写寄存器而不是HAL?

我还在第6章看了STM的计时器烹饪书,但还没有让它工作。 https://www.st.com/content/ccc/resource/technical/document/application_note/group0/91/01/84/3f/7c/67/41/3f/DM00236305/files/DM00236305.pdf/jcr:content/translations/en.DM00236305.pdf

非常感谢您的任何反馈!

亲切的问候,托比

答案

第一部分完成了。

TIM2的配置: - 配置为主设备,周期为10秒。 - 使用TIM_TRGO_UPDATE作为从定时器的输出触发器。

我首先使用STM32CubeMX创建了计时器,然后检查了被调用的HAL函数。

static void Timer2_Init(){
    /* activate clock for TIM2 peripheral */
    __HAL_RCC_TIM2_CLK_ENABLE();
    /* Prescaler */
    TIM2->PSC = 44999; // bus is running with 90MHz
    /* set counter mode */
    TIM2->CR1 &= ~(TIM_CR1_DIR | TIM_CR1_CMS);
    TIM2->CR1 |= TIM_COUNTERMODE_UP;
    /* Auto-Reload Register */
    TIM2->ARR = 20000;
    /* Set Clock Division */
    TIM2->CR1 &= ~ TIM_CR1_CKD;
    TIM2->CR1 |= TIM_CLOCKDIVISION_DIV1;

    /* set Auto-Reload-Preload */
    //TIM2->CR1 |= (0 << 7);
    /* Update Event - if this timer is configured as Master with output TRGO_UPDATE
     * the slave timer TIM 1 will get a trigger and run one time
     *
     * This bit can be set by software, it is automatically cleared by hardware.
     * 0: No action
     * 1: Reinitialize the counter and generates an update of the registers. Note that the prescaler
     * counter is cleared too (anyway the prescaler ratio is not affected). For more see manual. */
    //TIM2->EGR = TIM_EGR_UG;

    /* Set Clock Source */
    TIM2->SMCR &= ~(TIM_SMCR_SMS | TIM_SMCR_TS | TIM_SMCR_ETF | TIM_SMCR_ETPS | TIM_SMCR_ECE | TIM_SMCR_ETP);

    /* Master Configuration */
    TIM2->CR2 &= ~TIM_CR2_MMS;
    TIM2->CR2 |= TIM_TRGO_UPDATE;
    TIM2->SMCR &= ~TIM_SMCR_MSM;
    TIM2->SMCR |= TIM_SMCR_MSM;

    TIM2->CR1 = TIM_CR1_CEN;
}

接下来TIM1的初始化: - 配置为主。 - 将ARR设置为5秒。 - 将CCR1设置为1秒的脉冲长度。

我再次使用STM32CubeMX创建代码,然后检查所有HAL函数的内容。

static void Timer1_Init(){
    /* activate clock for TIM1 peripheral */
    __HAL_RCC_TIM1_CLK_ENABLE();
    /* Edited Registers of HAL_TIM_Base_Init(&htim1) */
    /* Prescaler */
    TIM1->PSC = 17999; // bus is running with 180MHz
    /* set counter mode */
    TIM1->CR1 &= ~(TIM_CR1_DIR | TIM_CR1_CMS); 
    TIM1->CR1 |= TIM_COUNTERMODE_UP; 
    /* Auto-Reload-Register */
    TIM1->ARR = 49999; 
    TIM1->CR1 &= ~ TIM_CR1_CKD; 
    TIM1->CR1 |= TIM_CLOCKDIVISION_DIV1; 
    /* repetition counter if pulse should be displayed more than 1 time */
    TIM1->RCR = 0; 
    /* Auto-Reload Preload Enable */
    //TIM1->CR1 |=TIM_CR1_ARPE;
    /* update event */
    TIM1->EGR = TIM_EGR_UG; 


    /* Edited registers of HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) */
    TIM1->SMCR &= ~(TIM_SMCR_SMS | TIM_SMCR_TS | TIM_SMCR_ETF | TIM_SMCR_ETPS | TIM_SMCR_ECE | TIM_SMCR_ETP);


    /* One Pulse Mode: Edited registers of HAL_TIM_OnePulse_Init(&htim1, TIM_OPMODE_SINGLE) */
    //TIM1->CR1 &= ~TIM_CR1_OPM;
    TIM1->CR1 |= TIM_CR1_OPM; 


    /* Slave Mode configuration: edited registers of HAL_TIM_SlaveConfigSynchro(&htim1, &sSlaveConfig) */
    TIM1->SMCR &= ~TIM_SMCR_TS; 
    TIM1->SMCR |= TIM_TS_ITR1; 
    TIM1->SMCR &= ~TIM_SMCR_SMS; 
    TIM1->SMCR |= (TIM_SMCR_SMS_2 | TIM_SMCR_SMS_1); // = TIM_SLAVEMODE_TRIGGER -

//  TIM1->DIER &= ~TIM_DIER_TIE;
//  TIM1->DIER &= ~TIM_DIER_TDE;


    /* HAL_TIM_PWM_ConfigChannel: HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) */
    /* Disable the Channel 1: Reset the CC1E Bit */
//  TIM1->CCER &= ~TIM_CCER_CC1E;
    /* Reset the Output Compare Mode Bits */
    TIM1->CCMR1 &= ~TIM_CCMR1_OC1M; 
    TIM1->CCMR1 &= ~TIM_CCMR1_CC1S; 
    /* Select the Output Compare (OC) Mode 1 */
    TIM1->CCMR1 |= (TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1); // = TIM_OCMODE_PWM1 
    /* Reset and set the Output N Polarity level to LOW */
    TIM1->CCER &= ~TIM_CCER_CC1P; 
    TIM1->CCER |= TIM_CCER_CC1P; // = TIM_OCPOLARITY_LOW 
    /* Reset the Output N State */
//  TIM1->CCER &= ~TIM_CCER_CC1NP;
    //TIM1->CCER |= 0x00000000U;
    /* Reset the Output N State */
//  TIM1->CCER &= ~TIM_CCER_CC1NE;
    /* IS_TIM_BREAK_INSTANCE */
    /* Reset the Output Compare and Output Compare N IDLE State */
//  TIM1->CR2 &= ~TIM_CR2_OIS1;
//  TIM1->CR2 &= ~TIM_CR2_OIS1N;
    /* Set the Output Idle state */
    //TIM1->CR2 |= 0x00000000U;
    /* Set the Capture Compare Register: Pulse */
    TIM1->CCR1 = 40000; 
    /* Set the Preload enable bit for channel 1 */
    TIM1->CCMR1 |= TIM_CCMR1_OC1PE; 
    /*  Configure the Output Fast mode */
//  TIM1->CCMR1 &= ~TIM_CCMR1_OC1FE;
    //TIM1->CCMR1 |= 0x00000000U;

    /* Edited registers by HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1) */
    /* Enable the Capture compare channel */
    TIM1->CCER |= (1 << 0); // = TIM_CCER_CC1E 
    /* Enable the main output */
    TIM1->BDTR |= TIM_BDTR_MOE; 

    /* Initialize the GPIO Pin for output: HAL_TIM_MspPostInit(&htim1) */
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    __HAL_RCC_GPIOA_CLK_ENABLE();
    GPIO_InitStruct.Pin = GPIO_PIN_8;
    GPIO_InitStruct.Pin = GPIO_PIN_8;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* Enable Counter: will be automatically enabled with trigger event */
    //TIM1->CR1 = TIM_CR1_CEN; 
}

下一步是配置第二个从定时器(TIM3),它将编辑TIM1的寄存器。

static void Timer3_Init(){
    /* activate clock for TIM1 peripheral */
    __HAL_RCC_TIM3_CLK_ENABLE();
    /* Edited Registers of HAL_TIM_Base_Init(&htim1) */
    /* Prescaler */
    TIM3->PSC = 50000; //44999;
    /* set counter mode */
    TIM3->CR1 &= ~(TIM_CR1_DIR | TIM_CR1_CMS);
    TIM3->CR1 |= TIM_COUNTERMODE_UP;
    /* Auto-Reload-Register */
    TIM3->ARR = 11000;
    TIM3->CR1 &= ~ TIM_CR1_CKD;
    TIM3->CR1 |= TIM_CLOCKDIVISION_DIV1;
    /* update event */
    TIM3->EGR = TIM_EGR_UG;

    /* Edited registers of HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) */
    TIM3->SMCR &= ~(TIM_SMCR_SMS | TIM_SMCR_TS | TIM_SMCR_ETF | TIM_SMCR_ETPS | TIM_SMCR_ECE | TIM_SMCR_ETP);

    /* One Pulse Mode: Edited registers of HAL_TIM_OnePulse_Init(&htim1, TIM_OPMODE_SINGLE) */
    //TIM1->CR1 &= ~TIM_CR1_OPM;
    TIM3->CR1 |= TIM_CR1_OPM;

    /* Slave Mode configuration: edited registers of HAL_TIM_SlaveConfigSynchro(&htim1, &sSlaveConfig) */
    TIM3->SMCR &= ~TIM_SMCR_TS;
    TIM3->SMCR |= TIM_TS_ITR1;
    TIM3->SMCR &= ~TIM_SMCR_SMS;
    TIM3->SMCR |= (TIM_SMCR_SMS_2 | TIM_SMCR_SMS_1); // = TIM_SLAVEMODE_TRIGGER

    /* HAL_TIM_PWM_ConfigChannel: HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) */
    /* Disable the Channel 1: Reset the CC1E Bit */
    /* Reset the Output Compare Mode Bits */
    TIM3->CCMR1 &= ~TIM_CCMR1_OC1M;
    TIM3->CCMR1 &= ~TIM_CCMR1_CC1S;
    /* Select the Output Compare (OC) Mode 1 */
    TIM3->CCMR1 |= (TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1); // = TIM_OCMODE_PWM1
    /* Reset and set the Output N Polarity level to HIGH */
    TIM3->CCER &= ~TIM_CCER_CC1P; // = TIM_OCPOLARITY_HIGH
    /* Set the Capture Compare Register: Pulse */
    TIM3->CCR1 = 0;
    /* Set the Preload enable bit for channel 1 */
    //TIM3->CCMR1 |= TIM_CCMR1_OC1PE;

    HAL_NVIC_SetPriority(TIM3_IRQn, 0, 1);
    HAL_NVIC_EnableIRQ(TIM3_IRQn);
    TIM3->DIER = TIM_DIER_CC1IE; //DMA Interrupt Enable Register (DIER): Interrupt "Capture/Compare 1 interrupt enable"

    /* warning: setting this bit will cause the timer running continuously, but timer should only start with trigger,
     * so don't set the CEN bit - let the trigger do the job automatically */
    //TIM3->CR1 = TIM_CR1_CEN;
}

最后是TIM3的IRQ处理程序:

void TIM3_IRQHandler(void)
{
    if (((TIM3->SR & TIM_FLAG_CC1) == TIM_FLAG_CC1) != RESET)
    {
        if (((TIM3->DIER &

以上是关于STM32F4一个主定时器触发两个从属时间的主要内容,如果未能解决你的问题,请参考以下文章

STM32F4 PWM和中断用同一个定时器

无法在 STM32f4xx 上启用定时器中断

STM32F4 HAL库开发 -- RTC

STM32F4 HAL库开发 -- RTC

STM32F4 HAL库开发 -- RTC

STM32F4 定时器 - 预分频器或周期值必须除以二才能得到我期望的结果