#include "global.h" #include "hw_pwm.h" typedef struct { TIM_TypeDef *base; //对象实体 int unit_in_hz; //1秒多少hz uint16_t ch; //通道选择 uint16_t irqn; //中断源 } hw_pwm_t; typedef struct { GPIO_TypeDef *pulse_port; //端口 uint16_t pulse_pin; //引脚 uint32_t remap; //复用功能位置 GPIO_TypeDef *dir_port; //方向功能端口 uint16_t dir_pin; //方向功能引脚 GPIO_TypeDef *en_port; //使能功能端口 uint16_t en_pin; //使能功能引脚 GPIO_TypeDef *alr_port; //报警功能端口 uint16_t alr_pin; //报警功能引脚 GPIO_TypeDef *clr_port; //报警清除功能端口 uint16_t clr_pin; //报警清除功能引脚 GPIO_TypeDef *tmode_port; //模式切换端口 uint16_t tmode_pin; //模式切换引脚 GPIO_TypeDef *tarr_port; //转矩达到端口 uint16_t tarr_pin; //转矩达到引脚 } hw_pwm_pin_t; static hw_pwm_pin_t pin_maps[HW_PWM_NUMBER] = { { GPIOA, 3, 0, GPIOE, 15, GPIOE, 10, GPIOG, 15, GPIOD, 14, GPIOD, 14, GPIOG, 15}, { GPIOE, 9, GPIO_FullRemap_TIM1, GPIOG, 7, GPIOE, 12, GPIOG, 12, GPIOD, 15 ,GPIOD,15,GPIOG,12}, { GPIOD, 12, GPIO_Remap_TIM4, GPIOE, 14, GPIOE, 13, GPIOG, 10, GPIOD, 0 ,GPIOD,0,GPIOG,10} }; /* PWM分布 GPIO_Remap_TIM4 TIM4_CH1 PB6 PD12 TIM4_CH2 PB7 PD13 TIM4_CH3 PB8 PD14 TIM4_CH4 PB9 PD15 ------------------------------------- GPIO_PartialRemap_TIM3 GPIO_FullRemap_TIM3 TIM3_CH1 PA6 PB4 PC6 TIM3_CH2 PA7 PB5 PC7 TIM3_CH3 PB0 PB0 PC8 TIM3_CH4 PB1 PB1 PC9 ------------------------------------- GPIO_PartialRemap1_TIM2 GPIO_PartialRemap2_TIM2 GPIO_FullRemap_TIM2 TIM2_CH1 PA0 PA15 PA0 PA15 TIM2_CH2 PA1 PB3 PA1 PB3 TIM2_CH3 PA2 PA2 PC8 PC8 TIM2_CH4 PA3 PA3 PC9 PC9 ------------------------------------- GPIO_FullRemap_TIM1 TIM1_CH1 PA8 PE9 TIM1_CH2 PA9 PE11 TIM1_CH3 PA10 PE13 TIM1_CH4 PA11 PE14 ------------------------------------- */ static hw_pwm_t hw_pwm_maps[HW_PWM_NUMBER] = { { TIM5, 10000000, 4, TIM5_IRQn }, //TIM3_CH4 GPIOC_9 { TIM1, 10000000, 1, TIM1_UP_IRQn } , //TIM1_CH1 GPIOA_8 { TIM4, 10000000, 1, TIM4_IRQn } }; //周期寄存器表 uint16_t *hw_pwm_period_registers[HW_PWM_NUMBER]; //占空比寄存器表 uint16_t *hw_pwm_dutycycle_registers[HW_PWM_NUMBER]; //配置寄存器表 uint16_t *hw_pwm_cr_registers[HW_PWM_NUMBER]; //配置寄存器表 uint16_t *hw_pwm_egr_registers[HW_PWM_NUMBER]; //方向管脚读写表 hw_pin_readwrite_t hw_pwm_dir_rw_map[HW_PWM_NUMBER]; //使能管脚读写表 hw_pin_readwrite_t hw_pwm_en_rw_map[HW_PWM_NUMBER]; //回调函数,需要使用PWM前进行注册 static pwm_handle pwm_handle_maps[HW_PWM_NUMBER]; //回调参数 static void *pwm_hanlde_parames[HW_PWM_NUMBER]; //X轴 void TIM5_IRQHandler(void) { if(TIM5->SR & (1 << 0)) { TIM5->SR &= ~(1 << 0); pwm_handle_maps[HW_PWM_1](pwm_hanlde_parames[HW_PWM_1]); } } //Y轴 void TIM1_UP_IRQHandler(void) { if (TIM1->SR & (1 << 0)) { TIM1->SR &= ~(1 << 0); pwm_handle_maps[HW_PWM_2](pwm_hanlde_parames[HW_PWM_2]); } } //Z轴 void TIM4_IRQHandler(void) { if (TIM4->SR & (1 << 0)) { TIM4->SR &= ~(1 << 0); pwm_handle_maps[HW_PWM_3](pwm_hanlde_parames[HW_PWM_3]); } } /** * 默认指针函数 * * @author LXZ (121919) * * @param handler */ void hw_pwm_default_handler(void *handler) { } /** * 设置方向 * * @author lxz * * @param no * @param dir */ void hw_pwm_set_dir(unsigned char no, int dir) { hw_pwm_pin_t *pwm_pin = &pin_maps[no]; if (pwm_pin->dir_port != (void *)0) { if (dir) { pwm_pin->dir_port->BSRR = 1 << (pwm_pin->dir_pin + 16); } else { pwm_pin->dir_port->BSRR = 1 << (pwm_pin->dir_pin); } } } /** * 获取方向 * * @author lxz * * @param no * * @return int */ int hw_pwm_get_dir(unsigned char no) { hw_pwm_pin_t *pwm_pin = &pin_maps[no]; if (pwm_pin->dir_port != (void *)0) { return (pwm_pin->dir_port->IDR >> pwm_pin->dir_pin) & (0x01) == 0x01; } return 0; } /** * 设置使能状态 * * @author lxz * * @param no * @param dir */ void hw_pwm_set_enable(unsigned char no, int en) { hw_pwm_pin_t *pwm_pin = &pin_maps[no]; if (pwm_pin->en_port != (void *)0) { if (en) { pwm_pin->en_port->BSRR = 1 << (pwm_pin->en_pin + 16); } else { pwm_pin->en_port->BSRR = 1 << pwm_pin->en_pin; } } } /** * 获取使能状态 * * @author lxz * * @param no * * @return int */ int hw_pwm_get_enable(unsigned char no) { hw_pwm_pin_t *pwm_pin = &pin_maps[no]; if (pwm_pin->en_port != (void *)0) { return (pwm_pin->en_port->IDR >> pwm_pin->en_pin) & (0x01)==0x01; } return 0; } /** * 获取报警状态 * * @author lxz * * @param no * * @return int */ int hw_pwm_get_alr(unsigned char no) { hw_pwm_pin_t *pwm_pin = &pin_maps[no]; if (pwm_pin->alr_port != (void *)0) { return (pwm_pin->alr_port->IDR >> pwm_pin->alr_pin) & (0x01)==0x01; } return 0; } /** * 设置报警清除 * * @author lxz * * @param no * @param dir */ void hw_pwm_set_clr(unsigned char no, int en) { hw_pwm_pin_t *pwm_pin = &pin_maps[no]; if (pwm_pin->clr_port != (void *)0) { if (en) { pwm_pin->clr_port->BSRR = 1 << (pwm_pin->clr_pin + 16); } else { pwm_pin->clr_port->BSRR = 1 << pwm_pin->clr_pin; } } } /** * 获取扭矩到状态 * * @author lxz * * @param no * * @return int */ int hw_pwm_get_tarr(unsigned char no) { hw_pwm_pin_t *pwm_pin = &pin_maps[no]; if (pwm_pin->tarr_port != (void *)0) { return (pwm_pin->tarr_port->IDR >> pwm_pin->tarr_pin) & (0x01)==0x01; } return 0; } /** * 设置转矩模式 * * @author lxz * * @param no * @param dir */ void hw_pwm_set_tmode(unsigned char no, int en) { hw_pwm_pin_t *pwm_pin = &pin_maps[no]; if (pwm_pin->tmode_port != (void *)0) { if (en) { pwm_pin->tmode_port->BSRR = 1 << (pwm_pin->tmode_pin + 16); } else { pwm_pin->tmode_port->BSRR = 1 << pwm_pin->tmode_pin; } } } /** * 获取脉冲的频率 * * @author lxz * * @param no * * @return int */ int hw_pwm_get_clk(unsigned char no) { return hw_pwm_maps[no].unit_in_hz; } /** * 启动pwm * * @author lxz (2019/5/20/周一) * * @param no */ void hw_pwm_start(unsigned char no) { HW_PWM_ON(no); } /** * 停止PWM * * @author lxz (2019/5/20/周一) * * @param no */ void hw_pwm_stop(unsigned char no) { HW_PWM_OFF(no); } /** * 设置PWM的周期 * * @author lxz * * @param no * @param value */ void hw_pwm_set_period(unsigned char no, int value) { HW_PWM_PERIOD(no) = value; HW_PWM_DUTYCYCLE(no) = value >> 1; } /** * 注册PWM中断的处理事件 * * @author lxz * * @param no * @param handle * @param para */ void hw_pwm_it_register(unsigned char no, pwm_handle handle, void *para) { if (no < HW_PWM_NUMBER) { pwm_hanlde_parames[no] = para; pwm_handle_maps[no] = handle; } } static void hw_pwm_pulse_init(int index) { hw_pwm_pin_t *pwm_pin = &pin_maps[index]; uint32_t port = (uint32_t)pwm_pin->pulse_port; uint16_t pin = pwm_pin->pulse_pin; if (port >= GPIOA_BASE && port <= GPIOG_BASE) { RCC->APB2ENR |= 1 << ((port - APB2PERIPH_BASE) / 0x400); GPIO_Set((GPIO_TypeDef *)port, 1 << pin, GPIO_MODE_AF_PP, GPIO_SPEED_50M, GPIO_PUPD_PU); GPIO_Remap_Set(pwm_pin->remap, 1); } } static void hw_pwm_dir_init(int index) { hw_pwm_pin_t *pwm_pin = &pin_maps[index]; uint32_t port = (uint32_t)pwm_pin->dir_port; uint16_t pin = pwm_pin->dir_pin; if (port >= GPIOA_BASE && port <= GPIOG_BASE) { RCC->APB2ENR |= 1 << ((port - APB2PERIPH_BASE) / 0x400); GPIO_Set((GPIO_TypeDef *)port, 1 << pin, GPIO_MODE_OUT_PP, GPIO_SPEED_50M, GPIO_PUPD_PU); hw_pwm_dir_rw_map[index].idr = (uint16_t *)(port + 16); hw_pwm_dir_rw_map[index].odr = (uint16_t *)(port + 24); hw_pwm_dir_rw_map[index].pin = (1 << pin); hw_pwm_dir_rw_map[index].level = 0; } } //使能IO初化 static void hw_pwm_on_init(int index) { hw_pwm_pin_t *pwm_pin = &pin_maps[index]; uint32_t port = (uint32_t)pwm_pin->en_port; uint16_t pin = pwm_pin->en_pin; if (port >= GPIOA_BASE && port <= GPIOG_BASE) { RCC->APB2ENR |= 1 << ((port - APB2PERIPH_BASE) / 0x400); GPIO_Set((GPIO_TypeDef *)port, 1 << pin, GPIO_MODE_OUT_PP, GPIO_SPEED_50M, GPIO_PUPD_PU); hw_pwm_en_rw_map[index].idr = (uint16_t *)(port + 16); hw_pwm_en_rw_map[index].odr = (uint16_t *)(port + 24); hw_pwm_en_rw_map[index].pin = (1 << pin); hw_pwm_en_rw_map[index].level = 1; //HW_PWM_SET_EN(index, 1);// } } static void hw_pwm_clr_init(int index) { hw_pwm_pin_t *pwm_pin = &pin_maps[index]; uint32_t port = (uint32_t)pwm_pin->clr_port; uint16_t pin = pwm_pin->clr_pin; if (port >= GPIOA_BASE && port <= GPIOG_BASE) { RCC->APB2ENR |= 1 << ((port - APB2PERIPH_BASE) / 0x400); GPIO_Set((GPIO_TypeDef *)port, 1 << pin, GPIO_MODE_OUT_PP, GPIO_SPEED_50M, GPIO_PUPD_PU); hw_pwm_en_rw_map[index].idr = (uint16_t *)(port + 16); hw_pwm_en_rw_map[index].odr = (uint16_t *)(port + 24); hw_pwm_en_rw_map[index].pin = (1 << pin); hw_pwm_en_rw_map[index].level = 1; } } static void hw_pwm_alr_init(int index) { hw_pwm_pin_t *pwm_pin = &pin_maps[index]; uint32_t port = (uint32_t)pwm_pin->alr_port; uint16_t pin = pwm_pin->alr_pin; if (port >= GPIOA_BASE && port <= GPIOG_BASE) { RCC->APB2ENR |= 1 << ((port - APB2PERIPH_BASE) / 0x400); GPIO_Set((GPIO_TypeDef *)port, 1 << pin, GPIO_MODE_IPU, GPIO_SPEED_50M, GPIO_PUPD_PU); hw_pwm_en_rw_map[index].idr = (uint16_t *)(port + 16); hw_pwm_en_rw_map[index].odr = (uint16_t *)(port + 24); hw_pwm_en_rw_map[index].pin = (1 << pin); hw_pwm_en_rw_map[index].level = 1; } } static void hw_pwm_tmode_init(int index) { hw_pwm_pin_t *pwm_pin = &pin_maps[index]; uint32_t port = (uint32_t)pwm_pin->tmode_port; uint16_t pin = pwm_pin->tmode_pin; if (port >= GPIOA_BASE && port <= GPIOG_BASE) { RCC->APB2ENR |= 1 << ((port - APB2PERIPH_BASE) / 0x400); GPIO_Set((GPIO_TypeDef *)port, 1 << pin, GPIO_MODE_OUT_PP, GPIO_SPEED_50M, GPIO_PUPD_PU); hw_pwm_en_rw_map[index].idr = (uint16_t *)(port + 16); hw_pwm_en_rw_map[index].odr = (uint16_t *)(port + 24); hw_pwm_en_rw_map[index].pin = (1 << pin); hw_pwm_en_rw_map[index].level = 1; } } static void hw_pwm_tarr_init(int index) { hw_pwm_pin_t *pwm_pin = &pin_maps[index]; uint32_t port = (uint32_t)pwm_pin->tarr_port; uint16_t pin = pwm_pin->tarr_pin; if (port >= GPIOA_BASE && port <= GPIOG_BASE) { RCC->APB2ENR |= 1 << ((port - APB2PERIPH_BASE) / 0x400); GPIO_Set((GPIO_TypeDef *)port, 1 << pin, GPIO_MODE_IPU, GPIO_SPEED_50M, GPIO_PUPD_PU); hw_pwm_en_rw_map[index].idr = (uint16_t *)(port + 16); hw_pwm_en_rw_map[index].odr = (uint16_t *)(port + 24); hw_pwm_en_rw_map[index].pin = (1 << pin); hw_pwm_en_rw_map[index].level = 1; } } static void hw_pwm_timer_init(int index,int clk) { hw_pwm_t *pwm = &hw_pwm_maps[index]; uint32_t tim_base = (uint32_t)pwm->base; TIM_TypeDef *timx = pwm->base; uint16_t psc = 1; if (tim_base >= TIM2_BASE && tim_base <= TIM5_BASE) { uint32_t en_mask = 1 << ((tim_base - APB1PERIPH_BASE) / 0x400); do { RCC->APB1ENR |= en_mask; } while (RCC->APB1ENR & en_mask == 0); psc = (clk * 1000000) / (pwm->unit_in_hz) - 1; } else if (tim_base >= TIM1_BASE && tim_base <= TIM8_BASE) { uint32_t en_mask = 1 << ((tim_base - APB2PERIPH_BASE) / 0x400); do { RCC->APB2ENR |= en_mask; } while (RCC->APB2ENR & en_mask == 0); psc = (clk * 1000000) / (pwm->unit_in_hz) - 1; } else { do { //无效的定时器 } while (1); } //初始化定时器 timx->PSC = psc; //设置预分频,得到一个基本的时钟单元 timx->ARR = 1000; //没有意义 timx->SMCR = 0; timx->DIER |= 1 << 0; //使能更新中断 timx->CR1 &= ~(3 << 8); //不分频 timx->CR1 &= ~(3 << 5); //边沿计数模式 timx->CR1 &= ~(1 << 4); //向上计数 timx->CR1 |= (1 << 2); //限制只有上溢中断 if (timx == TIM8 || timx == TIM1) { timx->CR1 |= 1 << 7; timx->BDTR |= 1 << 15; //MOE使能输出 } //timx->CR1 |= (1 << 7); //ARR寄存器不缓冲 timx->CCR1 = 0; timx->CCR2 = 0; timx->CCR3 = 0; timx->CCR4 = 0; timx->CR2 = 0; timx->CCER |= (1 << ((pwm->ch - 1) * 4)); //使能PWM通道 { timx->CCER &= ~(1 << ((pwm->ch - 1) * 4 + 1)); //高电平有效 } if (pwm->ch <= 2) { uint32_t ccmr = timx->CCMR1; uint32_t offset = (pwm->ch - 1) * 8; ccmr &= ~(3 << (offset + 0)); //输出模式 ccmr |= (1 << (offset + 2)); //比较快速使能 ccmr |= (0 << (offset + 3)); //预装载使能禁止 ccmr |= (7 << (offset + 4)); //PWM模式1, timx->CCMR1 = ccmr; } else { uint32_t ccmr = timx->CCMR2; uint32_t offset = (pwm->ch - 3) * 8; ccmr &= ~(3 << (offset + 0)); //输出模式 ccmr |= (1 << (offset + 2)); //比较快速使能 ccmr |= (0 << (offset + 3)); //预装载使能禁止 ccmr |= (7 << (offset + 4)); //PWM模式1, timx->CCMR2 = ccmr; } //中断向量使能 //MY_NVIC_Init(1, 3, pwm->irqn, 2); hw_pwm_period_registers[index] = (uint16_t *)(tim_base + 0x2C); hw_pwm_dutycycle_registers[index] = (uint16_t *)(tim_base + 0x34 + (pwm->ch - 1) * 4); hw_pwm_cr_registers[index] = (uint16_t *)(tim_base + 0x00); hw_pwm_egr_registers[index] = (uint16_t *)(tim_base + 0x10); HW_PWM_SET_PERIOD(index, 1000); HW_PWM_ON(index); hw_delay_us(1); HW_PWM_OFF(index); Sys_NVIC_Init(1, 1, pwm->irqn, 1); } /** * 初始化硬件 */ void hw_pwm_init(int clk) { //初始化IO int index = 0; while (index < HW_PWM_NUMBER) { hw_pwm_pulse_init(index); hw_pwm_dir_init(index); hw_pwm_on_init(index); hw_pwm_clr_init(index); hw_pwm_alr_init(index); hw_pwm_tarr_init(index); hw_pwm_tmode_init(index); index++; } //设置默认参数变量 index = 0; while (index < HW_PWM_NUMBER) { pwm_handle_maps[index] = hw_pwm_default_handler; pwm_hanlde_parames[index] = (void *)0; index++; } //初始化硬件 index = 0; while (index < HW_PWM_NUMBER) { hw_pwm_timer_init(index, clk); index++; } } /** * 关闭所有的脉冲输出 * * @author lxz (2019/5/30/周四) */ void hw_pwm_close_all(void) { int index = 0; while (index < HW_PWM_NUMBER) { HW_PWM_OFF(index); index++; } }