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.実験現象が推論と矛盾する場合は、プログラムを注意深く分析する必要があります。