嵌入式系统中的定时器与外设设备详解
1. 系统定时器概述
在嵌入式应用里,系统定时器是不可或缺的一部分。它的用途广泛,可用于测量经过的时间、记录实际的日期和时间、调度线程等。由于其在嵌入式应用中极为常见,几乎每个微控制器单元(MCU)都会在同一芯片上集成定时器硬件。
以Cortex - M3为例,它包含一个名为“SysTick”的定时器。这是一个计数器,可被编程设置为一个初始值,即“重载值”。在CPU时钟的每个周期,计数器会减1。当计数器减到0时,会触发一个SysTick中断,并自动重新加载计数器,开始下一个倒计时序列。多线程系统通常利用SysTick计数器来提供周期性中断,一般会将计数器的重载值编程为每秒产生1000次中断。
2. SysTick定时器的配置步骤
-
计算重载值
:
由于CPU时钟可以被编程为不同的速率,重载值是CPU时钟速率的函数。以下是相关代码示例:
#define TICK_RATE_HZ 1000 // 1000 interrupts/sec (1 kHz)
#define CPU_CLOCK_HZ 6000000 // default core clock is 6 MHz
#define SYST_RVR 0xE000E014 // Adrs of SysTick Reload Value Register
*((uint32_t *) SYST_RVR) = ( CPU_CLOCK_HZ / TICK_RATE_HZ ) – 1 ;
-
配置SysTick控制和状态寄存器
:
设置好重载值后,需要配置SysTick控制和状态寄存器,以告知计数器使用哪个时钟源、启用SysTick中断并开启计数器。代码如下:
#define SYST_CSR 0xE000E010 // Adrs of SysTick Control & Status Registers
#define SYSTICK_CLK 0x00000004 // Use core clock to drive SysTick counter
#define SYSTICK_INT 0x00000002 // Enable SysTick interrupt generation
#define SYSTICK_ENABLE 0x00000001 // Enables the SysTick counter
*((uint32_t *) SYST_CSR) = SYSTICK_CLK | SYSTICK_INT | SYSTICK_ENABLE ;
-
配置嵌套向量中断控制器(NVIC)
:
还需要配置NVIC中的相关寄存器,以设置SysTick中断的优先级。示例代码如下:
#define NVIC_SHPR 0xE000ED18 // Adrs of System Handler Priority Registers
#define SYSTICK_EXC_NMBR 15 // Exception number of SysTick interrupt
#define SYSTICK_PRIORITY 250 // Typically a low priority (high number)
((uint8_t *) NVIC_SHPR)[SYSTICK_EXC_NMBR - 4] = SYSTICK_PRIORITY ;
3. SysTick中断处理程序
SysTick中断处理程序通常会递增一个变量,用于记录已经发生的SysTick中断次数。如果配置为每秒发生1000次中断,那么这个计数器将记录经过的毫秒数(0.001秒)。
4. 其他外设设备的中断处理
Cortex - M3的中断处理程序可以写成普通的C函数。除了SysTick处理程序外,可能还需要为输入或输出数据的设备编写处理程序。
对于输入设备,处理程序通常会从设备读取数据,并将其放入相关的队列中。而输出设备的中断表示上一个输出命令已完成,其处理程序通常会检查输出队列,看是否有更多数据要发送到设备。如果有可用的输出数据,会将其从队列中移除并发送。
安装处理程序只需将其入口点地址存储在向量表的适当位置。向量表的一些入口位置由Cortex - M3架构预先定义,而其他位置则取决于特定实现中可用的外设设备,需要在MCU的文档中查找。
5. 外设设备初始化和中断处理程序的示例资源
有许多优秀的源代码示例可展示如何初始化特定的外设设备,以及如何为其实现中断处理程序。这些示例可以在相关网站的实验室作业中找到,也可以在Stellaris外设驱动库和FreeRTOS实时内核的源代码中找到。
6. 相关概念和操作的表格总结
| 概念/操作 | 描述 |
|---|---|
| SysTick定时器 | Cortex - M3中的计数器,可产生周期性中断 |
| 重载值 | 计数器的初始值,与CPU时钟速率相关 |
| SysTick控制和状态寄存器 | 用于配置时钟源、启用中断和开启计数器 |
| 嵌套向量中断控制器(NVIC) | 用于设置SysTick中断的优先级 |
| 输入设备中断处理程序 | 读取设备数据并放入队列 |
| 输出设备中断处理程序 | 检查输出队列并发送数据 |
7. SysTick定时器配置流程的mermaid流程图
graph TD;
A[开始] --> B[计算重载值];
B --> C[配置SysTick控制和状态寄存器];
C --> D[配置NVIC设置中断优先级];
D --> E[完成配置];
8. 数据表示与类型转换
在嵌入式系统开发中,数据的表示和类型转换是非常重要的基础概念。
8.1 数据表示
数据的表示方式多种多样,常见的有以下几种:
-
整数的二进制表示
:整数可以用二进制形式表示,有2的补码有符号数、符号加绝对值表示法以及无符号表示法等。例如,8位二进制模式可以表示不同范围的整数,计算时要注意加法、减法的运算规则以及范围和溢出问题。
-
实数的二进制表示
:实数的二进制表示分为定点实数和浮点实数。定点实数使用固定的小数位数,而浮点实数则通过指数和尾数来表示。
-
ASCII文本表示
:文本通常用ASCII码来表示,每个字符对应一个特定的ASCII值。
-
二进制编码十进制(BCD)
:用于表示十进制数,每个十进制数字用4位二进制编码。
8.2 数据类型转换
数据类型转换包括隐式转换和显式转换。隐式转换通常在不同类型的数据进行运算时自动发生,而显式转换则需要使用强制类型转换运算符。例如,在C语言中,可以使用
(type)
的形式进行显式转换。数据类型转换可能会导致数据类型降级或升级,需要注意数据精度的损失。
9. 内存管理
内存管理在嵌入式系统中至关重要,它直接影响系统的性能和稳定性。
9.1 内存分配方式
- 自动分配 :在函数内部声明的局部变量通常采用自动分配方式,当函数执行结束时,这些变量所占用的内存会自动释放。
-
动态分配
:使用
malloc()、calloc()等函数在运行时动态分配内存,使用完后需要使用free()函数释放内存,否则会导致内存泄漏。 - 静态分配 :全局变量和静态变量采用静态分配方式,它们在程序启动时就分配好内存,直到程序结束才释放。
9.2 内存管理的注意事项
- 内存碎片 :动态分配和释放内存可能会导致内存碎片问题,影响内存的有效使用。可以采用池化分配方案来减少内存碎片。
- 内存泄漏 :忘记释放动态分配的内存会导致内存泄漏,使系统可用内存逐渐减少,最终可能导致系统崩溃。
10. 线程调度与同步
在多线程的嵌入式系统中,线程调度和同步是保证系统正常运行的关键。
10.1 线程调度算法
- 优先级调度 :根据线程的优先级来决定线程的执行顺序,高优先级的线程优先执行。但可能会出现优先级反转和饥饿问题。
- 速率单调调度 :根据任务的周期来分配优先级,周期越短的任务优先级越高。
- 截止日期驱动调度 :根据任务的截止日期来安排任务的执行顺序,确保任务在截止日期前完成。
10.2 线程同步机制
- 互斥锁 :用于保护共享资源,同一时间只允许一个线程访问共享资源。
- 信号量 :可以用来控制对共享资源的访问数量,也可以用于线程间的同步。
- 条件变量 :与互斥锁配合使用,允许线程在某个条件满足时继续执行。
11. 中断处理的详细流程
中断处理是嵌入式系统中处理外部事件的重要机制,其详细流程如下:
1.
中断发生
:外部设备或内部事件触发中断信号。
2.
保存现场
:CPU保存当前的执行状态,包括程序计数器、寄存器等。
3.
查找中断向量
:根据中断号在中断向量表中查找对应的中断处理程序入口地址。
4.
执行中断处理程序
:跳转到中断处理程序执行,完成相应的任务。
5.
恢复现场
:中断处理程序执行完毕后,恢复之前保存的执行状态。
6.
继续执行主程序
:CPU继续执行被中断的主程序。
以下是中断处理流程的mermaid流程图:
graph TD;
A[中断发生] --> B[保存现场];
B --> C[查找中断向量];
C --> D[执行中断处理程序];
D --> E[恢复现场];
E --> F[继续执行主程序];
12. 常见指令集与操作的总结表格
| 指令集/操作 | 描述 |
|---|---|
| ARM Cortex - M3指令集 | 包括数据处理指令、转移指令、堆栈指令等,具有高效、低功耗的特点 |
| 数据处理指令 | 如加法、减法、逻辑运算等,用于对数据进行各种操作 |
| 转移指令 | 用于改变程序的执行流程,如跳转、调用子程序等 |
| 堆栈指令 | 用于管理堆栈,如入栈、出栈操作 |
13. 总结
嵌入式系统开发涉及到众多的技术领域,包括定时器配置、外设设备中断处理、数据表示与类型转换、内存管理、线程调度与同步以及中断处理等。通过深入理解这些技术,并掌握相关的操作步骤和代码实现,能够开发出高效、稳定的嵌入式系统。在实际开发过程中,要根据具体的需求选择合适的技术和算法,同时注意内存泄漏、优先级反转等常见问题,以确保系统的可靠性和性能。
嵌入式系统定时器与中断详解
超级会员免费看
466

被折叠的 条评论
为什么被折叠?



