123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604 |
- #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++;
- }
- }
|