STM32G031 TIM 产生两路占空比可调,相位可调的PWM波(combined pwm)
1 把BLDC电机绕组当成蜂鸣器,产生蜂鸣音时,测得的驱动波形为 u,w上桥发出PWM时,v相下桥同时变高,其他任何时候,任何相都是低。
2 图3所示,PWM发出300ms,停顿300ms.
3 图4所示,u,w两相周期约290us,高电平时间10us, u,w两相相位差约10us,
本篇随便即来产生这样的波形。
4 采用组合PWM的方式:
Reference manual摘抄如下:
Combined PWM mode can be selected independently on two channels (one OCx output per
pair of CCR registers) by writing ‘1100’ (Combined PWM mode 1) or ‘1101’ (Combined PWM
mode 2) in the OCxM bits in the TIMx_CCMRx register.
When a given channel is used as combined PWM channel, its complementary channel must
be configured in the opposite PWM mode (for instance, one in Combined PWM mode 1 and
the other in Combined PWM mode 2).
本人对该模式的理解为:ch1引脚的高低状态由 OC1和OC2的组合方式决定,当OC1为PWM1模式时,OC2只能为Combined PWM2模式,
也就是说ch1引脚的输出 由 OC1的PWM1 和OC2的PWM2两者组合而成,可以是or,也可以是and. 如图2所示。
网上有人解释该模式为:
故事要从产生一组带有相移的 PWM波,并且动态改变PWM脉宽和周期说起;
基于对前面描述的PWM1、PWM2、Combined PWM1和Combined PWM2的理解,下面示例演示Combined PWM2的实现方式。
假设使用TIM2的通道1和通道2,首先将TIM2配置为向上计数,通道1配置为PWM1,CCRX=2,即计数值到2时,OC2REF无效,输出低电平;
假设使用TIM2的通道1和通道2,首先将TIM2配置为向上计数,通道1配置为PWM1,CCRX=2,即计数值到2时,OC2REF无效,输出低电平;
通道2配置为Combined PWM2,CCRX=1,此时通道2 OC2REF与PWM2相同,即计数值小于1时无效,输出低电平。
COmbined PWM2 的输出OC2REFC为 OC1REF 和OC2REF的与操作,如下图1所示:
COmbined PWM2 的输出OC2REFC为 OC1REF 和OC2REF的与操作,如下图1所示:
引脚最终的输出由OC2REFC和极性定义决定,当极性定义为高电平时,引脚输出则为OC2REFC的值,从而实现特殊的PWM波。
COmbined PWM1于Combined PWM2相似,其OC2REFC为OC1REF 和OC2REF的或操作。
注意:Combined PWM模式相邻通道为(CH1、CH2)和(CH3、Ch4),且第一个通道为PWM1时,第二通道必须为Combined PWM2,
反之,第一个通道为PWM2时,第二个通道必须为CombinedPWM1。

图1

图2

图3

图4
5 测试程序关键部分代码
int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_TIM1_Init(); /* USER CODE BEGIN 2 */ HAL_TIM_Base_Start(&htim1); HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1); // HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_2); HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_3); // HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_4); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ HAL_Delay(1000); HAL_TIM_PWM_Stop(&htim1,TIM_CHANNEL_1); HAL_TIM_PWM_Stop(&htim1,TIM_CHANNEL_3); HAL_Delay(1000); HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_3); /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ }
void MX_TIM1_Init(void) { /* USER CODE BEGIN TIM1_Init 0 */ /* USER CODE END TIM1_Init 0 */ TIM_ClockConfigTypeDef sClockSourceConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; TIM_OC_InitTypeDef sConfigOC = {0}; TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0}; /* USER CODE BEGIN TIM1_Init 1 */ /* USER CODE END TIM1_Init 1 */ htim1.Instance = TIM1; htim1.Init.Prescaler = 8-1; htim1.Init.CounterMode = TIM_COUNTERMODE_UP; htim1.Init.Period = 2327; htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim1.Init.RepetitionCounter = 0; htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; 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.MasterOutputTrigger2 = TIM_TRGO2_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK) { Error_Handler(); } sConfigOC.OCMode = TIM_OCMODE_COMBINED_PWM2; sConfigOC.Pulse = 50-1; 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.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 100-1; if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != HAL_OK) { Error_Handler(); } sConfigOC.OCMode = TIM_OCMODE_COMBINED_PWM2; sConfigOC.Pulse = 150-1; if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_3) != HAL_OK) { Error_Handler(); } sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 200-1; if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_4) != HAL_OK) { Error_Handler(); } sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE; sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE; sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF; sBreakDeadTimeConfig.DeadTime = 0; sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE; sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH; sBreakDeadTimeConfig.BreakFilter = 0; sBreakDeadTimeConfig.BreakAFMode = TIM_BREAK_AFMODE_INPUT; sBreakDeadTimeConfig.Break2State = TIM_BREAK2_DISABLE; sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_HIGH; sBreakDeadTimeConfig.Break2Filter = 0; sBreakDeadTimeConfig.Break2AFMode = TIM_BREAK_AFMODE_INPUT; sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE; if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN TIM1_Init 2 */ /* USER CODE END TIM1_Init 2 */ HAL_TIM_MspPostInit(&htim1); }
6 测试程序产生的波形如下图 所示,从波形可知,符合设计要求。


浙公网安备 33010602011771号