【STM32—寄存器版本】输入捕获实验

本人使用的是正点原子的ministm32

整体思路

本次实验用到的寄存器仍然是之前学过的那几个,但是在用法上却更深入一些,本次实验的难点个人认为有两个,一是理解按键捕获的原理,二是理解按键捕获的实现方法。

按键捕获的原理:
定时器向上计数,定时器被设置为上升沿捕捉,当按键被按下时,捕捉到上升沿,于是记录此时的计数值为t1,然后立刻设为下降沿捕获,并且将计数值清0,再次向上计数,直到t2发生下降沿捕获时,记录此时的计数值为CCRx2。通过这个数据我们可以计算出按键按下的时间,即高电平持续时间。但是注意,我们的定时器是有时间限制的,一旦超过定时器的最大时间就会清0重新计时(溢出),所以我们计算高电平持续时间的时候应该这样计算:
溢出次数N*一次计时最大值ARR+CCRx2

按键捕获的实现方法这个等代码列出来之后再解释把

主要代码部分

main函数

#include "sys.h"
#include "usart.h"  
#include "delay.h" 
#include "led.h" 
#include "timer.h"
#include "into.h"
extern u8 TIM2CH1_CAPTURE_STA;//输入捕获状态
extern u16 TIM2CH1_CAPTURE_VAL;//输入捕获值
int main(){
 u32 temp=0;
 Stm32_Clock_Init(9);
 uart_init(72,9600);
 delay_init(72);
 LED_Init();
 TIM1_PWM_Init(899,0);//10Khz的计数频率。计数5K次为500ms
 TIM2_Cap_Init(0XFFFF,72-1);//以1Mhz计算
 while(1){
  delay_ms(10);
  LED0_PWM_VAL++;//呼吸灯
 if(LED0_PWM_VAL==300)
  LED0_PWM_VAL=0;
 if(TIM2CH1_CAPTURE_STA&0X80)//成功补获一次
 {
 temp = TIM2CH1_CAPTURE_STA&0X3F;//溢出了多少次
 temp*=65536;//溢出次数乘以每次溢出的时间等于溢出时间总和
  temp+=TIM2CH1_CAPTURE_VAL;//得到高电平总时间
  printf("HIGH:%d us\r\n",temp);     //打印总高电平时间
  TIM2CH1_CAPTURE_STA=0;       //开启下一次捕获
  }
 }
}

into.c

#include "into.h"
#include "led.h"
void TIM2_Cap_Init(u16 arr,u16 psc){
 RCC->APB1ENR|=1<<0;   //TIM2时钟使能
 RCC->APB2ENR|=1<<2;//使能A时钟
 GPIOA->CRL&= 0XFFFFFFF0;
 GPIOA->CRL |=0X00000008;//输入
 GPIOA->ODR |=0<<0;//下拉
 TIM2->ARR=arr;
 TIM2->PSC=psc;
 TIM2->CCMR1|=1<<0;//选择输入IC1映射带TI1上
 TIM2->CCMR1|=1<<4;//IC1F是0001模式,2个事件后有效
 TIM2->CCMR1|=0<<10;//配置输入分频为不分频 
 TIM2->CCER |= 1<<0;//允许捕获计数器
 TIM2->CCER|=0<<1;//上升沿触发
 TIM2->DIER|=1<<1;//允许捕获中断
 TIM2->DIER|=1<<0;//允许更新中断
 TIM2->CR1 |=0x01;//使能定时器2
 MY_NVIC_Init(2,0,TIM2_IRQn,2);//抢占2,子优先级0,组2
 //捕获状态
 //定时器2中断服务
}
 u8 TIM2CH1_CAPTURE_STA=0;//输入捕获状态
 u16 TIM2CH1_CAPTURE_VAL;//输入捕获值
 void TIM2_IRQHandler(void){
  u16 tsr;
  tsr = TIM2->SR;//寄存器状态
  if((TIM2CH1_CAPTURE_STA&0X80)==0)
   {//还未捕获成功
   if(tsr&0X01)
    {//是否有更新事件产生
    if(TIM2CH1_CAPTURE_STA & 0X40)
     {//已经捕获到高电平
     if((TIM2CH1_CAPTURE_STA & 0X3F)==0X3F)
     {
     TIM2CH1_CAPTURE_STA|=0x80;//标记成功捕获了一次
     TIM2CH1_CAPTURE_VAL=0XFFFF;//捕获值为
     }
     else
      {
     TIM2CH1_CAPTURE_STA++;
      }
     }
    }
   if(tsr&0x02){ //捕获1发生捕获事件
    if(TIM2CH1_CAPTURE_STA&0X40)//捕获到一个下降沿
     {
    TIM2CH1_CAPTURE_STA|=0X80;
    TIM2CH1_CAPTURE_VAL=TIM2->CCR1;//获得当前的捕获值
    TIM2->CCER &=~(1<<1);//变为检测上升沿   
     }
   else
    {    //还未开始,第一次捕捉上升沿
    TIM2CH1_CAPTURE_VAL=0;
    TIM2CH1_CAPTURE_STA=0X40;//标记捕捉到了上升延
    TIM2->CNT=0;//计数器清空
    TIM2->CCER|=1<<1;//设为下降沿捕获
    }
  }
 }
 
 TIM2->SR=0;//清除中断标志位
}

into.h

#ifndef _INTO_H
#define _INTO_H
#include "sys.h"
void TIM2_Cap_Init(u16 arr,u16 psc);
#endif

其他timer函数的内容可以移步上篇csdn,主要说明一下into.c的代码逻辑 前面的配置先不多说了,重点是TIM2_IRQHandler,TIM2的中断函数
我们定义了一个八位的变量TIM2CH1_CAPTURE_STA
bit5~0:捕获高电平后定时器溢出的次数
bit6:捕获到高电平的标志
bit 7:捕获完成的标志
TIM2CH1_CAPTURE_VAL
记录捕获到下降沿时TIM2_CNT的值

首先我们设置为上升沿捕获,当上升中断捕获到来时,如果TIM2CH1_CAPTURE_STA的第六位还不是1,那我们先消除一切配置,将TIM2CH1_CAPTURE_STA,TIM2CH1_CAPTURE_VAL和TIM2->CNT清0,然后再手动把TIM2CH1_CAPTURE_STA的第六位置1,意为捕捉到了高电平,然后再设置位下降沿捕获,如果高电平持续时间过长,那就会发生溢出,在TIM2CH1_CAPTURE_STA中对溢出进行记数,当最大溢出次数来临(0~5位都满了),就强制捕获完成,把TIM2CH1_CAPTURE_STA第七位置为1,标记成功捕获了一次高电平,读取定时器的捕获值到TIM2CH1_CAPTURE_VAL中,最后再设置为上升沿捕获,回到初始状态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值