123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623 |
- #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; //方向功能引脚
- //unsigned short dir_level; //有效电平 0时,表示高电平是正方向,低电平是反方向,1时表示高电平是反方向,低电平是正方向
- 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] = {
- { GPIOC, 9, GPIO_FullRemap_TIM3, GPIOA, 8, GPIOA, 8,0,0,0,0,0,0,0,0 },
- { GPIOA, 8, 0, GPIOC, 9, GPIOC, 9,0,0,0,0,0,0,0,0 } //1
- };
- /* 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] = {
- { TIM3, 4000000, 4, TIM3_IRQn }, //TIM3_CH4 GPIOC_9
- { TIM1, 4000000, 1, TIM1_UP_IRQn } //TIM1_CH1 GPIOA_8
- };
- //周期寄存器表
- 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];
- //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]);
- }
- }
- //X轴
- void TIM3_IRQHandler(void)
- {
- if (TIM3->SR & (1 << 0))
- {
- TIM3->SR &= ~(1 << 0);
- pwm_handle_maps[HW_PWM_1](pwm_hanlde_parames[HW_PWM_1]);
- }
- }
- /**
- * 默认指针函数
- *
- * @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];
- unsigned char DIR_TYPE;//类型
- unsigned char DIR_CH;//通道
-
- if(no==0)//X轴
- {
- DIR_TYPE=SET_XDIR_TYPE;
- DIR_CH=SET_XDIR_CH;
- }
- else if(no==1)//Y轴
- {
- DIR_TYPE=SET_YDIR_TYPE;
- DIR_CH=SET_YDIR_CH;
- }
-
- switch(DIR_TYPE)
- {
- //脉冲输出类型
- case PULSE_OUTPUT_TYPE:
- 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);
- }
- }
- break;
- //Y输出类型
- case Y_OUTPUT_TYPE:
- switch(DIR_CH)
- {
- case 0:
- if(dir) {Y00=1; M0304=1;}else {Y00=0; M0304=0;}break;
- case 1:
- if(dir) {Y01=1; M0305=1;}else {Y01=0; M0305=0;}break;
- case 2:
- if(dir) {Y02=1; M0306=1;}else {Y02=0; M0306=0;}break;
- case 3:
- if(dir) {Y03=1; M0307=1;}else {Y03=0; M0307=0;}break;
- case 4:
- if(dir) {Y04=1; M0308=1;}else {Y04=0; M0308=0;}break;
- case 5:
- if(dir) {Y05=1; M0309=1;}else {Y05=0; M0309=0;}break;
- case 6:
- if(dir) {Y06=1; M0310=1;}else {Y06=0; M0310=0;}break;
- case 7:
- if(dir) {Y07=1; M0311=1;}else {Y07=0; M0311=0;}break;
- case 10:
- if(dir) {Y10=1; M0312=1;}else {Y10=0; M0312=0;}break;
- case 11:
- if(dir) {Y11=1; M0313=1;}else {Y11=0; M0313=0;}break;
- case 12:
- if(dir) {Y12=1; M0314=1;}else {Y12=0; M0314=0;}break;
- case 13:
- if(dir) {Y13=1; M0315=1;}else {Y13=0; M0315=0;}break;
- case 14:
- if(dir) {Y14=1; M0316=1;}else {Y14=0; M0316=0;}break;
- case 15:
- if(dir) {Y15=1; M0317=1;}else {Y15=0; M0317=0;}break;
- case 16:
- if(dir) {Y16=1; M0318=1;}else {Y16=0; M0318=0;}break;
- case 17:
- if(dir) {Y17=1; M0319=1;}else {Y17=0; M0319=0;}break;
- case 20:
- if(dir) {Y20=1; M0320=1;}else {Y20=0; M0320=0;}break;
- case 21:
- if(dir) {Y21=1; M0321=1;}else {Y21=0; M0321=0;}break;
- case 22:
- if(dir) {Y22=1; M0322=1;}else {Y22=0; M0322=0;}break;
- case 23:
- if(dir) {Y23=1; M0323=1;}else {Y23=0; M0323=0;}break;
- case 24:
- if(dir) {Y24=1; M0324=1;}else {Y24=0; M0324=0;}break;
- case 25:
- if(dir) {Y25=1; M0325=1;}else {Y25=0; M0325=0;}break;
- case 26:
- if(dir) {Y26=1; M0326=1;}else {Y26=0; M0326=0;}break;
- default:
- break;
- }
- break;
- //不使用方向
- case NO_USE_TYPE:
- break;
- default:
- break;
- }
- }
- /**
- * 获取方向
- *
- * @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);
- }
- 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_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;
- }
- }
- 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_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)
- {
- if(index == 0)//X轴配置时
- {
- if(SET_PULSE_TYPE & X_AXIS_PULSE_ENABLE)
- {
- hw_pwm_pulse_init(index);
- }
-
- if(SET_PULSE_TYPE & Y_DIR_ENABLE)
- {
- hw_pwm_dir_init(index);
- }
-
- if(SET_PULSE_TYPE & Y_ON_ENABLE)
- {
- hw_pwm_on_init(index);
- }
- }
- else//Y轴配置时
- {
- if(SET_PULSE_TYPE & Y_AXIS_PULSE_ENABLE)
- {
- hw_pwm_pulse_init(index);
- }
-
- if(SET_PULSE_TYPE & X_DIR_ENABLE)
- {
- hw_pwm_dir_init(index);
- }
-
- if(SET_PULSE_TYPE & X_ON_ENABLE)
- {
- hw_pwm_on_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)
- {
- if(index == 0)
- {
- if(SET_PULSE_TYPE & X_AXIS_PULSE_ENABLE)
- {
- hw_pwm_timer_init(index, clk);
- }
- }
- else
- {
- if(SET_PULSE_TYPE & Y_AXIS_PULSE_ENABLE)
- {
- 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++;
- }
- }
|