1.通用定时器(TIM2-TIM5)主要特性
(1)==16 位(TIM3 和 TIM4)==或 32 位(TIM2 和 TIM5) 递增、递减和递增/递减自动重载计数器。
(2)16 位可编程预分频器,用于对计数器时钟频率进行分频 (即运行时修改),分频系数介于 1 到 65536 之间。
(3)多达 4 个独立通道,可用于:
— 输入捕获
— 输出比较
— PWM 生成(边沿和中心对齐模式)
— 单脉冲模式输出
(4)使用外部信号控制定时器且可实现多个定时器互连的同步电路。
(5)发生如下事件时生成中断/DMA 请求:
— 更新:计数器上溢/下溢、计数器初始化(通过软件或内部/外部触发)
— 触发事件(计数器启动、停止、初始化或通过内部/外部触发计数)
— 输入捕获
— 输出比较
(6)支持定位用增量(正交)编码器和霍尔传感器电路
(7)外部时钟触发输入或逐周期电流管理
2.功能实现
2.1输入捕获/输出比较
输入捕获的实现代码(获取key2的按下时间并打印)
//TIM5输入捕获初始化函数
void TIM5_ICInit(u8 PreemptionPriority, u8 SubPriority)
{
//开启GPIOA时钟线
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
//开启TIM5时钟线
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
//引脚配置为复用模式
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
//初始化GPIO
GPIO_Init(GPIOA, &GPIO_InitStructure);
//将PA0引脚重映射到TIM5上
GPIO_PinAFConfig(GPIOA,GPIO_PinSource0,GPIO_AF_TIM5);
//配置时基单元
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_Period = 10000-1;
TIM_TimeBaseInitStruct.TIM_Prescaler = 8400-1;
//仅限于TIM1/TIM8配置PWM需要
//TIM_TimeBaseInitStruct.TIM_RepetitionCounter = ;
//时基单元初始化
TIM_TimeBaseInit(TIM5, &TIM_TimeBaseInitStruct);
//软件产生更新事件
TIM_GenerateEvent(TIM5, TIM_EventSource_Update);
//清除标志位
TIM_ClearFlag(TIM5, TIM_FLAG_Update);
//清空计数器
TIM_SetCounter(TIM5, 0);
//输入捕获配置
TIM_ICInitTypeDef TIM_ICInitStruct;
//使用通道1
TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;
//设置滤波模式为2
TIM_ICInitStruct.TIM_ICFilter = 2;
//边沿触发模式选择双边沿触发
TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_BothEdge;
//选择不分频
TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;
//选择输入源为TI1FP1
TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;
//初始化输入捕获
TIM_ICInit(TIM5, &TIM_ICInitStruct);
//开启通道1
TIM_CCxCmd(TIM5, TIM_Channel_1, TIM_CCx_Enable);
//开启更新中断和通道1中断
TIM_ITConfig(TIM5, TIM_IT_Update|TIM_IT_CC1, ENABLE);
//配置优先级分组
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = TIM5_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = PreemptionPriority;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = SubPriority;
NVIC_Init(&NVIC_InitStruct);
}
//TIM5中断处理函数
void TIM5_IRQHandler(void)
{
static u32 time5 = 0;
//判断是否是因更新中断进的中断
if(TIM_GetITStatus(TIM5, TIM_IT_Update) == SET)
{
time5++;
//清除标志位
TIM_ClearITPendingBit(TIM5, TIM_IT_Update);
}
//判断是否是因通道1中断进的中断
if(TIM_GetITStatus(TIM5, TIM_IT_CC1) == SET)
{
if(key1)
{
TIM6_DelayMs(40);
//清空计数器
TIM_SetCounter(TIM5, 0);
//开启TIM5
TIM_Cmd(TIM5, ENABLE);
}
else
{
TIM6_DelayMs(40);
double miao = (double)(TIM_GetCounter(TIM5)+1)/10000 + time5;
printf("key1按键时长 = %.2lf\r\n",miao);
time5 = 0;
//关闭TIM5
TIM_Cmd(TIM5, DISABLE);
}
//清除标志位
TIM_ClearITPendingBit(TIM5, TIM_IT_CC1);
}
}
2.2PWM实现
void PWM_Init(u16 x)
{
//开启GPIOC时钟线
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
//开启TIM3时钟线
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOC,GPIO_PinSource6,GPIO_AF_TIM3);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_Period = 10*x-1;
TIM_TimeBaseInitStruct.TIM_Prescaler = 8400-1;
//仅限于TIM1/TIM8配置PWM需要
//TIM_TimeBaseInitStruct.TIM_RepetitionCounter = ;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct);
//软件产生更新事件
TIM_GenerateEvent(TIM3, TIM_EventSource_Update);
//清除标志位
TIM_ClearFlag(TIM3, TIM_FLAG_Update);
//清空计数器
TIM_SetCounter(TIM3, 0);
//使能定时器
TIM_Cmd(TIM3, ENABLE);
//PWM配置
TIM_OCInitTypeDef TIM_OCInitStruct;
//输出比较模式设置为PWM1
TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;
//有效电平设为低电平
TIM_OCInitStruct.TIM_OCPolarity =TIM_OCPolarity_Low;
//使能输出状态
TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
//设置比较值
TIM_OCInitStruct.TIM_Pulse = 0;
TIM_OC1Init(TIM3, &TIM_OCInitStruct);
//打开通道1
TIM_CCxCmd(TIM3, TIM_Channel_1, TIM_CCx_Enable);
}
//在其他地方可通过调用
TIM_SetCompare1(TIM3,x);
//实现修改比较值x