STM32输出比较模式
搜索好久,各种文章良莠不齐,转载以下几篇
http://www.eeworld.com.cn/mcu/article_2016101130334.html(输出比较冻结模式)
http://www.eeworld.com.cn/mcu/article_2016101130330.html(输出比翻转模式)
http://www.eeworld.com.cn/mcu/article_2016101130334.html(输出比较主动模式)
http://www.dqzdhw.com/danpianji/1138.html(输出比较非主动模式)
就为了这个东西,搞了几个小时,故余虽愚,卒获有所闻。
再附上一篇大佬的神作:
http://blog.sina.com.cn/s/blog_3ba262a10101esd1.html
转自:https://www.cnblogs.com/sanshijvshi/p/10317574.html
HAL库代码我来补充:如下
pwm.c文件
/* *TIM3 init function * 定时器初始化 * 该定时器的 时钟频率源 为 72MHZ * 预分频设置为 0 则 计数时钟频率为 72MHZ/(PSC+1) =1mhz * 计数一次的时间 是 1/1000000= 1 us */ void MX_TIM3_Init(void) { TIM_ClockConfigTypeDef sClockSourceConfig = {0}; //时钟配置结构体 变量 TIM_MasterConfigTypeDef sMasterConfig = {0}; //定时器主配置结构 变量 TIM_OC_InitTypeDef sConfigOC = {0}; //输出比较结构体 变量 htim3.Instance = TIM3; //操作的是定时器3 htim3.Init.Prescaler = 71; //这样计数一次的时间就是 1个 us htim3.Init.CounterMode = TIM_COUNTERMODE_UP; //向上计数 htim3.Init.Period = 65535; //自动重装载设置值 htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; //关闭自动重装载 if (HAL_TIM_Base_Init(&htim3) != HAL_OK) //按照句柄 设置定时器的时基单元 { Error_Handler(); } sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; //选取内部时钟 if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK) { Error_Handler(); } if (HAL_TIM_OC_Init(&htim3) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK) { Error_Handler(); } //sConfigOC.OCMode = TIM_OCMODE_TOGGLE; //输出比较 输出翻转 sConfigOC.OCMode=TIM_OCMODE_TIMING; //因项目用到的功能是任意一个引脚,便可输出方波所以启用此模式 sConfigOC.Pulse = CCR1_Val; //比较的脉冲值 这样一配置完 运行后就进入中断程序 sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; //最初默认为 高电平 sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; // 此参数 在输出比较下无效 if (HAL_TIM_OC_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) //以此参数初始化通道1 { Error_Handler(); } sConfigOC.Pulse = CCR2_Val; if (HAL_TIM_OC_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2) != HAL_OK) //以此参数初始化通道2 { Error_Handler(); } sConfigOC.Pulse = CCR3_Val; if (HAL_TIM_OC_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_3) != HAL_OK) //以此参数初始化通道3 { Error_Handler(); } sConfigOC.Pulse = CCR4_Val; if (HAL_TIM_OC_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)//以此参数初始化通道4 { Error_Handler(); } HAL_TIM_MspPostInit(&htim3); //执行4个通道的 GPIO功能的初始化 HAL_TIM_OC_Start_IT(&htim3,TIM_CHANNEL_1); //开启定时器 开启中断 HAL_TIM_OC_Start_IT(&htim3,TIM_CHANNEL_2); HAL_TIM_OC_Start_IT(&htim3,TIM_CHANNEL_3); HAL_TIM_OC_Start_IT(&htim3,TIM_CHANNEL_4); } void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle) { if(tim_baseHandle->Instance==TIM3) { /* USER CODE BEGIN TIM3_MspInit 0 */ /* USER CODE END TIM3_MspInit 0 */ /* TIM3 clock enable */ __HAL_RCC_TIM3_CLK_ENABLE(); // 使能 定时器 3 的时钟 /* TIM3 interrupt Init */ HAL_NVIC_SetPriority(TIM3_IRQn, 1, 2); //设置中断优先级 HAL_NVIC_EnableIRQ(TIM3_IRQn); //使能定时器3 的全局中断 /* USER CODE BEGIN TIM3_MspInit 1 */ /* USER CODE END TIM3_MspInit 1 */ } } void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(timHandle->Instance==TIM3) { /* USER CODE BEGIN TIM3_MspPostInit 0 */ /* USER CODE END TIM3_MspPostInit 0 */ __HAL_RCC_GPIOA_CLK_ENABLE(); // 使能 GPIOA 端口的时钟 /**TIM3 GPIO Configuration PA6 ------> TIM3_CH1 PA7 ------> TIM3_CH2 PB0 ------> TIM3_CH3 PB1 ------> TIM3_CH4 */ #if 0 //用到输出翻转时用到 __HAL_RCC_GPIOB_CLK_ENABLE(); //使能 GPIOB 端口的时钟 GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; //开启复用功能 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; //处于高速的状态 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); #endif GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; //开启复用功能 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; //处于高速的状态 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USER CODE BEGIN TIM3_MspPostInit 1 */ /* USER CODE END TIM3_MspPostInit 1 */ } } void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle) { if(tim_baseHandle->Instance==TIM3) { /* USER CODE BEGIN TIM3_MspDeInit 0 */ /* USER CODE END TIM3_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_TIM3_CLK_DISABLE(); //关闭时钟 /* TIM3 interrupt Deinit */ HAL_NVIC_DisableIRQ(TIM3_IRQn); //关闭中断 /* USER CODE BEGIN TIM3_MspDeInit 1 */ /* USER CODE END TIM3_MspDeInit 1 */ } } //重写中断回调函数 void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim) { static u16 capture1 = 0; static u16 capture2 = 0; static u16 capture3 = 0; static u16 capture4 = 0; if(htim==(&htim3)) { if(__HAL_TIM_GET_IT_SOURCE(&htim3,TIM_IT_CC1)) { //得到通道1当前的计数值 capture1=__HAL_TIM_GET_COMPARE(&htim3,TIM_CHANNEL_1); __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_1,capture1+CCR1_Val); MIDA=~MIDA; __HAL_TIM_CLEAR_IT(&htim3,TIM_IT_CC1); } if(__HAL_TIM_GET_IT_SOURCE(&htim3,TIM_IT_CC2)) { //得到通道1当前的计数值 capture2=__HAL_TIM_GET_COMPARE(&htim3,TIM_CHANNEL_2); __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_2,capture2+CCR2_Val); MIDB=~MIDB; __HAL_TIM_CLEAR_IT(&htim3,TIM_IT_CC2); } if(__HAL_TIM_GET_IT_SOURCE(&htim3,TIM_IT_CC3)) { //得到通道1当前的计数值 capture3=__HAL_TIM_GET_COMPARE(&htim3,TIM_CHANNEL_3); __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_3,capture3+CCR3_Val); MIDC=~MIDC; __HAL_TIM_CLEAR_IT(&htim3,TIM_IT_CC3); } if(__HAL_TIM_GET_IT_SOURCE(&htim3,TIM_IT_CC4)) { //得到通道1当前的计数值 capture4=__HAL_TIM_GET_COMPARE(&htim3,TIM_CHANNEL_4); __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_4,capture4+CCR4_Val); MIDD=~MIDD; __HAL_TIM_CLEAR_IT(&htim3,TIM_IT_CC4); } } }
PWM.H文件如下:
#define KHZ2 250 #define KHZ3 167 #define KHZ4 125 #define KHZ5 100 #define KHZ10 50 PWM_EXT __IO uint16_t CCR1_Val ; PWM_EXT __IO uint16_t CCR2_Val ; PWM_EXT __IO uint16_t CCR3_Val ; PWM_EXT __IO uint16_t CCR4_Val ; #define MIDA PAout(4) #define MIDB PAout(5) #define MIDC PAout(6) #define MIDD PAout(7) PWM_EXT TIM_HandleTypeDef htim3; /*定时器句柄*/ PWM_EXT void MX_TIM3_Init(void); PWM_EXT void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);