带你模仿正点原子到寄存器编写–SYSTICK(delay函数)
以下是本篇文章正文内容,下面案例可供参考
邓家文-广州华软软件学院
一、 前提了解
系统时钟systick是STM32内部的硬件资源,我们首先要知道,MCU内部资源应该在Cortex-M3权威指南上查询;而STM32中文参考手册主要是对MCU外部外设资源的描述。
二、 手册查询和分析
经过上面的分析我们应该有个大致的配置思维了。
三、 程序编写
1、.h文件的编写
这一段程序就没什么好说的,清除的,我发布的DMA实验有详细的说明。
2、.c文件
①用无论是用内部还是外部的时钟,都需要使能使用到的时钟。
然后获取已转换过来的外部时钟频率
②将获取到的source_clk单位是MHz,将进来的时钟频率f*source_clk=10^-6秒,设置到最基本的每微秒的(source_cl)载值后,在乘我们需要的us数即转化为计数器要计数的载数值,然后清除计数器的值,从(空白页)开始计数,计完数后要关闭计数器并漂白计数器。
③这个ms级延时函数与us级延时函数是相似的,这里我就不多讲了。
不理解计数的话,看如下:
假设进来分频后的时钟就为9MHz,那么也就是每秒节拍数是9000000次,f=1/9000000,那我需要一个周期为1us,即
f9=1/1000000s = 1us,f是真实的时钟频率,而9是我们让程序在这个时钟频率下计算9次得到软件分频后的1us
那么重载值就是9nus就是需要延时nus微秒,这个重载值不得超过0xFFFFFF值。**
四、 Keil仿真调试
运行delay_ms1(1000);这行程序总共计数72005299-5215=72000084次,(在72MHZ)情况下,所以这可以近似认为1s。至于sec为什么7.2秒,我也不清楚,希望各位大神能告诉我。
五、 程序:
test.c:
#include "stdio.h"
#include "gpio.h"
#include "USART1.h"
#include "delay_ms.h"
#include "clock.h"
#include "USART1.h"
#include "key.h"
#include "DMA.h"
int main(void)
{
RCC_Config(9);
delay_init1(72);
GPIO_Init();
while(1)
{
GPIOB->GPIO_ODR^=1<<5;
delay_ms1(1000);
GPIOE->GPIO_ODR^=1<<5;
}
}
delay.h:
#ifndef __DELAY_MS_H
#define __DELAY_MS_H
#include "RCC.h"
#define SYSTICK_BASE (0xE000E010)
typedef struct
{
volatile unsigned int CTRL;
volatile unsigned int LOAD;
volatile unsigned int VAL;
volatile unsigned int CALIB;
}SYSTICK_Type;
#define SYSTICK ((SYSTICK_Type *) SYSTICK_BASE)
static u16 source_clk;
static u16 count_us=0;
static u16 count_ms=0;
void delay_init1(u8 sysclk);
void delay_ms1(u16 nms);
void delay_us1(u16 nus);
#endif
delay.c
#include "delay_ms.h"
void delay_init1(u8 sysclk)
{
SYSTICK->CALIB&=~(1<<2);
source_clk=sysclk/8;
}
void delay_us1(u16 nus)
{
u32 temp;
count_us=source_clk;
SYSTICK->LOAD=count_us*nus;
SYSTICK->VAL=0x00;
SYSTICK->CTRL=0x01 ;
do
{
temp=SYSTICK->CTRL;
}while((temp&0x01)&&!(temp&(1<<16)));
SYSTICK->CTRL=0x00;
SYSTICK->VAL=0X00;
}
void delay_ms1(u16 nms)
{
u32 temp;
count_ms=source_clk*1000;
SYSTICK->LOAD=count_ms*nms;
SYSTICK->VAL=0x00;
SYSTICK->CTRL=0x01 ;
do
{
temp=SYSTICK->CTRL;
}while((temp&0x01)&&!(temp&(1<<16)));
SYSTICK->CTRL=0x00;
SYSTICK->VAL=0X00;
}