单片机:实现计数器(附带源码)

一、单片机计数器功能概述

单片机中的计数器一般是由硬件定时器模块实现的,计数器可以被配置为不同的模式,例如:

  • 普通计数模式:计数器从零开始增加,直到某个最大值后清零或中断。
  • 事件计数模式:计数器根据外部信号(例如脉冲信号)进行计数。
  • 定时模式:计数器根据时钟信号进行计数,常用于定时器的实现。

单片机计数器的常见应用场景包括:

  • 测量事件的发生次数(如脉冲计数)。
  • 精确控制时间间隔(如定时器)。
  • 实现PWM信号生成等。

本文以一个基于STM32单片机的简单计数器例子为基础,逐步讲解如何实现计数器的功能。

二、硬件平台介绍

我们以STM32系列单片机为例,它拥有多个定时器模块,可以配置为计数器模式,且支持外部事件触发。STM32的定时器有丰富的功能,可以灵活配置为各种模式来满足计数器需求。

本例使用STM32F103系列单片机,并假设使用标准库来操作硬件。STM32F103拥有多个定时器(如TIM1, TIM2, TIM3等),每个定时器都支持16位或32位的计数功能,并且可以通过外部引脚触发。

三、计数器源码实现

以下是一个简单的计数器实现例子:使用STM32F103的TIM2定时器在计数模式下计数外部信号的脉冲数,并在计数达到一定值后触发中断。

#include "stm32f10x.h"

// 定义计数器的最大值
#define COUNTER_MAX 1000

// 计数器变量
volatile uint32_t counter_value = 0;

// 中断服务函数
void TIM2_IRQHandler(void) {
    if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {
        // 计数器溢出,重置计数器
        counter_value++;
        
        if (counter_value >= COUNTER_MAX) {
            // 当计数达到最大值时,执行一些操作
            // 在此可以添加额外的功能,如LED闪烁、发送信号等
            counter_value = 0;  // 重置计数器
        }

        // 清除中断标志
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
    }
}

void Timer_Init(void) {
    // 1. 开启TIM2时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    // 2. 配置TIM2为计数模式
    TIM_TimeBaseInitTypeDef TIM_InitStructure;
    TIM_InitStructure.TIM_Prescaler = 7199;  // 分频值,将系统时钟72MHz分频为10kHz
    TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;  // 向上计数
    TIM_InitStructure.TIM_Period = 999;  // 自动重载寄存器,设置计数周期
    TIM_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_InitStructure.TIM_RepetitionCounter = 0;

    TIM_TimeBaseInit(TIM2, &TIM_InitStructure);

    // 3. 启用TIM2更新中断
    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

    // 4. 配置并使能中断
    NVIC_EnableIRQ(TIM2_IRQn);

    // 5. 启动定时器
    TIM_Cmd(TIM2, ENABLE);
}

int main(void) {
    // 系统初始化
    SystemInit();

    // 初始化计时器
    Timer_Init();

    // 主循环
    while (1) {
        // 这里可以执行其他任务
        // 计数器的工作是由中断触发的,因此主循环可以空转
    }
}
1. RCC_APB1PeriphClockCmd
  • 作用:启用单片机外设的时钟,使得相应外设可以正常工作。在这段代码中,它的作用是启动定时器 TIM2 的时钟。
  • 工作原理:STM32单片机的每个外设都需要通过相应的时钟源来供电,只有时钟使能后,外设才会工作。比如,在计时器的例子中,RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); 用于启动 TIM2 定时器模块的时钟。
2. TIM_TimeBaseInit
  • 作用:初始化定时器的基本设置,配置定时器的计数模式、预分频器、自动重载值等。
  • 工作原理
    • 计数模式 (TIM_CounterMode):决定了定时器计数的方向(向上、向下或向上/下计数)。在这段代码中使用的是向上计数模式 TIM_CounterMode_Up,即计数器的值从 0 开始,逐步增大。
    • 预分频器 (TIM_Prescaler):设定定时器的时钟频率,通常用于降低定时器时钟频率以适应应用需求。例如,如果系统时钟为 72 MHz,设置预分频器为 7199,将定时器的频率降到 10 kHz(72 MHz / 7200)。这样可以使定时器每 1 毫秒溢出一次。
    • 自动重载寄存器 (TIM_Period):设定定时器的最大计数值,通常作为定时器的溢出条件。例如,TIM_Period = 999 表示定时器的计数值最大为 999,达到此值时会溢出。
3. TIM_ITConfig
  • 作用:启用定时器的中断功能。定时器每次溢出时,如果启用了中断,CPU 会跳转到中断处理函数。
  • 工作原理:当定时器计数达到预设的溢出值(即 TIM_Period),定时器会触发更新事件。如果启用了更新中断(TIM_IT_Update),则会触发中断请求并进入对应的中断处理函数 TIM2_IRQHandler
    • 例如,TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); 会使得 TIM2 在溢出时触发中断。
4. NVIC_EnableIRQ
  • 作用:启用外部中断的请求。STM32的中断控制器(NVIC)管理所有外部中断,使用该函数使能中断。
  • 工作原理:STM32的外设中断会被NVIC管理,通过该函数可以开启对应定时器的中断服务功能。
    • 例如,NVIC_EnableIRQ(TIM2_IRQn); 会启用 TIM2 的中断请求,当 TIM2 溢出时,会跳转到中断服务函数 TIM2_IRQHandler
5. TIM_Cmd
  • 作用:启动定时器。调用该函数后,定时器开始计数。
  • 工作原理:通过设置定时器的启用标志,将定时器设置为工作状态。只有在定时器启动之后,计数器才开始执行计数任务。
    • 例如,TIM_Cmd(TIM2, ENABLE); 启动 TIM2 定时器,使其开始按照预定的频率进行计数。
6. TIM2_IRQHandler
  • 作用:定时器 TIM2 的中断服务函数(ISR)。定时器每次溢出时会触发该中断。
  • 工作原理
    • TIM2_IRQHandler 中,我们检查是否是定时器溢出中断发生,通常使用 TIM_GetITStatus 来确认。
    • 当定时器溢出时,counter_value 增加 1。如果计数器的值超过设定的最大值 COUNTER_MAX,则执行相应的操作(如重置计数器)。
    • 最后,调用 TIM_ClearITPendingBit 清除中断标志,防止中断请求重复触发。
7. TIM_GetITStatus
  • 作用:检查定时器是否触发了更新中断。
  • 工作原理:定时器会在每次溢出时触发更新中断,使用 TIM_GetITStatus 可以检测定时器的中断状态,确定是否需要处理中断。返回值为 RESET 表示中断未发生,SET 表示中断已经发生。
8. TIM_ClearITPendingBit
  • 作用:清除定时器的中断标志位。
  • 工作原理:每次定时器触发中断后,必须清除相应的中断标志,避免中断请求一直被保持,导致 CPU 不断响应中断。调用该函数可以清除定时器的溢出中断标志。
9. SystemInit
  • 作用:系统初始化函数,用于进行系统时钟配置、外设初始化等工作。
  • 工作原理:通常在 main() 函数开始执行之前会调用该函数,它是一个由系统启动代码生成的函数,通常只做一些基础配置,比如时钟源选择、PLL 配置等。
10. 主程序中的 while (1) 循环
  • 作用:这是主程序的无限循环,它在 STM32 设备中通常用于保持程序的运行。
  • 工作原理:因为计数器的功能是由定时器中断触发的,所以主循环可以执行其他任务,或者保持空转。没有特别的处理逻辑,除非其他外设或任务需要在主循环中处理。
四、总结

通过这个简单的计数器例子,我们展示了如何使用 STM32F103 的定时器来实现计数器功能。定时器在此实现了脉冲计数的功能,当计数器达到设定的最大值时,可以触发特定操作。中断机制使得计数器的工作能够异步进行,主程序可以同时执行其他任务。

在实际应用中,定时器和计数器可以用于更复杂的任务,例如外部脉冲计数、时间延迟生成、PWM波形生成等。单片机的灵活性和定时器的强大功能使得计数器能够广泛应用于各类嵌入式项目中。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

c语言----选择结构

基本概念 选择结构是C语言中用于根据条件判断来执行不同代码块的结构。它允许程序在不同的条件下执行不同的操作,使程序具有决策能力。 if语句 单分支if语句 语法格式: if (条件表达式) { 执行语句块; } 功能: 当条件表达式的值为真&#…

RK3588 , mpp硬编码rgb, 保存MP4视频文件.

RK3588 , mpp硬编码yuv, 保存MP4视频文件. ⚡️ 传送 ➡️ RK3588, FFmpeg 拉流 RTSP, mpp 硬解码转RGBRk3588 FFmpeg 拉流 RTSP, 硬解码转RGBUbuntu x64 架构, 交叉编译aarch64 FFmpeg mppCode Init MppMPP_RET init_mpp

uniapp blob格式转换为video .mp4文件使用ffmpeg工具

前言 介绍一下这三种对象使用场景 您前端一旦涉及到文件或图片上传Q到服务器,就势必离不了 Blob/File /base64 三种主流的类型它们之间 互转 也成了常态 Blob - FileBlob -Base64Base64 - BlobFile-Base64Base64 _ File uniapp 上传文件 现在已获取到了blob格式的…

【Linux运维】配置ssh免密登录

1.场景描述 内网环境,需要同步17服务器的文件到10服务器进行备份。因为每次输入密码比较繁琐,如果实现免密登录后,即可简化脚本。 要求:需要2台服务器-免密登录 2.方案分析 (1)现状:登录需要输…

使用Python从阿里云物联网平台获取STM32温度数据

在物联网(IoT)应用中,设备数据的采集与监控至关重要。本文将详细介绍如何使用Python从阿里云物联网平台获取STM32设备的温度数据。我们将从已有的Java代码出发,逐步将其转换为Python,并处理在过程中遇到的问题&#xf…

职场上,如何做好自我保护?

今天我们讨论一个话题:在职场上,如何保护好自己?废话不多说,我们直接上干货。 (一) 1.时刻准备一点零食或代餐,如果遇到长时间的会议,就补充点能量。代餐最好选流体,这…

网络编程 02:IP 地址,IP 地址的作用、分类,通过 Java 实现 IP 地址的信息获取

一、概述 记录时间 [2024-12-18] 前置文章:网络编程 01:计算机网络概述,网络的作用,网络通信的要素,以及网络通信协议与分层模型 本文讲述网络编程相关知识——IP 地址,包括 IP 地址的作用、分类&#xff…

tryhackme-Pre Security-HTTP in Detail(HTTP的详细内容)

任务一:What is HTTP(S)?(什么是http(s)) 1.What is HTTP? (HyperText Transfer Protocol)(什么是 HTTP?(超文本传输协议)) http是你查看网站的时候遵循的…

UDP网络编程套接

目录 本文核心 预备知识 1.端口号 认识TCP协议 认识UDP协议 网络字节序 socket编程接口 sockaddr结构 UDP套接字编程 服务端 客户端 TCP与UDP传输的区别 可靠性: 传输方式: 用途: 头部开销: 速度: li…

MyBatis-Plus中isNull与SQL语法详解:处理空值的正确姿势

目录 前言1. 探讨2. 基本知识3. 总结 前言 🤟 找工作,来万码优才:👉 #小程序://万码优才/r6rqmzDaXpYkJZF 基本的Java知识推荐阅读: java框架 零基础从入门到精通的学习路线 附开源项目面经等(超全&#x…

EGO Swarm翻译

目录 摘要 Ⅰ 介绍 Ⅱ 相关工作 A . 单四旋翼局部规划 B . 拓扑规划 C. 分布式无人机集群 Ⅲ 基于梯度的局部规划隐式拓扑轨迹生成 A.无需ESDF梯度的局部路径规划 B.隐式拓扑轨迹生成 Ⅳ 无人机集群导航 A 机间避碰 B. 定位漂移补偿 C. 从深度图像中去除agent Ⅴ …

电商数据采集电商,行业数据分析,平台数据获取|稳定的API接口数据

电商数据采集可以通过多种方式完成,其中包括人工采集、使用电商平台提供的API接口、以及利用爬虫技术等自动化工具。以下是一些常用的电商数据采集方法: 人工采集:人工采集主要是通过基本的“复制粘贴”的方式在电商平台上进行数据的收集&am…

PostgreSQL和Postgis安装

Windows下PostgreSQL和对应的版本的Postgis安装 PostgreSQL安装 1、官网下载地址 https://www.enterprisedb.com/downloads/postgres-postgresql-downloads 2、根据自己的系统下载完成,Windows下可以直接傻瓜式安装就OK 建议不要通过自带的这个程序安装postgis,…

代码开发相关操作

使用Vue项目管理器创建项目:(vue脚手架安装一次就可以全局使用) windowR打开命令窗口,输入vue ui,进入GUI页面,点击创建-> 设置项目名称,在初始化git下面输入:init project&…

Vulnhub DC-6靶机攻击实战(一)

导语   之前的分享中我们介绍了关于Vulnhub虚拟机前五个机器的攻防演练测试,接下来我们继续分享Vulnhub DC-6靶机攻击实战。 文章目录 搭建测试环境第一步、信息采集第二步、wpscan爆破第三步、开始查找其他的用户第四步、提权总结搭建测试环境 首先需要从Vulnhub官网中下载…

深度学习之超分辨率算法——FRCNN

– 对之前SRCNN算法的改进 输出层采用转置卷积层放大尺寸,这样可以直接将低分辨率图片输入模型中,解决了输入尺度问题。改变特征维数,使用更小的卷积核和使用更多的映射层。卷积核更小,加入了更多的激活层。共享其中的映射层&…

深度学习从入门到精通——图像分割实战DeeplabV3

DeeplabV3算法 参数配置关于数据集的配置训练集参数 数据预处理模块DataSet构建模块测试一下数据集去正则化模型加载模块DeepLABV3 参数配置 关于数据集的配置 parser argparse.ArgumentParser()# Datset Optionsparser.add_argument("--data_root", typestr, defa…

大数据操作实验一

1.Postgresql 1.1 数据库的对象创建 1.1.1 创建数据库(Database) 鼠标右键database进行创建 1.1.2 创建图(Schema) 鼠标右键schema,然后创建schema图纸 1.1.3 创建表(Table) 鼠标右键Table,创建表 1.2数据库实列化 1.2.1 实列化静态数据 提…

IDEA2024如何创建一个普通的Java Web项目工程(JSP)

本章教程,主要介绍如何在IDEA2024 专业版本中,创建一个普通的Java Web项目。 一、新建项目 二、配置项目 依次点击File——Project Structure——Modules 修改路径中的web为webapp,然后点击Create Artifact默认保存。 至此,一个基础的Java web就创建完成了。

Linux下mysql 8.0安装教程

本文介绍了如何在Linux下安装MySQL8.0,供大家参考,具体内容如下 准备工作: mysql8.0 rpm文件 测试工具(比如 idea的database工具) 安装步骤: 1. 下载mysql的repo源,下载地址: 进入Linux系统,输入指令: 1 wgethttps://dev.mysql.com/get/mysql80-community-rele…