STM32F4-正点原子探索者-SYSTEM文件夹下的delay.c文件内延时函数详解

本文详细介绍了STM32的SysTick定时器初始化过程,包括delay_init、delay_ms和delay_us函数的工作原理。通过SysTick_CLKSourceConfig配置时钟源,利用SysTick_Config进行定时器初始化,并探讨了SysTick结构体中的各个寄存器。此外,还解释了如何通过SysTick实现微秒和毫秒级别的延时函数。

目录

笔记:

首先是对应的头文件delay.h中的函数:

1、delay_init(u8 SYSCLK);

此处将把关于UCOS相关代码忽略,后面学习:

注:以下为SysTick结构体详解,与主体函数只是有一定联系,可略过。

SysTick结构体中的CTRL就是系统控制和状态寄存器(SysTick Control and Status Register):

SysTick结构体中的LOAD就是重转载数据寄存器(24位):

SysTick结构体中的VAL就是当前值寄存器(24位):

SysTick结构体中的CALIB就是校准数值寄存器(24位)(不常用):

SysTick_Config函数让SysTick定时器初始化过程:

2、void delay_ms(u16 nms);和delay_us(u32 nus);


笔记:

首先是对应的头文件delay.h中的函数:

#ifndef __DELAY_H
#define __DELAY_H 			   
#include <sys.h>	
  
void delay_init(u8 SYSCLK);
void delay_ms(u16 nms);
void delay_us(u32 nus);

#endif

可以看到只有三个函数,delay_init(u8 SYSCLK)是SysTick定时器初始化的函数,delay_ms(u16 nms)是计毫秒的,delay_us(u32 nus)是计微秒的。

在调用相关的函数之前,一定要先初始化!

关于fac_msfac_us,在文件一开始有这样的定义(一开始是0,后来根据实际情况改变):

static u8  fac_us=0;							//us延时倍乘数			   
static u16 fac_ms=0;							//ms延时倍乘数,在os下,代表每个节拍的ms数

这两个全局变量的作用会在第二节讲到。

1、delay_init(u8 SYSCLK);

//初始化延迟函数
//当使用OS的时候,此函数会初始化OS的时钟节拍
//SYSTICK的时钟固定为AHB时钟的1/8
//SYSCLK:系统时钟频率
void delay_init(u8 SYSCLK)
{
#if SYSTEM_SUPPORT_OS 						//如果需要支持OS.
	u32 reload;
#endif
 	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); 
	fac_us=SYSCLK/8;						//不论是否使用OS,fac_us都需要使用
#if SYSTEM_SUPPORT_OS 						//如果需要支持OS.
	reload=SYSCLK/8;						//每秒钟的计数次数 单位为M	   
	reload*=1000000/delay_ostickspersec;	//根据delay_ostickspersec设定溢出时间
											//reload为24位寄存器,最大值:16777216,在168M下,约合0.7989s左右	
	fac_ms=1000/delay_ostickspersec;		//代表OS可以延时的最少单位	   
	SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;   	//开启SYSTICK中断
	SysTick->LOAD=reload; 					//每1/delay_ostickspersec秒中断一次	
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; 	//开启SYSTICK    
#else
	fac_ms=(u16)fac_us*1000;				//非OS下,代表每个ms需要的systick时钟数   
#endif
}	

此处将把关于UCOS相关代码忽略,后面学习:

这里出现了SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); 这个函数作用就是配置外部时钟源(下文紧接着会介绍),具体定义是:

void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
{
  /* Check the parameters */
  assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));
  if (SysTick_CLKSource == SysTick_CLKSource_HCLK)
  {
    SysTick->CTRL |= SysTick_CLKSource_HCLK;
  }
  else
  {
    SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;
  }
}

加上宏定义:

#define SysTick_CLKSource_HCLK_Div8    ((uint32_t)0xFFFFFFFB)
#define SysTick_CLKSource_HCLK         ((uint32_t)0x00000004)
#define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SysTick_CLKSource_HCLK) || \
                        
### 正点原子STM32F407探索者开发板灯光控制示例代码 对于正点原子STM32F407探索者开发板上的灯光控制,可以利用HAL库来简化硬件抽象层次的操作。下面提供一段基于该平台的简单LED控制程序实例。 #### 初始化部分 在`main.c`文件中的`int main(void)`函数里完成必要的初始化操作: ```c #include "stm32f4xx_hal.h" // 定义全局变量用于计数器 u16 times = 0; void SystemClock_Config(void); static void MX_GPIO_Init(void); int main(void) { HAL_Init(); // 配置系统时钟至指定频率 SystemClock_Config(); // GPIO端口初始化 MX_GPIO_Init(); while (1) { if ((USART_RX_STA & 0x8000)) { if (USART_RX_BUF[0] == '0') LED1 = USART_RX_BUF[1]; USART_RX_STA = 0; } else { times++; if (!(times % 30)) LED0 = !LED0; // 切换LED状态 delay_ms(10); // 延迟一段时间 } } } ``` 这段代码展示了基本框架结构,在这里主要关注于GPIO接口以及定时翻转LED的状态[^3]。 为了实现更复杂的逻辑比如通过按键触发不同的LED行为模式,则可以在原有基础上进一步扩展功能模块。例如引入中断服务例程处理外部事件输入,或是增加更多种类的外设交互机制如UART接收命令字节从而动态调整输出电平高低等特性。 #### 扩展功能——按键控制双LED 如果希望加入按键控制两个不同颜色或位置的LED的功能,那么可以在上述基础上做如下改动: - 添加额外的IO引脚定义并将其关联到相应的物理管脚上; - 修改循环体内部判断语句以便区分来自不同源的数据流; - 调整延时参数以适应新的应用场景需求; 具体来说就是针对每一个新增加的目标对象创建独立的工作单元,并确保它们之间相互协作而不冲突。 ```c if(KEY_GetKeyState(BUTTON_KEY1)==KEY_ON){ LED_Toggle(LED_RED); // 按键按下时切换红色LED状态 } if(KEY_GetKeyState(BUTTON_KEY2)==KEY_ON){ LED_Toggle(LED_GREEN); // 另一按键按下时切换绿色LED状态 } ``` 以上片段说明了如何根据实际按压情况改变特定指示灯的行为方式[^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值