stm32F4学习笔记03-System文件夹下delay.c sys.c usart.c实现原理解析。

    今天学习一下正点原子的工程System文件夹delay.c sys.c usart.c源文件实现的原理

    1.delay.c

           delay_init()函数

 1 //初始化延迟函数
 2 //当使用OS的时候,此函数会初始化OS的时钟节拍
 3 //SYSTICK的时钟固定为AHB时钟的1/8
 4 //SYSCLK:系统时钟频率
 5 void delay_init(u8 SYSCLK)
 6 {
 7 #if SYSTEM_SUPPORT_OS                       //如果需要支持OS.
 8     u32 reload;
 9 #endif
10      SysTick->CTRL&=~(1<<2);                //SYSTICK使用外部时钟源     
11     fac_us=SYSCLK/8;                        //不论是否使用OS,fac_us都需要使用
12 #if SYSTEM_SUPPORT_OS                       //如果需要支持OS.
13     reload=SYSCLK/8;                        //每秒钟的计数次数 单位为M       
14     reload*=1000000/delay_ostickspersec;    //根据delay_ostickspersec设定溢出时间
15                                             //reload为24位寄存器,最大值:16777216,在168M下,约合0.7989s左右    
16     fac_ms=1000/delay_ostickspersec;        //代表OS可以延时的最少单位       
17     SysTick->CTRL|=1<<1;                    //开启SYSTICK中断
18     SysTick->LOAD=reload;                   //每1/delay_ostickspersec秒中断一次    
19     SysTick->CTRL|=1<<0;                    //开启SYSTICK    
20 #else
21     fac_ms=(u16)fac_us*1000;                //非OS下,代表每个ms需要的systick时钟数   
22 #endif
23 }    

使用了条件编译的方法,在不支持OS的条件下,函数主要干了这几件事:设置了Sysstick的时钟源为外部时钟源
因为systick的固定时钟为AHB时钟的1/8,所以每个fac_us可以看成每个us时钟需要滴答的节拍数。
同理fac_ms = fac_us*1000也是一样的道理;
关于systick的学习:
通过代码跟踪:
1 #define SysTick       ((SysTick_Type   *)     SysTick_BASE  )       
2 
3 #define SysTick_BASE        (SCS_BASE +  0x0010UL) 
4 
5 #define SCS_BASE            (0xE000E000UL)       

   通过翻阅《Cortex-M3与M4权威指南》一书P135页  Memory Map 0xE0000000 - 0xFFFFFFFF 为system的Private Peripherqal Bus 中间有那么一段地址空间(0XE000E000-0XE000EFFF),4KB的空间是System Control Space(SCS)的地址范围。

   截取部分文档所说:The NVIC and SCB are located inside the System Control Space (SCS) address range from 0xE000E000, with a size of 4KB. The   SCS also contains registers for the SysTick timer, Memory Protection Unit (MPU), debug registers, etc. Almost all of the registers in this   address range can only be accessed by code running in privileged access level. The only exception is a register called the Software Trigge  -r Interrupt Register (STIR), which can be set up to be accessible in unprivileged mode.

  红色的字体表示 也就是4KB的空间包括了systick timer寄存器配置。进一步查找  SCS_BASE + 0X0010 = 0XE000E010

  在P350页中也有说明  该地址是systick->CTRL寄存器的地址

 

 

  delay_us()函数的实现
 1 //延时nus
 2 //nus为要延时的us数.    
 3 //注意:nus的值,不要大于798915us(最大值即2^24/fac_us@fac_us=21)
 4 void delay_us(u32 nus)
 5 {        
 6     u32 temp;             
 7     SysTick->LOAD=nus*fac_us;                 //时间加载               
 8     SysTick->VAL=0x00;                        //清空计数器
 9     SysTick->CTRL=0x01 ;                      //开始倒数      
10     do
11     {
12         temp=SysTick->CTRL;
13     }while((temp&0x01)&&!(temp&(1<<16)));    //等待时间到达   
14     SysTick->CTRL=0x00;                       //关闭计数器
15     SysTick->VAL =0X00;                       //清空计数器 
16 }

简单的定时器使用,这里简要说明一下。
LOAD寄存器装载的是需要定时的节拍数。
VAL寄存器装载的是当前定时器内容的值,所以需要清零。
CTRL寄存器的第0位是定时器的使能位 第15位为定时器定时时间到的标志位 置一。
delay_ms的实现和delay_us的实现相似,但是需要注意的是定时的Ms必须小于798ms




 

sys.c

Stm32_Clock_Set()函数

 1 //时钟设置函数
 2 //Fvco=Fs*(plln/pllm);
 3 //Fsys=Fvco/pllp=Fs*(plln/(pllm*pllp));
 4 //Fusb=Fvco/pllq=Fs*(plln/(pllm*pllq));
 5 
 6 //Fvco:VCO频率
 7 //Fsys:系统时钟频率
 8 //Fusb:USB,SDIO,RNG等的时钟频率
 9 //Fs:PLL输入时钟频率,可以是HSI,HSE等. 
10 //plln:主PLL倍频系数(PLL倍频),取值范围:64~432.
11 //pllm:主PLL和音频PLL分频系数(PLL之前的分频),取值范围:2~63.
12 //pllp:系统时钟的主PLL分频系数(PLL之后的分频),取值范围:2,4,6,8.(仅限这4个值!)
13 //pllq:USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频),取值范围:2~15.
14 
15 //外部晶振为8M的时候,推荐值:plln=336,pllm=8,pllp=2,pllq=7.
16 //得到:Fvco=8*(336/8)=336Mhz
17 //     Fsys=336/2=168Mhz
18 //     Fusb=336/7=48Mhz
19 //返回值:0,成功;1,失败。
20 u8 Sys_Clock_Set(u32 plln,u32 pllm,u32 pllp,u32 pllq)
21 { 
22     u16 retry=0;
23     u8 status=0;
24     RCC->CR|=1<<16;                //HSE 开启 
25     while(((RCC->CR&(1<<17))==0)&&(retry<0X1FFF))retry++;//等待HSE RDY
26     if(retry==0X1FFF)status=1;    //HSE无法就绪
27     else   
28     {
29         RCC->APB1ENR|=1<<28;    //电源接口时钟使能
30         PWR->CR|=3<<14;         //高性能模式,时钟可到168Mhz
31         RCC->CFGR|=(0<<4)|(5<<10)|(4<<13);//HCLK 不分频;APB1 4分频;APB2 2分频. 
32         RCC->CR&=~(1<<24);    //关闭主PLL
33         RCC->PLLCFGR=pllm|(plln<<6)|(((pllp>>1)-1)<<16)|(pllq<<24)|(1<<22);//配置主PLL,PLL时钟源来自HSE
34         RCC->CR|=1<<24;            //打开主PLL
35         while((RCC->CR&(1<<25))==0);//等待PLL准备好 
36         FLASH->ACR|=1<<8;        //指令预取使能.
37         FLASH->ACR|=1<<9;        //指令cache使能.
38         FLASH->ACR|=1<<10;        //数据cache使能.
39         FLASH->ACR|=5<<0;        //5个CPU等待周期. 
40         RCC->CFGR&=~(3<<0);        //清零
41         RCC->CFGR|=2<<0;        //选择主PLL作为系统时钟     
42         while((RCC->CFGR&(3<<2))!=(2<<2));//等待主PLL作为系统时钟成功. 
43     } 
44     return status;
45 }  

 

Stm32_Clock_Init()函数

STM32F4时钟介绍:(参考STM32F4英文参考手册)

SYSCLK的时钟来源:                            

   HSI oscillator clock   High Speed Internal clock

   HSE oscillator clock   High Speed External clock

   PLL clock         锁相环时钟电路

第二时钟源:                                   用途

    LSI(32KHZ)            Low Speed Internal clock      watchdog RTC used for Auto Wakeup

   LSE(32.768KHZ)      Low Speed External clock      drivers RTC(RTCCLK)

 

    


 

 

  





















  






















 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

    

转载于:https://www.cnblogs.com/xiaoqi254789/articles/6826870.html

你可能感兴趣的:(stm32F4学习笔记03-System文件夹下delay.c sys.c usart.c实现原理解析。)