快毕业了,最近和几个哥们做项目。那哥们做了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;
} |