掌握的标准:
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,一个枚举量这是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.使用实例
TRANSLATE with x English TRANSLATE with COPY THE URL BELOW Back EMBED THE SNIPPET BELOW IN YOUR SITE Enable collaborative features and customize widget: Bing Webmaster Portal Back 此页面的语言为中文(简体) 翻译为- 中文(简体)
- 中文(繁体)
- 丹麦语
- 乌克兰语
- 乌尔都语
- 亚美尼亚语
- 俄语
- 保加利亚语
- 克罗地亚语
- 冰岛语
- 加泰罗尼亚语
- 匈牙利语
- 卡纳达语
- 印地语
- 印尼语
- 古吉拉特语
- 哈萨克语
- 土耳其语
- 威尔士语
- 孟加拉语
- 尼泊尔语
- 布尔语(南非荷兰语)
- 希伯来语
- 希腊语
- 库尔德语
- 德语
- 意大利语
- 拉脱维亚语
- 挪威语
- 捷克语
- 斯洛伐克语
- 斯洛文尼亚语
- 旁遮普语
- 日语
- 普什图语
- 毛利语
- 法语
- 波兰语
- 波斯语
- 泰卢固语
- 泰米尔语
- 泰语
- 海地克里奥尔语
- 爱沙尼亚语
- 瑞典语
- 立陶宛语
- 缅甸语
- 罗马尼亚语
- 老挝语
- 芬兰语
- 英语
- 荷兰语
- 萨摩亚语
- 葡萄牙语
- 西班牙语
- 越南语
- 阿塞拜疆语
- 阿姆哈拉语
- 阿尔巴尼亚语
- 阿拉伯语
- 韩语
- 马尔加什语
- 马拉地语
- 马拉雅拉姆语
- 马来语
- 马耳他语
- 高棉语