4.2 pwm相关

发布时间 2024-01-06 16:22:27作者: 深渊之巅

脉宽调制相关知识

在stm32中,pwm代表脉冲宽度调制,通过调整信号的脉冲宽度和周期来模拟不同的电压或功率级别。

pwm的相关参数: 周期、占空比、极性、脉冲宽度、对齐方式

pwm通过改变周期控制频率,通过占空比(脉冲宽度)控制输出电压

周期:

  两个上升沿之间的时间间隔。

 

极性:

  设置高电平有效还是低电平有效

 

占空比:

  一个周期之间的有效电平时间 / 一个周期时间 

 

脉冲宽度:  

  一个pwm周期之间,有效电平的时间, 宽度W = 占空比 * T

 

对其方式:

  

边沿对其: 计时器中采用自然溢出

 

中心对齐设置另外一个寄存器,当计时器数值<目标寄存器执行+1操作,当计时器数值>目标寄存器时执行-1操作

 

#include "includes.h"
#include "pwm.h"
//GPIO口基地址放入常数数据组GPIO_ARR[0]~GPIO_ARR[5]中
//static const GPIO_TypeDef * GPIO_ARR[] =
//       {(GPIO_TypeDef *)GPIOA_BASE,(GPIO_TypeDef *)GPIOB_BASE,
//        (GPIO_TypeDef *)GPIOC_BASE,(GPIO_TypeDef *)GPIOD_BASE,
//        (GPIO_TypeDef *)GPIOE_BASE,(GPIO_TypeDef *)GPIOH_BASE};
//定时器模块2地址映射
TIM_TypeDef *PWM_ARR[]={TIM2};
//*****************************内部函数******************************
void tim_mux_val(uint16_t pwmNo,uint8_t* TIM_i,uint8_t* chl);
void tim_timer_init1(uint16_t TIM_i,uint32_t f,uint16_t MOD_Value);

//*****************************对外接口函数******************************

//=====================================================================
//函数名称:  pwm_init
//功能概要:  pwm初始化函数
//参数说明:  pwmNo:pwm模块号,在gec.h的宏定义给出,如PWM_PIN0表示PWM0通道
//          clockFre:时钟频率,单位:hz,取值:375、750、1500、3000、6000、
//                                                   12000、24000、48000
//          period:周期,单位为个数,即计数器跳动次数,范围为1~65536
//          duty:占空比:0.0~100.0对应0%~100%
//          align:对齐方式 ,在头文件宏定义给出,如PWM_EDGE为边沿对其。
//          pol:极性,在头文件宏定义给出,如PWM_PLUS为正极性
//函数返回:  无
//注意:          因为GEC中给出的PWM和输入捕捉都是同一模块的,只是通道不同,所以为防止在使用多组
//          PWM和输入捕捉时,频率篡改,需要使得使用到的clockFre和period参数保持一致。
//     占空比:是指高电平在一个周期中所占的时间比例。
//=====================================================================
void pwm_init(uint16_t pwmNo,uint32_t clockFre,uint16_t period,double duty,
                                               uint8_t align,uint8_t pol)
{
    uint8_t TIM_i,chl;  //由timx_Chy解析出的tim模块号、通道号临时变量
    uint32_t temp;
    //(防止越界
    if(duty>100.0) duty=100.0;  
    //(1)获得解析的tim模块号和通道号并对相应的引脚进行引脚复用
    tim_mux_val(pwmNo,&TIM_i,&chl);
    //(2)PWM对齐方式的设定
    if(align == PWM_CENTER)//中心对齐
    {
        tim_timer_init1(TIM_i,clockFre,period/2);
        PWM_ARR[TIM_i]->CR1 |= TIM_CR1_CMS;//设置中心对齐
        if(pol == PWM_PLUS)             //正极性    
        {
            temp = (uint32_t)(duty*period/200);
            if(temp >= 65536)  temp=65535;
            switch(chl) 
            {
                case 1:    //通道1
                {
                     PWM_ARR[TIM_i]->CCMR1 &= ~TIM_CCMR1_OC1M_Msk;
                     PWM_ARR[TIM_i]->CCMR1 |= 6 << TIM_CCMR1_OC1M_Pos; //选择PWM模式1
                     PWM_ARR[TIM_i]->CCER &= ~TIM_CCER_CC1P_Msk;       //设置为正极性
                     PWM_ARR[TIM_i]->CCR1=temp;  //设置占空比
                     PWM_ARR[TIM_i]->CCMR1 &=~TIM_CCMR1_OC1PE_Msk;
                     PWM_ARR[TIM_i]->CCMR1 |=TIM_CCMR1_OC1PE_Msk;     //使能ch1预装载寄存器
                     PWM_ARR[TIM_i]->CCER |= TIM_CCER_CC1E_Msk;         //使能PWM输出
                     //PWM_ARR[TIM_i]->CCER |= TIM_CCER_CC1NP_Msk;      
                     break;
                 }
                case 2:   //通道2
                {
                    PWM_ARR[TIM_i]->CCMR1 &= ~TIM_CCMR1_OC2M_Msk;
                    PWM_ARR[TIM_i]->CCMR1 |= 6 << TIM_CCMR1_OC2M_Pos; //选择PWM模式1
                    PWM_ARR[TIM_i]->CCER &= ~TIM_CCER_CC2P_Msk;       //设置为正极性
                    PWM_ARR[TIM_i]->CCR2=temp;  //设置占空比
                    PWM_ARR[TIM_i]->CCMR1 &=~TIM_CCMR1_OC2PE_Msk;
                    PWM_ARR[TIM_i]->CCMR1 |=TIM_CCMR1_OC2PE_Msk;     //使能ch2预装载寄存器
                    PWM_ARR[TIM_i]->CCER |= TIM_CCER_CC2E_Msk;
                    //PWM_ARR[TIM_i]->CCER |= TIM_CCER_CC2NP_Msk;     //使能PWM输出
                    break;
                 }
                case 3:   //通道3
                   {
                    PWM_ARR[TIM_i]->CCMR2 &= ~TIM_CCMR2_OC3M_Msk;
                    PWM_ARR[TIM_i]->CCMR2 |= 6 << TIM_CCMR2_OC3M_Pos; //选择PWM模式1
                    PWM_ARR[TIM_i]->CCER &= ~TIM_CCER_CC3P_Msk;       //设置为正极性
                    PWM_ARR[TIM_i]->CCR3=temp;  //设置占空比
                    PWM_ARR[TIM_i]->CCMR2 &=~TIM_CCMR2_OC3PE_Msk;
                    PWM_ARR[TIM_i]->CCMR2 |=TIM_CCMR2_OC3PE_Msk;     //使能ch3预装载寄存器
                    PWM_ARR[TIM_i]->CCER |= TIM_CCER_CC3E_Msk;
                    //PWM_ARR[TIM_i]->CCER |= TIM_CCER_CC3NP_Msk;      //使能PWM输出
                    break;
                }
                case 4:  //通道4
                {
                    PWM_ARR[TIM_i]->CCMR2 &= ~TIM_CCMR2_OC4M_Msk;
                    PWM_ARR[TIM_i]->CCMR2 |= 6 << TIM_CCMR2_OC4M_Pos; //选择PWM模式1
                    PWM_ARR[TIM_i]->CCER &= ~TIM_CCER_CC4P_Msk;       //设置为正极性
                    PWM_ARR[TIM_i]->CCR4=temp;  //设置占空比
                    PWM_ARR[TIM_i]->CCMR2 &=~TIM_CCMR2_OC4PE_Msk;
                    PWM_ARR[TIM_i]->CCMR2 |=TIM_CCMR2_OC4PE_Msk;     //使能ch4预装载寄存器
                    PWM_ARR[TIM_i]->CCER |= TIM_CCER_CC4E_Msk;
                    //PWM_ARR[TIM_i]->CCER |= TIM_CCER_CC4NP_Msk;      //使能PWM输出
                    break;
                }
            }
        }
        else   //负极性
        {
            temp = (uint32_t)(period*(100-duty)/200);
            if(temp >= 65536)  temp=65535;
            switch(chl)
            {
                case 1: //通道1
                {
                    PWM_ARR[TIM_i]->CCMR1 &= ~TIM_CCMR1_OC1M_Msk;
                    PWM_ARR[TIM_i]->CCMR1 |= 6 << TIM_CCMR1_OC1M_Pos; //选择PWM模式1
                    PWM_ARR[TIM_i]->CCER &= TIM_CCER_CC1P_Msk;       //设置为负极性
                    PWM_ARR[TIM_i]->CCR1=temp;  //设置占空比
                    PWM_ARR[TIM_i]->CCMR1 &=~TIM_CCMR1_OC1PE_Msk;
                    PWM_ARR[TIM_i]->CCMR1 |=TIM_CCMR1_OC1PE_Msk;     //使能ch1预装载寄存器
                    PWM_ARR[TIM_i]->CCER |= TIM_CCER_CC1E_Msk;
                    //PWM_ARR[TIM_i]->CCER |= TIM_CCER_CC1NP_Msk;      //使能PWM输出
                    break;
                }
                case 2:   //通道2
                   {
                    PWM_ARR[TIM_i]->CCMR1 &= ~TIM_CCMR1_OC2M_Msk;
                    PWM_ARR[TIM_i]->CCMR1 |= 6 << TIM_CCMR1_OC2M_Pos; //选择PWM模式1
                    PWM_ARR[TIM_i]->CCER &= TIM_CCER_CC2P_Msk;       //设置为负极性
                    PWM_ARR[TIM_i]->CCR2=temp;  //设置占空比
                    PWM_ARR[TIM_i]->CCMR1 &=~TIM_CCMR1_OC2PE_Msk;
                    PWM_ARR[TIM_i]->CCMR1 |=TIM_CCMR1_OC2PE_Msk;     //使能ch2预装载寄存器
                    PWM_ARR[TIM_i]->CCER |= TIM_CCER_CC2E_Msk;
                    //PWM_ARR[TIM_i]->CCER |= TIM_CCER_CC2NP_Msk;      //使能PWM输出
                    break;
                }
                case 3:   //通道3
                {
                    PWM_ARR[TIM_i]->CCMR2 &= ~TIM_CCMR2_OC3M_Msk;
                    PWM_ARR[TIM_i]->CCMR2 |= 6 << TIM_CCMR2_OC3M_Pos; //选择PWM模式1
                    PWM_ARR[TIM_i]->CCER &= TIM_CCER_CC3P_Msk;       //设置为负极性
                    PWM_ARR[TIM_i]->CCR3=temp;  //设置占空比
                    PWM_ARR[TIM_i]->CCMR2 &=~TIM_CCMR2_OC3PE_Msk;
                    PWM_ARR[TIM_i]->CCMR2 |=TIM_CCMR2_OC3PE_Msk;     //使能ch3预装载寄存器
                    PWM_ARR[TIM_i]->CCER |= TIM_CCER_CC3E_Msk;
                    //PWM_ARR[TIM_i]->CCER |= TIM_CCER_CC3NP_Msk;      //使能PWM输出
                    break;
                }
                case 4:  //通道4
                {
                    PWM_ARR[TIM_i]->CCMR2 &= ~TIM_CCMR2_OC4M_Msk;
                    PWM_ARR[TIM_i]->CCMR2 |= 6 << TIM_CCMR2_OC4M_Pos; //选择PWM模式1
                    PWM_ARR[TIM_i]->CCER &= TIM_CCER_CC4P_Msk;       //设置为负极性
                    PWM_ARR[TIM_i]->CCR4=temp;  //设置占空比
                    PWM_ARR[TIM_i]->CCMR2 &=~TIM_CCMR2_OC4PE_Msk;
                    PWM_ARR[TIM_i]->CCMR2 |=TIM_CCMR2_OC4PE_Msk;     //使能ch4预装载寄存器
                    PWM_ARR[TIM_i]->CCER |= TIM_CCER_CC4E_Msk;
                    //PWM_ARR[TIM_i]->CCER |= TIM_CCER_CC4NP_Msk;      //使能PWM输出
                    break;
                }
            }
        }
    }
    else                  //边沿对齐
    {
        tim_timer_init1(TIM_i,clockFre,period);
        PWM_ARR[TIM_i]->CR1 &= ~(TIM_CR1_DIR | TIM_CR1_CMS);//设置向上计数模式、边沿对齐
        //(3)PWM极性的设定和PWM占空比的设定
        temp = PWM_ARR[TIM_i]->ARR + 1;  //计算周期(period)
        if(pol == PWM_PLUS)             //正极性    
        {
            temp = (uint32_t)(temp*duty/100);  
            if(temp >= 65536)  temp=65535;
            switch(chl)
            {
                case 1: //通道1
                {
                    PWM_ARR[TIM_i]->CCMR1 &= ~TIM_CCMR1_OC1M_Msk;
                    PWM_ARR[TIM_i]->CCMR1 |= 6 << TIM_CCMR1_OC1M_Pos; //选择PWM模式1
                    PWM_ARR[TIM_i]->CCER &= ~TIM_CCER_CC1P_Msk;       //设置为正极性
                    PWM_ARR[TIM_i]->CCR1=temp;  //设置占空比
                    PWM_ARR[TIM_i]->CCMR1 &=~TIM_CCMR1_OC1PE_Msk;
                    PWM_ARR[TIM_i]->CCMR1 |=TIM_CCMR1_OC1PE_Msk;     //使能ch1预装载寄存器
                    PWM_ARR[TIM_i]->CCER |= TIM_CCER_CC1E_Msk;
                    //PWM_ARR[TIM_i]->CCER |= TIM_CCER_CC1NP_Msk;      //使能PWM输出
                    break;
                }
                case 2:   //通道2
                {
                    PWM_ARR[TIM_i]->CCMR1 &= ~TIM_CCMR1_OC2M_Msk;
                    PWM_ARR[TIM_i]->CCMR1 |= 6 << TIM_CCMR1_OC2M_Pos; //选择PWM模式1
                    PWM_ARR[TIM_i]->CCER &= ~TIM_CCER_CC2P_Msk;       //设置为正极性
                    PWM_ARR[TIM_i]->CCR2=temp;  //设置占空比
                    PWM_ARR[TIM_i]->CCMR1 &=~TIM_CCMR1_OC2PE_Msk;
                    PWM_ARR[TIM_i]->CCMR1 |=TIM_CCMR1_OC2PE_Msk;     //使能ch2预装载寄存器
                    PWM_ARR[TIM_i]->CCER |= TIM_CCER_CC2E_Msk;
                    //PWM_ARR[TIM_i]->CCER |= TIM_CCER_CC2NP_Msk;      //使能PWM输出
                    break;
                 }
                case 3:   //通道3
                {
                    PWM_ARR[TIM_i]->CCMR2 &= ~TIM_CCMR2_OC3M_Msk;
                    PWM_ARR[TIM_i]->CCMR2 |= 6 << TIM_CCMR2_OC3M_Pos; //选择PWM模式1
                    PWM_ARR[TIM_i]->CCER &= ~TIM_CCER_CC3P_Msk;       //设置为正极性
                    PWM_ARR[TIM_i]->CCR3=temp;  //设置占空比
                    PWM_ARR[TIM_i]->CCMR2 &=~TIM_CCMR2_OC3PE_Msk;
                    PWM_ARR[TIM_i]->CCMR2 |=TIM_CCMR2_OC3PE_Msk;     //使能ch3预装载寄存器
                    PWM_ARR[TIM_i]->CCER |= TIM_CCER_CC3E_Msk;
                    //PWM_ARR[TIM_i]->CCER |= TIM_CCER_CC3NP_Msk;      //使能PWM输出
                    break;
                }
                case 4:  //通道4
                {
                    PWM_ARR[TIM_i]->CCMR2 &= ~TIM_CCMR2_OC4M_Msk;
                    PWM_ARR[TIM_i]->CCMR2 |= 6 << TIM_CCMR2_OC4M_Pos; //选择PWM模式1
                    PWM_ARR[TIM_i]->CCER &= ~TIM_CCER_CC4P_Msk;       //设置为正极性
                    PWM_ARR[TIM_i]->CCR4=temp;  //设置占空比
                    PWM_ARR[TIM_i]->CCMR2 &=~TIM_CCMR2_OC4PE_Msk;
                    PWM_ARR[TIM_i]->CCMR2 |=TIM_CCMR2_OC4PE_Msk;     //使能ch4预装载寄存器
                    PWM_ARR[TIM_i]->CCER |= TIM_CCER_CC4E_Msk;
                    //PWM_ARR[TIM_i]->CCER |= TIM_CCER_CC4NP_Msk;      //使能PWM输出
                    break;
                }
            
            }
        }
        else   //负极性
        {
            temp = (uint32_t)(temp*(100-duty)/100);  
            if(temp >= 65536)  temp=65535;
            switch(chl)
            {
                case 1: //通道1
                {
                    PWM_ARR[TIM_i]->CCMR1 &= ~TIM_CCMR1_OC1M_Msk;
                    PWM_ARR[TIM_i]->CCMR1 |= 6 << TIM_CCMR1_OC1M_Pos; //选择PWM模式1
                    PWM_ARR[TIM_i]->CCER &= TIM_CCER_CC1P_Msk;       //设置为负极性
                    PWM_ARR[TIM_i]->CCR1=temp;  //设置占空比
                    PWM_ARR[TIM_i]->CCMR1 &=~TIM_CCMR1_OC1PE_Msk;
                    PWM_ARR[TIM_i]->CCMR1 |=TIM_CCMR1_OC1PE_Msk;     //使能ch1预装载寄存器
                    PWM_ARR[TIM_i]->CCER |= TIM_CCER_CC1E_Msk;
                    //PWM_ARR[TIM_i]->CCER |= TIM_CCER_CC1NP_Msk;      //使能PWM输出
                    break;
                 }
                case 2:   //通道2
                {
                    PWM_ARR[TIM_i]->CCMR1 &= ~TIM_CCMR1_OC2M_Msk;
                    PWM_ARR[TIM_i]->CCMR1 |= 6 << TIM_CCMR1_OC2M_Pos; //选择PWM模式1
                    PWM_ARR[TIM_i]->CCER &= TIM_CCER_CC2P_Msk;       //设置为负极性
                    PWM_ARR[TIM_i]->CCR2=temp;  //设置占空比
                    PWM_ARR[TIM_i]->CCMR1 &=~TIM_CCMR1_OC2PE_Msk;
                    PWM_ARR[TIM_i]->CCMR1 |=TIM_CCMR1_OC2PE_Msk;     //使能ch2预装载寄存器
                    PWM_ARR[TIM_i]->CCER |= TIM_CCER_CC2E_Msk;
                    //PWM_ARR[TIM_i]->CCER |= TIM_CCER_CC2NP_Msk;      //使能PWM输出
                    break;
                 }
                case 3:   //通道3
                {
                    PWM_ARR[TIM_i]->CCMR2 &= ~TIM_CCMR2_OC3M_Msk;
                    PWM_ARR[TIM_i]->CCMR2 |= 6 << TIM_CCMR2_OC3M_Pos; //选择PWM模式1
                    PWM_ARR[TIM_i]->CCER &= TIM_CCER_CC3P_Msk;       //设置为负极性
                    PWM_ARR[TIM_i]->CCR3=temp;  //设置占空比
                    PWM_ARR[TIM_i]->CCMR2 &=~TIM_CCMR2_OC3PE_Msk;
                    PWM_ARR[TIM_i]->CCMR2 |=TIM_CCMR2_OC3PE_Msk;     //使能ch3预装载寄存器
                    PWM_ARR[TIM_i]->CCER |= TIM_CCER_CC3E_Msk;
                    //PWM_ARR[TIM_i]->CCER |= TIM_CCER_CC3NP_Msk;      //使能PWM输出
                    break;
                }
                case 4:  //通道4
                   {
                    PWM_ARR[TIM_i]->CCMR2 &= ~TIM_CCMR2_OC4M_Msk;
                    PWM_ARR[TIM_i]->CCMR2 |= 6 << TIM_CCMR2_OC4M_Pos; //选择PWM模式1
                    PWM_ARR[TIM_i]->CCER &= TIM_CCER_CC4P_Msk;       //设置为负极性
                    PWM_ARR[TIM_i]->CCR4=temp;  //设置占空比
                    PWM_ARR[TIM_i]->CCMR2 &=~TIM_CCMR2_OC4PE_Msk;
                    PWM_ARR[TIM_i]->CCMR2 |=TIM_CCMR2_OC4PE_Msk;     //使能ch4预装载寄存器
                    PWM_ARR[TIM_i]->CCER |= TIM_CCER_CC4E_Msk;
                    //PWM_ARR[TIM_i]->CCER |= TIM_CCER_CC4NP_Msk;      //使能PWM输出
                    break;
                }
            }
        }
     }
    PWM_ARR[TIM_i]->EGR |= TIM_EGR_UG_Msk;  //初始化计数器;
    PWM_ARR[TIM_i]->CR1 |= TIM_CR1_CEN_Msk | TIM_CR1_ARPE_Msk;//使能定时器
}

//=====================================================================
//函数名称:  pwm_update
//功能概要:  timx模块Chy通道的PWM更新
//参数说明:  pwmNo:pwm模块号,在gec.h的宏定义给出,如PWM_PIN0表示PWM0通道
//          duty:占空比:0.0~100.0对应0%~100%
//函数返回:  无
//=====================================================================
void pwm_update(uint16_t pwmNo,double duty)
{
    uint8_t TIM_i,chl;  //由timx_Chy解析出的tim模块号、通道号临时变量
    uint32_t period;
    // 防止越界
    if(duty>100.0)  duty=100.0;
    //1. 获得解析的tpm模块号和通道号
    tim_mux_val(pwmNo,&TIM_i,&chl);
    period=PWM_ARR[TIM_i]->ARR;
    //2. 更新PWM通道寄存器值
    switch(chl)
    {
        case 1:PWM_ARR[TIM_i]->CCR1=(uint32_t)(period*duty/100);break;
        case 2:PWM_ARR[TIM_i]->CCR2=(uint32_t)(period*duty/100);break;
        case 3:PWM_ARR[TIM_i]->CCR3=(uint32_t)(period*duty/100);break;
        case 4:PWM_ARR[TIM_i]->CCR4=(uint32_t)(period*duty/100);break;
    }
}

//------以下为内部函数------
//=====================================================================
//函数名称:tpm_mux_val
//功能概要:将传进参数pwmNo进行解析,得出具体模块号与通道号(例:PWM_PIN0
//         解析出PORT引脚,并设置指定引脚为PWM功能)。
//参数说明:pwmNo:pwm模块号,在头文件的宏定义给出,如PWM_PIN0表示PWM0通道
//
//函数返回:无
//=====================================================================
void tim_mux_val(uint16_t pwmNo,uint8_t* TIM_i,uint8_t* chl)
{ 
    //uint8_t port,pin;
    //1.解析模块号和通道号
    switch(pwmNo)
    {
        case ((0<<8)|5):
                *TIM_i =0;
                *chl=1;
                RCC->AHB2ENR |=RCC_AHB2ENR_GPIOAEN_Msk;
                GPIOA->MODER &= ~GPIO_MODER_MODE5_Msk;
                GPIOA->MODER |= 2<<GPIO_MODER_MODE5_Pos;
                GPIOA->OTYPER &= ~GPIO_OTYPER_OT5_Msk;
                GPIOA->OSPEEDR &= ~GPIO_OSPEEDR_OSPEED5_Msk;
                GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD5_Msk;
                GPIOA->AFR[0] &= ~GPIO_AFRL_AFSEL5_Msk;
                GPIOA->AFR[0] |= 1<<GPIO_AFRL_AFSEL5_Pos;
        break;
        case ((0<<8)|15):
                *TIM_i =0;
                *chl=1;
                RCC->AHB2ENR |=RCC_AHB2ENR_GPIOAEN_Msk;
                GPIOA->MODER &= ~GPIO_MODER_MODE15_Msk;
                GPIOA->MODER |= 2<<GPIO_MODER_MODE5_Pos;
                GPIOA->OTYPER &= ~GPIO_OTYPER_OT15_Msk;
                GPIOA->OSPEEDR &= ~GPIO_OSPEEDR_OSPEED15_Msk;
                GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD15_Msk;
                GPIOA->AFR[1] &= ~GPIO_AFRH_AFSEL15_Msk;
                GPIOA->AFR[1] |= 1<<GPIO_AFRH_AFSEL15_Pos;
        break;
        case ((1<<8)|3):
                *TIM_i =0;
                *chl=2;
                RCC->AHB2ENR |=RCC_AHB2ENR_GPIOBEN_Msk;
                GPIOB->MODER &= ~GPIO_MODER_MODE3_Msk;
                GPIOB->MODER |= 2<<GPIO_MODER_MODE3_Pos;
                GPIOB->OTYPER &= ~GPIO_OTYPER_OT3_Msk;
                GPIOB->OSPEEDR &= ~GPIO_OSPEEDR_OSPEED3_Msk;
                GPIOB->PUPDR &= ~GPIO_PUPDR_PUPD3_Msk;
                GPIOB->AFR[0] &= ~GPIO_AFRL_AFSEL3_Msk;
                GPIOB->AFR[0] |= 1<<GPIO_AFRL_AFSEL3_Pos;
        break;
        case ((1<<8)|10):
                *TIM_i =0;
                *chl=3;
                RCC->AHB2ENR |=RCC_AHB2ENR_GPIOBEN_Msk;
                GPIOB->MODER &= ~GPIO_MODER_MODE10_Msk;
                GPIOB->MODER |= 2<<GPIO_MODER_MODE10_Pos;
                GPIOB->OTYPER &= ~GPIO_OTYPER_OT10_Msk;
                GPIOB->OSPEEDR &= ~GPIO_OSPEEDR_OSPEED10_Msk;
                GPIOB->PUPDR &= ~GPIO_PUPDR_PUPD10_Msk;
                GPIOB->AFR[1] &= ~GPIO_AFRH_AFSEL10_Msk;
                GPIOB->AFR[1] |= 1<<GPIO_AFRH_AFSEL10_Pos;
        break;
        case ((1<<8)|11):
               *TIM_i =0;
               *chl=4;
               RCC->AHB2ENR |=RCC_AHB2ENR_GPIOBEN_Msk;
               GPIOB->MODER &= ~GPIO_MODER_MODE11_Msk;
               GPIOB->MODER |= 2<<GPIO_MODER_MODE11_Pos;
               GPIOB->OTYPER &= ~GPIO_OTYPER_OT11_Msk;
               GPIOB->OSPEEDR &= ~GPIO_OSPEEDR_OSPEED11_Msk;
               GPIOB->PUPDR &= ~GPIO_PUPDR_PUPD11_Msk;
               GPIOB->AFR[1] &= ~GPIO_AFRH_AFSEL11_Msk;
               GPIOB->AFR[1] |= 1<<GPIO_AFRH_AFSEL11_Pos;
        break;
    }    
}

//===================================================================
//函数名称:  tim_timer_init1
//功能概要:  tim模块初始化,设置计数器频率f及计数器溢出时间MOD_Value。
//参数说明:  pwmNo:pwm模块号,在gec.h的宏定义给出,如PWM_PIN0表示PWM0通道
//          f:单位:Khz,取值:375、750、1500、3000、6000、12000、24000、48000
//          MOD_Value:单位个数:范围取决于计数器频率与计数器位数(16位)
//函数返回:  无
//===================================================================
void tim_timer_init1(uint16_t TIM_i,uint32_t f,uint16_t MOD_Value)
{
    //局部变量声明
    uint32_t clk_f;
    if(TIM_i==0)
    {
        //(1)使能定时器时钟
        RCC->APB1ENR1 |= RCC_APB1ENR1_TIM2EN;
        //(2)设置时钟频率 
        clk_f=MCU_SYSTEM_CLK /f;
        TIM2->PSC = clk_f-1;
        // (3)计数器清零
        TIM2->CNT = 0;
        //(4)设置溢出值
        if(MOD_Value == 0)
        {
            TIM2->ARR = 0; 
        }
        else
        {
            TIM2->ARR = (uint32_t)(MOD_Value-1);  
        }
        //(5)更新中断使能
        //TIM2->DIER |= TIM_DIER_UIE_Msk;
    }
}

 

 

输入捕捉与输出比较

输入捕获,当通道输入引脚出现指定的电平跳变时,将当前寄存器的值锁到一个寄存器中,可以用于测量pwm波形的频率,占空比,电平持续时间等问题。

输出比较,将计数器与比较寄存器相比较,大于输出一种波形,小于输出一种波形。可以做一些相应的动作,如:电平翻转等,常用于产生pwm波形。

 

 

//===================================================================
//函数名称:incap_init
//功能概要:incap模块初始化。
//参数说明:capNo:输入捕捉通道号(使用宏定义INCAP_PIN0、INCAP_PIN1、…)
//        clockFre:时钟频率,单位:Khz,取值:375、750、1500、3000、6000、
//                                                   12000、24000、48000
//        period:自动重装载器值,单位为个数,即计数器跳动次数,范围为1~65536
//        capmode:输入捕捉模式(上升沿、下降沿、双边沿),有宏定义常数使用
//函数返回:无
//注意:          因为GEC中给出的PWM和输入捕捉都是同一模块的,只是通道不同,所以为防止在使用多组
//          PWM和输入捕捉时,频率篡改,需要使得使用到的clockFre和period参数保持一致。

//capNo  #define  INCAP_PIN0  GEC_10  //GEC_10(PTC_NUM|2)//UART0_TX
//       #define  INCAP_PIN1  GEC_8  //GEC_8(PTC_NUM|3)//UART0_RX
//===================================================================
void incapture_init(uint16_t capNo,uint32_t clockFre,uint16_t period,uint8_t capmode)
{
    GPIO_TypeDef *gpio_ptr;    //声明gpio_ptr为GPIO结构体类型指针
    uint8_t port,pin;    //声明端口port、引脚pin变量
    uint8_t TIM_i,chl;  //由tpmx_Chy解析出的tim模块号、通道号临时变量
    uint32_t temp;       //临时存放寄存器里的值
    //gpio引脚解析
    port = (capNo>>8);     //解析出的端口
    pin = capNo;           //解析出的引脚号
    
    tim_mux_val(capNo,&TIM_i,&chl);//由对应模块号(PTx_num|y))得出时钟模块号和通道号
    timer_init2(TIM_i,clockFre,period);//时钟模块初始化

    //GPIO寄存器引脚复用
    gpio_ptr=GPIO_ARR[port];
    RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN_Msk<< (port * 1u);//使能GPIO时钟
    //进行模式选择,引脚选择备用功能
    temp = gpio_ptr->MODER;
    temp &= ~(GPIO_MODER_MODE0 << (pin * 2u));
    temp|=2<<(pin * 2u);
    gpio_ptr->MODER = temp;

    gpio_ptr->OTYPER &= ~(GPIO_OTYPER_OT0_Msk<<(pin * 1u));//推挽输出
    gpio_ptr->OSPEEDR &= ~(GPIO_OSPEEDR_OSPEED0<<(pin * 2u));//设置速度
    gpio_ptr->PUPDR &= ~(GPIO_PUPDR_PUPD0<<(pin * 2u));//下拉
   //引脚复用选择对应通道功能
    gpio_ptr->AFR[0]&=~(GPIO_AFRL_AFSEL0_Msk<< (pin * 4u));
    gpio_ptr->AFR[0]|=14<<(pin * 4u);
   
    if(TIM_i==15)
    {
        if(chl==1)
        {
            TIM15->CCMR1&=~TIM_CCMR1_IC1F;//无滤波器
            TIM15->CCMR1&=~TIM_CCMR1_IC1PSC;//无预分频器,捕获输入上每检测到一个边沿便执行捕获
            TIM15->CCMR1|=TIM_CCMR1_CC1S_0;//CC1 通道配置为输入,IC1 映射到 TI1 上
            //输入捕捉参数设定CC1P与CC1NP配合使用
            if(capmode == CAP_UP)//上升沿捕捉
            {
                TIM15->CCER&=~TIM_CCER_CC1P;
                TIM15->CCER&=~TIM_CCER_CC1NP;
             }
            else if(capmode == CAP_DOWN)//下降沿捕捉
            {
                TIM15->CCER|=TIM_CCER_CC1P;
                TIM15->CCER&=~TIM_CCER_CC1NP;
             }
            else if(capmode == CAP_DOUBLE)//双边沿捕捉
            {
                TIM15->CCER|=TIM_CCER_CC1P;
                TIM15->CCER|=TIM_CCER_CC1NP;
             }
            TIM15->CCER|=TIM_CCER_CC1E;//使能捕获,决定了是否可以实际将计数器值捕获到输入捕获/比较寄存器 1(TIMx_CCR1)
        }
        if(chl==2)
        {
            TIM15->CCMR1&=~TIM_CCMR1_IC2F;//无滤波器
            TIM15->CCMR1&=~TIM_CCMR1_IC2PSC;//无预分频器,捕获输入上每检测到一个边沿便执行捕获
            TIM15->CCMR1|=TIM_CCMR1_CC2S_0;//CC2 通道配置为输入,IC2 映射到 TI2 上
          //输入捕捉参数设定CC2P与CC2NP配合使用
            if(capmode == CAP_UP)//上升沿捕捉
            {
                TIM15->CCER&=~TIM_CCER_CC2P;
                TIM15->CCER&=~TIM_CCER_CC2NP;
             }
            else if(capmode == CAP_DOWN)//下降沿捕捉
            {
                TIM15->CCER|=TIM_CCER_CC2P;
                TIM15->CCER&=~TIM_CCER_CC2NP;
             }
            else if(capmode == CAP_DOUBLE)//双边沿捕捉
            {
                TIM15->CCER|=TIM_CCER_CC2P;
                TIM15->CCER|=TIM_CCER_CC2NP;
             }
            TIM15->CCER|=TIM_CCER_CC2E;//使能捕获,决定了是否可以实际将计数器值捕获到输入捕获/比较寄存器2(TIMx_CCR2)
        }
    }
}
//=====================================================================
//函数名称:incapture_value
//功能概要:获取该通道的计数器当前值
//参数说明:capNo:输入捕捉通道号(使用宏定义INCAP_PIN0、INCAP_PIN1、…)
//函数返回:通道的计数器当前值
//=====================================================================
uint16_t get_incapture_value(uint16_t capNo)
{
    uint8_t TIM_i,chl;  //由tapNo解析出的tim模块号、通道号临时变量
    uint16_t cnt=0;
    tim_mux_val(capNo,&TIM_i,&chl);//解析tim模块号和通道号
    if(TIM_i==15)
    {
        if(chl==1)
            cnt=TIM15->CCR1;
        else if(chl==2)
            cnt=TIM15->CCR2;
    }
    return cnt;
}

//===================================================================
//函数名称:cap_clear_flag
//功能概要:清输入捕捉中断标志位。
//参数说明:capNo:输入捕捉通道号(使用宏定义INCAP_PIN0、INCAP_PIN1、…)
//函数返回:无
//===================================================================
void cap_clear_flag(uint16_t capNo)
{
    uint8_t TIM_i,chl;  //由capNo解析出的tim模块号、通道号临时变量
    tim_mux_val(capNo,&TIM_i,&chl);
    if(TIM_i==15)
    {
        if(chl==1)
            TIM15->SR&=~TIM_SR_CC1IF;
        else if(chl==2)
            TIM15->SR&=~TIM_SR_CC2IF;
     }
}

//===================================================================
//函数名称:cap_get_flag
//功能概要:获取输入捕捉中断标志位。
//参数说明:capNo:输入捕捉通道号(使用宏定义INCAP_PIN0、INCAP_PIN1、…)
//函数返回:返回当前中断标志位
//===================================================================
uint8_t cap_get_flag(uint16_t capNo)
{
    uint8_t TIM_i,chl,flag;  //由capNo解析出的tim模块号、通道号临时变量
    flag=0;
    tim_mux_val(capNo,&TIM_i,&chl);   //解析tim模块号和通道号
    if(TIM_i==15)
    {
        if(chl==1)
        {
            if((TIM15->SR&=TIM_SR_CC1IF)==TIM_SR_CC1IF)
                flag=1;
            else flag=0;
         }
        else if(chl==2)
        {
            if((TIM15->SR&=TIM_SR_CC2IF)==TIM_SR_CC2IF)
                flag=1;
            else flag=0;
         }
    }
    return flag;
}

//===================================================================
//函数名称:cap_enable_int
//功能概要:使能输入捕捉中断。
//参数说明:capNo:输入捕捉通道号(使用宏定义INCAP_PIN0、INCAP_PIN1、…)
//函数返回:无
//===================================================================
void cap_enable_int(uint16_t capNo)
{
    uint8_t TIM_i,chl;  //由capNo解析出的tim模块号、通道号临时变量
    tim_mux_val(capNo,&TIM_i,&chl);   //解析tim模块号和通道号
    if(TIM_i==15)
    {
        if(chl==1)
        {
            TIM15->DIER|=TIM_DIER_CC1IE;//使能捕获中断
            NVIC_EnableIRQ(TIM1_BRK_TIM15_IRQn);    //开中断控制器IRQ中断
         }
        else if(chl==2)
        {
             TIM15->DIER|=TIM_DIER_CC2IE;//使能捕获中断
            NVIC_EnableIRQ(TIM1_BRK_TIM15_IRQn);    //开中断控制器IRQ中断
         }
     }

}
//===================================================================
//函数名称:outcmp_init
//功能概要:outcmp模块初始化。
//参数说明:outcmpNo:模块号,使用gec.h中宏定义,例如OUTCMP_PIN0
//        freq:单位:Khz,取值:375、750、1500、3000、6000、12000、24000、48000(频率决定精度)
//        cmpPeriod:单位:ms,范围取决于计数器频率与计数器位数(16位)
//        comduty:输出比较电平翻转位置占自动重装载寄存器值的比例:0.0~100.0对应0%~100%
//        cmpmode:输出比较模式(翻转电平、强制低电平、强制高电平),有宏定义常数使用
//函数返回:无
//===================================================================
void outcmp_init(uint16_t outcmpNo,uint32_t freq,uint32_t cmpPeriod,float cmpduty,uint8_t cmpmode)
{
//    GPIO_TypeDef * port_ptr;   //声明port_ptr为GPIO结构体类型指针
//    uint8_t port,pin;           //解析出的端口、引脚号临时变量
//    uint8_t mux_val;
    uint8_t TIM_i,chl;  //由timx_Chy解析出的tim模块号、通道号临时变量
    uint32_t mod;
    uint32_t clk_f;
    //防止越界
    if(cmpduty>100.0)  cmpduty=100.0;
    //1. gpio引脚解析
    //port = (outcmpNo>>8);    //解析出的端口
    //pin = outcmpNo;          //解析出的引脚号
    //2. 根据port,给局部变量port_ptr赋值,获得基地址
    //port_ptr = GPIO_ARR[port];  //获得GPIO模块相应口基地址
    //3. 获得解析的tim模块号和通道号
    outcmp_mux_val(outcmpNo,&TIM_i,&chl);
    //4.初始化TIM模块功能
    switch(TIM_i)
    {
        case 0:
        {
        RCC->APB1ENR1 |= RCC_APB1ENR1_TIM2EN;    //1)使能定时器时钟
        clk_f=MCU_SYSTEM_CLK /(freq*1000);
        TIM2->PSC = clk_f-1;    //2)设置时钟频率
        TIM2->ARR = (uint32_t)(MCU_SYSTEM_CLK_KHZ/(clk_f)*cmpPeriod-1);    //3)设置ARR寄存器
        TIM2->CNT = 0;    //4)计数器清零
        OUTCMP_ARR[TIM_i]->EGR |= TIM_EGR_UG_Msk;  //初始化定时器
        break;
        }
    }
    //5. 根据pin,指定该引脚功能为TIM的通道功能
    switch(outcmpNo)
    {
        case ((0<<8)|5):
            RCC->AHB2ENR |=RCC_AHB2ENR_GPIOAEN_Msk;
            GPIOA->MODER &= ~GPIO_MODER_MODE5_Msk;
            GPIOA->MODER |= 2<<GPIO_MODER_MODE5_Pos;
            GPIOA->OTYPER &= ~GPIO_OTYPER_OT5_Msk;
            GPIOA->OSPEEDR &= ~GPIO_OSPEEDR_OSPEED5_Msk;
            GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD5_Msk;
            GPIOA->AFR[0] &= ~GPIO_AFRL_AFSEL5_Msk;
            GPIOA->AFR[0] |= 1<<GPIO_AFRL_AFSEL5_Pos;
            break;
        case ((0<<8)|15):
            RCC->AHB2ENR |=RCC_AHB2ENR_GPIOAEN_Msk;
            GPIOA->MODER &= ~GPIO_MODER_MODE15_Msk;
            GPIOA->MODER |= 2<<GPIO_MODER_MODE5_Pos;
            GPIOA->OTYPER &= ~GPIO_OTYPER_OT15_Msk;
            GPIOA->OSPEEDR &= ~GPIO_OSPEEDR_OSPEED15_Msk;
            GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD15_Msk;
            GPIOA->AFR[1] &= ~GPIO_AFRH_AFSEL15_Msk;
            GPIOA->AFR[1] |= 1<<GPIO_AFRH_AFSEL15_Pos;
            break;
        case ((1<<8)|3):
            RCC->AHB2ENR |=RCC_AHB2ENR_GPIOBEN_Msk;
            GPIOB->MODER &= ~GPIO_MODER_MODE3_Msk;
            GPIOB->MODER |= 2<<GPIO_MODER_MODE3_Pos;
            GPIOB->OTYPER &= ~GPIO_OTYPER_OT3_Msk;
            GPIOB->OSPEEDR &= ~GPIO_OSPEEDR_OSPEED3_Msk;
            GPIOB->PUPDR &= ~GPIO_PUPDR_PUPD3_Msk;
            GPIOB->AFR[0] &= ~GPIO_AFRL_AFSEL3_Msk;
            GPIOB->AFR[0] |= 1<<GPIO_AFRL_AFSEL3_Pos;
            break;
        case ((1<<8)|10):
            RCC->AHB2ENR |=RCC_AHB2ENR_GPIOBEN_Msk;
            GPIOB->MODER &= ~GPIO_MODER_MODE10_Msk;
            GPIOB->MODER |= 2<<GPIO_MODER_MODE10_Pos;
            GPIOB->OTYPER &= ~GPIO_OTYPER_OT10_Msk;
            GPIOB->OSPEEDR &= ~GPIO_OSPEEDR_OSPEED10_Msk;
            GPIOB->PUPDR &= ~GPIO_PUPDR_PUPD10_Msk;
            GPIOB->AFR[1] &= ~GPIO_AFRH_AFSEL10_Msk;
            GPIOB->AFR[1] |= 1<<GPIO_AFRH_AFSEL10_Pos;
            break;
        case ((1<<8)|11):
            RCC->AHB2ENR |=RCC_AHB2ENR_GPIOBEN_Msk;
            GPIOB->MODER &= ~GPIO_MODER_MODE11_Msk;
            GPIOB->MODER |= 2<<GPIO_MODER_MODE11_Pos;
            GPIOB->OTYPER &= ~GPIO_OTYPER_OT11_Msk;
            GPIOB->OSPEEDR &= ~GPIO_OSPEEDR_OSPEED11_Msk;
            GPIOB->PUPDR &= ~GPIO_PUPDR_PUPD11_Msk;
            GPIOB->AFR[1] &= ~GPIO_AFRH_AFSEL11_Msk;
            GPIOB->AFR[1] |= 1<<GPIO_AFRH_AFSEL11_Pos;
            break;
    }
    //6. 输出比较模式的设定
    OUTCMP_ARR[TIM_i]->CCMR2 &=~TIM_CCMR2_CC3S; //设置通道3为输出
    OUTCMP_ARR[TIM_i]->CCMR2 &=~TIM_CCMR2_OC3PE;   //输出预载除能
    OUTCMP_ARR[TIM_i]->CCER &=~TIM_CCER_CC3P;   //设置有效电平为高
    if(cmpmode == CMP_REV)        //翻转模式
        OUTCMP_ARR[TIM_i]->CCMR2 |=    0x3UL<<TIM_CCMR2_OC3M_Pos;
    else if(cmpmode == CMP_LOW)   //强制低电平模式
        OUTCMP_ARR[TIM_i]->CCMR2 |=    0x2UL<<TIM_CCMR2_OC3M_Pos;
    else if(cmpmode == CMP_HIGH)  //强制高电平模式
    {
      OUTCMP_ARR[TIM_i]->CCMR2 |= 0x1UL<<TIM_CCMR2_OC3M_Pos;
    }
    //7. 输出比较相位的设定
    mod=OUTCMP_ARR[TIM_i]->ARR+1;   //读ARR寄存器的值
    OUTCMP_ARR[TIM_i]->CCR3=(uint32_t)(mod*(cmpduty/100.0));
  
    OUTCMP_ARR[TIM_i]->CR1 |= TIM_CR1_CEN_Msk;//使能计数器
    OUTCMP_ARR[TIM_i]->CCER |=TIM_CCER_CC3E;  //通道3输出比较使能
   
    
}

//===================================================================
//函数名称:outcmp_enable_int
//功能概要:使能tim模块中断。
//参数说明:outcmpNo:模块号,使用gec.h中宏定义,例如OUTCMP_PIN0
//函数返回:无
//===================================================================
void outcmp_enable_int(uint16_t outcmpNo)
{
    uint8_t TIM_i,chl;  //由timx_Chy解析出的tim模块号、通道号临时变量
    outcmp_mux_val(outcmpNo,&TIM_i,&chl);
    OUTCMP_ARR[TIM_i]->DIER |= (0x1UL<<chl);
    //开TIM中断
    NVIC_EnableIRQ(OUTCMP_IRQ[TIM_i]);
}

//===================================================================
//函数名称:outcmp_disable_int
//功能概要:禁用tim模块中断。
//参数说明:outcmpNo:模块号,使用gec.h中宏定义,例如OUTCMP_PIN0
//函数返回:无
//===================================================================
void outcmp_disable_int(uint16_t outcmpNo)
{
    uint8_t TIM_i,chl;  //由timx_Chy解析出的tim模块号、通道号临时变量
    outcmp_mux_val(outcmpNo,&TIM_i,&chl);
    OUTCMP_ARR[TIM_i]->DIER &= ~(0x1UL<<chl);
    //关TIM中断
    NVIC_DisableIRQ(OUTCMP_IRQ[TIM_i]);
}

//===================================================================
//函数名称:outcmp_get_int
//功能概要:获取TIM模块中断标志
//参数说明:outcmpNo:模块号,使用gec.h中宏定义,例如OUTCMP_PIN0
//函数返回:中断标志 1=有中断产生;0=无中断产生
//===================================================================
uint8_t outcmp_get_int(uint16_t outcmpNo)
{
  uint8_t TIM_i,chl;  //由timx_Chy解析出的tim模块号、通道号临时变量
  outcmp_mux_val(outcmpNo,&TIM_i,&chl);
  //获取TIM_i模块中断标志位
  if((OUTCMP_ARR[TIM_i]->SR & TIM_SR_UIF)==TIM_SR_UIF)
    return 1;
  else
    return 0;
}

//===================================================================
//函数名称:outcmp_chl_get_int
//功能概要:获取TIM通道中断标志
//参数说明:outcmpNo:模块号,使用gec.h中宏定义,例如OUTCMP_PIN0
//函数返回:中断标志 1=有中断产生;0=无中断产生
//===================================================================
uint8_t outcmp_chl_get_int(uint16_t outcmpNo)
{
   uint8_t TIM_i,chl;  //由timx_Chy解析出的tim模块号、通道号临时变量
   outcmp_mux_val(outcmpNo,&TIM_i,&chl);
   //获取TIM_i模块chl通道中断标志位
   if((OUTCMP_ARR[TIM_i]->SR&(0x1UL<<chl))==(0x1UL<<chl))
       return 1;
   else
       return 0;
}

//===================================================================
//函数名称:outcmp_clear_int
//功能概要:清除TIM中断标志
//参数说明:outcmpNo:模块号,使用gec.h中宏定义,例如OUTCMP_PIN0
//函数返回:清除中断标志位
//===================================================================
void outcmp_clear_int(uint16_t outcmpNo)
{
    uint8_t TIM_i,chl;  //由timx_Chy解析出的tim模块号、通道号临时变量
    outcmp_mux_val(outcmpNo,&TIM_i,&chl);
    //清除TIM_i模块中断标志位
    BCLR(0,OUTCMP_ARR[TIM_i]->SR);
}

//===================================================================
//函数名称:outcmp_clear_chl_int
//功能概要:清除TIM通道中断标志
//参数说明:outcmpNo:模块号,使用gec.h中宏定义,例如OUTCMP_PIN0
//函数返回:清除TIM通道中断标志位
//===================================================================
void outcmp_clear_chl_int(uint16_t outcmpNo)
{
    uint8_t TIM_i,chl;  //由timx_Chy解析出的tim模块号、通道号临时变量
    outcmp_mux_val(outcmpNo,&TIM_i,&chl);
    //清除TIM_i模块chl通道中断标志位
    BCLR(chl,OUTCMP_ARR[TIM_i]->SR);
}

//=====================================================================
//函数名称:outcmp_mux_val
//功能概要:将传进参数timx_Chy进行解析,得出具体模块号与通道号
//参数说明:timx_Chy:模块通道号
//
//函数返回:无
//=====================================================================
void  outcmp_mux_val(uint16_t timx_Chy,uint8_t* TIM_i,uint8_t* chl)
{
    //1.解析模块号和通道号
    switch(timx_Chy)
    {
        case OUTCMP_PIN0:*TIM_i =0;*chl=3;break;
        case OUTCMP_PIN1:*TIM_i =0;*chl=4;break;
        case OUTCMP_PIN2:*TIM_i =0;*chl=2;break;
        case OUTCMP_PIN3:*TIM_i =0;*chl=1;break;
        case OUTCMP_PIN4:*TIM_i =0;*chl=1;break;
        
    }
    
}