基础自学-关于STM32F103C8T6的定时器输入捕获实现

本文详细介绍了STM32单片机输入捕获功能的原理及应用,包括如何使用输入捕获检测外部信号变化,如方波个数、信号频率等。文中还提供了具体的配置代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

让自己别忘了大学里学的东西,那么就把它记录下下来,效率会比忘记然后重新再去找资料再重头学高的多 吐舌头

原理部分:
 
关于自己的理解:
输入捕获,顾名思义,就是在单片机上找到一个对应的引脚,而这个引脚是作为输入端,来检测外面来的信号,当外面的信号处于某种跳变的时候,该引脚会触发一个标志位,并将标志位发给单片机,最后结果可以是产生中断,也可以是普通的标志位,所以说白了就是单片机的这个功能可以用来捕获外部信号的某种跳变(上升沿,下降沿,或者两者都可).
遇到过的作用:
1.检测方波个数, 2.检测信号频率, 3.超声波测试, 4.DTH11数据接收.

代码部分:

首先:找到在单片机上这些对应的引脚

由资料可知Tim34个通道分别在PA6,PA7,PB0,PB1四个引脚上(如下图),又因为我们是输入捕获,是检测外来的信号,所以将对应的引脚设置成输入模式(下拉).

其次:明确对于输入捕获功能用到的一些参数

1. 定时器的捕获通道 :ICInitStructure.TIM_Channel

    每个定时器对应有4个通道,分别CH1~CH4

2. 定时器的捕获条件  : ICInitStructure.TIM_ICPolarity

    捕获条件有三种: 1. 外部信号的上升沿 2. 外部信号的下降沿  3. 外部信号的双边沿

3. 定时器的捕获通道对应的引脚 : ICInitStructure.TIM_ICSelection

    有三种模式:1. 直接模式 CHx-ICx  2. 间接模式 CH1-IC2,CH2-IC1,CH3-IC4,CH4-CH3. 3. 忽略

4. 定时器的捕获频率  : ICInitStructure.TIM_ICPrescaler

    有四种模式:1. 每次触发  2. 每两个触发一次  3. 每四个触发一次  4. 每八个触发一次

5. 定时器的捕获滤波  :ICInitStructure.TIM_ICFilter
    忽略
最后::整体的参考代码
//---M_Tim3.c文件  //
#include <M_all.h>  

void Tim3_Base_Init(u32 Period, u32 Prescaler)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;             //结构体_定时器基础-声明     
		
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);        //时钟开启_Tim3
	
	
	TIM_TimeBaseStructure.TIM_Period = Period;                 //结构体_定时器基础-定时器顶端值设定

	TIM_TimeBaseStructure.TIM_Prescaler = Prescaler;           //结构体_定时器基础-定时器分频值设定

	TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;             //结构体_定时器基础-忽略

	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//结构体_定时器基础-计数模式-向上计数

	TIM_TimeBaseInit(TIM3, & TIM_TimeBaseStructure);           //结构体_定时器基础-结束配置
		
	
	TIM_ARRPreloadConfig(TIM3, ENABLE);	                       //开关_使能定时器计数功能
	
	TIM_Cmd(TIM3, ENABLE);                                     //开关_定时器总开关
	
}




void Tim3_IC1_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;                       //结构体_引脚-声明
	
	TIM_ICInitTypeDef TIM_ICInitStructure;                     //结构体_输入捕获-声明
	
	NVIC_InitTypeDef NVIC_InitStructure;                       //结构体_中断-声明
	
	
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);       //时钟开启_GPIO-A
	
	
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;                  //结构体_引脚-PA6

	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;          //结构体_引脚-引脚频率_50Mhz
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;              //结构体_引脚-引脚模式_下拉输入
	
	GPIO_Init(GPIOA, &GPIO_InitStructure);	                   //结构体_引脚-结束配置
	
	
	
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;           //结构体_输入捕获-通道设定-通道1
	
	TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_BothEdge;         //结构体_输入捕获-触发模式-双边触发
	
	TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;       //结构体_输入捕获-通道引脚对应-CH1=通道1
	
	TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;      //结构体_输入捕获-触发间隔-每次触发
	
	TIM_ICInitStructure.TIM_ICFilter = 0x0;                    //结构体_输入捕获-忽略
	
	TIM_ICInit(TIM3,&TIM_ICInitStructure);                     //结构体_输入捕获-结束配置



	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;            //结构体_中断-中断对象_Tim3

	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //结构体_中断-先占优先级 0 级

	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;         //结构体_中断-从优先级 3 级

	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //结构体_中断-使能该IRQ通道

	NVIC_Init(&NVIC_InitStructure);                            //结构体_中断-结束配置
	
	
	TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE );	                 //开关_使能输入捕获触发中断
	
}






void TIM3_IRQHandler(void) //TIM3 中断
{

	if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)            //判断_中断来源-TIM3_输入捕获触发中断
	{
		TIM_ClearITPendingBit(TIM3, TIM_IT_CC1 );                //清除_标志-TIM3_输入捕获中断标志
		
	}
}


PS:而捕获定时器的定时的那些参数无关,因为它相当于是条件触发,而不是通过计数触发,从而只要开启定时器和输入捕获功能即可,每次只要检测到预设的跳变就会产生触发。而且,像这种触发一般都是通过中断来显示出来的,所以配置了中断程序STM32固件库里面的结构体配置往往都只是涉及到模式的配置,而并没有开关使能等内容,所以并不是说结构体配置完就可以用了,所以 特意把对应功能的使能命令放在函数的末尾,把涉及到的寄存器放在最上面,方便理解和记忆,一般涉及到哪些寄存器、外设和功能,那么找对应的使能开关,然后使能它们即可。

这些都是自己的理解,如果有错反馈哦


#include "led.h" #include "delay.h" #include "key.h" #include "sys.h" #include "exti.h" #include "timer.h" #include "usart.h" #include "IWDG.h" //int main(void) //中断 //{ ////delay_init(); //LED_Init(); ////KEY_Init(); ////NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); ////EXTIX_Init(); //LED=0; //while(1); //} //int main(void) //定时器中断 //{ // NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // delay_init(); // LED_Init(); // // TIM3_Int_Init(1999,7199);//((1+7199)/72M)*(1+9999)=1秒*/反 // while(1); //} //int main(void) //pwm //{ // u16 ledpwmval=0; // u8 dir=1; // delay_init(); // NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // uart_init(115200); // LED_Init (); // // TIM3_PWM_Init(199,7199);//50Hz // while(1) // { // delay_ms(10); // if(dir)ledpwmval++; // else ledpwmval --; // if(ledpwmval >1000) // dir=0; // if(ledpwmval ==0) // dir=1; // TIM_SetCompare2(TIM3,5); // delay_ms(500); // TIM_SetCompare2(TIM3,10); // delay_ms(500); // TIM_SetCompare2(TIM3,15); // delay_ms(500); // TIM_SetCompare2(TIM3,20); // delay_ms(500); // TIM_SetCompare2(TIM3,25); // delay_ms(500); // } //} //int main() //串口 //{ // u16 t; // u16 len; // u16 times=0; // delay_init(); // NVIC_PriorityGroupConfig (NVIC_PriorityGroup_2 ); // uart_init(115200); // LED_Init(); // KEY_Init(); // while(1) // { // if(USART_RX_STA&0x8000) // { // len=USART_RX_STA&0x3fff;//得到此次接收的数据长度 // printf("\r\n您发送的消息为:\r\n\r\n"); // for(t=0;t<len;t++) // { // USART_SendData(USART1,USART_RX_BUF[t]); // while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET); // } // printf("\r\n\r\n");//插入换行 // USART_RX_STA=0; // } // else // { // times++; // if(times%500000==0) // { // LED=!LED; // } // } // } //} extern void TIM4_Cap_Init(u16 arr,u16 psc); extern u8 TIM4CH1_CAPTURE_STA; //输入捕获状态 输入捕获实验 extern u16 TIM4CH1_CAPTURE_VAL; //输入捕获值 int main(void) { u32 temp=0; delay_init(); //延时函数初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级 uart_init(115200); //串口初始化为115200 LED_Init(); //LED端口初始化 // TIM3_PWM_Init(899,0); //不分频。PWM频率72000/(899+1)=80Khz TIM4_Cap_Init(0XFFFF,72-1); //以1Mhz的频率计数 while(1) { delay_ms(10); TIM_SetCompare2(TIM3,TIM_GetCapture2(TIM3)+1); if(TIM_GetCapture2(TIM3)==300) TIM_SetCompare2(TIM3,0); if(TIM4CH1_CAPTURE_STA&0X80)//成功捕获到了一次上升沿 { temp=TIM4CH1_CAPTURE_STA&0X3F; temp*=65536; //溢出时间总和 temp+=TIM4CH1_CAPTURE_VAL;//得到总的高电平时间 printf("HIGH:%d us\r\n",temp);//打印总的高点平时间 TIM4CH1_CAPTURE_STA=0;//开启下一次捕获 } } }
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值