STM32研究ノート(14)

STM32F103ZET6入力キャプチャ実験



序文

STM32の学習は3つのバージョンに分けることができます。
1.登録バージョン
2.ライブラリ関数バージョン
3.HALライブラリバージョン
個人的な理由により、STM32を学習するためにライブラリ関数バージョンを選択します。


ヒント:ソフトウェアのインストールなどの問題は説明されません!

1.入力キャプチャの基本原則

1はじめに

入力キャプチャモードは、パルス幅の測定または周波数の測定に使用できます。TIMx_CHxでエ​​ッジ信号を検出することにより、エッジ信号が変化したとき(立ち上がりエッジ/立ち下がりエッジなど)、現在のタイマー値(TIMx_CNT)を対応するキャプチャ/比較レジスタ(TIMx_CCRx)に格納して、キャプチャを完了します。

2.作業プロセス

ここに画像の説明を挿入
ここに画像の説明を挿入

2.関連レジスタ

1.キャプチャ/比較モードレジスタ(TIMx_CCMR1)

ここに画像の説明を挿入
TIMx_CCMR1は明らかに2チャネルの構成用であり、下位8ビット[7:0]はチャネル1のキャプチャ/比較を制御するために使用され、上位8ビット[15:8]はチャネル2のキャプチャ/比較を制御するために使用されます。 、TIMx CCMR2レジスタもあるため、CCMR2がチャネル3とチャネル4の制御に使用されていることがわかります。

2. TIMx_CMMR1のビット[7:0]

ここに画像の説明を挿入

3.イネーブルレジスタ(TIMx_CCER)をキャプチャ/比較します

ここに画像の説明を挿入

4.レジスタのキャプチャ/比較(TIMx_CCR1〜4)

ここに画像の説明を挿入

3つの操作手順

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

5.実験結果

ここに画像の説明を挿入
ここに画像の説明を挿入


総括する

1.ビデオを見た後は、必ず自分でプログラムを作成してください。
2.プログラムをプログラミングする前に、プログラムと実験現象についての理由を分析します。
3.実験現象が推論と矛盾する場合は、プログラムを注意深く分析する必要があります。

おすすめ

転載: blog.csdn.net/weixin_44935259/article/details/112966058