?STM32的PWM输出模式只能输出同频率不同占空比的方波,而在前几届比赛有考到输出不同频率不同占空比方波的情况。而STM32定时器的比较输出模式可以做到。
?而比赛不会考到很多理论上的东西,所以直接贴代码了。
【蓝桥杯嵌入式 - 比较输出PWM】一、初始化部分
- 计算周期
CCR1_Val = 1000000/p1;
CCR2_Val = 1000000/p2;
CCR1_duty = d1*CCR1_Val/100;
CCR2_duty = d2*CCR2_Val/100;
?因为后面时钟分频后为1MHz,所以计算周期直接用1000000。
2. 时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_AFIO, ENABLE);
?我们用TIM3的1、2通道,所以开启TIM3、GPIOA时钟。
2. GPIO初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
?这里记得服用推挽输出。
- NVIC初始化
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
- TimeBase初始化
TIM_TimeBaseStructure.TIM_Period = 0xffff;
TIM_TimeBaseStructure.TIM_Prescaler = 71;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = 0;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
?TIM_Period 填充为最大,0xffff,对时钟72分频,得到1MHz的时钟。
5. 输出初始化
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Disable);
TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
TIM_OC2Init(TIM3, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Disable);
- 使能
TIM_Cmd(TIM3, ENABLE);
TIM_ITConfig(TIM3, TIM_IT_CC1 | TIM_IT_CC2 , ENABLE);
二、中断
?这里要特别感谢 马一飞 学长,根据他的博客才实现了这个功能。
void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_CC1 );
capture = TIM_GetCapture1(TIM3);
if(flag_1)
TIM_SetCompare1(TIM3, capture + CCR1_duty );
else
TIM_SetCompare1(TIM3, capture + CCR1_Val - CCR1_duty);
flag_1 = (flag_1 + 1)%2;
} if (TIM_GetITStatus(TIM3, TIM_IT_CC2) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_CC2 );
capture = TIM_GetCapture2(TIM3);
if(flag_2)
TIM_SetCompare2(TIM3, capture + CCR2_duty );
else
TIM_SetCompare2(TIM3, capture + CCR2_Val - CCR2_duty);
flag_2 = (flag_2 + 1)%2;
}
}
最后
?比赛时时候这个代码可以在库例程的 OCToggle 里面进行复制呀~~~~~~~~~~