参考资料:
蓝桥杯嵌入式备赛手册
蓝桥杯嵌入式开发经验分享(9.PWM模式配置)
蓝桥杯嵌入式开发经验分享(11.输入捕获模式讲解)
STM32F1 定时器 PWM输入捕获两路
总目录:目录
中文STM32手册中8.3.7 定时器复用功能重映射
TIM2,TIM3是一样的,都是通用定时器,掌握其中一个,那么另外一个也是相同的配置,只不过是对应的复用引脚不同
arr=1000000/freq - 1
u32 freq
void TIM2_IRQHandler(void)
u8 status = 0;
u16 cnt = 0;
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
if(cnt++ == 500)
{
cnt = 0;
led_Control(LED_ALL, status);
status = !status;
}
}
}
(arr+1)*duty/100
#include "pwm.h"
#include "led.h"
void PWM_OC_Init(u32 freq,u8 duty)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
u32 arr = 1000000 / freq - 1;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOC, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
TIM_TimeBaseStructure.TIM_Period = arr;
TIM_TimeBaseStructure.TIM_Prescaler = 71;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE );
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = (arr+1)*duty/100;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC2Init(TIM2, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM2, ENABLE);
TIM_Cmd(TIM2, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
u8 status = 0;
u16 cnt = 0;
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
//if(cnt++ == 500)
//{
//cnt = 0;
//led_Control(LED_ALL, status);
//status = !status;
//}
GPIO_SetBits(GPIOD, GPIO_Pin_2);
GPIO_ResetBits(GPIOD, GPIO_Pin_2);
}
}
int main(void)
{
u16 LedPWMVal = 0, dir = 1;
SysTick_Config(SystemCoreClock/1000);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
led_Init();
PWM_OC_Init(500, 60);
while(1)
{
if(dir)
LedPWMVal++;
else
LedPWMVal--;
if(LedPWMVal>665)
dir = 0;
if(LedPWMVal == 0)
dir = 1;
TIM_SetCompare3(TIM2, LedPWMVal);
Delay_Ms(10);
}
}
别忘了吧stm32f10x_tim.c加到工程中再编译
这里我们设PA6频率为10KHz,占空比为10%,PA7频率为1KHz,占空比为20%
参考例程:Project->STM32F10x_StdPeriph_Examples->TIM->OCToggle中main.c
包含:
PWM的初始化完成
自己定义占空比变量分别执行下列函数
TIM_SetCompare1(TIM3, capture + (u16)CCR1_Val *zhankong1 );
TIM_SetCompare1(TIM3, capture + (u16)CCR1_Val *(1-zhankong1));
其中,CCRx_Val=频率为72M/72/频率
综上,pwm.c如下
#include "pwm.h"
__IO uint16_t CCR1_Val = 100;//72000000/72/10000
__IO uint16_t CCR2_Val = 1000;//72000000/72/1000
float zhankong1=0.1;
float zhankong2=1;
void PWM_OC_Init()
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* TIM3 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
/* GPIOA clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE);
TIM_TimeBaseStructure.TIM_Period = 65535;
TIM_TimeBaseStructure.TIM_Prescaler = 71;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
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_OutputState = TIM_OutputState_Enable;
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);
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_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
uint16_t capture = 0;
u8 pa6_state=0,pa7_state=0;
void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_CC1 );
capture = TIM_GetCapture1(TIM3);
if(pa6_state == 0)
{
TIM_SetCompare1(TIM3, capture + (u16)CCR1_Val * zhankong1 );
pa6_state = 1;
}
else
{
TIM_SetCompare1(TIM3, capture + (u16)CCR1_Val * (1 - zhankong1));
pa6_state = 0;
}
}
if (TIM_GetITStatus(TIM3, TIM_IT_CC2) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
capture = TIM_GetCapture2(TIM3);
if(pa7_state == 0)
{
TIM_SetCompare2(TIM3, capture + (u16)CCR2_Val * zhankong2 );
pa7_state = 1;
}
else
{
TIM_SetCompare2(TIM3, capture + (u16)CCR2_Val * (1 - zhankong2));
pa7_state = 0;
}
}
}
假设KEY1使PA6的占空比增加10%,KEY2使PA7的频率增加1KHz
stmf10x_it.c
zhankongx
或CCRx_Val
即可void EXTI0_IRQHandler(void)
{
Delay_Ms(10);
if(EXTI_GetITStatus(EXTI_Line0) != RESET)
{
zhankong1 += 0.1;
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
u16 pinlv2=1000;
void EXTI9_5_IRQHandler(void)
{
Delay_Ms(10);
if(EXTI_GetITStatus(EXTI_Line8) != RESET)
{
pinlv2+=1000;
CCR2_Val=(u16)(1000000/pinlv2);//72MHz/72
EXTI_ClearITPendingBit(EXTI_Line8);
}
}
main.c
#include "pwm.h"
void PWM_IC_Init()
{
TIM_ICInitTypeDef TIM_ICInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* TIM3 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
/* GPIOA clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0x0;
TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);
/* Select the TIM3 Input Trigger: TI2FP2 */
TIM_SelectInputTrigger(TIM3, TIM_TS_TI2FP2);
/* Select the slave Mode: Reset Mode */
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
/* Enable the Master/Slave Mode */
TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable);
/* TIM enable counter */
TIM_Cmd(TIM3, ENABLE);
/* Enable the CC2 Interrupt Request */
TIM_ITConfig(TIM3, TIM_IT_CC2, ENABLE);
}
__IO uint16_t IC2Value = 0;
__IO uint16_t DutyCycle = 0;
__IO uint32_t Frequency = 0;
void TIM3_IRQHandler(void)
{
/* Clear TIM3 Capture compare interrupt pending bit */
TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
/* Get the Input Capture value */
IC2Value = TIM_GetCapture2(TIM3);
if (IC2Value != 0)
{
/* Duty cycle computation */
DutyCycle = (TIM_GetCapture1(TIM3) * 100) / IC2Value;
/* Frequency computation */
Frequency = SystemCoreClock / IC2Value;
}
else
{
DutyCycle = 0;
Frequency = 0;
}
}
#include "stm32f10x.h"
#include "lcd.h"
#include "pwm.h"
#include "stdio.h"
u32 TimingDelay = 0;
extern __IO uint16_t IC2Value;
extern __IO uint16_t DutyCycle;
extern __IO uint32_t Frequency;
void Delay_Ms(u32 nTime);
//Main Body
int main(void)
{
u8 pwm[20];
SysTick_Config(SystemCoreClock/1000);
STM3210B_LCD_Init();
PWM_IC_Init();
LCD_Clear(Blue);
LCD_SetTextColor(Black);
LCD_SetBackColor(White);
while(1)
{
sprintf((char*)pwm, "DutyCycle : %d", DutyCycle);
LCD_DisplayStringLine(Line0,pwm);
sprintf((char*)pwm, "Frequency : %d", Frequency);
LCD_DisplayStringLine(Line2,pwm);
Delay_Ms(10);
}
}
//
void Delay_Ms(u32 nTime)
{
TimingDelay = nTime;
while(TimingDelay != 0);
}
main.c
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1|TIM_Channel_2;
)以及(TIM_ITConfig(TIM3, TIM_IT_CC1|TIM_IT_CC2, ENABLE);
)stm32f10x_it.c
__IO uint16_t IC3ReadValue1 = 0, IC3ReadValue2 = 0;//
__IO uint16_t DutyCycleValue1 = 0,DutyCycleValue2 = 0;
__IO uint16_t CaptureNumber = 0,CaptureNumber_DC = 0;//捕获计数
__IO uint32_t Capture = 0,Capture_DC = 0;//捕获时间,DC表示下降沿捕获时间
__IO uint32_t TIM3Freq = 0,TIM3DutyCycle = 0;//频率和占空比
__IO uint16_t _IC3ReadValue1 = 0, _IC3ReadValue2 = 0;
__IO uint16_t _DutyCycleValue1 = 0,_DutyCycleValue2 = 0;
__IO uint16_t _CaptureNumber = 0,_CaptureNumber_DC = 0;
__IO uint32_t _Capture = 0,_Capture_DC = 0;
__IO uint32_t _TIM3Freq = 0,_TIM3DutyCycle = 0;
void TIM3_IRQHandler(void)
{
//采用定时器溢出中断,不管定时器频率如何变化,总是会出现定时器溢出中断更新不及时的情况,即计数值已重新技术到比0大的值,但定时器溢出中断未产生
if(TIM_GetITStatus(TIM3, TIM_IT_CC1) == SET) //捕获1发生捕获事件
{
TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);//清楚中断标志位
if(_CaptureNumber_DC == 0)
{
//捕获到上升沿,计算时间
_DutyCycleValue1 = TIM_GetCapture1(TIM3);
if(_CaptureNumber == 0)
{
_IC3ReadValue1 = _DutyCycleValue1;
_CaptureNumber = 1;
}
else if(_CaptureNumber == 1)
{
_IC3ReadValue2 = _DutyCycleValue1;
if (_IC3ReadValue2 > _IC3ReadValue1)
_Capture = (_IC3ReadValue2 - _IC3ReadValue1);
else
_Capture = ((0xFFFF - _IC3ReadValue1) + _IC3ReadValue2);
_TIM3Freq = (uint32_t) SystemCoreClock / _Capture;
_CaptureNumber = 0;
}
TIM_OC1PolarityConfig(TIM3, TIM_ICPolarity_Falling);
_CaptureNumber_DC = 1;
}
else if(_CaptureNumber_DC==1)
{
_DutyCycleValue2 = TIM_GetCapture1(TIM3);
if (_DutyCycleValue2 > _DutyCycleValue1)
_Capture_DC = (_DutyCycleValue2 - _DutyCycleValue1);
else
_Capture_DC = ((0xFFFF - _DutyCycleValue1) + _DutyCycleValue2);
//计算占空比=下降沿捕获时间/总捕获时间
_TIM3DutyCycle = _Capture_DC/_Capture;
//设置为上升沿捕获
TIM_OC1PolarityConfig(TIM3, TIM_ICPolarity_Rising);
_CaptureNumber_DC = 0;
}
}
/*Initialize TIM3 CC2 IT*/
if(TIM_GetITStatus(TIM3, TIM_IT_CC2) == SET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
if(CaptureNumber_DC == 0)
{
DutyCycleValue1 = TIM_GetCapture2(TIM3);
if(CaptureNumber == 0)
{
IC3ReadValue1 = DutyCycleValue1;
CaptureNumber = 1;
}
else if(CaptureNumber == 1)
{
IC3ReadValue2 = DutyCycleValue1;
if (IC3ReadValue2 > IC3ReadValue1)
Capture = (IC3ReadValue2 - IC3ReadValue1);
else
Capture = ((0xFFFF - IC3ReadValue1) + IC3ReadValue2);
TIM3Freq = (uint32_t) SystemCoreClock / Capture;
CaptureNumber = 0;
}
TIM_OC2PolarityConfig(TIM3, TIM_ICPolarity_Falling);
CaptureNumber_DC = 1;
}
else if(CaptureNumber_DC==1)
{
DutyCycleValue2 = TIM_GetCapture2(TIM3);
if (DutyCycleValue2 > DutyCycleValue1)
Capture_DC = (DutyCycleValue2 - DutyCycleValue1);
else
Capture_DC = ((0xFFFF - DutyCycleValue1) + DutyCycleValue2);
TIM3DutyCycle = Capture_DC/Capture;
TIM_OC2PolarityConfig(TIM3, TIM_ICPolarity_Rising);
CaptureNumber_DC = 0;
}
}
}
int main(void)
{
u8 pwm[20];
SysTick_Config(SystemCoreClock/1000);
STM3210B_LCD_Init();
LCD_Clear(Blue);
LCD_SetBackColor(Blue);
LCD_SetTextColor(White);
Pwm_Ic_Init();
while(1)
{
LCD_DisplayStringLine(Line1,pwm);
LCD_DisplayStringLine(Line3,pwm);
Delay_Ms(10);
}
}
单路输出利用主从模式,占用另一个通道的CCRX获得高电平时间。
双路输出不能用主从模式,且需要调节上升/下降沿触发。注意要配置TIM_TimeBaseStructure;