5

STM32 学习12 输入捕获与触摸按键

 1 month ago
source link: https://blog.51cto.com/u_4029519/10228418
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

STM32 学习12 输入捕获与触摸按键

精选 原创

STM32 学习12 输入捕获与触摸按键

  • 一、输入捕获介绍
  • 2. STM32F1 资源
  • 3. 捕获原理
  • 二、输入捕获配置步骤
  • 1. 使能时钟、设置端口模式
  • 2. 初始化定时器
  • 3. 设置捕获参数
  • 4. 开启捕获和定时器中断(溢出中断|更新中断)
  • 6. 编写定时器中断服务函数
  • 7. 使能定时器
  • 三、代码实现
  • 1. catch_utils.h
  • 2. catch_utils.c
  • 3. main.c
  • 四、触摸按键捕获

一、输入捕获介绍

输入捕获(Input Capture)是一种用于测量外部信号脉冲宽度或者频率的技术,常用于测量传感器输出、编码器信号、脉冲调制信号等。输入捕获通常通过定时器模块来实现输入捕获功能。

2. STM32F1 资源

STM32F1除了基本定时器TIM6和TIM7,其它定时器都具有输入捕获功能。

3. 捕获原理

捕获原理是指通过定时器模块捕获外部信号的特定事件,例如脉冲的上升沿或下降沿,以便测量脉冲宽度或频率。 输入捕获时,相应的ICx检测到跳变沿,TIMx_CCRx寄存器记录TIMx_CNT计数值;下次跳变时,对TIMx_CNT值进行比较。

图示如下:

STM32 学习12 输入捕获与触摸按键_初始化

注意CNT计数的次数是 STM32 学习12 输入捕获与触摸按键_初始化_02,因为在检测周期里计数可能多次溢出,需要记录溢出次数N。

由计数效数*CNT计数周期,即捕获到信号持续时间。

二、输入捕获配置步骤

1. 使能时钟、设置端口模式

定时器需要的头文件在 stm32f10_tim.h 文件中。

下面示例使用 PA0/TIM5_CH1 引脚。

STM32 学习12 输入捕获与触摸按键_学习_03
RCC_APB1PerihpClockCmd(RCC_APB1Periph_TIM5,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
// GPIO 设置为输入拉低
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD;

2. 初始化定时器

配置定时器的时钟源、预分频器、计数模式等。

void TIM_TimeBaseInit(TIM_TypeDef *TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);

3. 设置捕获参数

开启捕获。

void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStrcut);

typedef struct{
   uint16_t TIM_Channel;		// 通道
   uint16_t TIM_ICPolarity;		// 捕获极性
   uint16_t TIM_ICSelection;	// 映射
   uint16_t TIM_ICPRescaler;	// 分频系数
   uint16_t TIM_ICFilter;		// 滤波器长度
} TIM_ICInitTypeDef;

// 设置通道1
TIM_OC1PolarityConfig(TIM5, TIM_ICPolarity_Rising);

4. 开启捕获和定时器中断(溢出中断|更新中断)

void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);
// 捕获通道1
TIM_ITConfig(TIM5, TIM_IT_Update|TIM_IT_CC1,ENABLE);

NVIC_Init()

6. 编写定时器中断服务函数

TIM5_IRQHandler

7. 使能定时器

void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);

三、代码实现

1. catch_utils.h

#ifndef __CATCH_UTILS_H__
#define __CATCH_UTILS_H__
#include "stm32f10x.h"
#include "stdio.h"

// 定时器溢出的次数
static u8 TIM5_Overflow = 0;
// 捕获到上升沿
static u8 TIM5_Capture = 0;
void catch_gpio_init(u16 period, u16 prescaler);
void catch_timer_enable(void);
#endif

2. catch_utils.c

#include "catch_utils.h"

#define RISING 0
#define FALLING 1


/**
 * @brief  捕获初始化
*/
void catch_gpio_init(u16 period, u16 prescaler)
{
    // GPIO 初始化
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 定时器初始化
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_TimeBaseStructure.TIM_Period = period;
    TIM_TimeBaseStructure.TIM_Prescaler = prescaler;
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);

    // 输入捕获初始化
    TIM_ICInitTypeDef TIM_ICInitStructure;
    TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
    TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
    TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
    TIM_ICInitStructure.TIM_ICFilter = 0x00;
    TIM_ICInit(TIM5, &TIM_ICInitStructure);
    TIM_OC1PolarityConfig(TIM5, TIM_ICPolarity_Rising);

    // 开启捕获和定时器中断
    TIM_ITConfig(TIM5, TIM_IT_Update | TIM_IT_CC1, ENABLE);
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

/**
 * 中断函数
*/
void TIM5_IRQHandler(void)
{
    // 如果捕获到,要翻转一下捕获方向,如果捕获到下降沿,就设置为上升沿,并计算捕获时间并输出
    if (TIM_GetITStatus(TIM5, TIM_IT_CC1))
    {
        if (TIM5_Capture == RISING)
        {
            printf("catch rising irq, TIM5_Capture= %d \n", TIM5_Capture);
            TIM5_Capture = FALLING;
            // 关闭定时器
            TIM_Cmd(TIM5, DISABLE);
            TIM_SetCounter(TIM5, 0);
            TIM5_Overflow = 0;
            TIM_OC1PolarityConfig(TIM5, TIM_ICPolarity_Falling);
            TIM_Cmd(TIM5, ENABLE);
        }
        else
        {
            // 捕获到下降沿
            TIM5_Capture = RISING;
            // 计算 总时间
            u16 time = TIM_GetCapture1(TIM5);
            u32 total_time = TIM5_Overflow * 0xffff + time;
            printf("catch falling irq, capture time= %d, overflow count = %d \n, total=%dus", time, TIM5_Overflow, total_time);
            TIM_OC1PolarityConfig(TIM5, TIM_ICPolarity_Rising);
        }
        TIM_ClearITPendingBit(TIM5, TIM_IT_CC1);
    }else if(TIM_GetITStatus(TIM5, TIM_IT_Update)){
        TIM5_Overflow++;
        TIM_ClearITPendingBit(TIM5, TIM_IT_Update);
    }
}
/**
 * @brief 使能定时器
*/
void catch_timer_enable(void)
{
    TIM_Cmd(TIM5, ENABLE);
}

3. main.c

#include "gpio_utils.h"
#include "rcc_utils.h"
#include "stm32f10x.h"
#include "sys_tick_utils.h"
#include "led_utils.h"
#include "usart_utils.h"
#include "stdio.h"
#include "catch_utils.h"

// 主函数
int main(void)
{
	GPIO_Configuration(); // 调用GPIO配置函数
	// tick 初始化
	sys_tick_init(72);
	led_all_off();
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	USART3_Init(9600);
	printf("starting...");

	// led 初始化
	custom_led_init();

	int i = 0;
	// 捕获初始化
	catch_gpio_init(0xffff, 72 - 1);
	catch_timer_enable();
	
	while (1) // 无限循环
	{
		delay_ms(990);
		led_lightn(i);
		i++;
		if(i>9){
			i=0;
		}
	}
}

四、触摸按键捕获

我的开发板没有带触摸组件,所以本实验使用外置的触摸按键模块。

STM32 学习12 输入捕获与触摸按键_嵌入式硬件_04

这个触摸按键在感应到触摸时,会在SIG引脚输出高电平。 直接把SIG接在 PA0 上即可使用。

但该电路对原KEY_UP按键模块有影响,开发板按键按下的时候,PA0 获取不到足够高的电平。

运行中串口输出示例

STM32 学习12 输入捕获与触摸按键_#include_05
  • 收藏
  • 评论
  • 分享
  • 举报

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK