管理系统开发公司 【STM32】圭臬库与HAL库对照学习教程四--延时函数详解_hal

【STM32】圭臬库与HAL库对照学习教程四--延时函数详解 一、绪论二、前期准备三、SysTick定时器先容1、SysTick定时器简介2、SysTick定时器寄存器先容(1) CTRL寄存器(2)LOAD寄存器(3)VAL寄存器(4)CALIB寄存器 3、SysTick定时器的时钟开端5、SysTick定时器成立秩序 四、圭臬库的延时1、圭臬库的成立秩序2、SysTick定时器成立标准3、主标准4、软件仿真秩序5、实验恶果 五、HAL库的延时1、HAL库的成立秩序2、SysTick定时器成立标准3、实验恶果3、对于HAL_Delay()函数(1)函数情况(2)函数标准(3)标准评释

STM32一玄门程:【STM32】圭臬库与HAL库对照学习系列教程大全

一、绪论

咱们在单片机顶用的延时基分内为三种, 轮回延时、SysTick滴答定时器延时、SysTick滴答定时器中断延时 ,轮回延时即是让CPU约束while轮回,while轮回完后,在现实底下的标准,while轮回的时辰,即是延时的时辰,这么的花样不仅占用CPU资源况兼不好胁制延豪迈间,因此无论是圭臬库依然HAL库一般皆使用STM32芯片上的SysTick滴答定时器完成延时。

二、前期准备 STM32斥地板(我使用的是普中的STM32F103ZE的Z200系列)(非必要)STM32cubemx、Keil5(MDK)斥地板道理图(非必要) 三、SysTick定时器先容 1、SysTick定时器简介

SysTick定时器也叫SysTick滴答定时器,它是Cortex-M3内核的一个外设,被镶嵌在NVIC中。它是一个24位向下递减的定时器,每计数一次所需时辰为1/SYSTICK,SYSTICK是系统定时器时钟,它不错平直取自系统时钟,还不错通过系统时钟8分频后赢得。当定时器计数到0时,将从LOAD 寄存器中自动重装定时器初值,再行向下递减计数,如斯周而复始。要是开启SysTick中断的话,当定时器计数到0,将产生一个中断信号。因此惟有知说念计数的次数就不错准确得到它的延豪迈间。

2、SysTick定时器寄存器先容 (1) CTRL寄存器

CTRL是SysTick定时器的胁制及情状寄存器。其相应位功能如下:

图片管理系统开发公司

(2)LOAD寄存器

LOAD是SysTick定时器的重装载数值寄存器。其相应位功能如下:

图片

(3)VAL寄存器

VAL是SysTick定时器确现时数值寄存器。其相应位功能如下:

图片

(4)CALIB寄存器

CALIB是SysTick定时器的校准数值寄存器。其相应位功能如下:

图片

汇总一下:

寄存器形色CTRLSysTick 胁制和情状寄存器LOADSysTick 重装载值寄存器CALIBSysTick 校准值寄存器 3、SysTick定时器的时钟开端

其在时钟树的位置:

图片

不错看到SysTick定时器的时钟开端由系统频率SYSCLK历程AHB分频,在历程8分频(可汲取)得到。

关联时钟树的栽培不错看这篇著述:【STM32】STM32圭臬库与HAL库对照学习教程非凡篇–系统时钟RCC详讲

5、SysTick定时器成立秩序

SysTick定时器的操作或然不错分为 4 步: (1)成立SysTick定时器的时钟源。 (2)成立SysTick定时器的重装启动值(要是要使用中断的话,就将中断使能翻开)。 (3)清零SysTick定时器现时计数器的值。 (4)翻开SysTick定时器。

四、圭臬库的延时 1、圭臬库的成立秩序

(1)复制上一讲的工程,并定名为4、SysTick定时器延时。

图片

(2)在工程中新建Public文献夹,标明是内部保存的是通用的标准。

图片

(3)在Public文献夹内成立Delay文献夹,用来保存SysTick定时器的标准。

图片

(4)翻开工程,新建两个文献并定名为:Delay.h和Delay.c,保存在刚成立的Delay文献夹内。 ①

图片

图片

(5)添加文献到目次并添加文献旅途。 ①

图片

图片

(6)使用SysTick定时器要添加misc.c文献。

图片

2、SysTick定时器成立标准

Delay.h的标准:

#ifndef DELAY_H_
#define DELAY_H_

#include "stm32f10x.h"

//1s=1000ms=1000000us
void SysTick_Init(u8 SYSTICK);  //SysTick时钟启动化函数
void Delay_us(u32 nus);          //微秒级延时函数  
void Delay_ms(u32 nus);          //毫秒级延时函数

#endif

Delay.c的标准:

#include "Delay.h"

static u16 fac_us;   //计fac_us个数为1us - SysTick时钟频率
static u32 fac_ms;   //计fac_ms个数为1ms

/*************************************************
*函数名:     SysTick_Init
*函数功能:   SysTick定时器启动化
*输入:       SYSTICK:我方成立的系统时钟,莫得成立时,默许成立是72M。 
*复返值:     无
**************************************************/
void SysTick_Init(u8 SYSTICK)
{
	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //汲取8分频
	fac_us = SYSTICK/8;     //因为进行了8分频
	fac_ms = (u16)fac_us*1000; 
	
}

/*************************************************
*函数名:     Delay_us
*函数功能:   微秒级延时函数
*输入:       nus:延时的微秒数
							防范:nus的值,不要大于798915us(最大值即2^24/fac_us@fac_us=21)
*复返值:     无
**************************************************/
void Delay_us(u32 nus)
{
	u32 temp;                     //储存CTRL寄存器的值
	SysTick->LOAD = nus*fac_us;   //成立要数到值
	SysTick->VAL  = 0x00;         //清空计数器的值
	SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; //SysTick定时器使能
	do
	{
		temp = SysTick->CTRL;
	}while((temp&0x01)&&!(temp&(1<<16))); //判断是否计数到达
	
	SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk;  //SysTick定时器失能
	SysTick->VAL  = 0x00;         //清空计数器的值
}

/*************************************************
*函数名:      Delay_ms 
*函数功能:    毫秒级延时函数
*输入:        nus:延时nus毫秒
*复返值:      无
**************************************************/
void Delay_ms(u32 nus)
{
	u32 temp;                     //储存CTRL寄存器的值
	SysTick->LOAD = nus*fac_ms;   //成立要数到值
	SysTick->VAL  = 0x00;         //清空计数器的值
	SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; //SysTick定时器使能
	do
	{
		temp = SysTick->CTRL;
	}while((temp&0x01)&&!(temp&(1<<16))); //判断是否计数到达
	SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk;  //SysTick定时器失能
	SysTick->VAL  = 0x00;         //清空计数器的值
}

图片

3、主标准
#include "LED.h"
#include "Delay.h"


/*************************************************
*函数名:    main
*函数功能: 主函数
*输入:     无  
*复返值:   无
**************************************************/
int main()
{
	SysTick_Init(72);
	LED_Init();
	while(1)
	{
		GPIO_SetBits(LED0_GPIO_Port, LED0_Pin);
		GPIO_ResetBits(LED1_GPIO_Port, LED1_Pin);
		Delay_ms(1000);
		GPIO_SetBits(LED1_GPIO_Port, LED1_Pin);
		GPIO_ResetBits(LED0_GPIO_Port, LED0_Pin);
		Delay_ms(1000);
	}
}

图片

龙头分析:上期龙头上升2个点位,开出0路号码03,最近10期龙头分布在01-07之间,012路比为2:5:3,0路龙头走势较冷,1路龙头表现活跃,最近3期龙头升降走势为下降→下降→上升,本期预计龙头逐渐下降,关注1路龙头号码01。

遗漏分析:上期奖号遗漏总值为48,比前期遗漏总值低了2点,管理系统开发公司开出14个热码奖号,比前期热码多出现2个,开出4个温码奖号,比前期温码少出现1个,开出2个冷码奖号,比前期冷码少出现1个,最近10期奖号冷温热码个数比为21:59:120,遗漏总值出现范围在41-69之间,本期预计冷温热码个数比为1:3:16,看好遗漏总值出现在30附近。

app
4、软件仿真秩序

(1)凭证我方斥地板的外部时钟晶振频率参数成立,我的是8MHz。

图片

(2)Debug选项成立。

图片

(3)点击Debug,翻开示波器,成立参数。 ①

图片

图片

图片

5、实验恶果

软件仿真恶果: ①

图片

图片

不错看到LED电平翻转的时辰终结是1s,评释延豪迈间是1s。

硬件仿真恶果(引脚上下电平捏续时辰):

图片

五、HAL库的延时 1、HAL库的成立秩序

(1)复制2.LED工程并定名为3.SysTick.

图片

(2)在工程中新建Public文献夹,标明是内部保存的是通用的标准。

图片

(3)在Public文献夹内成立Delay文献夹,用来保存SysTick定时器的标准。

图片

(4)翻开工程,新建两个文献并定名为:Delay.h和Delay.c,保存在刚成立的Delay文献夹内。 ①

图片

图片

(5)添加文献到目次并添加文献旅途。 ①

图片

图片

2、SysTick定时器成立标准

Delay.h:

#ifndef DELAY_H_
#define DELAY_H_

#include "stm32f1xx_hal.h"

void SysTick_Init(uint8_t SYSCLK); //SysTick定时器启动化函数
void Delay_us(uint32_t nus);       //微秒级延时函数
void Delay_ms(uint16_t nms);       //毫秒级延时函数



#endif

Delay.c:

#include "Delay.h"

static uint32_t  fac_us=0;							//1us计数fac_us个数		   

/*******************************************************************************
* 函 数 名:          SysTick_Init
* 函数功能:          SysTick启动化函数
* 输    入:          SYSCLK:系统时钟频率
* 输    出:          无
*******************************************************************************/
void SysTick_Init(uint8_t SYSCLK)
{
 	HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);//SysTick频率为HCLK 
	fac_us=SYSCLK;						//保存1us所需的计数次数  
}								    

/*************************************************
*函数名:            Delay_us
*函数功能:          微秒级延时函数
*输入:              nus:延时nus微秒
                     防范:nus的取值为0~190887435(最大值即2^32/fac_us@fac_us=22.5)
*复返值:            无
**************************************************/	 
void Delay_us(uint32_t nus)
{		
	uint32_t ticks;
	uint32_t told,tnow,tcnt=0;
	uint32_t reload=SysTick->LOAD;				//LOAD的值	    	 
	ticks=nus*fac_us; 						//需要的节奏数 
	told=SysTick->VAL;        				//刚投入时的计数器值
	while(1)
	{
		tnow=SysTick->VAL;	
		if(tnow!=told)
		{	    
			if(tnow<told)tcnt+=told-tnow;	//这里防范一下SYSTICK是一个递减的计数器就不错了.
			else tcnt+=reload-tnow+told;	    
			told=tnow;
			if(tcnt>=ticks)break;			//时辰首先/等于要延长的时辰,则退出.
		}  
	};
}

/*************************************************
*函数名:            Delay_ms
*函数功能:          毫秒级延时函数
*输入:              nus:延时nus毫秒
*复返值:            无
**************************************************/	
void Delay_ms(uint16_t nms)
{
	uint32_t i;
	for(i=0;i<nms;i++) Delay_us(1000);
}

图片

3、实验恶果

与圭臬库的实验恶果雷同,然而这里依然放一下测试的图片。

图片

3、对于HAL_Delay()函数 (1)函数情况

HAL_Delay()这个函数是HAL库自带的毫秒级延时函数,基本上在以后的工程中,莫得格外情况,咱们皆不使用我方建的延时函数,基本上皆用HAL_Delay()这个函数,函数使用的是SysTick滴答定时器中断延时。

(2)函数标准
__weak void HAL_Delay(uint32_t Delay)
{
  uint32_t tickstart = HAL_GetTick();
  uint32_t wait = Delay;

  /* Add a freq to guarantee minimum wait */
  if (wait < HAL_MAX_DELAY)
  {
    wait += (uint32_t)(uwTickFreq);
  }

  while ((HAL_GetTick() - tickstart) < wait)
  {
  }
}
(3)标准评释 函数是一个弱界说函数,不错再行被界说。函数通过HAL_GetTick()赢得计数值,计数值1ms加1,直到加到你写入的值,跳出终末的while轮回,标准扫尾。uwTickFreq这个值是为1的,也即是说会多延时1ms,这么作念是为了退守用户写入延时0ms这种无道理的延时。防范:这个函数是有中断的,不要把这个函数放到我方的中断回调函数里,要是SysTick定时器中断的优先级小于你使用某个中断的优先级这么可能会导致标准卡在HAL_Delay()这个函数里。

备注:这个我嗅觉我方意会的还不是很彻底,但愿有大佬能出著述,深化酌量一下这个函数的兑现。

到这里著述就扫尾啦!

图片

本站仅提供存储劳动,系数实质均由用户发布,如发现存害或侵权实质,请点击举报。

下一篇:没有了

Powered by 江西管理系统开发 @2013-2022 RSS地图 HTML地图

Copyright Powered by站群 © 2013-2024 云迈科技 版权所有