STM32F4 | SYSTEM文件夹介绍 | delay文件夹 | sys文件夹 | usart文件夹


  在 新建工程模板——库函数版本中,我们用到了一个 SYSTEM 文件夹里面的代码,此文件夹里面的代码由 ALIENTEK 提供,是 STM32F4xx 系列的底层核心驱动函数,可以用在 STM32F4xx 系列的各个型号上面,方便大家快速构建自己的工程。 SYSTEM 文件夹下包含了 delaysysusart 等三个文件夹。分别包含了 delay.csys.cusart.c及其头文件。

一、delay 文件夹代码介绍

  delay 文件夹内包含了 delay.cdelay.h 两个文件,这两个文件用来实现系统的延时功能,其中包含 7 个函数:

  • void delay_osschedlock(void);
  • void delay_osschedunlock(void);
  • void delay_ostimedly(u32 ticks);
  • void SysTick_Handler(void);
  • void delay_init(u8 SYSCLK);
  • void delay_ms(u16 nms);
  • void delay_us(u32 nus);

  在介绍这些函数之前,我们先了解一下编程思想:CM4 内核的处理和 CM3 一样,内部都包含了一个 SysTick 定时器,SysTick 是一个 24 位的倒计数定时器,当计到 0 时,将从 RELOAD寄存器中自动重装载定时初值。只要不把它在 SysTick 控制及状态寄存器中的使能位清除,就永不停息。我们就是利用 STM32的内部 SysTick来实现延时的,这样既不占用中断,也不占用系统定时器。
  这里,我们以 UCOSII 为例,介绍如何实现操作系统和我们的 delay 函数共用 SysTick 定时器。首先,我们简单介绍下 UCOSII 的时钟:ucos 运行需要一个系统时钟节拍(类似 “心跳”),而这个节拍是固定的(由 OS_TICKS_PER_SEC 宏定义设置),比如要求 5ms 一次(即可设置:OS_TICKS_PER_SEC=200),在 STM32 上面,一般是由 SysTick 来提供这个节拍,也就是 SysTick要设置为 5ms 中断一次,为 ucos 提供时钟节拍,而且这个时钟一般是不能被打断的(否则就不准了)。
  因为在 ucossystick 不能再被随意更改,如果我们还想利用 systick 来做 delay_us 或者delay_ms 的延时,就必须想点办法了,这里我们利用的是时钟摘取法。以 delay_us 为例,比如:delay_us(50),在刚进入 delay_us 的时候先计算好这段延时需要等待的 systick 计数次数,这里为 50*180(假设系统时钟为 180Mhz,因为我们设置 systick 的频率为系统时钟频率,那么 systick每增加 1,就是 1/180us),然后我们就一直统计 systick 的计数变化,直到这个值变化了 50*180,一旦检测到变化达到或者超过这个值,就说明延时 50us 时间到了。这样,我们只是抓取 SysTick计数器的变化,并不需要修改 SysTick 的任何状态,完全不影响 SysTick 作为 UCOS 时钟节拍的功能,这就是实现 delay 和操作系统共用 SysTick 定时器的原理。

1.delay_init 函数

  该函数用来初始化 2 个重要参数:fac_us 以及 fac_ms;同时把 SysTick 的时钟源选择为外部时钟,如果需要支持操作系统(OS),只需要在 sys.h 里面,设置 SYSTEM_SUPPORT_OS 宏的值为 1 即可,然后,该函数会根据delay_ostickspersec 宏的设置,来配置 SysTick 的中断时间,并开启 SysTick中断。具体代码如下:

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

可以看到,delay_init 函数使用了条件编译,来选择不同的初始化过程,如果不使用 OS 的时候,只是设置一下 SysTick 的时钟源以及确定 fac_us 值。而如果使用 OS 的时候,则会进行一些不同的配置,这里的条件编译是根据SYSTEM_SUPPORT_OS这个宏来确定的,该宏在sys.h里面定义。SysTickMDK 定义了的一个结构体,里面包含 CTRLLOADVALCALIB 等 4 个寄存器,

/**
  \brief  Structure type to access the System Timer (SysTick).
 */
typedef struct
{
   
  __IOM uint32_t CTRL;                   /*!< Offset: 0x000 (R/W)  SysTick Control and Status Register */
  __IOM uint32_t LOAD;                   /*!< Offset: 0x004 (R/W)  SysTick Reload Value Register */
  __IOM uint32_t VAL;                    /*!< Offset: 0x008 (R/W)  SysTick Current Value Register */
  __IM  uint32_t CALIB;                  /*!< Offset: 0x00C (R/ )  SysTick Calibration Register */
} SysTick_Type;

  CTRLSysTick控制和状态寄存器。SysTick->CTRL 的各位定义如图所示:
在这里插入图片描述
  LOADSysTick自动重装载除值寄存器。SysTick-> LOAD 的定义如图所示:
在这里插入图片描述
  VALSysTick当前值寄存器。SysTick-> VAL 的定义如图所示:
在这里插入图片描述
  CALIBSysTick校准值寄存器。SysTick-> CALIB 不常用,在这里我们也用不到,故不介绍了。
  SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);这句代码把 SysTick 的时钟选择为内核时钟,这里需要注意的是:SysTick 的时钟源自 HCLK,假设我们外部晶振为 25M,然后倍频到 180MHZ,那么 SysTick 的时钟即为 180Mhz,也就是 SysTick 的计数器 VAL 每减 1,就代表时间过了 1/180us。所以fac_us=SYSCLK;这句话就是计算在 SYSCLK 时钟频率下延时 1us需要多少个 SysTick 时钟周期。
  在不使用 OS 的时候:fac_usus 延时的基数,也就是延时 1usSystick 定时器需要走过的时钟周期数。 当使用 OS 的时候,fac_us,还是 us 延时的基数,不过这个值不会被写到SysTick->LOAD 寄存器来实现延时,而是通过时钟摘取的办法实现的。而fac_ms 则代表 ucos 自带的延时函数所能实现的最小延时时间(如 delay_ostickspersec=200,那么 fac_ms 就是 5ms)。

2.delay_us 函数

  该函数用来延时指定的 us,其参数 nus 为要延时的微秒数。该函数有使用 OS 和不使用 OS两个版本,这里我们首先介绍不使用 OS 的时候,实现函数如下:

//延时nus
//nus为要延时的us数.	
//nus:0~190887435(最大值即2^32/fac_us@fac_us=22.5)	 
void delay_us
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值