您好,欢迎来到叨叨游戏网。
搜索
您的当前位置:首页带你模仿正点原子编程风格到深入学习寄存器并手把手编写STM32F103寄存器程序(SYSTICK滴答时钟之delay延时)

带你模仿正点原子编程风格到深入学习寄存器并手把手编写STM32F103寄存器程序(SYSTICK滴答时钟之delay延时)

来源:叨叨游戏网

带你模仿正点原子到寄存器编写–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,即
f
9=1/1000000s = 1us,f是真实的时钟频率,而9是我们让程序在这个时钟频率下计算9次得到软件分频后的1us
那么重载值就是9
nus就是需要延时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);				//72MHz
	delay_init1(72);			//打开延时
	GPIO_Init();				//初始化LED口

  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"

//systick寄存器基地址
#define SYSTICK_BASE			(0xE000E010)

//systick寄存器结构体
typedef struct
{
	volatile unsigned int CTRL;		//SysTick控制及状态寄存器
	volatile unsigned int LOAD;		//SysTick重装载数值寄存器
	volatile unsigned int VAL;		//SysTick当前数值寄存器
	volatile unsigned int CALIB;	//SysTick校准数值寄存器
}SYSTICK_Type;	

//systick寄存器指针
#define SYSTICK					 	((SYSTICK_Type *) SYSTICK_BASE)

static u16 source_clk;
static u16 count_us=0;							//us延时最小单位载值->倍乘值
static u16 count_ms=0;							//ms延时最小单位载值->倍乘值

void delay_init1(u8 sysclk);
void delay_ms1(u16 nms);
void delay_us1(u16 nus);

#endif

delay.c

#include "delay_ms.h"

//初始化systick作为delay延时函数
void delay_init1(u8 sysclk)
{
	SYSTICK->CALIB&=~(1<<2);                    //使能外部时钟
  source_clk=sysclk/8;                        //转化为外部时钟源的频率,8分频,历72MHz/8=9MHz(也就是进来一开始的时钟)
}

//延时最大是有个度的
//假设时钟就为9MHz,那么也就是每秒节拍数是9000000次,f=1/9000000
//那我需要一个周期为1us,f*9=1/1000000 s = 1us 
//那么以1us,我们可以设置多少微秒呢?f*load_max=18135us约为18ms
//最大重载值

//微秒延时
void delay_us1(u16 nus)
{
	u32 temp;                                   //保存当前计数器值
  count_us=source_clk;                        //单位频率MHz也就是us级别,10^-6秒
	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;                   //单位频率KHz也就是ms级别,10^-3秒
  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;       				          //清空计数器	
	
}

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- gamedaodao.net 版权所有 湘ICP备2024080961号-6

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务