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

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

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

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

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

  • 测量事件的发生次数(如脉冲计数)。
  • 精确控制时间间隔(如定时器)。
  • 实现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分频为10kHzTIM_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波形生成等。单片机的灵活性和定时器的强大功能使得计数器能够广泛应用于各类嵌入式项目中。

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

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

相关文章

隐私清理工具Goversoft Privazer

PrivaZer 是一款专为隐私保护而生的 Windows 系统清理工具,支持深度扫描、清除无用文件和隐私痕迹。 PrivaZer - 深度扫描磁盘,自动清理上网痕迹,全面保护 Windows 的网络隐私 释放磁盘空间 硬盘空间告急,想清理却又无从下手&…

基于Spring Boot的医院质控上报系统

一、系统背景与意义 医院质控上报系统旨在通过信息化手段,实现医院质量控制的标准化、流程化和自动化管理。该系统能够帮助医院实时监控医疗质量数据,及时发现和处理潜在的质量问题,从而确保医疗服务的安全性和有效性。同时,系统…

Java-30 深入浅出 Spring - IoC 基础 启动IoC 纯XML启动 Bean、DI注入

点一下关注吧!!!非常感谢!!持续更新!!! 大数据篇正在更新!https://blog.csdn.net/w776341482/category_12713819.html 目前已经更新到了: MyBatis&#xff…

Python-基于Pygame的小游戏(坦克大战-1.0(世界))(一)

前言:创作背景-《坦克大战》是一款经典的平面射击游戏,最初由日本游戏公司南梦宫于1985年在任天堂FC平台上推出。游戏的主题围绕坦克战斗,玩家的任务是保卫自己的基地,同时摧毁所有敌人的坦克。游戏中有多种地形和敌人类型,玩家可…

多核并发编译引起的编译错误

编译某个模型的工程化代码,模型里有多个算子使用了tensorrt plugin方式实现的,编译时总是报插件相关的目标文件找不到: CMake Error at /opt/conda/share/cmake-3.22/Modules/FindCUDA/make2cmake.cmake:48 (file):file failed to open for reading (No…

【达梦数据库】Coredump文件生成与分析

目录 背景参考链接分析Coredump文件获取问题SQL1、查看Coredump文件生成路径2、使用gdb工具读取Coredump文件3、记录崩溃线程堆栈4、记录当前崩溃线程号5、使用dmrdc工具分析Coredump文件6、寻找线程号对应SQL7、重新执行SQL,复现问题 记录Coredump文件中所有线程的…

【爬虫一】python爬虫基础合集一

【爬虫一】python爬虫基础合集一 1. 网络请求了解1.1. 请求的类型1.2. 网络请求协议1.3. 网络请求过程简单图解1.4. 网络请求Headers(其中的关键字释义):请求头、响应头 2. 网络爬虫的基本工作节点2.1. 了解简单网络请求获取响应数据的过程所涉及要点 1. 网络请求了…

基于SCUI的后台管理系统

一、SCUI Admin 官方地址:https://python-abc.xyz/scui-doc/ 高性能中后台前端解决方案,基于 Vue3、elementPlus 持续性的提供独家组件和丰富的业务模板帮助你快速搭建企业级中后台前端任务。 预览地址:https://python-abc.xyz/scui-doc/de…

vscode不同的项目使用不同的环境变量或编译环境

转载请标明出处:小帆的帆的博客 假如电脑中安装的两套C编译环境,想要切换编译环境时可以在操作系统的环境变量中调整顺序,然后排在前面的环境就会被使用。 这样做的弊端: 麻烦容易忘,忘了项目不报错就可能就不会发现…

知网研学 | 知网文献(CAJ+PDF)批量下载

知网文献(CAJPDF)批量下载 一、知网研学安装二、插件及脚本安装三、CAJ批量下载四、脚本下载及PDF批量下载浏览器取消拦截窗口 一、知网研学安装 批量下载知网文件,格式为es6文件,需使用知网研学软件打开,故需先安装该…

Mybatis-plus-Join--分页查询

数据表四张: user: id,username,create_time,update_time product: id,name,price,number(库存),create_time,update_times order: id,quantity,order_time(下单时间),update_time order_detail:id,product_id,order_id,quant…

Docker 容器中启用 SSH 服务

在 Docker 容器中运行 SSH 服务需要一些调整,因为 Docker 容器通常使用 init 系统而不是完整的 systemd。以下是配置 SSH 服务在 Docker Ubuntu 容器中运行的步骤: 1. 安装 SSH 服务 如果还未安装 OpenSSH,请先安装: apt update…

运输时间超声波流量计基本原理解析

通过从上游传感器向下游传感器发送超声波脉冲并再次返回来测量流体速度。这些信号沿流向和逆流向交替发射。由于信号在其中传播的流体正在流动,因此超声信号沿流向的传播时间比逆流向的传播时间短。测量由此产生的传输时间差 Δt,并允许流量计确定沿超声…

【大模型】大模型项目选择 RAGvs微调?

RAG 输入问题,在知识库匹配知识,构建提示词:基于{知识}回答{问题} 微调 用知识问答对重新训练大模型权重,输入问题到调整后的大模型 如何选择 如果业务要求较高,RAG和微调可以一起使用 1-动态数据 选择RAG 原因&a…

<mutex>注释 11:重新思考与猜测、补充锁的睡眠与唤醒机制,结合 linux0.11 操作系统代码的辅助(上)

(46)问题的起源: 因为上面的内核代码,我们编写多线程代码时,对手里的家伙事不那么自信。但我们知道,多线程在竞争锁时,若得不到锁,会进入睡眠,并会在被唤醒后重新尝试得…

flask_socketio 以继承 Namespace方式实现一个网页聊天应用

点击进入上一篇,可作为参考 实验环境 python 用的是3.11.11 其他环境可以通过这种方式一键安装: pip install flask3.1.0 Flask-SocketIO5.4.1 gevent-websocket0.10.1 -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple pip list 详情如下&am…

LOS/NLOS环境建模与三维TOA定位,MATLAB仿真程序,可自定义锚点数量和轨迹点长度

本代码的主要功能是建模 LOS(视距)和 NLOS(非视距)环境下的定位系统,估计目标的动态位置,三维空间 文章目录 运行结果源代码代码介绍 总结 运行结果 10个点的轨迹定位: 50个点的轨迹定位&#…

Centos创建共享文件夹拉取文件

1.打开VMware程序,鼠标右检你的虚拟机,打开设置 2.点击选项——共享文件夹——总是启用 点击添加,设置你想要共享的文件夹在pc上的路径(我这里已经添加过了就不加了) 注意不要中文,建议用share&#xff0c…

【一文了解】C#重点-委托1

本篇文章来学习一下C#的委托,委托是C#中的一个重要概念,它允许将方法作为参数传递给其他方法。C#中的委托类似于C或C中的函数指针,并且类型安全。 委托 1.委托的定义 委托(delegate)是方法的代理/代表,委托…

C++算法第十一天

本篇文章我们继续学习动态规划 目录 第一题 题目链接 题目解析 代码原理 代码编写 第二题 题目链接 题目解析 代码原理 代码编写 第三题 题目链接 题目解析 代码原理 代码编写 第四题 题目链接 题目解析 代码原理 代码编写 第五题 题目链接 题目解析 代…