蓝桥杯嵌入式 - 比较输出PWM

?STM32的PWM输出模式只能输出同频率不同占空比的方波,而在前几届比赛有考到输出不同频率不同占空比方波的情况。而STM32定时器的比较输出模式可以做到。
?而比赛不会考到很多理论上的东西,所以直接贴代码了。
【蓝桥杯嵌入式 - 比较输出PWM】一、初始化部分

  1. 计算周期
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);

?这里记得服用推挽输出。
  1. 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);

  1. 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);

  1. 使能
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 里面进行复制呀~~~~~~~~~~

    推荐阅读