#include "board.h" typedef struct { uint32_t base; //对象实体 int unit_in_hz; //1秒多少hz uint16_t ch; //通道选择 uint16_t irqn; //中断源 } hw_pwm_t; typedef struct { uint32_t pulse_port; //端口 unsigned short pulse_pin; //引脚 unsigned short pulse_af; //复用功能位置 uint32_t dir_port; //方向功能端口 unsigned short dir_pin; //方向功能引脚 unsigned short dir_level; //有效电平 0时,表示高电平是正方向,低电平是反方向,1时表示高电平是反方向,低电平是正方向 uint32_t en_port; //使能功能端口 unsigned short en_pin; //使能功能引脚 unsigned short en_level; //有效电平 0时,表示高电平是正方向,低电平是反方向,1时表示高电平是反方向,低电平是正方向 } hw_pwm_pin_t; static hw_pwm_pin_t pin_maps[HW_PWM_NUMBER] = { { GPIOA, 8, 2, GPIOF, 5, 0, GPIOC, 3 ,0}, { GPIOB, 15, 1, GPIOC, 13,0, GPIOA, 6 ,0} }; static hw_pwm_t hw_pwm_maps[HW_PWM_NUMBER] = { { TIMER0, 8000000, 0, TIMER0_BRK_UP_TRG_COM_IRQn }, { TIMER14, 8000000, 1, TIMER14_IRQn } }; //=======================================编码器定义========================================// typedef struct { uint32_t base; //对象实体 uint16_t irqn; //中断源 uint16_t period; //一圈的总脉冲数 } hw_tim_encoder_t; typedef struct { uint32_t aport; //端口 unsigned short apin; //引脚 uint32_t bport; //方向功能端口 unsigned short bpin; //方向功能引脚 unsigned short af; //复用功能位置 } hw_encode_pin_t; static hw_encode_pin_t encoder_pin_maps[HW_ENCODER_NUMBER] = { { GPIOA, 6, GPIOA, 7, 1 } }; static hw_tim_encoder_t encoders[HW_ENCODER_NUMBER] = { { TIMER2, TIMER2_IRQn, 10000 } }; //PWM编号分配,必须与硬件一致 #define TIM0_TO_PWM HW_PWM_1 #define TIM14_TO_PWM HW_PWM_2 //编码器编号分配,必须与硬件一致 注:GD32E230仅TIM0、TIM2支持 #define HW_TIM2_TO_ENCODER 0 #if defined(HW_TIM0_TO_ENCODER) && defined(TIM0_TO_PWM) #error "TIM0 can't as encoder and pwm at the same time!" #endif #if defined(HW_TIM2_TO_ENCODER) && defined(TIM2_TO_PWM) #error "TIM2 can't as encoder and pwm at the same time!" #endif //周期寄存器表 uint32_t *hw_pwm_period_registers[HW_PWM_NUMBER]; //占空比寄存器表 uint32_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]; //编码器圈数保存 static int encoder_cycles[HW_ENCODER_NUMBER] = { 0 }; //回调函数,需要使用PWM前进行注册 static pwm_handle pwm_handle_maps[HW_PWM_NUMBER]; //回调参数 static void *pwm_hanlde_parames[HW_PWM_NUMBER]; #if defined(TIM0_TO_PWM) || defined(HW_TIM0_TO_ENCODER) void TIMER0_BRK_UP_TRG_COM_IRQHandler(void) { #if defined(TIM0_TO_PWM) if (TIMER_INTF(TIMER0) & (1 << 0)) { TIMER_INTF(TIMER0) &= ~(1 << 0); pwm_handle_maps[TIM0_TO_PWM](pwm_hanlde_parames[TIM0_TO_PWM]); } #endif #if defined(HW_TIM0_TO_ENCODER) if (TIMER_INTF(TIMER0) & (1 << 0)) { if (TIMER_CTL0(TIMER0) & (1 << 4)) { encoder_cycles[HW_TIM0_TO_ENCODER]--; } else if ((TIMER_CTL0(TIMER0) & (1 << 4)) == 0) { encoder_cycles[HW_TIM0_TO_ENCODER]++; } TIMER_INTF(TIMER0) &= ~(1 << 0); } #endif } #endif #if defined(TIM2_TO_PWM) || defined(HW_TIM2_TO_ENCODER) void TIMER2_IRQHandler(void) { #if defined(TIM2_TO_PWM) if (TIMER_INTF(TIMER2) & (1 << 0)) { TIMER_INTF(TIMER2) &= ~(1 << 0); pwm_handle_maps[TIM2_TO_PWM](pwm_hanlde_parames[TIM2_TO_PWM]); } #endif #if defined(HW_TIM2_TO_ENCODER) if (TIMER_INTF(TIMER2) & (1 << 0)) { if (TIMER_CTL0(TIMER2) & (1 << 4)) { encoder_cycles[HW_TIM2_TO_ENCODER]--; } else if ((TIMER_CTL0(TIMER2) & (1 << 4)) == 0) { encoder_cycles[HW_TIM2_TO_ENCODER]++; } TIMER_INTF(TIMER2) &= ~(1 << 0); } #endif } #endif #if defined(TIM13_TO_PWM) void TIMER13_IRQHandler(void) { if (TIMER_INTF(TIMER13) & (1 << 0)) { TIMER_INTF(TIMER13) &= ~(1 << 0); pwm_handle_maps[TIM13_TO_PWM](pwm_hanlde_parames[TIM13_TO_PWM]); } } #endif #if defined(TIM14_TO_PWM) void TIMER14_IRQHandler(void) { if (TIMER_INTF(TIMER14) & (1 << 0)) { TIMER_INTF(TIMER14) &= ~(1 << 0); pwm_handle_maps[TIM14_TO_PWM](pwm_hanlde_parames[TIM14_TO_PWM]); } } #endif #if defined(TIM15_TO_PWM) void TIMER15_IRQHandler(void) { if (TIMER_INTF(TIMER15) & (1 << 0)) { TIMER_INTF(TIMER15) &= ~(1 << 0); pwm_handle_maps[TIM15_TO_PWM](pwm_hanlde_parames[TIM15_TO_PWM]); } } #endif #if defined(TIM16_TO_PWM) void TIMER16_IRQHandler(void) { if (TIMER_INTF(TIMER16) & (1 << 0)) { TIMER_INTF(TIMER16) &= ~(1 << 0); pwm_handle_maps[TIM16_TO_PWM](pwm_hanlde_parames[TIM16_TO_PWM]); } } #endif /** * 默认指针函数 * * @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) { if (pin_maps[no].dir_port != 0) { if (dir) { GPIO_BOP(pin_maps[no].dir_port) = 1 << pin_maps[no].dir_pin; } else { GPIO_BOP(pin_maps[no].dir_port) = 1 << (pin_maps[no].dir_pin+16); } } } /** * 获取方向 * * @author lxz * * @param no * * @return int */ int hw_pwm_get_dir(unsigned char no) { if (pin_maps[no].dir_port != 0) { return (GPIO_ISTAT(pin_maps[no].dir_port) >> pin_maps[no].dir_pin) & (0x01) == 0x01; } return 0; } /** * 设置使能状态 * * @author lxz * * @param no * @param dir */ void hw_pwm_set_enable(unsigned char no, int en) { if (pin_maps[no].en_port != 0) { if (en) { GPIO_BOP(pin_maps[no].en_port) = 1 << pin_maps[no].en_pin; } else { GPIO_BOP(pin_maps[no].en_port) = 1 << (pin_maps[no].en_pin +16); } } } /** * 获取使能状态 * * @author lxz * * @param no * * @return int */ int hw_pwm_get_enable(unsigned char no) { if (pin_maps[no].en_port != 0) { return (GPIO_ISTAT(pin_maps[no].en_port) >> pin_maps[no].en_pin) & (0x01); } return 0; } /** * 获取脉冲的频率 * * @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; } } /** * 设置定时器的基频 * * @author LXZ (051220) * * @param no * @param clock */ void hw_pwm_set_clock(unsigned char no, int clock) { uint32_t tim_base = hw_pwm_maps[no].base; uint16_t psc = 1; HW_PWM_OFF(no); hw_pwm_maps[no].unit_in_hz=clock; //初始化外设时钟 rcu_periph_clock_enable(rcu_periph_clock_bit(tim_base)); psc = (HW_BOART_CORE_FREQ * 1000000) / (hw_pwm_maps[no].unit_in_hz) - 1; //初始化定时器 TIMER_PSC(tim_base) = psc; //设置预分频,得到一个基本的时钟单元 TIMER_CAR(tim_base) = 1000; //没有意义 } /** * 初始化硬件 */ void hw_pwm_init(int clk) { //初始化IO int index = 0; while (index < HW_PWM_NUMBER) { //PULSE uint32_t port = pin_maps[index].pulse_port; uint32_t pin = 1 << pin_maps[index].pulse_pin; uint32_t af = pin_maps[index].pulse_af; if (port != 0) { //使能时钟 rcu_periph_clock_enable(rcu_periph_clock_bit(port)); //配置IO为AF gpio_mode_set(port, GPIO_MODE_AF, GPIO_PUPD_PULLUP, pin); gpio_output_options_set(port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, pin); gpio_af_set(port, af, pin); } //DIR port = pin_maps[index].dir_port; pin = 1 << pin_maps[index].dir_pin; if (port != 0) { //使能时钟 rcu_periph_clock_enable(rcu_periph_clock_bit(port)); //配置IO为AF gpio_mode_set(port, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, pin); gpio_output_options_set(port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, pin); 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 = pin_maps[index].dir_level; } //EN port = pin_maps[index].en_port; pin = 1 << pin_maps[index].en_pin; if (port != 0) { //使能时钟 rcu_periph_clock_enable(rcu_periph_clock_bit(port)); //配置IO为AF gpio_mode_set(port, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, pin); gpio_output_options_set(port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, pin); 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_dir_rw_map[index].level = pin_maps[index].dir_level; HW_PWM_SET_EN(index, pin_maps[index].dir_level); } 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) { uint32_t tim_base = hw_pwm_maps[index].base; uint16_t psc = (clk * 1000000) / (hw_pwm_maps[index].unit_in_hz) - 1; //初始化外设时钟 rcu_periph_clock_enable(rcu_periph_clock_bit(tim_base)); timer_deinit(tim_base); //初始化定时器 TIMER_PSC(tim_base) = psc; //设置预分频,得到一个基本的时钟单元 TIMER_CAR(tim_base) = 1000; //没有意义 TIMER_SMCFG(tim_base) = 0; TIMER_DMAINTEN(tim_base) |= 1 << 0; //使能更新中断 TIMER_CTL0(tim_base) &= ~(3 << 8); //不分频 TIMER_CTL0(tim_base) &= ~(3 << 5); //边沿计数模式 TIMER_CTL0(tim_base) &= ~(1 << 4); //向上计数 TIMER_CTL0(tim_base) |= (1 << 2); //限制只有上溢中断 TIMER_CTL0(tim_base) |= 1 << 7; TIMER_CCHP(tim_base) |= 1 << 15; //MOE使能输出 TIMER_CTL1(tim_base) = 0; TIMER_CHCTL2(tim_base) |= (1 << ((hw_pwm_maps[index].ch - 1) * 4)); //使能PWM通道 TIMER_CHCTL2(tim_base) &= ~(1 << ((hw_pwm_maps[index].ch - 1) * 4 + 1)); //高电平有效 if (hw_pwm_maps[index].ch <= 2) { uint32_t ccmr = TIMER_CHCTL0(tim_base); uint32_t offset = (hw_pwm_maps[index].ch - 1) * 8; ccmr &= ~(3 << (offset + 0)); //输出模式 ccmr |= (1 << (offset + 2)); //比较快速使能 ccmr |= (0 << (offset + 3)); //预装载使能禁止 ccmr |= (7 << (offset + 4)); //PWM模式1, TIMER_CHCTL0(tim_base) = ccmr; } else { uint32_t ccmr = TIMER_CHCTL1(tim_base); uint32_t offset = (hw_pwm_maps[index].ch - 3) * 8; ccmr &= ~(3 << (offset + 0)); //输出模式 ccmr |= (1 << (offset + 2)); //比较快速使能 ccmr |= (0 << (offset + 3)); //预装载使能禁止 ccmr |= (7 << (offset + 4)); //PWM模式1, TIMER_CHCTL1(tim_base) = ccmr; } //中断向量使能 hw_pwm_period_registers[index] = (uint32_t *)(tim_base + 0x2C); hw_pwm_dutycycle_registers[index] = (uint32_t *)(tim_base + 0x34 + (hw_pwm_maps[index].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, 3, hw_pwm_maps[index].irqn, 2); 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++; } } /** * 读取编码器当前值 * * @author LXZ (042020) * * @param index * * @return int */ int hw_encoder_get(int index) { int cycle = 0; int value = 0; uint32_t tim_base = encoders[index].base; do { cycle = encoder_cycles[index]; value = TIMER_CNT(tim_base); } while (cycle != encoder_cycles[index]); return cycle * encoders[index].period + value; } /** * 设置编码器当前值 * * @author LXZ (042020) * * @param index * @param count */ void hw_encoder_set(int index, int count) { uint32_t tim_base = encoders[index].base; encoder_cycles[index] = count / encoders[index].period; TIMER_CNT(tim_base) = count % encoders[index].period; } /** * 编码器接口初始化 * * @author LXZ (010420) * * @param void */ void hw_encoder_init(void) { int index = 0; while (index < HW_ENCODER_NUMBER) { //A PORT uint32_t port = encoder_pin_maps[index].aport; uint16_t pin = encoder_pin_maps[index].apin; uint16_t af = encoder_pin_maps[index].af; if (port != 0) { //使能时钟 rcu_periph_clock_enable(rcu_periph_clock_bit(port)); //配置IO为AF gpio_mode_set(port, GPIO_MODE_AF, GPIO_PUPD_PULLUP, pin); gpio_output_options_set(port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, pin); gpio_af_set(port, af, pin); } //B PORT port = encoder_pin_maps[index].bport; pin = encoder_pin_maps[index].bpin; if (port != 0) { //使能时钟 rcu_periph_clock_enable(rcu_periph_clock_bit(port)); //配置IO为AF gpio_mode_set(port, GPIO_MODE_AF, GPIO_PUPD_PULLUP, pin); gpio_output_options_set(port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, pin); gpio_af_set(port, af, pin); } index++; } index = 0; while (index < HW_ENCODER_NUMBER) { uint32_t tim_base = encoders[index].base; //初始化外设时钟 rcu_periph_clock_enable(rcu_periph_clock_bit(tim_base)); timer_deinit(tim_base); //初始化定时器 TIMER_PSC(tim_base) = 0; //设置预分频,得到一个基本的时钟单元 TIMER_CAR(tim_base) = encoders[index].period-1; //没有意义 TIMER_SMCFG(tim_base) = 0; TIMER_DMAINTEN(tim_base) |= 1 << 0; //使能更新中断 TIMER_CTL0(tim_base) &= ~(3 << 8); //不分频 TIMER_CTL0(tim_base) &= ~(3 << 5); //边沿计数模式 TIMER_CTL0(tim_base) &= ~(1 << 4); //向上计数 TIMER_CTL0(tim_base) |= (1 << 2); //限制只有上溢中断 // TIMER_CTL0(tim_base) |= 1 << 7; // TIMER_CCHP(tim_base) |= 1 << 15; //MOE使能输出 TIMER_CTL1(tim_base) = 0; TIMER_CHCTL2(tim_base) =0 ; TIMER_CHCTL0(tim_base) = 0; TIMER_CHCTL1(tim_base) = 0; TIMER_SMCFG(tim_base) = 0; TIMER_CNT(tim_base) = 0; TIMER_SMCFG(tim_base) = 3<<0; TIMER_CHCTL0(tim_base) = (1 << 0) | (3 << 4) | (1 << 8) | (3 << 12); //使能T1、T2映射 TIMER_CHCTL2(tim_base) |= (1 << 0) | (1 << 4); //使能捕获通道1、2 TIMER_INTF(tim_base) = 0; TIMER_CTL0(tim_base)|= 1 << 0; //开启定时器 Sys_NVIC_Init(1, 3, encoders[index].irqn, 2); index++; } }