STM32完全学习3:标准库

掌握的标准:

1.搞清楚库对STM32硬件的封装和表达方式

2.彻底理解苦衷使用的结构体式访问硬件寄存器的方式

3.初步建立起面向对象式编程的概念

4.以模块为单位去研究模块的库函数,并且用库函数编程,实验结果,分析代码,从而熟悉库函数的使用方法

5.思维能够穿透库函数直达内部对寄存器的操作

 标准库——方便,由芯片厂商提供数据手册、示例代码、开发环境

整体框架和层次认识,要会没有外设库时C语言直接操作寄存器的方式(看原理图,查数据手册,位操作等)

 

规范化编程的意识和能力

C语言基础

 

 

 

外设库的结构介绍:

固件库的架构

CMSIS: ARM核心相关内容,大部分由ARM公司决定

  CoreSupport:内核相关的寄存器集合及封装

  DeviceSupport:startup起始代码

 

STM32F10x_StdPeriph_Driver:外设驱动

  inc(include,头文件,.h)

  src(source,源文件,.c)

 预先定义了各种寄存器的基地址,可以直接使用

 

标准库对硬件信息的封装方式

1. 寄存器地址的封装

2.寄存器位定义的封装

3.外设操作的封装 

 

宏定义和API(帮助手册或者源码 )

使用结构体的方式访问寄存器的原理

寄存器的版本:使用C语言访问内存地址,并且赋值

C语言访问寄存器的本质是C语言访问内存,本质思路是定义一个指针(临时变量)指向这块内存,然后解引用*p = xx这种方式去解引用指针,从而向目标内存中写入内容。

缺陷:当寄存器多了之后,每一个寄存器都需要定义,很麻烦

解决思路:打包成结构体,用结构体批量定义。

why:不用数组?

个人理解:使用数组,每个元素之间的距离都是固定的数据类型大小,不能进行数据填充或者调整。

具体做法:把整个模块的所有寄存器(地址相邻)打包在同一个结构体中,每个寄存器对应结构体中的一个元素,然后结构体的基地址对应寄存器组的基地址。

定义了一个结构体,结构体中的数据类型占据大小和寄存器地址对应。

使用结构体的方式访问寄存器的实践

复制代码
typedef struct{
    volatile unsigned int CRL;
    volatile unsigned int CRH;
    volatile unsigned int IDR;
    volatile unsigned int ODR;
    volatile unsigned int BSRR;
    volatile unsigned int BRR;
    volatile unsigned int LCKR;
}LED_Typedef;
复制代码

结构体对齐问题需要考虑,如果存在为空的部分,需要填充padding。或者直接定义一个比较长的结构,只使用低X位或者高X位。

使用标准库重写LED的程序

void LED_Init(){
    RCC->APB2ENR = 0x00000010;
    GPIOC->ODR = 0x00000000;
    GPIOC->ODR = 0x000000aa;
}

对硬件进行了封装

 RCC模块的标准库解析

 位带操作:将其中一位对应到一个u32的区域,bitband操作

 bit mask:位掩码,事先把设定的数提前封装好。
 RCC_Define()和RCC_HSEConfig()
 枚举可以限制参数范围,或者使用assert_param()进行判断——assert机制是c语言中判断对错的工具,使用最多的场景就是判断库函数中传参对不对。
bypass:直接提供了一个外部时钟。
RCC_WaitForHSEStartUp(),返回值为errorstatus,一个枚举量
1
2
3
4
这是ST库里面的宏定义,定义如下: 
#define __I volatile const  /*!< defines 'read only' permissions*/
#define  __O  volatile      /*  !< defines 'write only' permissions  */
#define __IO  volatile      /* !< defines 'read / write' permissions */

RCC_AdjustHSICalibrationValue()校准

RCC_HSICmd()

 

使用库函数重写系统时钟设定

   
复制代码
void SysClick_Init(){
    ErrorStatus hse_status;
    //1.开启外部时钟HSE
    RCC_HSEConfig(RCC_HSE_ON);
    //等待HSEON稳定
    hse_status = RCC_WaitForHSEStartUp();
    if(hse_status==SUCCESS){
        FLASH->ACR |= 0x10;
        FLASH->ACR &= (~0x03);
        FLASH->ACR |= 0x02;
        
        //2.设置PLL,HB和APB2未分频,APB1被2分频,
        //配置HCLK为SYSCLK/1;
        RCC_HCLKConfig(RCC_SYSCLK_Div1);
        //APB1被2分频,APB2为HCLK/1
        RCC_PCLK1Config(RCC_HCLK_Div2);
        RCC_PCLK2Config(RCC_HCLK_Div1);
        //选择HSE/1为时钟源,同时设置频率为9倍
        RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9);
        //打开PLL开关
        RCC_PLLCmd(ENABLE);
        //等待PLL稳定
        while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET);
        //切换系统时钟为PLLCLK
        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
        while(RCC_GetSYSCLKSource()!=0x08);
    }else while(1);
        
}
复制代码

 

 GPIO库解析

标准库中的面向对象的思想

面向对象的三大特征:封装,继承和多态。

各种数据类型结构体就是一种封装。

标准库就是为了被复用。

GPIO的编程模式是典型的面向对象式编程。

步骤:

1.先构造对象

2.用对象构造实例

3.填充实例

4.使用实例

 
 
 
posted @   zxkic  阅读(296)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
点击右上角即可分享
微信分享提示