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);