西宁网站建设维护,网站域名 空间申请表,室内设计公司排名100,找人做个网站建设制作报价方案一、为什么要会有标志外设库
1、传统单片机软件开发方式 (1)芯片厂商提供数据手册、示例代码、开发环境 (2)单片机软件工程师面向产品功能#xff0c;查阅数据手册#xff0c;参考官方示例代码进行开发 (3)硬件操作的方式是用C语言对寄存器进行读写以操作硬件 (4)主要工作量…一、为什么要会有标志外设库
1、传统单片机软件开发方式 (1)芯片厂商提供数据手册、示例代码、开发环境 (2)单片机软件工程师面向产品功能查阅数据手册参考官方示例代码进行开发 (3)硬件操作的方式是用C语言对寄存器进行读写以操作硬件 (4)主要工作量分2块一是调通各种外设二是实现产品功能 (5)在简单单片机如51单片机上这一套工作的很好但是随着单片机变复杂就带来一些问题 2、外设库有什么价值 (1)外设库其实就是以前芯片公司提供的示例代码的标准化产物 (2)外设库简化了我们开发产品的2大工作量的第一个 (3)外设库以源码方式提供这个源码本身写的很标准可以用作学习素材 3、学习和使用外设库的难点 (1)要有规范化编程的意识和能力 (2)C语言功底要过关 (3)要有一定的框架和层次认识 (4)要会没有外设库时直接C语言操作寄存器的方式看原理图、查数据手册、位操作等 二、外设库的结构介绍和之后的学习方法
1.外设库的结构介绍
(1)最新版本库的下载和解压
官方网站STM32标准外设软件库: 相关产品 (2)建立SourceInsight工程 1先在盘符中建立一个文件夹然后再sourceInsight中打开这个文件夹 (3)文件夹结构和主要文件的作用 1.Project 2.Libraries CMSISSTM32内部ARM核心相关内容 CM3Cortex-M3 CoreSupport 内核相关的一些设置的寄存器集合及其封装 DeviceSupport ST STM32F10x startup起始文件 https://www.cnblogs.com/amanlikethis/p/3989989.html stm32f10x.h【STM32常见数据结构的封装】 system_stm32f10x.c system_stm32f10x.h STM32F10x_StdPeriph_Driver外设驱动 incinclude头文件.h srcsource源文件, .c 2.system_stm32f10x.c 在这个文件中定义了2个函数和一个全局变量时钟相关的 3、后续的学习方法 (1)先搞清楚库对STM32这个硬件的封装和表达方式【对外设进行封装】 (2)再彻底理解库中使用的结构体式访问硬件寄存器的方式 (3)初步建立起面向对象式编程的概念并且去体会 (4)以模块为单位去研究这个模块的库函数并且用库函数去编程并且实验结果并且分析代码去体会去熟悉库函数使用的方法 (5)最终达到什么程度眼里有库心中无库。用人话说就是思维能够穿透库函数直达内部对寄存器的操作。 三、标准库对硬件信息的封装方法
1.寄存器地址的封装
1.手动操作寄存器地址 2.库文件中的寄存器地址stm32f10x.h) 2.寄存器位定义的封装
1.直接通过移位操作位寄存器 2.使用宏定义进行位寄存器 不用直接写数字而使用宏定义 3.外设操作的封装
1.自定义函数 2.使用库函数 .c文件对其进行封装 四、使用结构体方式访问寄存器的原理
1.最原始的方法 1C语言访问寄存器的本质是c语言访问内存本质思路是 定义一个指针指向这块内存然后*pxx这种方式去解引用指针从而向没有标内存中写入内容。 2缺陷当寄存器多了之后每一个寄存器都要定义一套套路很麻烦 3解决思路就是打包批发式定义用结构体为什么不用数组的方式来进行打包。具体方法把整个模块的所有寄存器地址是连续的打包在一个结构体中每一个寄存器对应结构体中的一个元素然后结构体基地址对应寄存器组的基地址将来就可以通过结构体的各个元素来访问各个寄存器了。 2.使用结构体 结构体方式来访问寄存器和指针式访问寄存器本质上其实是一样的区别是c语言的封装不同。 TIM的 GPIO的 五、使用结构体方式访问寄存器的实践
1.原始方式
gpio.h
#define GPIOB_CRH 0x40010C04
#define GPIOB_CRL 0x40010C00
#define GPIOB_ODR 0x40010C0C
#define GPIOB_BSRR 0x40010C10
#define GPIOB_BRR 0x40010C14#define RCC_APB2ENR 0x40021018#define rGPIOB_CRH (*((unsigned int *)GPIOB_CRH))
#define rGPIOB_ODR (*((unsigned int *)GPIOB_ODR))
#define rGPIOB_BSRR (*((unsigned int *)GPIOB_BSRR))
#define rGPIOB_BRR (*((unsigned int *)GPIOB_BRR))
#define rRCC_APB2ENR (*((unsigned int *)RCC_APB2ENR))void led_flash(void);void led_init();
void delay();
gpio.c
/**点亮led灯
*/#include gpio.hvoid delay(){unsigned int i0,j0;for(i0;i1000;i){for(j0;j4000;j){}}
}void led_init(){rRCC_APB2ENR 0x00000008;rGPIOB_CRH 0x33333333;rGPIOB_ODR 0x0000aa00;//全灭}
void led_flash(void){unsigned int i0;for(i0;i3;i){rGPIOB_ODR 0x00000000;//全亮delay();rGPIOB_ODR 0x0000ff00;//全灭delay();}
}
void main(void){led_init();led_flash();
}2.使用结构体的方式对寄存器访问
注意点 我们在定义相关寄存器的结构体的时候要注意顺序问题一定要按照寄存器偏移量从低到高要不然会出现问题。 3.两者对比 代码
gpio.h
#define GPIOB_BASE 0x40010C00
#define GPIOC_BASE 0x40011000#define GPIOB_CRH (GPIOB_BASE 0x04)
#define GPIOB_ODR (GPIOB_BASE 0x0C)
#define GPIOB_BSRR (GPIOB_BASE 0x10)
#define GPIOB_BRR (GPIOB_BASE 0x14)#define GPIOC_CRL (GPIOC_BASE 0x00)
#define GPIOC_ODR (GPIOC_BASE 0x0C)
#define GPIOC_BSRR (GPIOC_BASE 0x10)
#define GPIOC_BRR (GPIOC_BASE 0x14)#define RCC_APB2ENR 0x40021018//-------------------------------------------------#define rGPIOB_CRH (*((unsigned int *)GPIOB_CRH))
#define rGPIOB_ODR (*((unsigned int *)GPIOB_ODR))
#define rGPIOB_BSRR (*((unsigned int *)GPIOB_BSRR))
#define rGPIOB_BRR (*((unsigned int *)GPIOB_BRR))#define rGPIOC_CRL (*((unsigned int *)GPIOC_CRL))
#define rGPIOC_ODR (*((unsigned int *)GPIOC_ODR))
#define rGPIOC_BSRR (*((unsigned int *)GPIOC_BSRR))
#define rGPIOC_BRR (*((unsigned int *)GPIOC_BRR))#define rRCC_APB2ENR (*((unsigned int *)RCC_APB2ENR))//用结构体的方式对寄存器访问
typedef struct{unsigned int CRL;unsigned int CRH;unsigned int IDR;unsigned int ODR;unsigned int BSRR;unsigned int BRR;unsigned int LCKR;
}GPIO_Typedef;void led_flash(void);void led_init();
void delay();
gpio.c
/**点亮led灯
*/#include gpio.hvoid delay(){unsigned int i0,j0;for(i0;i1000;i){for(j0;j4000;j){}}
}/*
原始方法
void led_init(){rRCC_APB2ENR 0x00000008;rGPIOB_CRH 0x33333333;rGPIOB_ODR 0x0000aa00;//隔一个亮一个}
void led_flash(void){unsigned int i0;for(i0;i3;i){rGPIOB_ODR 0x00000000;//全亮delay();rGPIOB_ODR 0x0000ff00;//全灭delay();}
}
*/void led_init(){GPIO_Typedef *p(GPIO_Typedef *)GPIOB_BASE;//因为RCC部分还没有定义结构体所以还是按照原来的方式去操作rRCC_APB2ENR 0x00000008;//结构体只能使用【-】p-CRH0x33333333;p-ODR0x0000aa00;
}
void led_flash(void){GPIO_Typedef *p(GPIO_Typedef *)GPIOB_BASE;unsigned int i0;for(i0;i3;i){p-ODR 0x00000000;//全亮delay();p-ODR 0x0000ff00;//全灭delay();}
}void main(void){led_init();led_flash();
}4.小技巧
1.将基地址指针作为全局变量 因为在每一个函数开始之前都要使用到基地址 2.结构体元素填充 我们前面提到说在定义结构体的时候一定一定要按照寄存器的偏移量从小到大的顺序定义要不然出错但是我们在一些地方可能空缺出来没有寄存器所以我们需要一个占位将其补充要不然后面的其他寄存器可能受到影响。 3.寄存器可操作位数不同 我们在学习RCC时钟的时候遇到一些寄存器可以操作32位但是有一些只能操作16位。此时我们可以将其直接写入不用管是否用足32位也可以分成2个16位写入。 //用结构体的方式对寄存器访问
typedef struct{unsigned int CRL;unsigned int CRH;//unsigned int IDR;//将32位的IDR分为2个16位unsigned short IDR;unsigned short paddingIDR;//此16位用不到unsigned int ODR;unsigned int BSRR;unsigned int BRR;unsigned int LCKR;
}GPIO_Typedef;
六、使用标准库重写LED的程序
1.分析标准库自带的文件模板 1.完整目录 2.User,Driver 3.CMSIS.startup 4.配置注意点 2.stm32f10x.h 选择芯片类型 在“stm32f10x.h”有可以查看要修改可以在options--》c/c中进行修改宏定义 2.宏定义的设置 3.外部晶振时钟设置 3.stm32f10x_conf.h
1.包含所有外设的头文件 这个头文件是标准库的模板中的将所有需要使用到的头文件包含进去 所以在整个工程中无论我们创建一个什么类型的.c文件只要我们定义了 【“stm32f10x.h”】 则就等价于将所有的外设器件的.h文件包含进来了 2.assert_param断言机制 4.正式自己搭建文件目录
1.文件结构 2.文件导入
1.startup 2.CMSIS 3.stdperiph_driver 4.user 3.配置 自定义宏定义在stm32f10x.hstm32f10_conf.h文件中查找 4.出现问题 将配置中的”断言“去除 5.代码修改 #include stm32f10x.h/**使用标准库重写LED的程序
*//*
//原始代码
void led_init(){//GPIO_Typedef *p(GPIO_Typedef *)GPIOB_BASE;//因为RCC部分还没有定义结构体所以还是按照原来的方式去操作rRCC_APB2ENR 0x00000008;//结构体只能使用【-】//p-CRH0x33333333;pGPIOB-CRH0x33333333;//p-ODR0x0000aa00;pGPIOB-ODR0x0000aa00;
}
*///第一步先去”stm32f10x.h文件中查找相关的寄存器
// 比如RCCGPIO
//第二步找到相关的寄存器的宏定义将其直接复制过来//使用HAL库
void led_init(){//GPIO_Typedef *p(GPIO_Typedef *)GPIOB_BASE;//因为RCC部分还没有定义结构体所以还是按照原来的方式去操作RCC-APB2ENR 0x00000008;//结构体只能使用【-】//p-CRH0x33333333;GPIOB-CRH0x33333333;//p-ODR0x0000aa00;GPIOB-ODR0x0000aa00;
}int main(){led_init();return 0;
}
七、RCC模块的标准库全解析
【STM32】RCC时钟模块使用HAL库-CSDN博客
八、CPIO模块的标准库全解析
【STM32】GPIO控制LEDHAL库版-CSDN博客
九、标准库中的面向对象思想
1、面向对象介绍 (1)一种编程思想面向过程、面向对象 (2)什么是对象 (3)面向对象三大特征封装、继承、多态 (4)面向对象编程思想和面向对象语言是两码事 2、标准库的面向对象特征 (1)各种数据类型结构体就是一种封装 (2)标准库是为了被复用 (3)GPIO的编程模式是典型的面向对象式编程 典型面向对象的编程模式 第1步先构建对象可以理解为定义一个结构体类型 第2步用对象构造实例可以理解为用结构体类型来定义结构体变量malloc 第3步填充实例其实就是给结构体的各个元素赋值 第4步使用实例其实就是把结构体变量作为参数传给某个函数使用 第5步销毁实例其实就是把前面第2步定义的机构体变量给销毁掉free