首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >STM32F4一个主定时器触发两个从时间

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

Stack Overflow用户
提问于 2019-04-24 02:01:21
回答 1查看 3.7K关注 0票数 4

我对STM32F446RE的定时器同步有点困惑。

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

从站定时器有自己的周期(第一个从站的周期为4秒,第二个从站的最大周期为3秒)。第二个从定时器(即TIM1)将产生一个单脉冲输出。两个从机都应该运行一次,然后停止。只有在主定时器发送触发器的情况下,它们才会再次激活。我想使用1. slave来调整第二个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

非常感谢您的反馈!

亲切的问候,托比

EN

回答 1

Stack Overflow用户

发布于 2019-04-25 19:50:11

好了,第一部分已经完成了。

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

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

代码语言:javascript
复制
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秒。-设置脉冲长度为1秒的CCR1。

同样,我首先使用STM32CubeMX创建代码,然后检查所有HAL函数的内容。

代码语言:javascript
复制
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的寄存器。

代码语言:javascript
复制
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处理程序:

代码语言:javascript
复制
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的信息。但我认为,如果你想要更精确的计时,使用外部晶体振荡器或陶瓷谐振器可能会更好。

如果我做错了什么,或者我想做的事情不能以预期的方式工作,也请留下评论。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55816965

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档