基本配置:
TIM_HandleTypeDef htim8;
htim8.Instance = TIM8;
htim8.Init.Prescaler = ((1) - 1); // 预分频,可以降低时钟频率,这里设为0,不分频
htim8.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED1; //中心对齐模式1,递减计数的时候才会触发比较中断事件
htim8.Init.Period = ((PWM_PERIOD_CYCLES) / 2) ; // 168000000/18000/2
htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV2; // 84MHz用于生成死区
htim8.Init.RepetitionCounter = (REP_COUNTER); // 重复计数器1,两个脉冲中断一次
HAL_TIM_Base_Init(&htim8);
解释一下:
1、频率计算:
在中心对齐模式下,计数器从 0 开始计数到自动重载值( TIMx_ARR 寄存器的内容)-1,生成计数器上溢事件;然后从自动重载值开始向下计数到 1 并生成计数器下溢事件。之后从0 开始重新计数。
这里的ARR即为 htim8.Init.Period配置的168000000/18000/2。
所以生成波形的频率为f = 168M / (ARR)∗(PSC+1) = 18000 * 2 = 36kHz。
2、ClockDivision:用于死区时间配置
死区:控制电机的三个桥臂,每个桥臂上有两个MOSFET,这两个MOSFET不可以同时导通,否则会短路烧板子;又由于MOSFET的导通和关断需要时间,所以为避免同时导通,插入死区时间,先保证一个关断了,另一个再打开。
由手册可知:
CKD[1:0]:时钟分频 (Clock division)
此位域指示定时器时钟 (CK_INT) 频率与死区发生器以及数字滤波器( ETR、 TIx)所使用的
死区及采样时钟 (tDTS) 之间的分频比,
00: tDTS = tCK_INT
01: tDTS = 2 * tCK_INT
10: tDTS = 4 * tCK_INT
11:保留,不要设置成此值
CK_INT是用户选择的内部时钟,这个配置项在这里可用于计算死区时间,计算方法:
位 7:0 DTG[7:0]:配置死区发生器 (Dead-time generator setup)
此位域定义插入到互补输出之间的死区持续时间。 DT 与该持续时间相对应。
DTG[7:5]=0xx => DT=DTG[7:0]x tdtg,其中 tdtg=tDTS。
DTG[7:5]=10x => DT=(64+DTG[5:0])xtdtg,其中 Tdtg=2xtDTS。
DTG[7:5]=110 => DT=(32+DTG[4:0])xtdtg,其中 Tdtg=8xtDTS。
DTG[7:5]=111 => DT=(32+DTG[4:0])xtdtg,其中 Tdtg=16xtDTS。
示例:
sBreakDeadTimeConfig.DeadTime = ((168 * 200 / 1000) / 2);// 死区时间
则符合DTG[7:5]=0xx => DT=DTG[7:0]x tdtg,其中 tdtg=tDTS,由于上面配置时钟分频为TIM_CLOCKDIVISION_DIV2,所以tDTS = 2 * tCK_INT = 2 * 168,则
DT = DTG[7:0] * tdtg = 16 * 2 * (1/168000000) = 200ns。
主从模式配置:
sSlaveConfig.SlaveMode = TIM_SLAVEMODE_TRIGGER; // 触发模式––触发信号 TRGI 出现上升沿时启动计数器(但不复位)。只控制计数器的启动。
sSlaveConfig.InputTrigger = TIM_TS_ITR1; // 触发源 ITR1 链接到TIM2的TRGO,由定时器2触发该时钟开始计时
HAL_TIM_SlaveConfigSynchronization(&htim8, &sSlaveConfig);
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; // 默认值
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; // 主从模式 ×
HAL_TIMEx_MasterConfigSynchronization(&htim8, &sMasterConfig);
PWM输出通道配置:
sConfigOC.OCMode = TIM_OCMODE_PWM1; // PWM1模式,TIMx_CNT > TIMx_CCRx,参考信号 OCxRef 即为低电平,否则其为高电平
sConfigOC.Pulse = 0; //有效电平持续时间
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; // 输出极性
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH; // 互补通道输出极性
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; // 快速模式 ×
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; // 空闲状态 RESET
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;//互补通道空闲状态
HAL_TIM_PWM_ConfigChannel(&htim8, &sConfigOC, TIM_CHANNEL_1);
HAL_TIM_PWM_ConfigChannel(&htim8, &sConfigOC, TIM_CHANNEL_2);// CH2
HAL_TIM_PWM_ConfigChannel(&htim8, &sConfigOC, TIM_CHANNEL_3);// CH3
sConfigOC.OCMode = TIM_OCMODE_PWM2;// PWM2模式,跟PWM1相反
sConfigOC.Pulse = (((PWM_PERIOD_CYCLES) / 2) - (HTMIN));// 比较值,触发ADC采样的时刻点,这里减去HTMIN为死区时间 + 噪声时间 + 3个周期的采样时间 + 触发转换的时间
HAL_TIM_PWM_ConfigChannel(&htim8, &sConfigOC, TIM_CHANNEL_4);
刹车与死区配置:
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_ENABLE; // OSSR √
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_ENABLE; // OSSI √
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_1; // LOCK Level 1 对BDTR.DTG/BKE/BKP/AOE , CR2.OISx/OISxN 执行写保护
sBreakDeadTimeConfig.DeadTime = ((DEAD_TIME_COUNTS) / 2);// 死区时间
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE; // 刹车 ×
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_LOW;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;//AOE ×
HAL_TIMEx_ConfigBreakDeadTime(&htim8, &sBreakDeadTimeConfig);
OSSR:
这里使能了OSSR,其功能详见手册:
当OSSR使能:
当互补通道都使能,则两个端口按照配置正常输出PWM波。
当互补通道都禁用,则两个端口禁止输出。
当互补通道有一个使能,一个禁用,则使能的端口按配置输出PWM波(去掉死区),禁用端口输出的电平由CCxP或CCxN来决定,即为无效电平。
OSSI:
这里使能了OSSI,这个是在MOE位为0时生效的。
当互补通道都禁用,则两个端口禁止输出。
当互补通道都使能,或者互补通道有一个使能一个禁用,则两个端口输出的电平由CCxP或CCxN来决定,即为无效电平。