测试以STM32G4系列的B-G474E-DPOW1为例,基础知识详见《基于STM32H7x3系列对定时器双向断路输入Bidirectional break inputs的理解》
测试描述
1.适用于STM32G474RETx Devices;
2.系统时钟设为170MHz,TIM1输入时钟选择APB2 clock (PCLK2),即TIM1CLK = HCLK = SystemCoreClock;
3.TIM1的计数频率设为85 MHz,即Prescaler = (TIM1CLK / TIM1 counter clock) – 1,Prescaler = ((SystemCoreClock) /85 MHz) – 1;
4.TIM1的输出频率设为85 KHz,即ARR = (TIM1 counter clock / TIM1 output clock) – 1=999;
5.设置TIM1通道占空比分别为:TIM1 Channel1 duty cycle = (TIM1_CCR1/ TIM1_ARR + 1)* 100 = 50%,TIM1 Channel2 duty cycle = (TIM1_CCR2/ TIM1_ARR + 1)* 100 = 37.5%,TIM1 Channel3 duty cycle = (TIM1_CCR3/ TIM1_ARR + 1)* 100 = 25%;
6.设置break触发源为TIM_BREAKINPUTSOURCE_COMP1和TIM_BREAKINPUTSOURCE_BKIN;
7.设置BKINP位为“1”,BKP位为“1”;
测试细节
设置break双向管脚:
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* htim_pwm)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(htim_pwm->Instance==TIM1)
{
/* USER CODE BEGIN TIM1_MspInit 0 */
/* USER CODE END TIM1_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_TIM1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**TIM1 GPIO Configuration
PA6 ------> TIM1_BKIN
*/
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF6_TIM1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN TIM1_MspInit 1 */
/* USER CODE END TIM1_MspInit 1 */
}
}
设置PWM输出管脚:
void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(htim->Instance==TIM1)
{
/* USER CODE BEGIN TIM1_MspPostInit 0 */
/* USER CODE END TIM1_MspPostInit 0 */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**TIM1 GPIO Configuration
PB13 ------> TIM1_CH1N
PB15 ------> TIM1_CH3N
PA8 ------> TIM1_CH1
PA9 ------> TIM1_CH2
PA10 ------> TIM1_CH3
PB0 ------> TIM1_CH2N
*/
GPIO_InitStruct.Pin = GPIO_PIN_13 | GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF6_TIM1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_TIM1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF6_TIM1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN TIM1_MspPostInit 1 */
/* USER CODE END TIM1_MspPostInit 1 */
}
}
设置比较器输出管脚:
void HAL_COMP_MspInit(COMP_HandleTypeDef* hcomp)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(hcomp->Instance==COMP1)
{
/* USER CODE BEGIN COMP1_MspInit 0 */
/* USER CODE END COMP1_MspInit 0 */
__HAL_RCC_GPIOB_CLK_ENABLE();
/**COMP1 GPIO Configuration
PB1 ------> COMP1_INP
*/
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USER CODE BEGIN COMP1_MspInit 1 */
/* USER CODE END COMP1_MspInit 1 */
}
}
配置break输入源:
sBreakInputConfig.Source = TIM_BREAKINPUTSOURCE_COMP1;
sBreakInputConfig.Enable = TIM_BREAKINPUTSOURCE_ENABLE;
sBreakInputConfig.Polarity = TIM_BREAKINPUTSOURCE_POLARITY_LOW;
if (HAL_TIMEx_ConfigBreakInput(&htim1, TIM_BREAKINPUT_BRK, &sBreakInputConfig) != HAL_OK)
{
Error_Handler();
}
sBreakInputConfig.Source = TIM_BREAKINPUTSOURCE_BKIN;
sBreakInputConfig.Enable = TIM_BREAKINPUTSOURCE_ENABLE;
sBreakInputConfig.Polarity = TIM_BREAKINPUTSOURCE_POLARITY_LOW;
if (HAL_TIMEx_ConfigBreakInput(&htim1, TIM_BREAKINPUT_BRK, &sBreakInputConfig) != HAL_OK)
{
Error_Handler();
}
配置死区及break双向IO:
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_ENABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_ENABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
sBreakDeadTimeConfig.DeadTime = 100;
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.BreakFilter = 0;
sBreakDeadTimeConfig.BreakAFMode = TIM_BREAK_AFMODE_BIDIRECTIONAL;
sBreakDeadTimeConfig.Break2State = TIM_BREAK2_DISABLE;
sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_HIGH;
sBreakDeadTimeConfig.Break2Filter = 0;
sBreakDeadTimeConfig.Break2AFMode = TIM_BREAK_AFMODE_INPUT;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_ENABLE;
if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
{
Error_Handler();
}
主函数:
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM1_Init();
MX_COMP1_Init();
/* Start COMP1 */
if(HAL_COMP_Start(&hcomp1) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}
/* Start channel 1 */
if (HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1) != HAL_OK)
{
/* PWM Generation Error */
Error_Handler();
}
/* Start channel 1N */
if(HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1) != HAL_OK)
{
/* Starting Error */
Error_Handler();
}
/* Start channel 2 */
if (HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2) != HAL_OK)
{
/* PWM Generation Error */
Error_Handler();
}
/* Start channel 2N */
if(HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_2) != HAL_OK)
{
/* Starting Error */
Error_Handler();
}
/* Start channel 3 */
if (HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3) != HAL_OK)
{
/* PWM generation Error */
Error_Handler();
}
/* Start channel 3N */
if(HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_3) != HAL_OK)
{
/* Starting Error */
Error_Handler();
}
/* Enable TIM1 BREAK */
MODIFY_REG(htim1.Instance->BDTR, TIM_BDTR_BKE, TIM_BREAK_ENABLE);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1) { }
}
测试过程与现象
Channel0~5分别为TIM1CH0,TIM1CH0N,TIM1CH1,TIM1CH1N,TIM1CH2,TIM1CH2N;Channel7为break双向IO;
1.COMP1引脚接低,正常输出6路互补通道;
2.COMP1引脚接高电平或将比较输出极性转变,定时器进入break状态,双向IO输出低电平;
3.将BKDSRM位置高,请求释放输出控制,等待所有系统断路请求消失,等待BKDSRM (BK2DSRM)位硬件清零。
4. COMP1引脚接低电平或将比较输出极性转变,定时器进入输出状态。