#include "pwm.h" #include "gpio.h" //捕获比较模式寄存器 const uint32 PWM_CCMR_ADDR[] = {0x7efec8, 0x7efec9, 0x7efeca ,0x7efecb, 0x7efee8, 0x7efee9, 0x7efeea, 0x7efeeb}; //捕获比较使能寄存器 const uint32 PWM_CCER_ADDR[] = {0x7efecc, 0x7efecd, 0x7efeec ,0x7efeed}; //控制寄存器,高8位地址 低8位地址 + 1即可 const uint32 PWM_CCR_ADDR[] = {0x7efed5, 0x7efed7, 0x7efed9, 0x7efedb, 0x7efef5, 0x7efef7, 0x7efef9, 0x7efefb}; //控制寄存器,高8位地址 低8位地址 + 1即可 const uint32 PWM_ARR_ADDR[] = {0x7efed2,0x7efef2}; //------------------------------------------------------------------------------------------------------------------- // @brief PWM_gpio初始化(内部使用用户无需关心) // @param pwmch PWM通道号及引脚 // @return void // Sample usage: //------------------------------------------------------------------------------------------------------------------- void pwm_set_gpio(PWMCH_enum pwmch) { switch(pwmch) { case PWMA_CH1P_P10: { gpio_mode(P1_0,GPO_PP); break; } case PWMA_CH1N_P11: { gpio_mode(P1_1,GPO_PP); break; } case PWMA_CH1P_P20: { gpio_mode(P2_0,GPO_PP); break; } case PWMA_CH1N_P21: { gpio_mode(P2_1,GPO_PP); break; } case PWMA_CH1P_P60: { gpio_mode(P6_0,GPO_PP); break; } case PWMA_CH1N_P61: { gpio_mode(P6_1,GPO_PP); break; } case PWMA_CH2P_P12: { gpio_mode(P1_2,GPO_PP); break; } case PWMA_CH2N_P13: { gpio_mode(P1_3,GPO_PP); break; } case PWMA_CH2P_P22: { gpio_mode(P2_2,GPO_PP); break; } case PWMA_CH2N_P23: { gpio_mode(P2_3,GPO_PP); break; } case PWMA_CH2P_P62: { gpio_mode(P6_2,GPO_PP); break; } case PWMA_CH2N_P63: { gpio_mode(P6_3,GPO_PP); break; } case PWMA_CH3P_P14: { gpio_mode(P1_4,GPO_PP); break; } case PWMA_CH3N_P15: { gpio_mode(P1_5,GPO_PP); break; } case PWMA_CH3P_P24: { gpio_mode(P2_4,GPO_PP); break; } case PWMA_CH3N_P25: { gpio_mode(P2_5,GPO_PP); break; } case PWMA_CH3P_P64: { gpio_mode(P6_4,GPO_PP); break; } case PWMA_CH3N_P65: { gpio_mode(P6_5,GPO_PP); break; } case PWMA_CH4P_P16: { gpio_mode(P1_6,GPO_PP); break; } case PWMA_CH4N_P17: { gpio_mode(P1_7,GPO_PP); break; } case PWMA_CH4P_P26: { gpio_mode(P2_6,GPO_PP); break; } case PWMA_CH4N_P27: { gpio_mode(P2_7,GPO_PP); break; } case PWMA_CH4P_P66: { gpio_mode(P6_6,GPO_PP); break; } case PWMA_CH4N_P67: { gpio_mode(P6_7,GPO_PP); break; } case PWMA_CH4P_P34: { gpio_mode(P3_4,GPO_PP); break; } case PWMA_CH4N_P33: { gpio_mode(P3_3,GPO_PP); break; } case PWMB_CH1_P20: { gpio_mode(P2_0,GPO_PP); break; } case PWMB_CH1_P17: { gpio_mode(P1_7,GPO_PP); break; } case PWMB_CH1_P00: { gpio_mode(P0_0,GPO_PP); break; } case PWMB_CH1_P74: { gpio_mode(P7_4,GPO_PP); break; } case PWMB_CH2_P21: { gpio_mode(P2_1,GPO_PP); break; } case PWMB_CH2_P54: { gpio_mode(P5_4,GPO_PP); break; } case PWMB_CH2_P01: { gpio_mode(P0_1,GPO_PP); break; } case PWMB_CH2_P75: { gpio_mode(P7_5,GPO_PP); break; } case PWMB_CH3_P22: { gpio_mode(P2_2,GPO_PP); break; } case PWMB_CH3_P33: { gpio_mode(P3_3,GPO_PP); break; } case PWMB_CH3_P02: { gpio_mode(P0_2,GPO_PP); break; } case PWMB_CH3_P76: { gpio_mode(P7_6,GPO_PP); break; } case PWMB_CH4_P23: { gpio_mode(P2_3,GPO_PP); break; } case PWMB_CH4_P34: { gpio_mode(P3_4,GPO_PP); break; } case PWMB_CH4_P03: { gpio_mode(P0_3,GPO_PP); break; } case PWMB_CH4_P77: { gpio_mode(P7_7,GPO_PP); break; } } } //------------------------------------------------------------------------------------------------------------------- // @brief PWM初始化 // @param pwmch PWM通道号及引脚 // @param freq PWM频率(10Hz-3MHz) // @param duty PWM占空比 // @return void // Sample usage: // pwm_init(PWM0_P00, 100, 5000); //初始化PWM0 使用引脚P0.0 输出PWM频率100HZ 占空比为百分之 5000/PWM_DUTY_MAX*100 // PWM_DUTY_MAX在zf_pwm.h文件中 默认为10000 //------------------------------------------------------------------------------------------------------------------- void pwm_init(PWMCH_enum pwmch,uint32 freq, uint32 duty) { uint32 match_temp; uint32 period_temp; uint16 freq_div = 0; P_SW2 |= 0x80; //GPIO需要设置为推挽输出 pwm_set_gpio(pwmch); //分频计算,周期计算,占空比计算 freq_div = (sys_clk / freq) >> 16; //多少分频 period_temp = sys_clk / freq ; period_temp = period_temp / (freq_div + 1) - 1; //周期 if(duty != PWM_DUTY_MAX) { match_temp = period_temp * ((float)duty / PWM_DUTY_MAX); // 占空比 } else { match_temp = period_temp + 1; // duty为100% } if(PWMB_CH1_P20 <= pwmch) //PWM5-8 { //通道选择,引脚选择 PWMB_ENO |= (1 << ((2 * ((pwmch >> 4) - 4)))); //使能通道 PWMB_PS |= ((pwmch & 0x03) << ((2 * ((pwmch >> 4) - 4)))); //输出脚选择 // 配置通道输出使能和极性 (*(unsigned char volatile far *) (PWM_CCER_ADDR[pwmch>>5])) |= (uint8)(1 << (((pwmch >> 4) & 0x01) * 4)); //设置预分频 PWMB_PSCRH = (uint8)(freq_div>>8); PWMB_PSCRL = (uint8)freq_div; PWMB_BKR = 0x80; //主输出使能 相当于总开关 PWMB_CR1 = 0x01; //PWM开始计数 } else { PWMA_ENO |= (1 << (pwmch & 0x01)) << ((pwmch >> 4) * 2); //使能通道 PWMA_PS |= ((pwmch & 0x07) >> 1) << ((pwmch >> 4) * 2); //输出脚选择 // 配置通道输出使能和极性 (*(unsigned char volatile far *) (PWM_CCER_ADDR[pwmch>>5])) |= (1 << ((pwmch & 0x01) * 2 + ((pwmch >> 4) & 0x01) * 0x04)); //设置预分频 PWMA_PSCRH = (uint8)(freq_div>>8); PWMA_PSCRL = (uint8)freq_div; PWMA_BKR = 0x80; // 主输出使能 相当于总开关 PWMA_CR1 = 0x01; //PWM开始计数 } //周期 (*(unsigned char volatile far *) (PWM_ARR_ADDR[pwmch>>6])) = (uint8)(period_temp>>8); //高8位 (*(unsigned char volatile far *) (PWM_ARR_ADDR[pwmch>>6] + 1)) = (uint8)period_temp; //低8位 //设置捕获值|比较值 (*(unsigned char volatile far *) (PWM_CCR_ADDR[pwmch>>4])) = match_temp>>8; //高8位 (*(unsigned char volatile far *) (PWM_CCR_ADDR[pwmch>>4] + 1)) = (uint8)match_temp; //低8位 //功能设置 (*(unsigned char volatile far *) (PWM_CCMR_ADDR[pwmch>>4])) |= 0x06<<4; //设置为PWM模式1 (*(unsigned char volatile far *) (PWM_CCMR_ADDR[pwmch>>4])) |= 1<<3; //开启PWM寄存器的预装载功 // P_SW2 &= 0x7F; } //------------------------------------------------------------------------------------------------------------------- // @brief PWM占空比设置 // @param pwmch PWM通道号及引脚 // @param duty PWM占空比 // @return void // Sample usage: pwm_duty(PWM0_P00, 5000); //初始化PWM0 使用引脚P0.0 输出PWM频率50HZ 占空比为百分之 5000/PWM_DUTY_MAX*100 // PWM_DUTY_MAX在fsl_pwm.h文件中 默认为10000 //------------------------------------------------------------------------------------------------------------------- void pwm_duty(PWMCH_enum pwmch, uint32 duty) { uint32 match_temp; uint32 arr = ((*(unsigned char volatile far *) (PWM_ARR_ADDR[pwmch>>6]))<<8) | (*(unsigned char volatile far *) (PWM_ARR_ADDR[pwmch>>6] + 1 )); // P_SW2 |= 0x80; if(duty != PWM_DUTY_MAX) { match_temp = arr * ((float)duty/PWM_DUTY_MAX); //占空比 } else { match_temp = arr + 1; } //设置捕获值|比较值 (*(unsigned char volatile far *) (PWM_CCR_ADDR[pwmch>>4])) = match_temp>>8; //高8位 (*(unsigned char volatile far *) (PWM_CCR_ADDR[pwmch>>4] + 1)) = (uint8)match_temp; //低8位 // P_SW2 &= ~0x80; } //------------------------------------------------------------------------------------------------------------------- // @brief PWM频率设置 // @param pwmch PWM通道号及引脚 // @param freq PWM频率(10Hz-3MHz) // @param duty PWM占空比 // @return void // Sample usage: pwm_freq(PWM0_P00, 50, 5000); //修改化PWM0 使用引脚P0.0 输出PWM频率50HZ 占空比为百分之 5000/PWM_DUTY_MAX*100 //------------------------------------------------------------------------------------------------------------------- void pwm_freq(PWMCH_enum pwmch, uint32 freq, uint32 duty) { uint32 match_temp; uint32 period_temp; uint16 freq_div = 0; //分频计算,周期计算,占空比计算 freq_div = (sys_clk / freq) >> 16; // 多少分频 period_temp = sys_clk / freq; period_temp = period_temp / (freq_div + 1) - 1; // 周期 if(duty != PWM_DUTY_MAX) { match_temp = period_temp * ((float)duty / PWM_DUTY_MAX); // 占空比 } else { match_temp = period_temp + 1; // duty为100% } // P_SW2 |= 0x80; if(PWMB_CH1_P20 <= pwmch) //PWM5-8 { //设置预分频 PWMB_PSCRH = (uint8)(freq_div>>8); PWMB_PSCRL = (uint8)freq_div; } else { //设置预分频 PWMA_PSCRH = (uint8)(freq_div>>8); PWMA_PSCRL = (uint8)freq_div; } //周期 (*(unsigned char volatile far *) (PWM_ARR_ADDR[pwmch>>6])) = (uint8)(period_temp>>8); //高8位 (*(unsigned char volatile far *) (PWM_ARR_ADDR[pwmch>>6] + 1)) = (uint8)period_temp; //低8位 //设置捕获值|比较值 (*(unsigned char volatile far *) (PWM_CCR_ADDR[pwmch>>4])) = match_temp>>8; //高8位 (*(unsigned char volatile far *) (PWM_CCR_ADDR[pwmch>>4] + 1)) = (uint8)match_temp; //低8位 // P_SW2 &= ~0x80; }