STM32 TIM PWM高阶操作:刹车及状态约束

刹车及状态约束是STM32 TIM PWM控制里面比较复杂的一部分,涉及到PWM波形产生前,中,后的管脚状态输出。

这里先引入两个描述,一个是“半高阻”,意思是STM32管脚输出高阻时,内部的上拉或者下拉设置仍然有效。一个是“全高阻”,意思是STM32管脚输出高阻时,内部上拉或者下拉也被断开,是完全的高阻态输出。

STM32 PWM 刹车特性

所谓刹车(Break, Shut-Down)是指在PWM信号输出过程中,接收到触发信号,停止PWM信号的输出。而PWM信号停止之前之后输出什么状态,则是需要明确设定,避免负载端出现异常。而刹车以及再出发也有相应的控制机制。

刹车实际上有快刹(Break,信号控制停止)和慢刹(Stop, 指令控制停止)两种方式,一般情况下慢刹也够用,所以快刹的详细介绍文章较少。这里会对慢刹和快刹都进行操作介绍。

以STM32F030K6T6芯片及STM32CUBEIDE开发环境为例,首先在TIM1配置一对互补PWM输出通道,设置为40KHz的PWM输出。

配置工作时钟为40MHz:
设置一对PWM互补输出:

设置为40KHz输出PWM:

STM32 PWM 慢刹机制

上述设置保存生成工程初始代码后,就可以在main函数里while循环前启动PWM,对于正通道CH的启动代码为:

HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);

而反通道CHN的启动代码为:

HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_1);

所以对于互补通道而言,正通道和反通道是各自启动,不是一个启动代码/指令实现正反通道同步启动。另外一方面,虽然正反通道可以不同时启动,但只要都启动了,就会按照配置时的输出电平相位关系输出。也就是说,后启动的通道并不是一定从一个脉冲的前沿电平开始输出,而是与先启动的通道从耦合着的相位电平输出。

慢刹车机制有两种,一种是实时代码停止PWM输出,此后PWM管脚进入半高阻态,如果没有设置内部上拉或下拉,则等同于进入全高阻态。如果设置了内部上拉或下拉,则由上拉电平决定PWM管脚电平。对于正通道CH的停止代码为:

HAL_TIM_PWM_Stop(&htim1,TIM_CHANNEL_1);

对于反通道CHN的停止代码为:

HAL_TIMEx_PWMN_Stop(&htim1,TIM_CHANNEL_1);

在没有内部上拉或下拉,并且外部无连接影响电平时,高阻输出的状态,对于万用表和示波器测的结果是0V状态。如果要重新进入PWM运行状态,只需要重新启动HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);和HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);即可。

另一种慢刹机制是实时代码关闭PWM模式,此后PWM管脚进入全高阻态,内部上拉或下拉无效。如果要重新进入PWM模式,需要重新初始化。
正通道和反通道的PWM模式关闭代码为:

   HAL_TIM_Base_DeInit(&htim1);

而当需要重新进入PWM模式,则需要初始化:

MX_TIM1_Init();

然后再使用HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);和HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);即可。

由上面介绍可知,再TIM1初始化PWM后,但没有输出PWM信号前,是半高阻态,如果设置了上拉或下拉,就会影响PWM信号输出前的默认电平状态。

STM32 PWM 快刹机制

快刹机制刹车信号的输入有三种: BRK, BRK_ARTH, BRK2, 对于具体的某一个TIM,能用于刹车输入的是上述三种的子集。如:


相关的刹车输入信号描述,可以参考官方的文档 Using STM32 device PWM shut-down features 。

这里主要基于BKIN–>BRK来描述PWM的刹车控制的机制和时序。

STM32 PWM BKIN快刹

首先,在PWM配置界面使能刹车输入:

这是总的刹车输入开关,一旦使能,自动会使能BRK输入:

实际上,这个时候还可以关闭BRK输入使能,而刹车输入开关不受影响,意味着虽然BRK输入关闭了,但是BRK_ARTH, BRK2刹车输入仍有效(当然也要先做相关输入配置):

这里需要采用BRK作为刹车输入,所以将其再使能:

刹车输入开关(Active-Break-Input)使能后, BKIN管脚就被征用了,不管后面设置是否使能BRK刹车输入。对于STM32F030K6T6, TIM1的BKIN管脚是PA6:
BRK Polarity是选择BRK的刹车有效电平,也就是选择BKIN管脚作为刹车输入的有效电平。BRK Polarity为High时,BKIN管脚收到上升沿电平后会产生PWM信号输出的刹车;BRK Polarity为Low时,BKIN管脚收到下降沿电平后会产生PWM信号输出的刹车;
PA5管脚靠近PA6管脚,将两个管脚短路帽短接,就可以通过PA5输出刹车信号给PA6刹车输入管脚,实现刹车的测试,将PA5管脚配置为输出:

在配置BRK Polarity为High时,用以下代码可以通过示波器测试刹车的功能:

/* USER CODE BEGIN Header */
/********************************************************************************* @file           : main.c* @brief          : Main program body******************************************************************************* @attention** Copyright (c) 2022 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************Written by Pegasus Yu in 2022*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes *//* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*/
TIM_HandleTypeDef htim1;/* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM1_Init(void);
/* USER CODE BEGIN PFP */
__IO float usDelayBase;
void PY_usDelayTest(void)
{__IO uint32_t firstms, secondms;__IO uint32_t counter = 0;firstms = HAL_GetTick()+1;secondms = firstms+1;while(uwTick!=firstms) ;while(uwTick!=secondms) counter++;usDelayBase = ((float)counter)/1000;
}void PY_Delay_us_t(uint32_t Delay)
{__IO uint32_t delayReg;__IO uint32_t usNum = (uint32_t)(Delay*usDelayBase);delayReg = 0;while(delayReg!=usNum) delayReg++;
}void PY_usDelayOptimize(void)
{__IO uint32_t firstms, secondms;__IO float coe = 1.0;firstms = HAL_GetTick();PY_Delay_us_t(1000000) ;secondms = HAL_GetTick();coe = ((float)1000)/(secondms-firstms);usDelayBase = coe*usDelayBase;
}void PY_Delay_us(uint32_t Delay)
{__IO uint32_t delayReg;__IO uint32_t msNum = Delay/1000;__IO uint32_t usNum = (uint32_t)((Delay%1000)*usDelayBase);if(msNum>0) HAL_Delay(msNum);delayReg = 0;while(delayReg!=usNum) delayReg++;
}/* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 *//* USER CODE END 0 *//*** @brief  The application entry point.* @retval int*/
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 */PY_usDelayTest();PY_usDelayOptimize();HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET); //no brakeHAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_1);PY_Delay_us(5000000);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET); //brake/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/** Initializes the RCC Oscillators according to the specified parameters* in the RCC_OscInitTypeDef structure.*/RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;RCC_OscInitStruct.HSIState = RCC_HSI_ON;RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL10;RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV2;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses clocks*/RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK){Error_Handler();}
}/*** @brief TIM1 Initialization Function* @param None* @retval None*/
static void MX_TIM1_Init(void)
{/* USER CODE BEGIN TIM1_Init 0 *//* USER CODE END TIM1_Init 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 = 3;htim1.Init.CounterMode = TIM_COUNTERMODE_UP;htim1.Init.Period = 249;htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;htim1.Init.RepetitionCounter = 0;htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;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 = 0;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();}sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;sBreakDeadTimeConfig.DeadTime = 0;sBreakDeadTimeConfig.BreakState = TIM_BREAK_ENABLE;sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;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);}/*** @brief GPIO Initialization Function* @param None* @retval None*/
static void MX_GPIO_Init(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};/* GPIO Ports Clock Enable */__HAL_RCC_GPIOA_CLK_ENABLE();/*Configure GPIO pin Output Level */HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);/*Configure GPIO pin : PA5 */GPIO_InitStruct.Pin = GPIO_PIN_5;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);}/* USER CODE BEGIN 4 *//* USER CODE END 4 *//*** @brief  This function is executed in case of error occurrence.* @retval None*/
void Error_Handler(void)
{/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state */__disable_irq();while (1){}/* USER CODE END Error_Handler_Debug */
}#ifdef  USE_FULL_ASSERT
/*** @brief  Reports the name of the source file and the source line number*         where the assert_param error has occurred.* @param  file: pointer to the source file name* @param  line: assert_param error line source number* @retval None*/
void assert_failed(uint8_t *file, uint32_t line)
{/* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

上述代码实现了驱动一组互补PWM输出5秒后,PA5输出刹车信号,PA6接收到刹车信号后,将PWM的输出刹车关闭。其中,延时函数PY_Delay_us()的原理参考 STM32 HAL us delay(微秒延时)的指令延时实现方式及优化 。

STM32 PWM BKIN快刹后恢复PWM输出

STM32 PWM BKIN快刹后恢复PWM输出有两种方式,和Automatic Output Status参数有关:

Automatic Output Status为Disable时,不能通过BRK刹车输入信号的电平反向恢复PWM输出,而需要重新初始化TIM和使能PWM输出。如下的代码对应刹车5秒后重新恢复TIM PWM输出,注意这里刹车后只使能PWM输出没有重新初始化TIM是无效的:

/* USER CODE BEGIN Header */
/********************************************************************************* @file           : main.c* @brief          : Main program body******************************************************************************* @attention** Copyright (c) 2022 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************Written by Pegasus Yu in 2022*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes *//* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*/
TIM_HandleTypeDef htim1;/* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM1_Init(void);
/* USER CODE BEGIN PFP */
float usDelayBase;
void PY_usDelayTest(void)
{uint32_t firstms, secondms;uint32_t counter = 0;firstms = HAL_GetTick()+1;secondms = firstms+1;while(uwTick!=firstms) ;while(uwTick!=secondms) counter++;usDelayBase = ((float)counter)/1000;
}void PY_Delay_us_t(uint32_t Delay)
{uint32_t delayReg;uint32_t usNum = (uint32_t)(Delay*usDelayBase);delayReg = 0;while(delayReg!=usNum) delayReg++;
}void PY_usDelayOptimize(void)
{uint32_t firstms, secondms;float coe = 1.0;firstms = HAL_GetTick();PY_Delay_us_t(1000000) ;secondms = HAL_GetTick();coe = ((float)1000)/(secondms-firstms);usDelayBase = coe*usDelayBase;
}void PY_Delay_us(uint32_t Delay)
{uint32_t delayReg;uint32_t msNum = Delay/1000;uint32_t usNum = (uint32_t)((Delay%1000)*usDelayBase);if(msNum>0) HAL_Delay(msNum);delayReg = 0;while(delayReg!=usNum) delayReg++;
}/* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 *//* USER CODE END 0 *//*** @brief  The application entry point.* @retval int*/
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 */PY_usDelayTest();PY_usDelayOptimize();HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);//no brakeHAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_1);PY_Delay_us(5000000);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);//brakePY_Delay_us(5000000);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);//no brakeMX_TIM1_Init();HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_1); //pwm output/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/** Initializes the RCC Oscillators according to the specified parameters* in the RCC_OscInitTypeDef structure.*/RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;RCC_OscInitStruct.HSIState = RCC_HSI_ON;RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL10;RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV2;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses clocks*/RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK){Error_Handler();}
}/*** @brief TIM1 Initialization Function* @param None* @retval None*/
static void MX_TIM1_Init(void)
{/* USER CODE BEGIN TIM1_Init 0 *//* USER CODE END TIM1_Init 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 = 3;htim1.Init.CounterMode = TIM_COUNTERMODE_UP;htim1.Init.Period = 249;htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;htim1.Init.RepetitionCounter = 0;htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;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 = 0;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();}sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;sBreakDeadTimeConfig.DeadTime = 0;sBreakDeadTimeConfig.BreakState = TIM_BREAK_ENABLE;sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;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);}/*** @brief GPIO Initialization Function* @param None* @retval None*/
static void MX_GPIO_Init(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};/* GPIO Ports Clock Enable */__HAL_RCC_GPIOA_CLK_ENABLE();/*Configure GPIO pin Output Level */HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);/*Configure GPIO pin : PA5 */GPIO_InitStruct.Pin = GPIO_PIN_5;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);}/* USER CODE BEGIN 4 *//* USER CODE END 4 *//*** @brief  This function is executed in case of error occurrence.* @retval None*/
void Error_Handler(void)
{/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state */__disable_irq();while (1){}/* USER CODE END Error_Handler_Debug */
}#ifdef  USE_FULL_ASSERT
/*** @brief  Reports the name of the source file and the source line number*         where the assert_param error has occurred.* @param  file: pointer to the source file name* @param  line: assert_param error line source number* @retval None*/
void assert_failed(uint8_t *file, uint32_t line)
{/* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

而当Automatic Output Status设置为Enable时,则BRK信号从刹车电平反向后,会自动恢复PWM信号的输出,与上面的方式效果一样,而减少了代码调用逻辑:

/* USER CODE BEGIN Header */
/********************************************************************************* @file           : main.c* @brief          : Main program body******************************************************************************* @attention** Copyright (c) 2022 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************Written by Pegasus Yu in 2022*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes *//* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*/
TIM_HandleTypeDef htim1;/* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM1_Init(void);
/* USER CODE BEGIN PFP */
float usDelayBase;
void PY_usDelayTest(void)
{uint32_t firstms, secondms;uint32_t counter = 0;firstms = HAL_GetTick()+1;secondms = firstms+1;while(uwTick!=firstms) ;while(uwTick!=secondms) counter++;usDelayBase = ((float)counter)/1000;
}void PY_Delay_us_t(uint32_t Delay)
{uint32_t delayReg;uint32_t usNum = (uint32_t)(Delay*usDelayBase);delayReg = 0;while(delayReg!=usNum) delayReg++;
}void PY_usDelayOptimize(void)
{uint32_t firstms, secondms;float coe = 1.0;firstms = HAL_GetTick();PY_Delay_us_t(1000000) ;secondms = HAL_GetTick();coe = ((float)1000)/(secondms-firstms);usDelayBase = coe*usDelayBase;
}void PY_Delay_us(uint32_t Delay)
{uint32_t delayReg;uint32_t msNum = Delay/1000;uint32_t usNum = (uint32_t)((Delay%1000)*usDelayBase);if(msNum>0) HAL_Delay(msNum);delayReg = 0;while(delayReg!=usNum) delayReg++;
}/* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 *//* USER CODE END 0 *//*** @brief  The application entry point.* @retval int*/
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 */PY_usDelayTest();PY_usDelayOptimize();HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);//no brakeHAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_1);PY_Delay_us(5000000);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);//brakePY_Delay_us(5000000);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);//no brake & PWM outut/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/** Initializes the RCC Oscillators according to the specified parameters* in the RCC_OscInitTypeDef structure.*/RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;RCC_OscInitStruct.HSIState = RCC_HSI_ON;RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL10;RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV2;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses clocks*/RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK){Error_Handler();}
}/*** @brief TIM1 Initialization Function* @param None* @retval None*/
static void MX_TIM1_Init(void)
{/* USER CODE BEGIN TIM1_Init 0 *//* USER CODE END TIM1_Init 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 = 3;htim1.Init.CounterMode = TIM_COUNTERMODE_UP;htim1.Init.Period = 249;htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;htim1.Init.RepetitionCounter = 0;htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;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 = 0;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();}sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;sBreakDeadTimeConfig.DeadTime = 0;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();}/* USER CODE BEGIN TIM1_Init 2 *//* USER CODE END TIM1_Init 2 */HAL_TIM_MspPostInit(&htim1);}/*** @brief GPIO Initialization Function* @param None* @retval None*/
static void MX_GPIO_Init(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};/* GPIO Ports Clock Enable */__HAL_RCC_GPIOA_CLK_ENABLE();/*Configure GPIO pin Output Level */HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);/*Configure GPIO pin : PA5 */GPIO_InitStruct.Pin = GPIO_PIN_5;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);}/* USER CODE BEGIN 4 *//* USER CODE END 4 *//*** @brief  This function is executed in case of error occurrence.* @retval None*/
void Error_Handler(void)
{/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state */__disable_irq();while (1){}/* USER CODE END Error_Handler_Debug */
}#ifdef  USE_FULL_ASSERT
/*** @brief  Reports the name of the source file and the source line number*         where the assert_param error has occurred.* @param  file: pointer to the source file name* @param  line: assert_param error line source number* @retval None*/
void assert_failed(uint8_t *file, uint32_t line)
{/* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

STM32 PWM BKIN快刹后PWM管脚输出状态

刹车后的默认管脚状态也是必要的设计要点。涉及到OSSI选项的控制。

注意Break And Dead Time Management里面的几项是独立的关系,譬如Automatic Output State设置成Enable或Disable不影响其余几项的实施。

OSSI使能后,CH IDLE STATE和CHN IDLE STATE才有效,用于设定刹车后的管脚状态输出。OSSI不使能,刹车后的管脚输出半高阻态,这时候CH IDLE STATE和CHN IDLE STATE的设置无任何效果。

STM32 PWM 互补输出的不补输出转态

STM32 PWM互补输出的不补输出转态和OSSR参数相关:

OSSR不使能,当互补输出正反两路的一路使能输出而另一路没有使能输出,没有使能输出的一路则输出半关闭高阻态,可以使用内部上下拉控制管脚状态。OSSR使能,当互补输出正反两路的一路使能输出而另一路没有使能输出,没有输出的一路则输出全关闭高阻态,内部上下拉无效。

STM32 PWM LOCK CONFIGURATION

因为PWM常用于控制功率输出负载,如果出现异常STM32程序跑飞,导致配置的寄存器混乱,进一步导致PWM输出异常,则会造成风险。Lock Configuration使能后,会形成保护机制,简而言之就是MCU启动后,代码配置Lock保护级别后,在下次重启前相关输出配置不能被修改。

有三个保护级别,Lock Level 3的保护级别最高。一般采用Lock Level 1即可,会在下次复位前冻结TIMx_BDTR 寄存器中的
DTG/BKE/BKP/AOE/BKF/BK2F/BK2E/BK2P 位,以及TIMx_CR2 寄存器中的OISx/OISxN位。

–End–

STM32 TIM PWM高阶操作:刹车及状态约束相关推荐

  1. STM32 TIM PWM中阶操作:互补PWM输出

    STM32 TIM PWM中阶操作详解:互补PWM输出 STM32 TIM可以输出管脚PWM信号适合多种场景使用,功能包括单线/非互补PWM输出,双线/互补PWM输出,以及死区时间和刹车控制等. 实际 ...

  2. 深度学习(17)TensorFlow高阶操作六: 高阶OP

    深度学习(17)TensorFlow高阶操作六: 高阶OP 1. Where(tensor) 2. where(cond, A, B) 3. 1-D scatter_nd 4. 2-D scatter ...

  3. 深度学习(16)TensorFlow高阶操作五: 张量限幅

    深度学习(16)TensorFlow高阶操作五: 张量限幅 1. clip_by_value 2. relu 3. clip_by_norm 4. Gradient clipping 5. 梯度爆炸实 ...

  4. 深度学习(15)TensorFlow高阶操作四: 填充与复制

    深度学习(15)TensorFlow高阶操作四: 填充与复制 1. Pad 2. 常用于Image Padding 3. tile 4. tile VS broadcast_to Outline pa ...

  5. 深度学习(14)TensorFlow高阶操作三: 张量排序

    深度学习(14)TensorFlow高阶操作三: 张量排序 一. Sort, argsort 1. 一维Tensor 2. 多维Tensor 二. Top_k 三. Top-k accuracy(To ...

  6. 深度学习(12)TensorFlow高阶操作一: 合并与分割

    深度学习(12)TensorFlow高阶操作一: 合并与分割 1. concat 2. stack: create new dim 3. Dim mismatch 4. unstuck 5. spli ...

  7. Tensorflow学习四---高阶操作

    Tensorflow学习四-高阶操作 Merge and split 1.tf.concat 拼接 a = tf.ones([4,32,8]) b = tf.ones([2,32,8]) print( ...

  8. PS高阶操作之字体特效

    PS高阶操作之字体特效 字体冰封效果 字体金属样式 字体冰封效果 新建一个白色的像素画布. 新建好画布后,用油漆桶刷成深蓝色. 打开通道,新建一个通道,选择文字工具. 调整文字大小和位置.在菜单栏中选 ...

  9. PS高阶操作之木质纹理

    PS高阶操作之木质纹理 制作木纹纹理 制作木纹相框 制作木纹纹理 新建画布,大小随意. 用油漆桶工具填充棕色,并解锁背景图层,菜单栏选择滤镜-杂色-添加杂色 数量-60 分布-高斯分布. 滤镜-模糊- ...

最新文章

  1. ACL 2019 | 基于知识增强的语言表示模型,多项NLP任务表现超越BERT(附论文解读)...
  2. Cocos2dx游戏开发系列笔记6:怎样让《萝莉快跑》的例子运行在vs和手机上
  3. JS提交表单页面不跳转、JS下载、动态创建from
  4. 浅析网络流量分析原理:如何把二进制“天书”变成“人话”
  5. IdHttpServer实现webservice
  6. Centos7+nginx1.12+mysql5.7+php7环境安装
  7. 基于Server-Sent Event的简单在线聊天室
  8. 洛谷-省选斗兽场-动态规划1
  9. 深度学习中的损失函数总结以及Center Loss函数笔记
  10. java项目经验案例_PLC与POE结合项目经验案例总结
  11. 51Nod 1131 - 覆盖数字的数量(分类讨论)
  12. junit测试mysql_使用Junit单元测试及操作MySQL数据库时出现错误及解决方法
  13. Tensorflow学习笔记 (用 tf.data 加载图片)
  14. EEPROM、FLASH、NOR FLASH、NAND FLASH 区别、关系总结
  15. 计算机辅助翻译在翻译实践中的应用,计算机辅助翻译在翻译实践中的应用
  16. pip国内镜像(清华大学镜像)
  17. java导出excel_Java使用poi组件导出Excel格式数据
  18. wordpress插件_2020年5个最佳WordPress电子商务插件比较
  19. printf中的%f
  20. 全球与中国射频仪表市场深度研究分析报告

热门文章

  1. 微信支付回调地址 http https问题
  2. 新浪乐居——走进用友软件园活动
  3. C练题笔记之:Leetcode-第 85 场双周赛---6157. 二进制字符串重新安排顺序需要的时间
  4. STM32单片机SPI通讯
  5. Linux 基础上机篇
  6. grafana mysql 时间段选择_mysql – 选择特定时间段内的所有可用项目
  7. RAW 264.7 小鼠单核巨噬细胞白血病细胞培养解决方案
  8. 24.零起点学算法22——华氏摄氏温度转换
  9. Java业务系统配置管理设计方案实现
  10. linux下测试网速