打印

STM32F407简便pwm配置函数

[复制链接]
245|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
王将|  楼主 | 2018-7-15 12:12 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
快毕业了,最近和几个哥们做项目。那哥们做了3年的飞卡,用惯了山外的底层,突然用st的,一时间没适应。
应他的要求,写了一个比较方便的pwm配置函数,能力有限,写完了也没咋做太多的测试,测试一个频率能输出就再没管了。

主要函数如下,详细参考附件:
u8 BSP_PWM_FastConfig(_PWMTnEnum pwmt, _CHnEnum chn, uint8_t mapGrp, uint32_t freq)
{
        TIM_TypeDef                 *TIM_For_PWM=(TIM_TypeDef *)pwmt;
        GPIO_TypeDef                 *pwm_port;
        GPIO_InitTypeDef        gpio;
        
        u32 pwmt_pin_num;
        u32 temp32;
        u32 psc;//预分频值,APB1和APB2的不一样!
        u8 temp8;
        u8 pwmt_num;
        u8 chn_num=chn;
        
        /* 参数判断!*/
        if(! IS_PWM_TIMER(pwmt)) return 1;//错误TIM,外设错误!
        if(! IS_PWM_CHANNEL(chn)) return 2;//错误通道号!
        if(mapGrp/2) return 3;//映射组别支持0和1,其他数值为错误!
        if(freq > 1000000) return 4;//频率最大支持1MHz!不过一般达不到!
        
        /* 获取所连接的gpio引脚! */
        switch(pwmt)//选择端口寻址序号!
        {
                case PWMT2  : pwmt_num = 0; break;
                case PWMT3  : pwmt_num = 1; break;
                case PWMT4  : pwmt_num = 2; break;
                case PWMT5  : pwmt_num = 3; break;
                case PWMT12 : pwmt_num = 4; break;
                case PWMT13 : pwmt_num = 5; break;
                case PWMT14 : pwmt_num = 6; break;
                case PWMT9  : pwmt_num = 7; break;
                case PWMT10 : pwmt_num = 8; break;
                case PWMT11 : pwmt_num = 9; break;
        }
        temp8                        = (pwmt_num<<1) + mapGrp;//考虑到pwm引脚的映射问题,分配两组配置值!
        pwm_port                =  PWM_Output_Table[temp8][chn_num].port;
        if(!pwm_port) return 5;//不可使用的外部连接引脚!
        pwmt_pin_num        = PWM_Output_Table[temp8][chn_num].pinNum;        

        /* 常规pwm配置!*/
        RCC_AHB1PeriphClockCmd((1<<(((u32)pwm_port - AHB1PERIPH_BASE)>>10)), ENABLE);//port clock enable!               

        gpio.GPIO_Pin   = (1<<pwmt_pin_num);
        gpio.GPIO_Speed = GPIO_Speed_50MHz;
        gpio.GPIO_Mode  = GPIO_Mode_AF;
        gpio.GPIO_OType = GPIO_OType_PP;
        gpio.GPIO_PuPd  = GPIO_PuPd_UP;//上拉
        GPIO_Init(pwm_port, &gpio);
                                
        switch(pwmt)//选择管脚复用函数!
        {
                case PWMT2  : temp8 = GPIO_AF_TIM2;  break;
                case PWMT3  : temp8 = GPIO_AF_TIM3;  break;
                case PWMT4  : temp8 = GPIO_AF_TIM4;  break;
                case PWMT5  : temp8 = GPIO_AF_TIM5;  break;
                case PWMT12 : temp8 = GPIO_AF_TIM12; break;
                case PWMT13 : temp8 = GPIO_AF_TIM13; break;
                case PWMT14 : temp8 = GPIO_AF_TIM14; break;        
                case PWMT9  : temp8 = GPIO_AF_TIM9;  break;
                case PWMT10 : temp8 = GPIO_AF_TIM10; break;
                case PWMT11 : temp8 = GPIO_AF_TIM11; break;
        }
        GPIO_PinAFConfig(pwm_port, pwmt_pin_num, temp8);
        
        /* 计算装载值(单次计数为1us,freq单位为Hz) */
        switch(pwmt)//选择管脚复用函数!
        {
                case PWMT2  : temp32  = RCC_APB1Periph_TIM2;  break;
                case PWMT3  : temp32  = RCC_APB1Periph_TIM3;  break;
                case PWMT4  : temp32  = RCC_APB1Periph_TIM4;  break;
                case PWMT5  : temp32  = RCC_APB1Periph_TIM5;  break;
                case PWMT12 : temp32  = RCC_APB1Periph_TIM12; break;
                case PWMT13 : temp32  = RCC_APB1Periph_TIM13; break;
                case PWMT14 : temp32  = RCC_APB1Periph_TIM14; break;        
                case PWMT9  : temp32  = RCC_APB2Periph_TIM9;  break;
                case PWMT10 : temp32  = RCC_APB2Periph_TIM10; break;
                case PWMT11 : temp32  = RCC_APB2Periph_TIM11; break;
        }
        
        if(pwmt_num <= 6)//tim2、3、4、5、12、13、14挂接在APB1上!
        {
                RCC_APB1PeriphClockCmd(temp32, ENABLE);
                psc = 84;        //根据晶振和RCC配置来确定,默认8M晶振,默认配置下APB1为42MHz!
        }else{//tim9、10、11挂接在APB2上!
                RCC_APB2PeriphClockCmd(temp32, ENABLE);
                psc = 168;        //根据晶振和RCC配置来确定,默认8M晶振,默认配置下APB2为84MHz!
        }

        TIM_For_PWM->ARR = 1000000/freq - 1;        //自动重装值
        TIM_For_PWM->PSC = psc - 1;                                //预分频值,单次计数为1M(1us)!若频率较慢,建议增大此值!!

        /* 相关寄存器写入,涉及到较多的移位,原理请参考寄存器位定义! */
        temp8 = chn%2;//寄存器分组,0、2和1、3        
        if(chn/2)
        {
                TIM_For_PWM->CCMR2        |= 6<<(4+(temp8<<3));        //PWM1模式,CNT<CCR为有效电平
                TIM_For_PWM->CCMR2        |= 1<<(3+(temp8<<3));        //预装载使能
                TIM_For_PWM->CCER        |= 1<<(8+(temp8<<2));        //输出使能
                TIM_For_PWM->CCER        |= 0<<(9+(temp8<<2));        //高电平有效               
        }else{
                TIM_For_PWM->CCMR1        |= 6<<(4+(temp8<<3));        //PWM1模式,CNT<CCR为有效电平
                TIM_For_PWM->CCMR1        |= 1<<(3+(temp8<<3));        //预装载使能
                TIM_For_PWM->CCER        |= 1<<(0+(temp8<<2));        //输出使能
                TIM_For_PWM->CCER        |= 0<<(1+(temp8<<2));        //高电平有效
        }   
        TIM_For_PWM->CR1                   |= 1<<7;                            //ARPE使能(自动重装载使能)
        TIM_For_PWM->CR1                |= 1<<0;                            //tim使能
        
        return 0;
}

使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

419

主题

419

帖子

0

粉丝