STM32 study notes (fourteen)

STM32F103ZET6 input capture experiment



Preface

The learning of STM32 can be divided into 3 versions.
1. Register version
2. Library function version
3. HAL library version
Due to personal reasons, I choose the library function version to learn STM32.


Tip: Problems such as software installation will not be explained! ! !

1. Basic principles of input capture

1 Introduction

Input capture mode can be used to measure pulse width or measure frequency. By detecting the edge signal on TIMx_CHx, when the edge signal changes (such as rising edge/falling edge), the current timer value (TIMx_CNT) is stored in the corresponding capture/compare register (TIMx_CCRx) to complete a capture .

2. Work process

Insert picture description here
Insert picture description here

2. Related registers

1. Capture/compare mode register (TIMx_CCMR1)

Insert picture description here
TIMx_CCMR1 is obviously for the configuration of 2 channels, the lower eight bits [7:0] are used to control the capture/compare channel 1, and the upper eight bits [15: 8] are used to control the capture/compare channel 2, because TIMx There is also the CCMR2 register, so you can know that CCMR2 is used to control channel 3 and channel 4.

2. Bit [7:0] of TIMx_CMMR1

Insert picture description here

3. Capture/compare enable register (TIMx_CCER)

Insert picture description here

4. Capture/compare register (TIMx_CCR1~4)

Insert picture description here

Three, operation steps

1. Corresponding pins

Insert picture description here

2. Operation steps

Insert picture description here
Insert picture description here

Fourth, the program source code

1.timer.h

code show as below:

#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

code show as below:

#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

code show as below:

#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;
		}
	 }
}

5. Experimental results

Insert picture description here
Insert picture description here


to sum up

1. After watching the video, be sure to write the program yourself.
2. Before programming the program, analyze the program and reason about the experimental phenomenon.
3. If the experimental phenomenon is inconsistent with the reasoning, the program must be carefully analyzed.

Guess you like

Origin blog.csdn.net/weixin_44935259/article/details/112966058