STM32教学练习——输入捕获实验(祝你实验顺利!)

输入捕获实验是大家接触定时器后遇到的第一个小困难,它承接定时器更新中断这个知识点和后续PWM的知识点(先了解方波、了解占空比,后续才能更好地理解pwm输出)

也能让大家了解到位操作,如本实验中的STA的8位都有着各自的职能

实验要求:

(1)用TIM4 CH4 (PB9)的输入捕功能测量周期或频率。学习板X9的1号引脚输出幅值3.3v频率1kHz的方波作为输入信号。

(2)设置输入捕获为上升沿检测,记录第一次上升沿发生时TIM4 CNT值;第二次上升沿到来时记录此刻TIM4 CNT值;前后两次TIM4 CNT之差即为方波周期对应的计数值TIM4计数频率已知,可计算出方波周期。

(3)将方波周期显示在4位LED数码管上(单位us)

实验流程图(手写,见谅):

timer.c

main.c

 捕获部分

主要代码

 main函数

#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "timer.h"
#include "74HC595_LED.h"

uint8_t u8DispBuf[5]={0,0x3f,0x06,0x4f,0x66};
extern u8  TIM4CH4_CAPTURE_STA;		//输入捕获状态		    				
extern u32	TIM4CH4_CAPTURE_VAL;	//输入捕获值  
 
int main(void)
{	
	TIM_OCInitTypeDef  TIM_OCInitStructure;
  u16 u16tmp;	
	uint32_t	u32tmp=0; 
	long long temp=0; 
	
	delay_init();	    	 //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
 	LED_Init();			     //LED端口初始化
	TIM4_CH4_Cap_Init(0XFFFF,72-1); //以1Mhz的频率计数
	Init74HC595();
	
  while(1)
	{	
 		if(TIM2CH3_CAPTURE_STA&0X80)        //成功捕获到了一次高电平 主函数里面在等,等到捕获到才发串口
		{
			temp = TIM2CH3_CAPTURE_STA&0X3F; // 0011 1111 即取出溢出的次数
			temp *= 0xFFFF;		 		        //溢出时间总和
			temp += TIM2CH3_CAPTURE_VAL;		  //得到总的高电平时间
			TIM4CH4_CAPTURE_STA = 0;			    //开启下一次捕获 即当前捕获时间+溢出时间
			
			u8DispBuf[1]= temp / 1000;
			u8DispBuf[2]= temp % 1000 / 100; 
			u8DispBuf[3]= temp % 100 / 10;	
			u8DispBuf[4]= temp % 10;
		}
		DispUpdate();			   
	}	 
}	 
 

timer.c

#include "timer.h"
#include "led.h"
//
//捕获状态
//[7]:1-成功捕获到一次高电平;0-尚未成功捕获.
//[6]:1-已捕获到上升沿;0-尚未捕获到上升沿.
//[5:0]:捕获上升沿后溢出的次数(对于32位定时器来说,1us计数器加1,溢出时间:4294秒)
u8  TIM4CH4_CAPTURE_STA=0;	//输入捕获状态		    				
u32	TIM4CH4_CAPTURE_VAL;		//输入捕获值(TIM2/TIM5是32位)
//   	 
//通用定时器3中断初始化
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器3!
TIM_ICInitTypeDef  TIM4_ICInitStructure;

//定时器2通道3输入捕获配置
//arr:自动重装值
//psc:时钟预分频数
void TIM4_CH4_Cap_Init(u16 arr,u16 psc)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);  	//TIM4时钟使能    
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); 	//使能PORTB时钟	
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);//PWM 输入捕获都要复用推挽
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //GPIOB9 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PB9 输入  输入捕获当然是输入的  
	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化PB
	GPIO_ResetBits(GPIOB,GPIO_Pin_9);
  	  
	TIM_TimeBaseStructure.TIM_Prescaler=psc;  //定时器分频
	TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
	TIM_TimeBaseStructure.TIM_Period=arr;   //自动重装载值
	TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; 	
	TIM_TimeBaseInit(TIM4,&TIM_TimeBaseStructure);
	
	//初始化TIM2输入捕获参数
	TIM4_ICInitStructure.TIM_Channel = TIM_Channel_4; //CC1S=01 	选择输入端 IC3映射到TI3上
  TIM4_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;	//上升沿捕获
  TIM4_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上
  TIM4_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;	 //配置输入分频,不分频 
  TIM4_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置输入滤波器 不滤波
  TIM_ICInit(TIM4, &TIM4_ICInitStructure);
		
	TIM_ITConfig(TIM4,TIM_IT_Update|TIM_IT_CC4,ENABLE);//允许更新中断 ,允许CC3IE捕获中断	 更新中断也要打开,因为万一方波太长了没检测到下降就会溢出 

	TIM4CH4_CAPTURE_STA = 0;	//开启一次捕获
  TIM_Cmd(TIM4,ENABLE ); 	//使能定时器5

  NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority =0;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器、
}

//定时器2中断服务程序	 
void TIM4_IRQHandler(void)
{ 		    
 	if((TIM4CH4_CAPTURE_STA&0X80)==0)		//尚未完成一次捕获	
	{
		if(TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)	//T4溢出
		{	     
			if(TIM4CH4_CAPTURE_STA&0X40)		//已捕获到上升沿了
			{
				if((TIM4CH4_CAPTURE_STA&0X3F)==0X3F)	//高电平太长了
				{
					TIM_Cmd(TIM4,DISABLE);			//关闭定时器4//					
					TIM4CH4_CAPTURE_STA|=0X80;	//标记成功捕获一次
					TIM4CH4_CAPTURE_VAL=0XFFFF;					
				}else TIM4CH4_CAPTURE_STA++;
			}	  	
		}
		if(TIM_GetITStatus(TIM4, TIM_IT_CC4) != RESET)	//发生捕获3事件
		{	
			if(TIM4CH4_CAPTURE_STA&0X40)	//已捕获到上升沿,本次依然是上升沿捕获 		
			{
				TIM_Cmd(TIM4,DISABLE);			//关闭定时器4//				
				TIM4CH4_CAPTURE_STA|=0X80;	//标记成功捕获到一次高电平脉宽,该标志由main主程序清除
			  TIM4CH4_CAPTURE_VAL=TIM_GetCapture4(TIM4);	//获取当前的捕获值.
	 			TIM_OC4PolarityConfig(TIM4,TIM_ICPolarity_Rising);	//CC4P=0 设置为上升沿捕获
			}else		//第一次捕获到上升沿,立标志、设下降沿捕获
			{
				TIM4CH4_CAPTURE_STA=0;			//清空
				TIM4CH4_CAPTURE_VAL=0;
				TIM4CH4_CAPTURE_STA|=0X40;	//标记捕获到上升沿
				TIM_Cmd(TIM4,DISABLE ); 		//关闭定时器4
	 			TIM_SetCounter(TIM4,0);
	 			TIM_OC4PolarityConfig(TIM4,TIM_ICPolarity_Rising);	//CC4P=1 继续上升沿捕获
				TIM_Cmd(TIM4,ENABLE );			//使能定时器4
			}		    
		}			     	    					   
 	}
	TIM_ClearITPendingBit(TIM4, TIM_IT_CC4|TIM_IT_Update);		//清除中断标志位
}




//PSC和ARR的范围为1-65535
/*TIM_IT_Update:更新中断,计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发) 
TIM_IT_CC1~4:都是捕获/比较中断,貌似都是平等的,即输入捕获,输出比较
TIM_IT_Trigger:触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)
*/
//● 计数器寄存器(TIMx_CNT)
//● 预分频寄存器(TIMx_PSC)
//● 自动重装载寄存器(TIMx_ARR)


祝大家实验顺利

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值