赞
踩
相比于通用定时器特性:
1)重复计数器
2)死区时间带可编程的互补输出
3)断路输入,用于将定时器的输出信号置于用户可选的安全配置中
1,配置定时器基础工作参数 HAL_TIM_PWM_Init()
2,定时器PWM输出MSP初始化 HAL_TIM_PWM_MspInit() 配置NVIC、CLOCK、GPIO等
3,配置PWM模式/比较值等 HAL_TIM_PWM_ConfigChannel()
4,设置优先级,使能中断 HAL_NVIC_SetPriority()、 HAL_NVIC_EnableIRQ()
5,使能定时器更新中断 __HAL_TIM_ENABLE_IT()
6,使能输出、主输出、计数器 HAL_TIM_PWM_Start()
7,编写中断服务函数 TIMx_IRQHandler()等 HAL_TIM_IRQHandler()
8,编写更新中断回调函数 HAL_TIM_PeriodElapsedCallback()
1.通过定时器8通道1实现指定个数PWM输出,用于控制LED1的亮灭
2,配置输出比较模式为:PWM模式1
通道输出极性为:高电平有效
占空比:50%
代码:
#include "./BSP/TIMER/atim.h" #include "./BSP/LED/led.h" //1.声明定时器句柄 TIM_HandleTypeDef g_timx_npwm_chy_handler; static uint32_t g_npwm_remain = 0; /** * @brief 高级定时器TIMX 通道Y PWM输出指定个数PWM 初始化函数(使用PWM模式1) * @note * 高级定时器的时钟来自APB2,而PCLK =168Mhz,我们设置PPRE2不分频 * 高级定时器的时钟 = 168Mhz * 定时器溢出时间计算方法: Tout = ((arr + 1) * (psc + 1)) / Ft us. * Ft = 定时器工作频率,单位:Mhz * * @param arr: 自动重装值 * @param psc: 预分频系数 * @retval 无 */ //2.配置通用定时器基本工作参数,PWM输出初始化 void atim_timx_npwm_chy_init(uint16_t arr, uint16_t psc) /* 通用定时器 PWM初始化函数 */ { //4.1定时器输出比较定时器结构体初始化 TIM_OC_InitTypeDef tim_oc_npwm_chy = {0}; //2.1通用定时器PWM输出初始化 g_timx_npwm_chy_handler.Instance = ATIM_TIMX_NPWM; //定时器x g_timx_npwm_chy_handler.Init.Period = arr; g_timx_npwm_chy_handler.Init.Prescaler = psc; g_timx_npwm_chy_handler.Init.CounterMode = TIM_COUNTERMODE_UP; g_timx_npwm_chy_handler.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; /* 使能TIMx_ARR进行缓冲 */ g_timx_npwm_chy_handler.Init.RepetitionCounter = 0; /* 重复计数器初始值 */ HAL_TIM_PWM_Init(&g_timx_npwm_chy_handler); //5.输出比较配置包,括PWM模式和比较值 tim_oc_npwm_chy.OCMode = TIM_OCMODE_PWM1; //输出比较模式 PWM1 tim_oc_npwm_chy.Pulse = arr/2; //设置比较值为自动加载值的一般,则占空比为50% tim_oc_npwm_chy.OCPolarity = TIM_OCPOLARITY_HIGH; //设置输出比较的极性为高 HAL_TIM_PWM_ConfigChannel(&g_timx_npwm_chy_handler,&tim_oc_npwm_chy,ATIM_TIMX_NPWM_CHY); //6,使能定时器更新中断 __HAL_TIM_ENABLE_IT(&g_timx_npwm_chy_handler,TIM_IT_UPDATE); //7,开启对应PWM通道使能输出并启动计时器 HAL_TIM_PWM_Start(&g_timx_npwm_chy_handler,ATIM_TIMX_NPWM_CHY); } //3.定时器PWM输出底层初始化,定时器时钟、引脚时钟使能,引脚复用配置 void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef * htm) { //3.1判断是否是TIM14 if(htm->Instance == ATIM_TIMX_NPWM) { GPIO_InitTypeDef gpio_init_struct; //3.3使能PF引脚口时钟 ATIM_TIMX_NPWM_CHY_GPIO_CLK_ENABLE(); //3.4使能定时器时钟 ATIM_TIMX_NPWM_CHY_CLK_ENABLE(); //3.2通道y的GPIO初始化 gpio_init_struct.Pin = ATIM_TIMX_NPWM_CHY_GPIO_PIN; /* 通道Y GPIO口 */ gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 复用推挽输出 */ gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */ gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */ gpio_init_struct.Alternate =ATIM_TIMX_NPWM_CHY_GPIO_AF; /* 端口复用到TIM8 */ HAL_GPIO_Init(ATIM_TIMX_NPWM_CHY_GPIO_PORT, &gpio_init_struct); //4 设置优先级、使能中断 HAL_NVIC_SetPriority(ATIM_TIMX_NPWM_IRQn,1,3); HAL_NVIC_EnableIRQ(ATIM_TIMX_NPWM_IRQn); } } /* 定时器8中断服务函数 */ void ATIM_TIMX_NPWM_IRQHandler(void) { HAL_TIM_IRQHandler(&g_timx_npwm_chy_handler); } /* 定时器更新中断回调函数 */ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim->Instance == ATIM_TIMX_NPWM) //如果是TIM8 { if(g_npwm_remain)//如果重复计数值大于0,则需要发送PWM波 { ///* 设置重复计数寄存器值为npwm-1, 即npwm个脉冲 */ ATIM_TIMX_NPWM->RCR = g_npwm_remain - 1; //通过软件更新事件,将RCR值缓冲到影子寄存器里面 HAL_TIM_GenerateEvent(&g_timx_npwm_chy_handler, TIM_EVENTSOURCE_UPDATE); //使能计数器 __HAL_TIM_ENABLE(&g_timx_npwm_chy_handler); //清零 g_npwm_remain = 0; } else { //关闭计数器 ATIM_TIMX_NPWM->CR1 &= ~(1 << 0); /* 关闭定时器TIMX,使用HAL Disable会清除PWM通道信息,此处不用 */ } } } /** * @brief 高级定时器TIMX NPWM设置PWM个数 * @param rcr: PWM的个数, 1~2^32次方个 * @retval 无 */ void atim_timx_npwm_chy_set(uint32_t npwm) { if(npwm == 0) return ; g_npwm_remain = npwm; //通过软件更新事件,将RCR值缓冲到影子寄存器里面 HAL_TIM_GenerateEvent(&g_timx_npwm_chy_handler, TIM_EVENTSOURCE_UPDATE); //使能计数器 __HAL_TIM_ENABLE(&g_timx_npwm_chy_handler); }
#ifndef __ATIM_H #define __ATIM_H #include "./SYSTEM/sys/sys.h" /******************************************************************************************/ /* 高级定时器 定义 */ /* TIMX 输出指定个数PWM 定义 * 这里输出的PWM通过PC6(TIM8_CH1)输出, 我们用杜邦线连接PC6和PF10, 然后在程序里面将PF10设置成浮空输入 * 就可以 看到TIM8_CH1控制LED1(GREEN)的亮灭, 亮灭一次表示一个PWM波 * 默认使用的是TIM8_CH1. * 注意: 通过修改这几个宏定义, 可以支持TIM1/TIM8定时器, 任意一个IO口输出指定个数的PWM */ #define ATIM_TIMX_NPWM_CHY_GPIO_PORT GPIOC #define ATIM_TIMX_NPWM_CHY_GPIO_PIN GPIO_PIN_6 #define ATIM_TIMX_NPWM_CHY_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOC_CLK_ENABLE(); }while(0) /* PC口时钟使能 */ #define ATIM_TIMX_NPWM_CHY_GPIO_AF GPIO_AF3_TIM8 #define ATIM_TIMX_NPWM TIM8 #define ATIM_TIMX_NPWM_IRQn TIM8_UP_TIM13_IRQn #define ATIM_TIMX_NPWM_IRQHandler TIM8_UP_TIM13_IRQHandler #define ATIM_TIMX_NPWM_CHY TIM_CHANNEL_1 /* 通道Y, 1<= Y <=4 */ #define ATIM_TIMX_NPWM_CHY_CCRX TIM8->CCR1 /* 通道Y的输出比较寄存器 */ #define ATIM_TIMX_NPWM_CHY_CLK_ENABLE() do{ __HAL_RCC_TIM8_CLK_ENABLE(); }while(0) /* TIM8 时钟使能 */ void atim_timx_npwm_chy_init(uint16_t arr, uint16_t psc); /* 高级定时器 输出指定个数PWM初始化函数 */ void atim_timx_npwm_chy_set(uint32_t npwm); /* 高级定时器 设置输出PWM的个数 */ #endif
#include "./SYSTEM/sys/sys.h" #include "./SYSTEM/usart/usart.h" #include "./SYSTEM/delay/delay.h" #include "./BSP/LED/led.h" #include "./BSP/KEY/key.h" #include "./BSP/TIMER/atim.h" int main(void) { uint8_t key = 0; uint8_t t = 0; GPIO_InitTypeDef gpio_init_struct; HAL_Init(); /* 初始化HAL库 */ sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */ delay_init(168); /* 延时初始化 */ usart_init(115200); /* 串口初始化为115200 */ led_init(); /* 初始化LED */ key_init(); /* 初始化按键 */ /* 将 LED1 引脚设置为输入模式, 避免和PC6冲突 */ gpio_init_struct.Pin = LED1_GPIO_PIN; /* LED1引脚 */ gpio_init_struct.Mode = GPIO_MODE_INPUT; /* 设置为输入 */ gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */ gpio_init_struct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; /* 高速模式 */ HAL_GPIO_Init(LED1_GPIO_PORT, &gpio_init_struct); /* 初始化LED1引脚 */ atim_timx_npwm_chy_init(10000 - 1, 8400 - 1); /* 20Khz的计数频率,2Hz的PWM频率. */ ATIM_TIMX_NPWM_CHY_CCRX = 5000; /* 设置PWM占空比,50%,这样可以控制每一个PWM周期,LED1(GREEN) * 有一半时间是亮的,一半时间是灭的,LED1亮灭一次,表示一个PWM波 */ atim_timx_npwm_chy_set(5); /* 输出5个PWM波(控制LED1(GREEN)闪烁5次) */ while (1) { key = key_scan(0); if (key == KEY0_PRES) /* KEY0按下 */ { atim_timx_npwm_chy_set(5); /* 输出5个PWM波(控制TIM8_CH1, 即PC6输出5个脉冲) */ } t++; delay_ms(10); if (t > 50) /* 控制LED0闪烁, 提示程序运行状态 */ { t = 0; LED0_TOGGLE(); } } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。