【DSP28335 入门教程】定时器中断:为你的系统注入精准的“心跳”

大家好,欢迎来到 DSP28335 的核心精讲系列。我们已经掌握了如何通过外部中断来响应“外部事件”,但系统内部同样需要一个精准的节拍器来处理“内部周期性任务”。单纯依靠 DELAY_US() 这样的软件延时,不仅精度差,而且会在延时期间霸占整个CPU,导致系统无法响应其他任何事情,这是专业开发中无法接受的。

今天,我们将学习嵌入式系统的“心脏”——CPU 定时器 (CPU Timer),并利用它来产生精确的定时器中断。掌握它,你就能创建一个非阻塞的、可以同时执行多个任务的、真正意义上的多任务雏形系统。

一、硬件原理:一个会自动重装的“数字沙漏”

F28335 内置了三个 32 位的 CPU 定时器 (Timer0, Timer1, Timer2)。要理解它们如何工作,我们首先要看懂其内部的硬件逻辑。

[图1: CPU 定时器硬件逻辑图]

这个看似复杂的图,其核心工作原理就像一个可以精确计时的“数字沙漏”:

  1. 时钟源 (Clock Source): 定时器的动力来自系统时钟 SYSCLKOUT。这就是“沙漏”中“沙子”下落的速度基准。

  2. 预分频器 (Prescaler):

    • PSCH:PSC (16位) 是一个预分-频计数器

    • TDDHR:TDDR (16位) 是一个定时器分频器

    • 它们组合起来,可以对输入的 SYSCLKOUT 进行分频。例如,如果 SYSCLKOUT 是 150MHz,我们可以设置一个 N 分频,让最终进入主计数器的时钟频率变为 150MHz / N。这允许我们实现更长时间的定时。

  3. 计数器 (Counter): TIMH:TIM 是一个 32 位的递减计数器。这是“沙漏”的上半部分。它在每个分频后的时钟脉冲到来时,数值减一。

  4. 周期寄存器 (Period Register): PRDH:PRD 是一个 32 位的周期寄存器。这是“沙漏”的下半部分,用来设定总的“沙子”量。

  5. 工作流程:

    • 启动: 当我们启动定时器时,PRD 的值被加载到 TIM 计数器中。

    • 递减: TIM 寄存器开始以分频后的时钟速度向下计数。

    • 中断: 当 TIM 减到 0 时,它会产生一个中断信号 (INT) 给 PIE 模块。

    • 重载: 与此同时,TIM 会自动将 PRD 的值重新加载进来,然后开始新一轮的递减计数。

这个“递减->归零->中断->重载”的过程周而复始,就为我们提供了一个稳定、精确的周期性中断信号,成为了系统的“心跳”。

二、控制枢纽:关键寄存器解析

要指挥定时器工作,我们必须学会操作它的控制寄存器。

[图2 & 图3: Timer0/1/2 寄存器地址映射]

每个定时器都有一组独立的寄存器。其中,最重要的就是控制寄存器 (TCR - Timer Control Register)

[图4 & 图5: TCR 寄存器位功能描述]

让我们来认识一下TCR中最重要的几个“开关”:

  • bit 15 (TIF): 中断标志位 (Timer Interrupt Flag)

    • 当计数器减到 0 时,硬件会自动将该位置 1。

    • 我们必须在中断服务函数中手动向该位写 1 来清除它,否则中断会不停地产生。

  • bit 14 (TIE): 中断使能位 (Timer Interrupt Enable)

    • 只有将该位置 1,当计数器减到 0 时,才会向 PIE 发出中断请求。

  • bit 5 (TRB): 重载控制位 (Timer Reload Bit)

    • 必须将该位置 1。当它为 1 时,每当定时器启动或计数器归零时,PRD 的值都会被重新加载到 TIM。这是实现周期性定时的关键。

  • bit 4 (TSS): 启动/停止位 (Timer Start/Stop)

    • 写 1 停止 定时器。

    • 写 0 启动 或 重新启动 定时器。

三、软件配置:五步点燃“心跳引擎”

TI 官方在 DSP2833x_CpuTimers.c 文件中为我们提供了一系列标准函数,极大地简化了定时器的配置。结合这些库函数,我们的配置流程非常清晰。

Step 1: 使能定时器外设时钟

任何外设工作的前提都是有时钟。

EALLOW;
SysCtrlRegs.PCLKCR3.bit.CPUTIMER0ENCLK = 1; // 开启 Timer 0 的时钟
EDIS;
Step 2: 初始化定时器参数 (使用库函数)

TI 提供了一个强大的函数 ConfigCpuTimer(),它能自动根据我们设定的 CPU 频率和想要的定时周期(微秒),计算出正确的 PRD 周期值并写入寄存器。

// 使用示例:
// 假设 Freq=150 (MHz), Period=500000 (us)
ConfigCpuTimer(&CpuTimer0, Freq, Period);```
 Step 3: 关联中断向量与 ISR
//在 PIE 中断向量表中,将 TINT0 (定时器0中断) 指向我们自己的中断服务函数 `TIM0_IRQn`。
EALLOW;
PieVectTable.TINT0 = &TIM0_IRQn;
EDIS;```
Step 4: 开启中断通路并启动定时器
// PIE 级:TINT0 属于第1组第7个中断
PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
// CPU 级
IER |= M_INT1;
// 全局
EINT;
// 启动定时器!
CpuTimer0Regs.TCR.bit.TSS = 0;
Step 5: 编写中断服务函数 (ISR)

这是中断发生时执行的代码。记得在函数末尾进行中断应答

interrupt void TIM0_IRQn(void)
{// ... 用户功能代码 ...// PIE 中断应答PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}

四、代码实战:双灯齐“闪”,各司其职

下面的代码将实现:

  • D2 指示灯:由 Timer0 中断精确控制,每 500ms 翻转一次。

  • D1 指示灯:在主函数 while(1) 循环中闪烁,证明 CPU 在没有中断时并未闲置。

time.h
#ifndef TIME_H_
#define TIME_H_#include "DSP2833x_Device.h"     // DSP2833x 头文件
#include "DSP2833x_Examples.h"   // DSP2833x 例子相关头文件// 声明初始化函数和中断服务函数
void TIM0_Init(float Freq, float Period);
interrupt void TIM0_IRQn(void);#endif /* TIME_H_ */
time.c
#include "time.h"
#include "leds.h"void TIM0_Init(float Freq, float Period)
{// Step 1: 使能时钟EALLOW;SysCtrlRegs.PCLKCR3.bit.CPUTIMER0ENCLK = 1;EDIS;// Step 3: 关联中断向量EALLOW;PieVectTable.TINT0 = &TIM0_IRQn;EDIS;// 手动进行一些基础配置CpuTimer0.RegsAddr = &CpuTimer0Regs;CpuTimer0Regs.PRD.all  = 0xFFFFFFFF; // 先设为最大值CpuTimer0Regs.TCR.bit.TSS = 1;       // 确保停止CpuTimer0Regs.TCR.bit.TRB = 1;       // 使能重载CpuTimer0.InterruptCount = 0;// Step 2: 使用库函数计算并配置周期ConfigCpuTimer(&CpuTimer0, Freq, Period);// Step 4: 开启中断通路并启动定时器IER |= M_INT1;PieCtrlRegs.PIEIER1.bit.INTx7 = 1;CpuTimer0Regs.TCR.bit.TSS = 0; // 启动!EINT;ERTM;
}// Step 5: 编写 ISR
interrupt void TIM0_IRQn(void)
{EALLOW;LED2_TOGGLE; // 精确的周期性任务PieCtrlRegs.PIEACK.bit.ACK1 = 1; // 中断应答EDIS;
}
main.c
#include "leds.h"
#include "time.h"void main()
{int i=0;InitSysCtrl();InitPieCtrl();IER = 0x0000;IFR = 0x0000;InitPieVectTable();LED_Init();// 初始化定时器0,CPU频率150MHz,定时周期500000us (0.5s)TIM0_Init(150, 500000);while(1){i++;if(i%2000==0){LED1_TOGGLE; // 主循环任务}DELAY_US(100);}
}

现象: 程序运行后,你会看到 D2 指示灯以非常精准的 1Hz 频率在闪烁,而 D1 指示灯则以 `while` 循环的速度在闪烁。D2 的闪烁完全不受主循环中 `DELAY_US` 的影响,反之亦然。这完美地展示了前台任务(中断)和后台任务(主循环)并行工作的场景。

### 总结

CPU 定时器中断是嵌入式开发从“入门”走向“专业”的分水岭。通过本次学习,你已经掌握了:
1.  定时器的**硬件工作原理**:基于递减计数器和周期寄存器实现周期性中断。
2.  **关键寄存器 TCR** 的配置方法,尤其是启动、停止和重载位。
3.  利用 TI 库函数进行**标准化配置的完整流程**。
4.  如何编写中断服务函数来执行**精确的周期性任务**。

定时器是操作系统的“时钟节拍”、PWM生成的“基准”、任务调度的“指挥官”。精通了它,你就拥有了构建复杂、实时、高效嵌入式系统的核心能力。

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

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

相关文章

从零开始:用代码解析区块链的核心工作原理

区块链技术被誉为信任的机器,它正在重塑金融、供应链、数字身份等众多领域。但对于许多开发者来说,它仍然像一个神秘的黑盒子。今天,我们将抛开炒作的泡沫,深入技术本质,用大约100行Python代码构建一个简易的区块链&am…

网络通信IP细节

目录 1.通信的NAT技术 2.代理服务器 3.内网穿透和内网打洞 1.通信的NAT技术 NAT技术产生的背景是我们为了解决IPV4不够用的问题,NAT在通信的时候可以对IP将私网IP转化为公网IP,全局IP要求唯一,但是私人IP不是唯一的。 将报文发给路由器进行…

国内真实的交换机、路由器和分组情况

一、未考虑拥挤情况理想状态的网络通信 前面我对骨干网: 宜春城区SDH网图分析-CSDN博客 数据链路层MAC传输: 无线通信网卡底层原理(Inter Wi-Fi AX201)_ax201ngw是cnvio转pci-e-CSDN博客 物理层、数据链路层、网络层及传输层…

atomic常用类方法

Java中的java.util.concurrent.atomic包提供了多种原子操作工具类,以下是核心类及其方法:‌1. AtomicBoolean‌‌方法‌:get():获取当前值set(boolean newValue):强制设置值compareAndSet(boolean expect, boolean upd…

算法题打卡力扣第3题:无重复字符的最长子串(mid)

文章目录题目描述解法一:暴力解解法二:滑动窗口题目描述 解法一:暴力解 遍历每一个可能的子串,然后逐一判断每个子串中是否有重复字符。 具体步骤: 使用两层嵌套循环来生成所有子串的起止位置: 外层循环 i…

HTML5 简介和基础骨架

一、HTML5 简介HTML5 是 HTML(超文本标记语言)的第五个主要版本,于 2014 年 10 月由 W3C(万维网联盟)正式发布。它不仅是对 HTML4.01 和 XHTML 的升级,更是一套完整的 Web 技术标准,包含了新的标…

.NET技术深度解析:现代企业级开发指南

每日激励: “不要一直责怪过去的自己,他曾经站在雾里也很迷茫” 🌟 Hello,我是蒋星熠Jaxonic! 🌈 在浩瀚无垠的技术宇宙中,我是一名执着的星际旅人,用代码绘制探索的轨迹。 &#x1…

苹果手机文本转音频,自行制作背诵素材

当你在学习一段专业内容或者背诵重要知识点时,是不是有时会觉得眼睛看久了疲惫,而且记忆效果也不太理想呢?利用手头的苹果手机或iPad,你可以轻松将文本内容生成音频文件,然后随时随地反复听,这对于备考人士…

电子电子技术知识------MOSFET管

电子电子技术知识------MOSFET管前言一、结构与符号二、工作原理1.小功率MOSFET(横向导电)2.电力MOS管三、基本特性总结前言 MOSFET是电力场效应晶体管的英文简写,又称功率mos管,mos管 一、结构与符号 二、工作原理 1.小功率M…

仿真波导中超短脉冲传输中的各种非线性效应所产生的超连续谱

在波导中,超短脉冲传输时会受到各种非线性效应的影响,从而产生超连续谱。这些非线性效应包括自相位调制(SPM)、交叉相位调制(XPM)、四波混频(FWM)等。基于MATLAB的仿真程序&#xff…

docker-compose的使用

目录 1-查看容器 2-查看docker镜像 3-运行两个容器 4-进入idea 编写docker-compose文件中的内容 5-编写配置文件 6-运行 7-docker-compose中的一些命令 启动服务 关闭服务 查看正在运行的容器 查看日志 重构新的服务 指令docker-compose 文件名 停止已运行的服务 启动 重启 1-查…

搭建分布式Hadoop集群[2025] 实战笔记

文章目录 一、实战目标 二、集群规划 1. 集群拓扑结构 2. 角色分配 说明: 三、环境准备 1. 修改 SSH 端口(安全加固) 操作步骤(所有节点执行): 2. FinalShell 连接配置 3. 防火墙配置 启动并配置 firewalld: 关闭并禁用防火墙(生产环境建议精细配置,测试环境可关闭):…

【自记录】Ubuntu20.04下Python自编译

因为需要新的Python版本,但是我们不希望修改系统原生的Python版本避免某些系统应用无法启动,因此自建一个干净的路径引入Python。 1.编译 以下在aarch64下测试,x64下可能有差异 必须把相关的devel包安装完毕,否则python可能缺功能…

Linux - 进程切换

🎁个人主页:工藤新一 🔍系列专栏:C面向对象(类和对象篇) 🌟心中的天空之城,终会照亮我前方的路 🎉欢迎大家点赞👍评论📝收藏⭐文章 文章目录进…

机器算法(五)模型选择与调优

一 交叉验证1 保留交叉验证HoldOutholdOut Cross-validation(Train-Test Split)在这种交叉验证技术中,整个技术集被随机划分为训练集和验证集。根据经验法则,整个数据集的近70%被用作训练集,其余30%被用作验证集,也就是最常使用的…

Ubuntu 服务器实战:Docker 部署 Nextcloud+ZeroTier,打造可远程访问的个人云

本次部署基于 Ubuntu 系统(桌面版 / Server 版通用,核心操作一致),硬件配置参考如下,低配置主机可顺畅运行: ubuntu服务器配置如下 硬件类型具体型号/参数CPUIntel Core i3-6100T内存条8GB(DD…

移动硬盘删除东西后,没有释放空间

请按照以下步骤,从最简单、最常见的原因开始排查和解决:主要原因和解决方案1. 检查操作系统回收站 (最常见原因!)这是最容易被忽略的一点。当您直接在外接移动硬盘上删除文件时,文件并不会直接消失,而是被移到了该移动…

spring boot驴友结伴游网站的设计与实现(代码+数据库+LW)

摘要 本文介绍了基于Spring Boot框架开发的驴友结伴游网站的设计与实现。该网站旨在为旅行爱好者提供一个便捷的平台,使他们能够轻松地寻找伙伴、预定酒店、参与活动以及分享旅行经历。系统主要分为两大模块:用户模块和管理员模块。用户可以通过注册账号…

人机之间的强交互与弱交互

人机交互不是简单的人机,其本质是人机环境系统的交互。在这个系统中,人和机器不是孤立的存在,而是在特定环境下相互影响、相互作用的一部分。人机之间的强交互与弱交互可以从以下几个方面来理解:1、人机强交互通常是指人与机器之间…

OpenCV 基础知识总结

学习网站 https://zhuanlan.zhihu.com/p/483604320 命名空间 using namespace cv; Mat 作用 创建图像(矩阵) 格式 Mat image; //创建一个空图像image,大小为0 Mat image(100,100,CV_8U); //指定矩阵大小(矩阵行数/列数&#xff09…