VESC 电机定时器TIMER PWM初始化
static void timer_reinit(int f_zv) {
utils_sys_lock_cnt();
/* 定时器恢复初始化 */
TIM_DeInit(TIM1);
TIM_DeInit(TIM8);
TIM_DeInit(TIM2);
/* 定时器基础 比较输出 高级定时器 结构体
stmf4 高级定时器结构体只适用定时器1和8
this structure is used only with TIM1 and TIM8.
*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
/* 清空计数器 */
TIM1->CNT = 0;
TIM2->CNT = 0;
TIM8->CNT = 0;
/* 初始化时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);
/*
分频 0
计数模式 中央对齐模式1
重载值 系统时钟/频率
时钟分频 这个分频主要用于死区和过滤时钟
重载值
*/
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned1;
TIM_TimeBaseStructure.TIM_Period = (SYSTEM_CORE_CLOCK / f_zv);
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
/* 初始化定时器结构体 */
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure);
/* 输出模式pwm1 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
/* 开始oc输出到对应引脚 */
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
/* 互补输出使能,互补通道完全反方向 */
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
/* 自动重载值 */
TIM_OCInitStructure.TIM_Pulse = TIM1->ARR / 2;
/* 输出极性,比较匹配之后输出口输出的极性 */
#ifndef INVERTED_TOP_DRIVER_INPUT
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; // gpio high = top fets on
#else
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
#endif
/* 空闲状态 */
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
/* 互补通道,输出极性,比较匹配之后输出口输出的极性 */
#ifndef INVERTED_BOTTOM_DRIVER_INPUT
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; // gpio high = bottom fets on
#else
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;
#endif
/* 互补通道空闲状态 */
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set;
/* 初始化定时器通道 */
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_OC2Init(TIM1, &TIM_OCInitStructure);
TIM_OC3Init(TIM1, &TIM_OCInitStructure);
TIM_OC4Init(TIM1, &TIM_OCInitStructure);
/* 使能预装载寄存器 */
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);
TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);
TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable);
/* 初始化定时器通道 */
TIM_OC1Init(TIM8, &TIM_OCInitStructure);
TIM_OC2Init(TIM8, &TIM_OCInitStructure);
TIM_OC3Init(TIM8, &TIM_OCInitStructure);
TIM_OC4Init(TIM8, &TIM_OCInitStructure);
/* 使能预装载寄存器 */
TIM_OC1PreloadConfig(TIM8, TIM_OCPreload_Enable);
TIM_OC2PreloadConfig(TIM8, TIM_OCPreload_Enable);
TIM_OC3PreloadConfig(TIM8, TIM_OCPreload_Enable);
TIM_OC4PreloadConfig(TIM8, TIM_OCPreload_Enable);
// Automatic Output enable, Break, dead time and lock configuration
/* 运行模式下的关闭状态选择 */
TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
/* 空闲模式下的关闭状态选择 */
TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
/* 作用: 止意外的修改.桥上的意外信号可能因起全桥短路要烧芯片的.
锁定级别配置,锁定关闭,寄存器无保护 */
TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_OFF;
/* 死区作用: 避免关闭前一个设备和打开后一个设备时因为开关速度的问题出现同时开启状态而增加负荷的情况,避免mos同时打开造成短路损坏
配置死区发生器,定义死区持续时间,可选设置范围为0x0至0xFF */
TIM_BDTRInitStructure.TIM_DeadTime = conf_general_calculate_deadtime(HW_DEAD_TIME_NSEC, SYSTEM_CORE_CLOCK);
/* 自动输出使能 */
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Disable;
#ifdef HW_USE_BRK
/* 用于快速硬件保护 软件将捕获BRK标志来报告故障代码*/
// Enable BRK function. Hardware will asynchronously stop any PWM activity upon an
// external fault signal. PWM outputs remain disabled until MCU is reset.
// software will catch the BRK flag to report the fault code
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable;
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_Low;
#else
/* 断路使能 */
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable;
/* 断路极性 */
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;
#endif
/* 使能配置 */
TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);
/* 开启互补通道输出 */
TIM_CCPreloadControl(TIM1, ENABLE);
/* 允许或禁止在定时器工作时向ARR的缓冲器中写入新值,以便在更新事件发生时载入覆盖以前的值 */
TIM_ARRPreloadConfig(TIM1, ENABLE);
/* 初始化结构体,使能定时器配置 */
TIM_BDTRConfig(TIM8, &TIM_BDTRInitStructure);
TIM_CCPreloadControl(TIM8, ENABLE);
TIM_ARRPreloadConfig(TIM8, ENABLE);
/* 初始化定时器2时钟 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
/* 分频 */
TIM_TimeBaseStructure.TIM_Prescaler = 0;
/* 计数模式 */
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
/* 定时器周期 */
TIM_TimeBaseStructure.TIM_Period = 0xFFFF;
/* 用于死区或者滤波分频 */
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
/* 重载值 */
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
/* 定时器模式 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
/* 互补通道 */
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
/* 占空比 */
TIM_OCInitStructure.TIM_Pulse = 250;
/* 设置极性 */
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
/* 反向设置极性 */
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
/* 设置空闲极性 */
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
/* 设置反向空闲极性 */
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set;
/* 设置初始化三个通道 */
TIM_OC1Init(TIM2, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);
TIM_OC2Init(TIM2, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);
TIM_OC3Init(TIM2, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM2, ENABLE);
TIM_CCPreloadControl(TIM2, ENABLE);
// PWM outputs have to be enabled in order to trigger ADC on CCx
TIM_CtrlPWMOutputs(TIM2, ENABLE);
#if defined HW_HAS_DUAL_MOTORS || defined HW_HAS_DUAL_PARALLEL
// See: STM32F4 Timer Internal Trigger Connection - IAmAProgrammer - 博客园
TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_Enable);
/* 主从模式 */
TIM_SelectMasterSlaveMode(TIM1, TIM_MasterSlaveMode_Enable);
/* 选择输入触发源定时器1 */
TIM_SelectInputTrigger(TIM8, TIM_TS_ITR0);
/* 触发 */
TIM_SelectSlaveMode(TIM8, TIM_SlaveMode_Trigger);
TIM_SelectOutputTrigger(TIM8, TIM_TRGOSource_Enable);
/* 更新输出触发 */
TIM_SelectOutputTrigger(TIM8, TIM_TRGOSource_Update);
/* 选择定时器8触发 */
TIM_SelectInputTrigger(TIM2, TIM_TS_ITR1);
/* 复位 */
TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset);
#else
/* 选择定时器1成为更新信号
每次计时器一更新那么TRGO这个信号就会变为有效信号、就能被其他需要这个信号的外设所识别,如果不指定触发源的话就是一个无效信号气的外设无法识别 */
TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_Update);
TIM_SelectMasterSlaveMode(TIM1, TIM_MasterSlaveMode_Enable);
/* 定时器1触发定时器2 */
TIM_SelectInputTrigger(TIM2, TIM_TS_ITR0);
/* 只要遇到上升沿,定时器2就会计数清零 */
TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset);
#endif
#ifdef HW_HAS_DUAL_MOTORS
TIM8->CNT = TIM1->ARR;
#else
TIM8->CNT = 0;
#endif
TIM1->CNT = 0;
/* 使能定时器 */
TIM_Cmd(TIM1, ENABLE);
TIM_Cmd(TIM2, ENABLE);
// Prevent all low side FETs from switching on
stop_pwm_hw((motor_all_state_t*)&m_motor_1);
#ifdef HW_HAS_DUAL_MOTORS
stop_pwm_hw((motor_all_state_t*)&m_motor_2);
#endif
/* 输出pwm */
TIM_CtrlPWMOutputs(TIM1, ENABLE);
TIM_CtrlPWMOutputs(TIM8, ENABLE);
TIMER_UPDATE_SAMP(MCPWM_FOC_CURRENT_SAMP_OFFSET);
// Enable CC2 interrupt, which will be fired in V0 and V7
TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE);
utils_sys_unlock_cnt();
/* 开启定时器2中断 */
nvicEnableVector(TIM2_IRQn, 6);
}