芯片为STM32F407ZG,使用的是高级定时器TIM1的PWM互补PWM输出。
效果:
函数
总体的:(通道0~3分别是CH一、CH1N、CH二、CH2N。)
细节:
测试
CH1和CH1N的死区时间是0.375us(公式算出来应该是公式0.3us左右,跟逻辑分析仪的采样频率有关系)
CH1和CH二、CH1N和CH2N是同步的,之前作H桥的话就须要这种吧(对角同时导通),有相位差的后面再研究。
spa
STM32CubeMX配置:
main函数
调试
/* USER CODE BEGIN 2 */ /****普通定时器***/ HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1); /****高级定时器互补输出***/ HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_2); HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_1); HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_2); /****寄存器方法修改比较寄存器的值,ARR的值cube配置为1000***/ TIM1->CCR1=249; TIM1->CCR2=249; /* USER CODE END 2 */
说明:
代码中普通定时器只是为了测试!
高级定时器与普通定时器用法有微笑区别,网上查资料老是误导,不少教程都提到要用HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_1)这一句,可是只有这一句CH1N会有输出,CH1就没了,走了很多弯路。
code
细看高级定时器的函数名,一个是PWM、一个是PWMN,而HAL_TIMEx_PWMN_Start与HAL_TIM_PWM_Start相比多了一个Ex,所在的.c文件也不相同。猜测带Ex的多是扩展功能吧blog
再来看看死区时间计算吧:
cubemx生成的代码以下:
教程
void MX_TIM1_Init(void) { TIM_ClockConfigTypeDef sClockSourceConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; TIM_OC_InitTypeDef sConfigOC = {0}; TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0}; htim1.Instance = TIM1; htim1.Init.Prescaler = 167; htim1.Init.CounterMode = TIM_COUNTERMODE_UP; htim1.Init.Period = 999; htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim1.Init.RepetitionCounter = 0; htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; if (HAL_TIM_Base_Init(&htim1) != HAL_OK) { Error_Handler(); } sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK) { Error_Handler(); } if (HAL_TIM_PWM_Init(&htim1) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK) { Error_Handler(); } sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 99; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET; if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) { Error_Handler(); } sConfigOC.Pulse = 199; if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != HAL_OK) { Error_Handler(); } sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_ENABLE; sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_ENABLE; sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF; sBreakDeadTimeConfig.DeadTime = 50; sBreakDeadTimeConfig.BreakState = TIM_BREAK_ENABLE; sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH; sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_ENABLE; if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK) { Error_Handler(); } HAL_TIM_MspPostInit(&htim1); }
sBreakDeadTimeConfig.DeadTime = 50;这句就是死区时间了,怎么算,参考STM32F4xx中文参考手册.pdf
DeadTime 是直接写入DTG[7:0],显然,当DeadTime <128时,最高位都是0,按照最上面的那条公式算就行了,DT=50Tdtg,其中,Tdtg=tDTS=1/164Mhz(tim1接在高速时钟APB2),算出来就是DT=501/164M=0.3048us了
图片
我的调试心得,感谢点赞,更多问题交流,+Q:cqkz52@qq.com同步