文章归档友情连接照片地图

通过SYSTICK的查询方式实现延时函数笔记

分类:电子设计  作者:rming  时间:2012-05-21

首先几个操作技巧,RVMDK中打开别人的项目文件,遇到自定义的函数或变量,可以通过右键里的goto the definition of ***或者reference查看定义变量的文件和代码位置(如图)。

代码跟踪

先上代码,后面解释

#include "sys.h"
#include "delay.h"
#include "usart.h"
int main(){
u8 t=0;
Stm32_Clock_Init(9);//72M
delay_init(72);// 延时初始化
uart_init(72,9600); // 设置串口1 波特率
while(1){
printf("t:%d
",t);
delay_ms(500);
t++;
}
}

下面是部分子函数

void delay_init(u8 SYSCLK)
{
SysTick->CTRL&=0xfffffffb;//bit2清空,选择外部时钟 HCLK/8
fac_us=SYSCLK/8;//计时基数 systick主频 HCLK/8=72/8=9MHZ,每次计数1/9us,所以计数为9时正好1us
fac_ms=(u16)fac_us*1000; //计时基数 1us*1000=1ms
}
void delay_ms(u16 nms)
{
u32 temp;
SysTick->LOAD=(u32)nms*fac_ms;//时间加载(SysTick->LOAD为24bit)
SysTick->VAL =0x00; //清空计数器
SysTick->CTRL=0x01 ; //开始倒数
do
{
temp=SysTick->CTRL;
}
while(temp&0x01&&!(temp&(1<CTRL=0x00; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}

SYSTICK 是RVMDK里定义的一个结构体(准确说是一个指针,指向了结构体),具体代码部分见RVMDK安装目录KeilARMINCSTSTM32F10x下的stm32f10x_map.h,515行,下面又把它强制类型转换成了指针,以便使用"->"方式调用赋值,我的理解就是一大堆地址定义。

SysTick是MDK定义了的一个结构体(在stm32f10x_map. h里面),里面包含CTRL、LOAD 、

VA L 、CALIB等4 个寄存器,各位定义如所示:

下面介绍STM32中的systick,Systick 部分内容属于NVIC控制部分,一共有4个寄存器,名称和地址分别是:

STK_CSR,        0xE000E010  –  控制寄存器
STK_LOAD,     0xE000E014  –  重载寄存器
STK_VAL,        0xE000E018  –  当前值寄存器
STK_CALRB,   0xE000E01C  –   校准值寄存器

首先看STK_CSR控制寄存器:寄存器内有4个位t具有意义

第0位:ENABLE,Systick 使能位  (0:关闭Systick功能;1:开启Systick功能)
第1位:TICKINT,Systick 中断使能位    (0:关闭Systick中断;1:开启Systick中断)
第2位:CLKSOURCE,Systick时钟源选择  (0:使用HCLK/8 作为Systick时钟;1:使用HCLK作为Systick时钟)
第3位:COUNTFLAG,Systick计数比较标志,如果在上次读取本寄存器后,SysTick 已经数到了0,则该位为1。如果读取该位,该位将自动清零

STK_LOAD  重载寄存器:

Systick是一个递减的定时器,当定时器递减至0时,重载寄存器中的值就会被重装载,继续开始递减。STK_LOAD  重载寄存器是个24位的寄存器最大计数0xFFFFFF。

 

STK_VAL当前值寄存器:

也是个24位的寄存器,读取时返回当前倒计数的值,写它则使之清零,同时还会清除在SysTick 控制及状态寄存器中的COUNTFLAG 标志。

STK_CALRB  校准值寄存器:

这个寄存器好像目前的水平我还用不到,大体意思明白点,把英文说明放这吧:

位31 NOREF :1=没有外部参考时钟(STCLK 不可用)0=外部参考时钟可用

位30 SKEW:1=校准值不是准确的1ms 0=校准值是准确的1ms

位[23:0] :Calibration value

 

当然也可以参考这个

SYSTICK的时钟频率,这里我们使用了外部时钟源,即RCC通关AHB时钟(HCLK)8分频后作为Cortex的系统定时器(Systic)的外部时钟,通过对Systic状态寄存器的设置,SYSTICK->CTRL寄存器第2位(0:使用HCLK/8 作为Systick时钟;1:使用HCLK作为Systick时钟),通过SYSTICK->CTRL&=0xfffffffb设置第二位为0以选择HCLK/8为SYSTICK时钟频率。

然后我们在延时函数初始化SYSTICK,设置计时基数,得到最小单位时间为1us的计数单位,以便设置SYSTICK->RELOAD计数数值。

然后下面我们就是利用计数器延时的过程了,①、时间加载(SysTick->LOAD为24bit)②、清空计数器 ③、开始倒数④、循环查询SysTick->CTRL状态位是否计数完毕   ⑤、关闭计数器⑥、清空计数器  (对应的代码就是上文中delay_ms的子函数了)

因为之前学过51,所以感觉和51的计数器差不多,不过多了一个时钟频率的选择,当然,除了查询方式的延时函数外,还可以采用中断方式,学到的时候在写。



  1. 挺好哩

  2. 给你的博客踩踩!

提交评论