定时器中断功能主要是两点:

        1.怎么配置的定时器中断时间间隔;

        2.中断里长什么样

一、定时器中断配置函数

        直接在bsp_basic_timer.c里找到下面函数:

void basic_timer_config(uint16_t pre,uint16_t per)
{/* Ò»¸öÖÜÆÚµÄʱ¼äT = 1/f, ¶¨Ê±Ê±¼ätime = T * ÖÜÆÚÉèÔ¤·ÖƵֵλpre,ÖÜÆÚλpertime = (pre + 1) * (per + 1) / psc_clk*/timer_parameter_struct timere_initpara; 							// ¶¨Ò嶨ʱÆ÷½á¹¹Ìå/* ¿ªÆôʱÖÓ */rcu_periph_clock_enable(BSP_TIMER_RCU); 							// ¿ªÆô¶¨Ê±Æ÷ʱÖÓ/* CK_TIMERx = 4 x CK_APB1  = 4x50M = 200MHZ */rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4); // ÅäÖö¨Ê±Æ÷ʱÖÓtimer_deinit(BSP_TIMER);														  // ¸´Î»¶¨Ê±Æ÷/* ÅäÖö¨Ê±Æ÷²ÎÊý */timere_initpara.prescaler = pre-1;                    //  ʱÖÓÔ¤·ÖƵֵ 0-65535   psc_clk = CK_TIMER / pretimere_initpara.alignedmode = TIMER_COUNTER_EDGE;     // ±ßÔµ¶ÔÆë                  timere_initpara.counterdirection = TIMER_COUNTER_UP;  // ÏòÉϼÆÊý    timere_initpara.period = per-1;                       // ÖÜÆÚ  /* ÔÚÊäÈë²¶»ñµÄʱºòʹÓà  Êý×ÖÂ˲¨Æ÷ʹÓõIJÉÑùƵÂÊÖ®¼äµÄ·ÖƵ±ÈÀý */timere_initpara.clockdivision = TIMER_CKDIV_DIV1;     // ·ÖƵÒò×Ó         /* Ö»Óи߼¶¶¨Ê±Æ÷²ÅÓÐ ÅäÖÃΪx£¬¾ÍÖØ¸´x+1´Î½øÈëÖÐ¶Ï */    timere_initpara.repetitioncounter = 0;							  // ÖØ¸´¼ÆÊýÆ÷ 0-255  timer_init(BSP_TIMER,&timere_initpara);								// ³õʼ»¯¶¨Ê±Æ÷/* ÅäÖÃÖжÏÓÅÏȼ¶ */nvic_irq_enable(BSP_TIMER_IRQ,3,2); 									// ÉèÖÃÖжÏÓÅÏȼ¶Îª 3,2/* ʹÄÜÖÐ¶Ï */timer_interrupt_enable(BSP_TIMER,TIMER_INT_UP);       // ʹÄܸüÐÂʼþÖÐ¶Ï /* ʹÄܶ¨Ê±Æ÷ */timer_enable(BSP_TIMER);
}

        定时器中断初始化流程:

  1. 启用定时器时钟

    • 代码rcu_periph_clock_enable(BSP_TIMER_RCU);
    • 功能:开启定时器模块的时钟(BSP_TIMER_RCU 定义了具体定时器外设,如 TIMER0)。
    • 说明:通过 RCU(Reset and Clock Unit)模块为定时器提供时钟信号。
  2. 配置定时器时钟分频

    • 代码rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);
    • 功能:设置定时器时钟为 APB1 时钟的 4 倍(4 × 50MHz = 200MHz)。
    • 说明:定时器时钟频率(CK_TIMER)决定计数速度,影响定时精度。
  3. 复位定时器

    • 代码timer_deinit(BSP_TIMER);
    • 功能:将定时器寄存器复位到默认状态,确保无残留配置。
    • 说明:清除之前的配置,为新设置做准备。
  4. 配置定时器参数

    • 代码
      timer_parameter_struct timere_initpara; timere_initpara.prescaler = pre-1; // 预分频值                                                                                                        timere_initpara.alignedmode = TIMER_COUNTER_EDGE; // 边沿对齐 timere_initpara.counterdirection = TIMER_COUNTER_UP; // 向上计数 timere_initpara.period = per-1; // 周期                    timere_initpara.clockdivision = TIMER_CKDIV_DIV1; // 时钟分频因子 timere_initpara.repetitioncounter = 0; // 重复计数器            timer_init(BSP_TIMER, &timere_initpara);
    • 功能
      • 定义并初始化定时器参数结构体 timer_parameter_struct
      • 设置预分频值 (pre-1),定时器计数频率 = CK_TIMER / (pre)。
      • 配置为边沿对齐模式(TIMER_COUNTER_EDGE)和向上计数(TIMER_COUNTER_UP)。
      • 设置周期值 (per-1),决定定时器溢出周期,定时时间 = (pre × per) / CK_TIMER。
      • 时钟分频因子为 1(TIMER_CKDIV_DIV1),不额外分频。
      • 重复计数器为 0(repetitioncounter = 0),无重复计数,适用于基本定时器。
      • 调用 timer_init 初始化定时器寄存器。
    • 说明定时时间计算公式为 time = (pre × per) / CK_TIMER,例如,若 pre=20000per=10000, CK_TIMER=200MHz,则 time = (20000 × 10000) / 200,000,000 = 1秒
  5. 配置中断优先级

    • 代码nvic_irq_enable(BSP_TIMER_IRQ, 3, 2);
    • 功能:启用定时器中断(BSP_TIMER_IRQ),设置 NVIC 中断优先级为抢占优先级 3,子优先级 2。
    • 说明:确保定时器中断能够被 CPU 响应,优先级决定中断处理顺序。
  6. 使能定时器更新中断

    • 代码timer_interrupt_enable(BSP_TIMER, TIMER_INT_UP);
    • 功能:启用定时器更新事件中断(TIMER_INT_UP),当计数器溢出时触发中断。
    • 说明:更新事件发生在计数器达到 per-1 并溢出时,触发中断处理程序。
  7. 启动定时器

    • 代码timer_enable(BSP_TIMER);
    • 功能:使能定时器,开始计数。
    • 说明:定时器按照配置的频率和周期运行,定期触发中断。

二、中断函数

        同样在bsp_basic_timer.c中的中断函数如下:

void BSP_TIMER_IRQHANDLER(void)
{/* ÕâÀïÊǶ¨Ê±Æ÷ÖÐ¶Ï */if(timer_interrupt_flag_get(BSP_TIMER,TIMER_INT_FLAG_UP) == SET){timer_interrupt_flag_clear(BSP_TIMER,TIMER_INT_FLAG_UP);  // Çå³ýÖжϱê־λ /* Ö´Ðй¦ÄÜ */gpio_bit_toggle(PORT_LED2,PIN_LED2);                      // ·­×ªledprintf("BSP_TIMER_IRQHANDLER!\r\n");          						// ´®¿Ú´òÓ¡BSP_TIMER_IRQHANDLER!}
}

        定时器中断函数在执行功能前主要进行了两个操作:

  1. 检查中断标志

    • 代码if(timer_interrupt_flag_get(BSP_TIMER, TIMER_INT_FLAG_UP) == SET)
    • 功能:检查定时器 BSP_TIMER 的更新中断标志位(TIMER_INT_FLAG_UP)是否置位(SET)。
    • 说明
      • 更新中断标志在定时器计数器溢出时自动置位,表示一次定时周期完成。
      • 条件判断确保只处理更新中断,避免误处理其他中断类型。
      • BSP_TIMER 是预定义的定时器,此处对应的是TIMER5,由历史会话中的 basic_timer_config 配置。

  1. 清除中断标志

    • 代码timer_interrupt_flag_clear(BSP_TIMER, TIMER_INT_FLAG_UP);
    • 功能:清除定时器的更新中断标志位。
    • 说明
      • 清除标志位以确保下一次中断能够正确触发。
      • 如果不清除,中断可能持续触发,导致程序异常或死锁。
      • 这是中断服务函数的标准操作,防止重复进入中断。

三、如何调用

        在main.c里面只需要配置一下 basic_timer_config函数就行,调用代码如下:

basic_timer_config(20000,10000);  // ¶¨Ê±Æ÷³õʼ»¯
  • 定时时间公式:time = (pre × per) / CK_TIMER
  • 代入参数
    pre = 20000 (实际预分频系数 19999 + 1)
  • per = 10000 (实际周期 9999 + 1)
  • CK_TIMER = 200,000,000 Hz
  • time = (20000 × 10000) / 200,000,000 = 200,000,000 / 200,000,000 = 1 秒

        运行后可以看到串口一直在输出:

        并且开发板上对应的LED2在闪烁

四、思考

为什么常常使用ADC时不直接放在 while(1) 主循环中使用 delay 控制采样间隔?

        不是不行,也可以,但是:

  1. 延时不精确,受主循环影响

    • 在主循环中使用 delay_ms(500) 等软件延时函数时,延时基于 CPU 空闲循环(如空指令循环)实现,但实际时间会因编译优化、系统时钟偏差或中断干扰而抖动(例如,串口中断或 GPIO 操作可能打断延时,导致采样间隔不均匀)。
    • 问题:采样间隔(如每 500ms 采样一次)无法严格控制,可能导致数据采集不均匀,影响信号处理精度(如历史会话中提到的 ADC 采样)。
    • 示例:若主循环中插入其他任务(如 LED 控制),延时函数会阻塞整个 CPU,造成采样时机漂移。
  2. 阻塞主循环,降低系统响应性

    • delay 是“忙等待”(busy-waiting),CPU 在延时期间完全闲置,无法处理其他任务(如用户输入、通信或外设事件)。
    • 问题:在多任务环境中(如实时控制系统),主循环被阻塞会导致系统响应迟钝,甚至错过关键事件。例如,定时器中断每 1 秒触发 LED 翻转,若也需要ADC 采样用 delay 阻塞 500ms,主循环就无法及时响应其他中断。
    • 效率低:CPU 利用率低下,浪费资源,尤其在低功耗应用中不友好。
  3. 不适合实时性和周期性要求

    • ADC 采样往往需要固定间隔(如传感器数据采集),主循环的软件延时无法保证硬件级精度,受温度、电压等因素影响。
    • 问题:在高速采样场景(如音频或电机控制),间隔抖动可能导致数据失真或系统不稳定。若 ADC 采样直接用 delay,与定时器中断(1 秒间隔)冲突,可能干扰整体流程。

为什么ADC采样常放到定时器中断中?

  1. 精确的硬件定时

    • 定时器使用硬件计数器(如 basic_timer_config(20000, 10000) 配置 1 秒间隔),基于系统时钟(CK_TIMER = 200MHz)精确控制中断触发时机,间隔误差极小(纳秒级)。
    • 优势:不受主循环影响,确保 ADC 采样严格周期性(如每 500ms 触发一次),提高数据一致性和精度。定时器可自动重载,无需软件干预。
  2. 非阻塞执行,提高系统效率

    • 中断服务函数(如 BSP_TIMER_IRQHANDLER)在定时器溢出时自动调用,执行 ADC 采样后快速返回,主循环继续运行其他任务。
    • 优势:避免阻塞,支持多任务并行。例如,历史会话中定时器中断可用于 ADC 触发采样,同时主循环处理串口输出或 LED 控制,CPU 利用率高。结合 DMA(直接内存访问)可进一步自动化数据传输,减少 CPU 负担。
  3. 增强实时性和可扩展性

    • 中断优先级机制(如 NVIC 设置抢占优先级 3)确保 ADC 采样及时响应,适用于实时系统(如工业控制)。
    • 优势:易于调整间隔(修改 pre 和 per 参数),并支持多通道采样(如定时器触发 ADC 多通道)。1 秒中断可扩展为 500ms ADC 采样,结合 timer_interrupt_enable(BSP_TIMER, TIMER_INT_UP) 实现周期触发。

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

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

相关文章

[Godot入门大全]目录

1 免责声明 资源分享免责声明: 本平台/本人所分享的各类资源(包括但不限于文字、图片、音频、视频、文档等),均来源于公开网络环境中的可分享内容或已获授权的传播素材。 本平台/本人仅出于信息交流、资源共享之目的进行传播&…

使用 StringRedisTemplate 实现 ZSet 滚动查询(处理相同分数场景)

1. 为什么需要改进当 ZSet 中存在相同分数 (score) 的元素时,单纯使用分数作为偏移会导致数据漏查或重复。例如:多条记录具有相同时间戳(作为分数)分页查询时可能跳过相同分数的元素或重复查询相同分数的元素改进方案:…

【Android】安装2025版AndroidStudio开发工具开发老安卓旧版App

为了开发老旧的安卓App,这里记录一下2025版AndroidStudio的安装过程,如果卸载以后,可以按照此文章的步骤顺利重新安装继续使用。 文章目录安装包Android SDK新建项目新建页面构建项目Gradle下载失败构建失败构建完成编译失败安装失败关于APP在…

Python跳过可迭代对象前部元素完全指南:从基础到高并发系统实战

引言:跳过前部元素的核心价值在数据处理和系统开发中,跳过可迭代对象的前部元素是常见且关键的操作。根据2024年数据处理报告:92%的数据清洗需要跳过文件头部85%的日志分析需要忽略初始记录78%的网络协议处理需跳过头部信息65%的机器学习训练…

ConcurrentHashMap扩容机制

ConcurrentHashMap的扩容为了提高效率,是多线程并发的每个线程控制一部分范围节点的扩容(根据cpu与数组长度确定控制多大范围)有两个核心参数sizeCtl:标记扩容状态 负数时代表正在扩容,存储量参与扩容的线程数,正数代表出发扩容的…

Spring Cloud Gateway 进行集群化部署

如果将 Gateway 单独部署为一个服务而不做任何高可用处理,它确实会成为一个单点故障(SPOF, Single Point of Failure)。如果这个唯一的 Gateway 实例因为服务器宕机、应用崩溃、部署更新或其他任何原因而不可用,那么整个系统的所有…

计算机网络:以太网中的数据传输

以太网中,数据的传输依赖于一系列标准化的技术规范,核心包括帧结构封装、介质访问控制机制和物理层编码技术,具体如下: 1. 以“帧(Frame)”为基本传输单元 以太网在数据链路层将网络层的数据包(…

元器件--USB TypC接口

USB TypC接口下图这些都是USB接口A口与B口的区别USB A口和B口最初由USB-IF在1996年引入。根据当时的USB协议,A口主要用于主设备(如电脑),而B口则用于从设备(如打印机和摄像头)。随着USB-C接口的日益普及&am…

多线程之HardCodedTarget(type=OssFileClient, name=file, url=http://file)异常

多线程之HardCodedTarget(typeOssFileClient, namefile, urlhttp://file)异常 摘要: 文档描述了多线程环境下调用Feign客户端OssFileClient时出现的HardCodedTarget异常。异常发生在异步保存文件到ES时,Feign调用未返回预期结果而直接打印了客户端对象。…

计算机视觉(十二):人工智能、机器学习与深度学习

人工智能 (AI):宏大的目标 人工智能是最广泛、最宏大的概念,它的目标是让机器能够模仿人类的智能行为,例如: 推理:像下棋程序一样,通过逻辑来做决策。规划:为实现一个目标而制定步骤&#xff0c…

容器元素的滚动条回到顶部

关闭再打开后,容器元素的滚动条回到顶部解决方法:1、通过打开开发者工具(F12),找到滚动条所属元素为 el-textarea__inner,其父类 class"el-textarea content"2、代码,通过元素的方法 …

分布式专题——2 深入理解Redis线程模型

1 Redis 简介 1.1 Redis 是什么? Redis 全称 Remote Dictionary Server(远程字典服务),是一个开源的高性能 Key-Value 数据库; 官网:Redis - The Real-time Data Platform; 引用官网上的⼀个…

simd学习

如何查看cpu是否支持simd?# 检查特定指令集 grep -o avx2 /proc/cpuinfo | head -1 # 检查AVX2 grep -o sse4 /proc/cpuinfo | head -1 # 检查SSE4 grep -o avx512 /proc/cpuinfo | head -1 # 检查AVX512gcc编译选项,增加支持simd-mavx2 -D__AVX2__SS…

LabVIEW汽车发动机振动测试

以某型号四缸汽油发动机为测试对象,借助 LabVIEW 平台与高精度数据采集硬件,开展发动机全工况振动测试。通过实时采集缸体、曲轴箱关键部位振动信号,分析振动特征与故障关联,验证发动机运行稳定性,为后期优化设计提供数…

android 四大组件—Service

启动服务startService//启动服务,通过类名 Intent intent new Intent(this, WiFiAutoLinkService.class); startService(intent); //通过字符串启动 Intent intent new Intent(); intent.setAction("com.launcher.app"); intent.setPackage("com.l…

https + 域名 + 客户端证书访问模式

项目使用金融云部署,对外暴露IP访问,因安全合规要求必须使用域名访问,但公司又不提供域名。故,改为 https 域名 客户端证书双向认证 访问模式,大大提升安全性。 1. 密钥文件类型 .key、.csr、.cer(或 .cr…

ICPC 2023 Nanjing R L 题 Elevator

[ProblemDiscription]\color{blue}{\texttt{[Problem Discription]}}[Problem Discription] 来源:洛谷。侵权则删。 [Analysis]\color{blue}{\texttt{[Analysis]}}[Analysis] 贪心。优先运送楼层高的货物,在能装下的情况下尽量多装。 因为运送货物的代价…

81-dify案例分享-零代码用 Dify 使用梦 AI 3.0 多模态模型,免费生成影视级视频

1.前言 即梦AI作为字节跳动旗下的AI绘画与视频生成平台,近年来不断推出新的模型和功能,以提升用户体验和创作能力。 即梦AI 3.0是即梦AI的最新版本,于2025年4月发布,标志着其在中文生图模型上的重大升级。该版本不仅在中文生图能…

SQL 进阶指南:视图的创建与使用(视图语法 / 作用 / 权限控制)

在 SQL 操作中,你是否遇到过 “频繁查询多表关联的固定结果”“不想让他人看到表中的敏感字段” 这类问题?比如 “每周都要查‘技术部员工的姓名、职位、薪资’”,每次都写多表关联语句很麻烦;又比如 “给实习生开放数据查询权限&…

【全部更新完毕】2025数学建模国赛C题思路代码文章高教社杯全国大学生数学建模-NIPT 的时点选择与胎儿的异常判定

B题全部更新完毕 包含完整的文章全部问题的代码、结果、图表 完整内容请看文末最后的推广群NIPT 的时点选择与胎儿的异常判定 摘要 在问题一中,我们以无创产前检测(NIPT)数据为研究对象,围绕“胎儿 Y 染色体浓度”(记为 (V)) 随孕…