之前为了学习嵌入式,写了有1M多的word文档的学习笔记,但是因为是边学边写的,总是难免有不清楚的地方或者疏漏的地方,因此在这里重新将学习笔记重新整理,以章节的形式写出博客,这也是前面关于整个stm32文件夹内博客的由来。说起来,Systick系统滴答实现很简单,说起来就是数据装载,自减,数据为0时触发中断,同时数据重载,看起来似乎不难,当然实际设计也不难,但其中涉及的知识点却不少(也算是第一次接触到ARM最重要的外设NVIC)
学习一种外设,那么首先肯定要查外设相关寄存器的功能*,systick本身寄存器比较少,仅有4个(参考cortex-m3权威指南8.7章节) CTRL 状态和控制寄存器 bit0 systick定时器使能位 bit1 systick中断使能位 bit2 systick时钟选择位 bit16 systick状态标志位,读取置0(不使能中断的可通过查询该标志位来实现系统滴答) LOAD 数值重载寄存器 当计数器到达0时将LOAD的值装载到“当前值寄存器” VAL 当前值寄存器 访问寄存器时的当前值,属性是写-清除。清零该值可以同时清零 CTRL的bit16 CALIB 校准值寄存器 用于Systick的时钟精确校准。 因为一般对时间的精确度并没有那么高,所以校准寄存器就不在说明,这里主要说明上面3个寄存器的配置: #define TICK_PER_SECOND 2 //每s滴答次数 Systick->LOAD = SYSCLK/TICK_PER_SECOND - 1; Systick->VAL = 0x0; Systick->CTRL = 0x00000007; //定时器使能,中断使能,选择系统时钟作为中断响应。 <时钟程序编写> 1.初始化系统时钟(具体参见rcc章节) 2. 使能相关GPIO口的时钟(参加流水灯中gpio配置) 3.初始化SysTick时钟(如上面的初始化寄存器代码) 4.确定向量表位置,设置SysTick中断优先级, 默认-1 语句如下
SCB->VTOR = 0x0800000000|(0x0 & (u32)0x1FFFFF80); //将向量表定位到flash的0x0偏移处
NVIC_SetPriority(SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); //设置优先级
本例中中断函数为
void SysTick_Handle(void)
{ //add person code } 即可实现系统滴答实验 当然滴答时钟初始化还有更简单的内部函数(在core_cm3.h中)直接调用SysTick_Config(SYSCLK/TICK_PER_SECOND)即可。 完成上面的初始化,用一个全局变量做标志位,即可利用系统滴答实现led闪烁。
这个程序比较简单,但其中涉及到ARM中断的知识却并不简单,关于ARM中的中断我会另开一页去讲,这里主要讲为什么中断函数名为SysTick_Handle(), 这个需要查看STM32F10X.s文件
向量表:_vector .......
DCD SysTick_Handler ; SysTick Handler
......
SysTick_Handler PROC
EXPORT SysTick_Handler [WEAK] B //跳转到当前指定地址. ENDP
DCD(伪代码,据定义伪指令一般用于为特定的数据分配存储单元,同时可完成已分配存储单元的初始化),了解过函数指针的应该知晓函数名某种意义也是一个地址,那么当SysTick中断产生时,就会转到名为SysTick_Handler的C语言函数。 当Systick->VAL中值置0,且中断和时钟使能时,此时中断产生,这时指令总线就会从向量表中找出正确的异常向量,然后在服务程序的入口取指(这也是为什么要重新定位向量表的原因,因为实际代码包括向量表都是在flash中的,定位向量表不是移动向量表,而是指定向量表的实际起始地址)。实际中断的产生比这复杂的多,这里不在赘述,后序会详细讲。
8. Systick系统滴答实现
最新推荐文章于 2024-04-14 17:40:37 发布