博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
寄存器篇学习1
阅读量:6388 次
发布时间:2019-06-23

本文共 4272 字,大约阅读时间需要 14 分钟。

正点原子的寄存器篇的工程,通常由以下文件组成:

Source Group startup_stm32f40_41_xxx.s   启动文件
USER   main.c 用户程序主文件
SYSTEM delay.c usart.c sys.c 原子团队自己写的文件
HARDWARE xxx.c   main.c里面调用的一些函数的申明

接下来分析以下几个固有的文件。

首先是delay.c

1 #include "delay.h"  2 #include "sys.h" 26   27 static u8  fac_us=0;//  us的延时          28 static u16 fac_ms=0;//  ms的延时//把uc_os相关的条件编译去掉后,就只剩下这些了,其实就是定义了初始化和三个延时函数。 一个延时x us(x作为参数传入函数),另两个延时都是ms延时,只是xms这个函数,基本计数单位还是systick,而后面的ms函数,调用了xms函数,延时更长了。 44 void delay_init(u8 SYSCLK) 45 { 49     SysTick->CTRL&=~(1<<2);      50     fac_us=SYSCLK/8;         51          61     fac_ms=(u16)fac_us*1000;  63 }                                    //SysTick是结构体指针,定义在core_cm4.h中: #define SysTick             ((SysTick_Type   *)     SysTick_BASE  ) //SysTick有4个寄存器来控制,见如下:

typedef struct

{
__IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
__IO uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
__IO uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
__I uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
} SysTick_Type;

SysTick_BASE 是寄存器的基地址,后面程序中通过如SysTick->LOAD的操作,完成对寄存器的调用。 后面的函数实现都比较好理解,就不啰嗦了。具体可以查询CPU中对SysTick的介绍
111 void delay_us(u32 nus)112 {        113     u32 temp;             114     if(nus==0)return;            115     SysTick->LOAD=nus*fac_us;    116     SysTick->VAL=0x00;            117     SysTick->CTRL=0x01 ;           118     do119     {120         temp=SysTick->CTRL;121     }while((temp&0x01)&&!(temp&(1<<16))); 122     SysTick->CTRL=0x00;       123     SysTick->VAL =0X00;       124 }131 void delay_xms(u16 nms)132 {                     133     u32 temp;           134     SysTick->LOAD=(u32)nms*fac_ms;135     SysTick->VAL =0x00;           136     SysTick->CTRL=0x01 ;          137     do138     {139         temp=SysTick->CTRL;140     }while((temp&0x01)&&!(temp&(1<<16)));141     SysTick->CTRL=0x00;       142     SysTick->VAL =0X00;       143 } 146 void delay_ms(u16 nms)147 {          148     u8 repeat=nms/540;                          150     u16 remain=nms%540;151     while(repeat)152     {153         delay_xms(540);154         repeat--;155     }156     if(remain)delay_xms(remain);157 }

后面的思路类同,不单独介绍这些文件,只有在main中直接或者间接调用了这些,再回去学习这些函数。

int main(void){     Stm32_Clock_Init(336,8,2,7);  //这个程序在卖家写的sys.c中,这个是对芯片内部时钟树的初始化,对RCC寄存器做了配置。    delay_init(168);         //已经介绍了    LED_Init();   //对GPIO进行配置,也在sys.c中,设置GPIO的各种模式                   while(1)    {        LED0=0;       //对GPIO的置位                  LED1=1;                        delay_ms(500);        LED0=1;                        LED1=0;                        delay_ms(500);    }}

一个小小的例子,引出好多东西,接下来需要了解的是RCC部分,GPIO部分。

下面先介绍时钟初始化做的一些事情:

void Stm32_Clock_Init(u32 plln,u32 pllm,u32 pllp,u32 pllq){      RCC->CR|=0x00000001;        //HISON置位,使能HSI    RCC->CFGR=0x00000000;        //CFGR清零    RCC->CR&=0xFEF6FFFF;        //HSEON,CSSON,PLLON使能     RCC->PLLCFGR=0x24003010;    //PLLCFGR恢复复位值     RCC->CR&=~(1<<18);            //HSEBYP 不旁路HSE振荡器    RCC->CIR=0x00000000;        //禁止RCC中断     Sys_Clock_Set(plln,pllm,pllp,pllq);//设置时钟 在下面框框中介绍}
u8 Sys_Clock_Set(u32 plln,u32 pllm,u32 pllp,u32 pllq){     u16 retry=0;    u8 status=0;    RCC->CR|=1<<16;                //开启HSE    while(((RCC->CR&(1<<17))==0)&&(retry<0X1FFF))retry++;//HSERDY位,等待HSE准备好    if(retry==0X1FFF)status=1;    //计时时间到了,HSE还没准备好    else                           //HSE准备好了,进入这个循环    {        RCC->APB1ENR|=1<<28;    //电源接口时钟使能        PWR->CR|=3<<14;         //高性能模式,频率可达168Mhz        RCC->CFGR|=(0<<4)|(5<<10)|(4<<13); //系统时钟不分频 ,APB1 4分频, APB2 4分频        RCC->CR&=~(1<<24);    //关闭主PLL        RCC->PLLCFGR=pllm|(plln<<6)|(((pllp>>1)-1)<<16)|(pllq<<24)|(1<<22);//配置主PLL,时钟来源与HSE         主要就是配置这个寄存器,HSE是8M进来,设置VCO的分频比N和M,内部系统时钟的PLL输出336M,然后再进一步的分下去。        RCC->CR|=1<<24;            //使能主PLL        while((RCC->CR&(1<<25))==0);//等待主PLL准备好        FLASH->ACR|=1<<8;        //指令预取使能        FLASH->ACR|=1<<9;        //指令cache使能        FLASH->ACR|=1<<10;        //数据cache使能        FLASH->ACR|=5<<0;        // 5个CPU周期        RCC->CFGR&=~(3<<0);        //清零        RCC->CFGR|=2<<0;        //选择主PLL作为系统时钟          while((RCC->CFGR&(3<<2))!=(2<<2));//等待主PLL作为系统时候成功    }     return status;}

 

转载于:https://www.cnblogs.com/nasduc/p/4668937.html

你可能感兴趣的文章
PHP杂记
查看>>
面试题整理10
查看>>
POP跳转页面,从3号跳回1号,
查看>>
[Android] keytools生成jsk文件以及获取sha1码
查看>>
一道算法题
查看>>
qt.network.ssl: QSslSocket: cannot call unresolved function SSLv23_client_method
查看>>
WM-结汇
查看>>
概述--Nginx集成Vcenter 6.X HTML Console系列之 1--(共4)
查看>>
mysql查询重复
查看>>
ORACLE触发器的管理与实际应用【weber出品】
查看>>
C# SQLite
查看>>
JNI_1
查看>>
C#Arcengine通过坐标点生成面(环形)
查看>>
来朗沃后的学习感受
查看>>
Uva 10328 逆向思维
查看>>
(转载)表服务器无法打开与报表服务器数据库的连接。所有请求和处理都要求与数据库建立连接。...
查看>>
团队成员贡献总结
查看>>
MAC下调试JSON接口的工具(HTTP抓包工具)
查看>>
Android设置Gridview中的内容不滚动,然后控件中的内容随便添加的效果。
查看>>
数论 --- 费马小定理 + 快速幂 HDU 4704 Sum
查看>>