4.硬件设计
4.1LED驱动电路
利用单片机产生得PWM驱动电路直接驱动LED电路来验证,当输出PWM宽度变化时可以看到此时LED亮度变化,此时只需要将LED上拉就可以实现验证。当输入为低电平时,LED灯发光
4.2 SPWM滤波方案
利用高级定时器,我们能产生一系列PWM脉宽随时间变化的PWM波形,通过简单的RC滤波就可以将SPWM滤波成正弦波
5.软件设计过程
5.1 四路pwm输出配置
5.1.1 GPIO初始化
初始化引脚(PA6、PA7,PB0、PB1),这里拿出初始化PA6例子
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource6,GPIO_AF_TIM3);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA,&GPIO_InitStructure);
5.1.2 定时器初始化配置
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ARRPreloadConfig(TIM3,ENABLE);
TIM_TimeBaseStructure.TIM_Prescaler=psc;
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period=arr;
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
TIM_Cmd(TIM3, ENABLE);
5.1.3 pwm输出配置
这里同样拿出PA6引脚对应得配置过程
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_Pulse=0;
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
TIM_CtrlPWMOutputs(TIM3,ENABLE);
5.2 占空比实现
TIM3_PWM_Init(arr-1,7-1);//tim3初始化
TIM_SetCompare1(TIM3,duty1);
TIM_SetCompare2(TIM3,duty2);
TIM_SetCompare3(TIM3,duty3);
TIM_SetCompare4(TIM3,duty4);
实验现象对比图
5.3 输出显示
显示代码:
OLED_ShowString(0,0,"Chann1:",16);
OLED_ShowFloatNum(56,0,(float)duty1/arr*100,7,16);
OLED_ShowString(112,0,"%",16);
OLED_ShowString(0,16,"Chann2:",16);
OLED_ShowFloatNum(56,16,(float)duty2/arr*100,7,16);
OLED_ShowString(112,16,"%",16);
OLED_ShowString(0,32,"Chann3:",16);
OLED_ShowFloatNum(56,32,(float)duty3/arr*100,7,16);
OLED_ShowString(112,32,"%",16);
OLED_ShowString(0,48,"Chann4:",16);
OLED_ShowFloatNum(56,48,(float)duty4/arr*100,7,16);
OLED_ShowString(112,48,"%",16);
实验现象图:
5.4 占空比调节
5.4.1按键设计模块
case 1: if(chmode == 1) chmode = 2;
else if(chmode == 2) chmode = 3;
else if(chmode == 3) chmode = 4;
else if(chmode == 4) chmode = 1;
key=0;break;
case 2: if(chmode == 1) duty1 += duty_index;
else if(chmode == 2) duty2 += duty_index;
else if(chmode == 3) duty3 += duty_index;
else if(chmode == 4) duty4 += duty_index;
key=0;break;
case 3: if(chmode == 1) duty1 -= duty_index;
else if(chmode == 2) duty2 -= duty_index;
else if(chmode == 3) duty3 -= duty_index;
else if(chmode == 4) duty4 -= duty_index;
key=0;break;//
case 4: if(duty_index == 1) duty_index = 2;
else if(duty_index == 2) duty_index = 4;
else if(duty_index == 4) duty_index = 5;
else if(duty_index == 5) duty_index = 6;
else if(duty_index == 6) duty_index = 10;
else if(duty_index == 10) duty_index = 40;
else if(duty_index == 40) duty_index = 1;
key=0;break;//
case 5: arr+=50;
key=0;break;//
case 6: arr-=50;
key=0;break;
5.4.2 显示模块
OLED_ShowString(0,0,"dutyIndex:",16);
OLED_ShowNum(80,0,duty_index,2,16);
OLED_ShowString(0,16,"Channel:",16);
OLED_ShowNum(64,16,chmode,1,16);
OLED_ShowString(0,32,"TIM1->ARR:",16);
OLED_ShowNum(80,32,arr,4,16);
实物现象对比图
通过按键1来切换不同的通道,按键2/3控制占空比的增减
5.5 spwm设计
对于高级定时器,可以添加死区
5.5.1 死区初始化
TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
TIM_BDTRInitStructure.TIM_AutomaticOutput=TIM_AutomaticOutput_Enable;
TIM_BDTRInitStructure.TIM_Break= TIM_Break_Disable;
TIM_BDTRInitStructure.TIM_BreakPolarity=TIM_BreakPolarity_High;
TIM_BDTRInitStructure.TIM_DeadTime=dead;//¸øËÀÇøʱ¼ä
TIM_BDTRInitStructure.TIM_LOCKLevel=TIM_LOCKLevel_OFF;
TIM_BDTRInitStructure.TIM_OSSRState=TIM_OSSRState_Enable;
TIM_BDTRInitStructure.TIM_OSSIState=TIM_OSSIState_Enable;
TIM_BDTRConfig(TIM1,&TIM_BDTRInitStructure);
5.5.2 spwm波表选择
这里我们可以简单的用c语言代码生成对应点数值,生成SPWM波表
float sin_value[672]=
{0.500000,0.504207,0.508415,0.512621,0.516826,0.521030,0.525232,0.529431,
0.533629,0.537823,0.542014,0.546201,0.550384,0.554563,0.558737,0.562906,
0.567069,0.571227,0.575378,0.579522,0.583660,0.587791,0.591913,0.596028,
0.600134,0.604232,0.608320,0.612399,0.616469,0.620528,0.624576,0.628614,
0.632640,0.636655,0.640657,0.644648,0.648626,0.652590,0.656542,0.660480,
0.664403,0.668313,0.672208,0.676087,0.679951,0.683800,0.687632,0.691448,
0.695248,0.699030,0.702795,0.706542,0.710271,0.713982,0.717673,0.721346,
0.725000,0.728634,0.732248,0.735841,
... ... ...
0.304752,0.308552,0.312368,0.316200,0.320049,0.323913,0.327792,0.331687,
0.335597,0.339520,0.343458,0.347410,0.351374,0.355352,0.359343,0.363345,
0.367360,0.371386,0.375424,0.379472,0.383531,0.387601,0.391680,0.395768,
0.399866,0.403972,0.408087,0.412209,0.416340,0.420477,0.424622,0.428773,
0.432931,0.437094,0.441263,0.445437,0.449616,0.453799,0.457986,0.462177,
0.466371,0.470569,0.474768,0.478970,0.483174,0.487379,0.491585,0.495793};
5.5.3 spwm中断程序
void TIM1_UP_TIM10_IRQHandler(void)
{
if(TIM_GetITStatus(TIM1,TIM_IT_Update)==SET)
{
spwm_duty = 1000*sin_value[cnt++];
if(cnt == 672)
cnt = 0;
TIM_SetCompare1(TIM1,spwm_duty);
}
TIM_ClearITPendingBit(TIM1,TIM_IT_Update);
}
实验现象图