参考STM32F1开发指南(精英版)库函数版---第五章

一、SystemInit时钟初始化函数

  使用V3.5版本的库函数,该函数在系统启动之后会自动调用:

    startup_stm32f10x_xx.s文件中:
; Reset handler Reset_Handler PROC EXPORT Reset_Handler [WEAK] IMPORT __main
IMPORT SystemInit LDR R0, =SystemInit BLX R0 LDR R0, =__main BX R0 ENDP
初始化之前首先通过宏定义定义系统时钟频率:
     #define SYSCLK_FREQ_72MHz  72000000
初始化之后的状态:
     SYSCLK (系统时钟)         72MHz

     AHB总线时钟(使用SYSCLK)        72MHz

     APB1总线时钟(PCLK1)     36MHz

     APB2总线时钟(PCLK2)          72MHz

     PLL时钟               72MHz
初始化之后可以通过变量 SystemCoreClock 获取系统变量。如果 SYSCLK=72MHz ,那么变量 SystemCoreClock
=72000000 。

二、Systick滴答定时器

1、Systick定时器,CM3,CM4内核芯片都有。

2、Systick定时器常用来做延时或者实时系统的心跳时钟

     
节省了MCU资源,不用浪费一个定时器。比如在UCOS中,分时复用,需要一个最小的时间戳,一般在STM32+UCOS系统中,都采用Systick作UCOS心跳时钟。

3、Systick定时器就是系统滴答定时器,一个24位的倒计数定时器。

     
计到0时,将从RELOAD寄存器中自动重装载定时初值。只要不把它在Systick控制及状态寄存器中的使能位清除,就永不停息,即使在睡眠模式下也能工作。

4、SysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常(异常号:15)。

5、Systick中断的优先级也可以设置。

6、4个Systick寄存器(参考Cortex M3权威指南)

①:CTRL                 SysTick控制和状态寄存器

位0:ENABLE  使能位:使用Systick定时器需要置1

位1:TICKINT :是否产生中断

位2:CLKSOURCE 时钟源(函数SysTick_CLKSourceConfig进行配置)

位16:COUNTFLAG:读取该位自动清零---->避免误读

对于STM32,外部时钟源是HCLK(AHB总线时钟)的1/8内核时钟是HCLK时钟。

配置函数:SysTick_CLKSourceConfig();

②:LOAD                SysTick 自动重装载除值寄存器

24位重装载寄存器,即使是32位,也只有24位有效

③:VAL                    SysTick 当前值寄存器 

④:CALIB                SysTick 校准值寄存器

7、固件库中的Systick相关函数:

    SysTick_CLKSourceConfig()    //Systick时钟源选择  misc.c文件中
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;
} } static __INLINE uint32_t SysTick_Config(uint32_t ticks) { if (ticks >
SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */ /* set
reload register */ SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; /*
set Priority for Cortex-M0 System Interrupts */ NVIC_SetPriority (SysTick_IRQn,
(1<<__NVIC_PRIO_BITS) - 1); SysTick->VAL = 0; /* Load the SysTick Counter Value
*/ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ return (0);
/* Function successful */ }
    SysTick_Config(uint32_t ticks) //初始化systick,时钟为HCLK,并开启中断     
//core_cm3.h/core_cm4.h文件中(两个中断时间间隔)

8、Systick中断服务函数

void SysTick_Handler(void);

9、用中断的方式实现delay延时
static __IO uint32_t TimingDelay; void Delay(__IO uint32_t nTime) {
TimingDelay = nTime; while(TimingDelay != 0); } void SysTick_Handler(void) { if
(TimingDelay != 0x00) { TimingDelay--; } } int main(void) { … if
(SysTick_Config(SystemCoreClock / 1000)) //systick时钟为HCLK,中断时间间隔1ms { while
(1); } while(1) { Delay(200);//2ms … } }
三、delay延时函数

如果使用中发现延时不一致,问题一般都是因为不同内核时钟不一样而已。修改tciks值即可。
void delay_ms(u16 nms) { u32 temp; SysTick->LOAD=(u32)nms*fac_ms;
//时间加载(SysTick->LOAD为24bit) SysTick->VAL =0x00; //清空计数器
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数 do { temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器 SysTick->VAL =0X00; //清空计数器 }

技术
下载桌面版
GitHub
Gitee
SourceForge
百度网盘(提取码:draw)
云服务器优惠
华为云优惠券
腾讯云优惠券
阿里云优惠券
Vultr优惠券
站点信息
问题反馈
邮箱:[email protected]
吐槽一下
QQ群:766591547
关注微信