STM32F103ZET6之输入捕获实验
文章目录
前言
对于STM32的学习可分为3个版本。
1.寄存器版本
2.库函数版本
3.HAL库版本
由于个人原因,选择库函数版本来进行STM32的学习。
提示:软件安装等问题,不进行讲解!!!
一、输入捕获基本原理
1.简介
输入捕获模式可以用来测量脉冲宽度或者测量频率。通过检测TIMx_CHx 上的边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候,将当前定时器的值(TIMx_CNT)存放到对应的捕获/比较寄存器(TIMx_CCRx)里面,完成一次捕获。
2.工作过程
二、相关寄存器
1.捕获/比较模式寄存器 (TIMx_CCMR1)
TIMx_CCMR1 明显是针对 2 个通道的配置,低八位[7: 0]用于捕获/比较通道 1 的控制,而高八位[15: 8]则用于捕获/比较通道 2 的控制,因为 TIMx 还有 CCMR2 这个寄存器,所以可以知道CCMR2 是用来控制通道 3 和通道 4
2.TIMx_CMMR1 的[7:0]位
3.捕获/比较使能寄存器 (TIMx_CCER)
4.捕获/比较寄存器(TIMx_CCR1~4)
三、操作步骤
1.相应引脚
2.操作步骤
四、程序源码
1.timer.h
代码如下:
#ifndef __TIMER_H
#define __TIMER_H
#include "sys.h"
void TIM3_Int_Init(u16 arr,u16 psc);
void TIM3_PWM(u16 arr,u16 psc);
void TIM5_Cap_Init(u16 arr,u16 psc);
#endif
2.timer.c
代码如下:
#include "timer.h"
#include "led.h"
void TIM3_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef IM_TimeBaseInitstr;
NVIC_InitTypeDef NVIC_Initstr;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//定时器时钟使能
IM_TimeBaseInitstr.TIM_Period=arr;
IM_TimeBaseInitstr.TIM_Prescaler=psc;
IM_TimeBaseInitstr.TIM_CounterMode=TIM_CounterMode_Up;
IM_TimeBaseInitstr.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM3, &IM_TimeBaseInitstr);//初始化时钟
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);//开启定时器中断
NVIC_Initstr.NVIC_IRQChannel=TIM3_IRQn;
NVIC_Initstr.NVIC_IRQChannelCmd=ENABLE;
NVIC_Initstr.NVIC_IRQChannelPreemptionPriority=0;
NVIC_Initstr.NVIC_IRQChannelSubPriority=2;
NVIC_Init(&NVIC_Initstr);//配置NVIC
TIM_Cmd(TIM3, ENABLE);//使能定时器
}
void TIM3_IRQHandler(void)//中断服务函数
{
if(TIM_GetITStatus(TIM3, TIM_IT_Update)==SET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);//清除更新中断标志
LED1=!LED1;
}
}
void TIM3_PWM(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_Initstr;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitstr;
TIM_OCInitTypeDef TIM_OCInitstr;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//定时器时钟使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE);//GPIOB和复用时钟
GPIO_Initstr.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_Initstr.GPIO_Pin=GPIO_Pin_5;
GPIO_Initstr.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_Initstr);//初始化IO口为复用功能输出
GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3 , ENABLE);//重映射,定时器3通道2映射PB5
TIM_TimeBaseInitstr.TIM_Period=arr;
TIM_TimeBaseInitstr.TIM_Prescaler=psc;
TIM_TimeBaseInitstr.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInitstr.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitstr);//初始化定时器3
TIM_OCInitstr.TIM_OCMode=TIM_OCMode_PWM2;
TIM_OCInitstr.TIM_OutputState=TIM_OutputState_Enable;
TIM_OCInitstr.TIM_OCPolarity=TIM_OCPolarity_High ;
TIM_OC2Init(TIM3, &TIM_OCInitstr);//设置定时器3通道2PWM的模式
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);//使能预装载寄存器
TIM_Cmd(TIM3, ENABLE);//使能定时器
}
TIM_ICInitTypeDef TIM5_ICInitstr;
void TIM5_Cap_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_Initstr;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitstr;
NVIC_InitTypeDef NVIC_Initstr;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_Initstr.GPIO_Mode=GPIO_Mode_IPD;
GPIO_Initstr.GPIO_Pin=GPIO_Pin_0;
GPIO_Initstr.GPIO_Speed= GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_Initstr);
TIM_TimeBaseInitstr.TIM_Period=arr;
TIM_TimeBaseInitstr.TIM_Prescaler=psc;
TIM_TimeBaseInitstr.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInitstr.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM5, &TIM_TimeBaseInitstr);
TIM5_ICInitstr.TIM_Channel=TIM_Channel_1;
TIM5_ICInitstr.TIM_ICPolarity=TIM_ICPolarity_Rising;
TIM5_ICInitstr.TIM_ICSelection=TIM_ICSelection_DirectTI;
TIM5_ICInitstr.TIM_ICPrescaler=TIM_ICPSC_DIV1;
TIM5_ICInitstr.TIM_ICFilter=0x00;
TIM_ICInit(TIM5, &TIM5_ICInitstr);
NVIC_Initstr.NVIC_IRQChannel=TIM5_IRQn;
NVIC_Initstr.NVIC_IRQChannelCmd=ENABLE;
NVIC_Initstr.NVIC_IRQChannelPreemptionPriority=2;
NVIC_Initstr.NVIC_IRQChannelSubPriority=0;
NVIC_Init(&NVIC_Initstr);
TIM_ITConfig(TIM5,TIM_IT_CC1, ENABLE);
TIM_Cmd(TIM5, ENABLE);
}
u8 TIM5CH1_CAPTURE_STA=0;//输入捕获状态
u16 TIM5CH1_CAPTURE_VAL;
void TIM5_IRQHandler(void)
{
if((TIM5CH1_CAPTURE_STA&0x80)==0)//未成功捕获
{
if(TIM_GetITStatus(TIM5, TIM_IT_Update)!=RESET)//发生更新中断
{
if(TIM5CH1_CAPTURE_STA&0x40)//捕获到高电平
{
if((TIM5CH1_CAPTURE_STA&0x3F)==0x3F)//高电平时间太长
{
TIM5CH1_CAPTURE_STA|=0x80;//捕获一次
TIM5CH1_CAPTURE_VAL=0xFFFF;
}
else
TIM5CH1_CAPTURE_STA++;
}
}
if(TIM_GetITStatus(TIM5, TIM_IT_CC1)!=RESET)//发生捕获中断
{
if(TIM5CH1_CAPTURE_STA&0x40)
{
TIM5CH1_CAPTURE_STA|=0x80;
TIM5CH1_CAPTURE_VAL=TIM_GetCapture1(TIM5);
TIM_OC1PolarityConfig(TIM5, TIM_ICPolarity_Rising);
}
else
{
TIM5CH1_CAPTURE_STA=0;
TIM5CH1_CAPTURE_VAL=0;
TIM_SetCounter(TIM5, 0);
TIM5CH1_CAPTURE_STA|=0x40;
TIM_OC1PolarityConfig(TIM5, TIM_ICPolarity_Falling);
}
}
}
TIM_ClearITPendingBit(TIM5,TIM_IT_Update|TIM_IT_CC1);
}
3.main.c
代码如下:
#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "beep.h"
#include "key.h"
#include "timer.h"
#include "usart.h"
extern u8 TIM5CH1_CAPTURE_STA;//输入捕获状态
extern u16 TIM5CH1_CAPTURE_VAL;
int main(void)
{
u32 temp=0;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
uart_init(115200);
delay_init();
LED_Init();
Beep_Init();
KEY_Init();
TIM5_Cap_Init(0xFFFF,72-1);//72M/72=1M
while(1)
{
if(TIM5CH1_CAPTURE_STA&0x80)
{
temp=TIM5CH1_CAPTURE_STA&0x3F;
temp*=65536;
temp+=TIM5CH1_CAPTURE_VAL;
printf("HIGH:%d us\r\n",temp);
TIM5CH1_CAPTURE_STA=0;
}
}
}
五、实验结果
总结
1.看完视频,一定自己写一遍程序。
2.烧写程序前,对程序进行分析,推理实验现象。
3.若实验现象与推理不一致,一定要认真分析程序。