实战_SysTick异常
本节课程使用CPU自带的SysTick定时器,让它产生周期性的中断,用来操作LED。
1.1 SysTick操作
Cortex-M处理器内部集成了一个小型的、名为SysTick的定时器。可以使用它来为操作系统提供系统时钟,也可以把它当做一般的定时器。
之所以在处理器内增加这样的定时器,是为了提高软件的可以移植性。
它是一个24位的定时器,向下计数。
在时钟源的驱动下,计数值到达0时,可以触发异常。然后我们就可以定义异常处理函数,每当触发异常时,就可以去执行函数中的操作。
它的框图如下:
在本程序中,只需要设置这几个寄存器即可:
我们通过定义一个结构体来操作这些寄存器
typedef struct
{
volatile unsigned int CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
volatile unsigned int LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
volatile unsigned int VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
volatile unsigned int CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
} SysTick_Type;
#define SysTick_BASE (0xE000E000 + 0x0010UL)
#define SYSTICK_FRE (8000000)
1.SysTick->CTRL
时钟源选择:
时钟源有两个,所以还要选择时钟源,这时我们需要操作如下几位
- bit2 设置为1,选择时钟来源为内部处理器的时钟;
- bit1 设置为1,使能异常
- bit0 设置为0,使能定时器
/* 3.选择时钟源,使能systick,使能异常 */
// 分别设置bit2,bit1,bit0
SysTickInit->CTRL = (1<<2) | (1<<1) | (1<<0);
2.SysTick->VAL
设置计数器VAL的值
已知基地址为:(0xE000E000 + 0x0010UL) ;我们通过定义一个宏来操作这个地址#define SysTick_BASE (0xE000E000 + 0x0010UL)
计数值count的计算:
1s钟产生1次异常
晶振8MHz,计时器count值为 val = 1/T ;
T = 1/8MHz
1s钟计数器的填充值应该为:val = 1/ 1/8M = 8000000
我们也通过定义一个宏来操作计数值:#define SYSTICK_FRE (8000000)
SysTickInit->VAL = SYSTICK_FRE;
3.SysTick->LOAD
LOAD自动重装寄存器也需要设置对应的重装值
/* 2.设置LOAD寄存器,重新加载值 */
SysTickInit->LOAD = SYSTICK_FRE;
1.2 清除SysTick异常
最后,当我们设置完上述寄存器后,还需要清除这个异常转态,让程序跳过异常,继续向下执行
清除systick的挂起状态
我们也通过宏定义来设置bit25
/* 清除异常状态 ;设置SCB中的ICSR为1*/
SCB->ICSR |= SCB_ICSR_PENDSTCLR_Msk;
1.3 通过systick异常来控制LED闪烁
代码实现:
- start.s
PRESERVE8
THUMB
; Vector Table Mapped to Address 0 at Reset
AREA RESET, DATA, READONLY
EXPORT __Vectors
;IMPORT HardFault_Handler
IMPORT SysTick_Handler
__Vectors DCD 0
DCD 0x08000009; //Reset_Handler ; Reset Handler
DCD 0 ; NMI Handler
DCD 0 ; Hard Fault Handler
DCD 0 ; MPU Fault Handler
DCD 0 ; Bus Fault Handler
DCD 0 ; Usage Fault Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; SVCall Handler
DCD 0 ; Debug Monitor Handler
DCD 0 ; Reserved
DCD 0 ; PendSV Handler
DCD SysTick_Handler ; SysTick Handler
AREA |.text|, CODE, READONLY
; Reset handler
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT mymain
IMPORT SystemInit
IMPORT uart_init
IMPORT SysTickInit
IMPORT LedInit
LDR SP, =(0x20000000+0x10000)
BL SystemInit
BL uart_init
BL SysTickInit
BL LedInit