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