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

时间:2019-04-23 18:01:21

标签: c

我对与STM32F446RE的计时器同步有些困惑。

我想使用1个定时器作为主机,使用2个定时器作为从机。主计时器(即TIM2)的周期为5秒,并同时启动其他两个计时器。

从属计时器具有自己的时间段(第一个从属设备的时间为4秒,第二个从属设备的时间最多为3秒)。第二个从属定时器(即TIM1)将产生一个单脉冲输出。两个从站均应运行1次并停止。仅当主计时器发送触发器时,才应再次激活它们。我想使用1.从站通过调用中断处理程序来适应第二个从站的周期,在该中断处理程序中,我将寄存器ARR和PSC和CCR1(用于一个脉冲)写入。

我试图用HAL做到这一点,但是它变得越来越混乱。有没有人知道如何通过编写寄存器而不是HAL来对此进行编码(小的代码片段会非常不错)?

我也看过了STM第6章的定时器手册,但是还没有开始工作。 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

非常感谢您的任何反馈!

亲切的问候, 托比

1 个答案:

答案 0 :(得分:0)

好的,第一部分完成了。

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 & TIM_DIER_CC1IE) == TIM_DIER_CC1IE) != RESET)
        {
            TIM3->SR = ~ TIM_FLAG_CC1;
            /* do something *
        }
    }
}

我很高兴收到有关此代码的任何反馈。

我刚刚注意到内部RC振荡器在我的测试环境中不是很准确。在手册DM00135183.pdf中的“ 6.2.2 HSI时钟”部分中,您可以了解有关精度以及如何调整HSI的信息。但是我认为,如果需要更精确的时序,最好使用外部晶体振荡器或陶瓷谐振器。

如果我做错了什么,或者我想做的事情无法按预期的方式进行,请也发表评论。