定时器搭配GPIO做定时扫描按键 -- STM32

news2024/11/27 18:27:41

STM32学习

    • 定时器(TIM)
      • 定时器工作原理
      • 定时器相关参数
      • 相关函数和配置参数
    • 通用输入/输出(GPIO)
      • GPIO原理
      • GPIO相关函数
    • 实现定时扫描按键
    • 总结

在STM32F103系列的单片机应用中,定时器(TIM)和通用输入/输出(GPIO)是常用的模块之一。这两个模块结合起来,可以实现非常多的实际应用,其中,定时器可以用来实现定时扫描按键,而GPIO可以用来控制LED等设备。

本文将介绍,在STM32F103系列的单片机中如何通过定时器和GPIO模块,实现定时扫描按键功能。
本文将从定时器、GPIO原理入手,讲解使用到的函数以及配置参数,最后做总结。

定时器(TIM)

使用定时器,需要先了解定时器的原理及其相关参数。

定时器工作原理

定时器是一种计算时间的模块,可以用来触发一些事件、完成一些操作或者调度系统任务。定时器的核心部分为计数器和控制寄存器。

定时器开始计数后,计数值会每次增加1,当计数值达到设定的上限值时,会触发一个中断或者其他的事件。同时,可以通过调整定时器的各个参数来控制计数器的计数速率、计数上限以及触发中断的条件。
在这里插入图片描述

定时器相关参数

在使用定时器前,需要对其相关参数进行配置,常用的定时器参数包括:

  • 周期(ARR):定时器计数器的上限值,当计数器增加到该值时,会触发定时器的中断或其他操作。
  • 预分频器(PSC):用于降低计数器输入时钟的频率,从而达到降低定时器计数速率的目的。
  • 计数模式(Counter Mode):定时器可以分为向上计数模式和向下计数模式,可以根据具体需求进行配置。
  • 输出比较通道(Output Compare Channel):可以通过定时器的输出比较通道来产生PWM波形等复杂的定时信号。

相关函数和配置参数

常用的配置定时器的函数包括:

void TIM_DeInit(TIM_TypeDef* TIMx);         //TIMx 定时器的初始化

void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);      //定时器基本配置

void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);       //开启或关闭定时器

void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1);      //设置定时器输出比较通道 1 的占空比

void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);      //允许或禁止定时器中断

void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);        //清除定时器的中断标志位

其中,TIM_TimeBaseInitTypeDef 结构体用于初始化定时器的基本配置参数,常用的配置参数包括:

//定时器基本配置结构体
typedef struct
{
  uint16_t TIM_Prescaler;           //定时器计数器的预分频值
  uint16_t TIM_CounterMode;         //定时器的计数模式(向上或向下)
  uint32_t TIM_Period;              //定时器计数器的上限值
  uint16_t TIM_ClockDivision;       //采样分频
  uint8_t TIM_RepetitionCounter;    //自动重载计数器值
} TIM_TimeBaseInitTypeDef;

在使用定时器时,需要对其进行初始化并配置相关参数。以下代码段为一个示例初始化函数:

void Timer_Init(void)
{
  TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
  TIM_TimeBaseInitStruct.TIM_Prescaler = 7200;
  TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInitStruct.TIM_Period = 1000-1;
  TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct);
  TIM_Cmd(TIM3, ENABLE);
}

该函数使用的是 TIM3 定时器,采用向上计数模式。定时器预分频器值为7200,计数到1000后(即从0计数到999),会触发定时器中断。TIM_Cmd() 函数用于启用定时器。

推荐查看之前文章:https://blog.csdn.net/hongyun1221/article/details/130973099

通用输入/输出(GPIO)

通用输入/输出(GPIO)是单片机上最为基础,也是最常用的模块之一。GPIO模块包含多个引脚,每个引脚具有输入和输出两种模式,可以用来控制各种外设,例如LED、按键等。

GPIO原理

GPIO模块的输入输出控制是通过寄存器进行的,每个IO口都与一个寄存器相关联,我们可以通过修改该寄存器的值来控制IO口的状态,从而实现相应的输入/输出功能。常见的GPIO寄存器包括:GPIOx_CRL、GPIOx_CRH、GPIOx_ODR、GPIOx_IDR、GPIOx_BSRR、GPIOx_BRR、GPIOx_LCKR等。

GPIO相关函数

在STM32F103系列单片机中,使用GPIO模块时,常用的函数包括:

void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);           //初始化GPIO引脚

void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);                   //GPIO引脚锁定

void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);      //设置或清除GPIO引脚的输出状态

uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);             //读取GPIO引脚的输入状态

其中,GPIO_InitTypeDef 结构体用于配置GPIO引脚的具体参数,常用的配置参数包括:

//GPIO 配置结构体
typedef struct
{
  uint16_t GPIO_Pin;            //需要初始化的GPIO引脚
  GPIOMode_TypeDef GPIO_Mode;   //GPIO引脚工作模式
  GPIOSpeed_TypeDef GPIO_Speed; //GPIO引脚速度
  GPIOOType_TypeDef GPIO_OType; //GPIO引脚输出类型
  GPIOPuPd_TypeDef GPIO_PuPd;   //GPIO引脚上下拉模式
} GPIO_InitTypeDef;

使用GPIO模块,需要对相关引脚进行初始化并配置其相应的工作模式、输出类型、上下拉模式等参数。以下为一个示例初始化函数:

void GPIO_InitExample(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);    //使能GPIOB的时钟
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;                   //初始化GPIOB的0号引脚
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;               //输入上拉模式
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;           //50MHz速度
  GPIO_Init(GPIOB, &GPIO_InitStruct);                      //初始化GPIOB
}

该函数使用的是GPIOB模块的0号引脚,初始化为输入上拉模式。

实现定时扫描按键

下面我们结合以上的知识,来实现简单的定时扫描按键功能。该功能的基本实现思路为:

  1. 初始化GPIO引脚,设置为输入上拉模式
  2. 初始化TIM定时器,启用定时中断
  3. 在定时器中断处理函数中检测按键状态

为了便于演示,我们使用开发板上的资源做一个示例:定时器每20ms扫描一次按键,按键配置LED亮灭。

主程序代码

int main(void){
    LED_GPIO_Init();
    KEY_GPIO_Init();
    TIM_EXIT_Init(20000-1, 72-1);
    while(1){
        
    }
}

定时器头文件

#ifndef __TIMER_H
#define __TIMER_H
#include "stm32f10x.h"


#define TIM             TIM3
#define TIM_CLK         RCC_APB1Periph_TIM3
#define TIM_IRQ         TIM3_IRQn
#define TIM_IRQHandler  TIM3_IRQHandler


void TIM_EXIT_Init(uint16_t arr, uint16_t psc);


#endif /* __TIMER_H */

定时器源代码

#include "bsp_timer.h"

void TIM_NVIC_Init(void){
    NVIC_InitTypeDef NVIC_InitStruct;
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
    NVIC_InitStruct.NVIC_IRQChannel = TIM_IRQ;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStruct);


}


void TIM_EXIT_Init(uint16_t arr, uint16_t psc){
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    TIM_NVIC_Init();
    RCC_APB1PeriphClockCmd(TIM_CLK, ENABLE);
    TIM_TimeBaseInitStruct.TIM_Prescaler = psc;
    TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInitStruct.TIM_Period = arr;
    TIM_TimeBaseInit(TIM, &TIM_TimeBaseInitStruct);
    TIM_ITConfig(TIM, TIM_IT_Update, ENABLE);
    TIM_Cmd(TIM, ENABLE);
}

按键源文件

#ifndef __KEY_H
#define __KEY_H


#include "stm32f10x.h"
typedef enum {
    key_button = 0,
    key_release = 1
} KeyStatus;


#define KEY_GPIO_PORT   GPIOB
#define KEY_GPIO_CLK    RCC_APB2Periph_GPIOB
#define KEY_GPIO_PIN    GPIO_Pin_1


void KEY_GPIO_Init(void);
void KEY_GPIO_Scan(void);


#endif /* __KEY_H */

总结

本文介绍了在STM32F103单片机中,如何使用定时器和GPIO模块实现定时扫描按键功能。通过学习定时器和GPIO的相关原理和函数,我们可以更加深入地了解STM32F103单片机的工作原理,从而更好地完成各类实际应用。

总的来说,定时器和GPIO模块是STM32F103单片机非常常用和重要的模块,掌握其相关知识和应用技巧,对于提高单片机的应用水平和开发效率具有重要的作用。

程序代码资源下载:https://download.csdn.net/download/hongyun1221/87852606

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/598113.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【名词解释】KiB和KB,MiB和MB,GiB和GB 等的区别以及1M带宽到底是多少?

目录 1. KiB和KB,MiB和MB,GiB和GB 2. 宽带速度 3. 单位换算 1. KiB和KB,MiB和MB,GiB和GB KiB和KB,MiB和MB,GiB和GB 等的区别: 1KB(kilobyte)10^31000byte, 1KiB(kibibyte)2^101024byte …

虹科干货 | 虹科Redis企业版数据库的延迟如此之小,proxy功不可没!

在Redis企业版集群的后台发生了许多事件,proxy(代理)隐藏了数据库客户端的所有活动。 大多数开发人员在构建应用程序时都会从小规模开始,使用简单的Redis开源(Redis OSS)数据库。在初期阶段,使用…

lnmp安装部署

文章目录 一、安装部署nginx二、安装部署mysql三、安装配置 PHP 解析环境四、部署 Discuz!社区论坛 Web 应用 一、安装部署nginx 1、安装依赖包 systemctl stop firewalld setenforce 0 yum -y install pcre-devel zlib-devel gcc gcc-c make2、创建运行用户 use…

设计模式之~解释器模式

简述: 解释器模式,给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。 解释器模式需要解决的是,如果一种特定类型的问题发生的频率足够高,那么可…

基于安全产品DNS隧道流量分析

域名准备 选择哪家的云都没问题,这里我选择的TX云,因为之前注册过了,自己拿来做个流量分析不成问题。 域名添加解析记录 需要准备自己的vps作为DNS隧道的服务端,且需要添加ns记录 iodined 关闭53端口关闭开机自启 systemctl …

数据在内存中存储的真相来了!!!

🤩本文作者:大家好,我是paper jie,感谢你阅读本文,欢迎一建三连哦。 🥰内容专栏:这里是《C知识系统分享》专栏,笔者用重金(时间和精力)打造,基础知识一网打尽&#xff0c…

【CMake报错】“检测到_ITERATOR_DEBUG_LEVEL和RuntimeLibrary不匹配” 的解决方案

👉博__主👈:米码收割机 👉技__能👈:C/Python语言 👉公众号👈:测试开发自动化 👉专__注👈:专注主流机器人、人工智能等相关领域的开发、…

外观模式详解:轻松搞定复杂子系统

一、概述 外观模式(Facade Pattern)是一种结构型设计模式,它为多个子系统中的操作提供一个统一的高层接口,用于访问复杂子系统的功能。其核心思想是通过一个外观类将子系统的复杂操作进行封装,客户端只需与外观类进行…

微信朋友圈如何批量发圈

做营销最重要的任务是什么? 毋庸置疑,就是发布朋友圈。 为什么要发圈呢? 发朋友圈是一种推广产品和服务的营销手段。 在如今社交媒体普及的时代,人们大多数时间都在线上,而朋友圈作为微信中的社交场景之一&#xff…

小程序开发,帮助小个体实现品牌化

在这个互联网时代,小程序成为了各大平台的必备。微信作为一款国民级的应用,如今已经拥有近10亿的用户,而小程序作为微信新推出的一款产品,已经被大家熟知。除了微信平台之外,小程序也被很多商家所青睐。因为小程序能带…

C++中《stack和queue的使用》

本文主要讲解栈和队列的常见接口的使用 文章目录 一、栈的介绍和使用1.1 stack的介绍1.2 stack的使用 二、queue的介绍和使用2.1 queue的介绍2.2 queue的使用 一、栈的介绍和使用 1.1 stack的介绍 1️⃣stack是一种容器适配器,专门用在具有后进先出操作的上下文环…

CS5366电路原理图|CS5366demobord参考电路|单芯片PD集成4K60Hz拓展坞芯片设计

ASL CS5366是Type-C转HDMI 4K60HZPDUSB3.0单芯片集成芯片,芯片方案带DSC压缩功能且最高可支持支持RGB 4:4:4 。 CS5366参数特性: 支持最高分辨率/定时4k60Hz 支持DSC v1.2a,并与前一版本向后兼容 支持DSC解码器和直通模式 嵌入式32位RISC-V…

2023年天府杯全国大学生数学建模竞赛B题中国环境问题的治理解题全过程

2023年天府杯全国大学生数学建模竞赛 B题 中国环境问题的治理 原题再现: 问题背景:   随着经济的快速发展和人口的持续增长,中国的环境问题已经成为了一个急需解决的重要问题。这些环境问题不仅对人们的健康和生活质量产生了巨大的影响&a…

笔试强训7

作者:爱塔居 专栏:笔试强训 作者简介:大三学生,希望和大家一起进步 目录 day9 day10 day9 一. 单选 1.下面程序的输出是:() String x"fmn"; x.toUpperCase(); String yx.replace(f,F); yy"wxy"; System.out…

Redis的内存策略(未完成)

过期Key处理: 1)Redis之所以性能强大,最主要的原因就是基于内存来存储,然而单节点的Redis内存不宜设置的过大,否则会影响持久化或者是主从复制的性能,可以通过修改配置文件来设置redis的最大内存,通过maxmemory 1gb&am…

为什么数字化转型就应该选择低代码?一文详解

数字化转型在这几年被反复提及,我们听得耳朵都快起茧子了。数字化在当前经济社会发展中扮演着越来越重要的角色,可以帮助企业更好地理解消费者和市场需求,更好地应对市场竞争,同时也可以提高企业效率,促进经济发展。 究…

WICC · 出海嘉年华倒计时!精彩不容错过,「指南」一手掌握

6.2 广州 WICC出海嘉年华 精彩不容错过 指南一手掌握 -高端峰会 圆桌会议- 超 有 料 话题剧透 如何在巨头林立的热门赛道成功突围? 如何在迅猛发展的新兴市场深挖价值? 如何在复杂合规政策下实现应用增长? 如何利用好底层技术优化本地化…

pip安装库提示Read timed out更换下载源

在使用pip install xx安装库的时候提示 Read timed out. 一般解决方案就两种: 1.延长timeout时间,治标不治本,谁知道到底该延长多少时间才能百分百每次安装都成功。 使用方式: pip --default-timeout1000 install 需要安装的库…

强化学习笔记-07 n-step Bootstrapping 多步TD时分学习

本文是博主对《Reinforcement Learning- An introduction》的阅读笔记,不涉及内容的翻译,主要为个人的理解和思考。 上一节介绍了TD算法,其采用了Bootstrapping方法,当前过去的预估以及即期收益来更新累积收益函数: 前…

通过期待已久的帕丽斯·希尔顿人物化身系列,成为元宇宙的偶像

5,555 个以帕丽斯希尔顿为主题的独特人物化身将于 5 月 31 日推出,每个人物化身均可在 The Sandbox 中使用。 我们与帕丽斯希尔顿及全球流行文化中心的下一代娱乐公司 11:11 Media 合作,很高兴宣布帕丽斯希尔顿的人物化身系列即将推出! 作为对…