1.为什么需要标准库

1.1、传统单片机软件开发方式

(1)芯片厂商提供数据手册、示例代码、开发环境
(2)单片机软件工程师面向产品功能,查阅数据手册,参考官方示例代码进行开发
(3)硬件操作的方式是用C语言对寄存器进行读写以操作硬件
(4)主要工作量分2块:一是调通各种外设,二是实现产品功能
(5)在简单单片机(如51单片机)上这一套工作的很好,但是随着单片机变复杂就带来一些问题

1.2、外设库有什么价值

(1)外设库其实就是以前芯片公司提供的示例代码的标准化产物
(2)外设库简化了我们开发产品的2大工作量的第一个
(3)外设库以源码方式提供,这个源码本身写的很标准,可以用作学习素材

1.3、学习和使用外设库的难点

(1)要有规范化编程的意识和能力
(2)C语言功底要过关
(3)要有一定的框架和层次认识
(4)要会没有外设库时直接C语言操作寄存器的方式(看原理图、查数据手册、位操作等)

1.4、再次强调

(1)外设库只是帮助我们简化编程,简化的主要是劳动量
(2)外设库一定程度上降低了编程难度,但是只会库、离了库就不会编程、库函数调用出了问题就束手无策这种还是没戏。(难度降低是对所有人的,你并不能从中得到好处)

2.外设库结构介绍

6.标准库引入 - 图1

2.1、文件夹结构和主要文件的作用

CMSIS(STM32内部ARM核心相关内容)
CM3(Cortex-M3)
CoreSupport
内核相关的一些设置的寄存器集合及其封装
DeviceSupport
ST
STM32F10x
startup(起始文件)
stm32f10x.h
system_stm32f10x.c
system_stm32f10x.h
STM32F10x_StdPeriph_Driver(外设驱动)
inc(include,头文件,.h)
src(source,源文件, .c)

2.2 、后续的学习方法

(1)先搞清楚库对STM32这个硬件的封装和表达方式
(2)再彻底理解库中使用的结构体式访问硬件寄存器的方式
(3)初步建立起面向对象式编程的概念并且去体会
(4)以模块为单位去研究这个模块的库函数,并且用库函数去编程,并且实验结果,并且分析代码,去体会去熟悉库函数使用的方法
(5)最终达到什么程度?眼里有库心中无库。用人话说就是:思维能够穿透库函数直达内部对寄存器的操作。

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

  • 寄存器地址的封装
  • 寄存器位定义的封装
  • 外设操作的封装

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

(1)C语言访问寄存器的本质是C语言访问内存,本质思路是:定义一个指针(临时变量)指向这块内存,然后*p = xx这种方式去解引用指针从而向目标内存中写入内容。
(2)缺陷:当寄存器多了之后每一个寄存器都要定义一套套路,很麻烦。
(3)解决思路:就是打包,批发式的定义,用结构体(想一下为什么不用数组?数组只能定义一种变量)的方式进行打包。具体做法是:把整个一个模块的所有寄存器(地址是连接的)打包在一个结构体中,每个寄存器对应结构体中的一个元素,然后结构体基地址对应寄存器组的基地址,将来就可以通过结构体的各个元素来访问各个寄存器了。
(4)结构体方式来访问寄存器和指针式访问寄存器,本质上其实是一样的,区别是C语言的封装不同。语法糖~~

  1. #define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
  2. // GPIOA 指针变量,本身占4个字节,指向一个数据类型是TIM_TypeDef的类型,指向的是一个内存区域
  3. #define GPIOA_BASE (APB2PERIPH_BASE + 0x0800)
  4. //不同端口的寄存器的列表
  5. typedef struct
  6. {
  7. __IO uint32_t CRL; 0
  8. __IO uint32_t CRH; 4
  9. __IO uint32_t IDR; 8
  10. __IO uint32_t ODR; c
  11. __IO uint32_t BSRR;
  12. __IO uint32_t BRR;
  13. __IO uint32_t LCKR;
  14. } GPIO_TypeDef;
  15. // 结构体自动计算偏移量

之前就玩儿过

  1. #ifndef H_GPIO_G
  2. #define H_GPIO_G
  3. typedef unsigned int u32;
  4. #define PERIPH_BASE 0x40000000
  5. #define GPIOG_BASE (PERIPH_BASE + 0x12000)
  6. #define RCC_APB2ENR ((unsigned int *)0x40021018)
  7. typedef struct
  8. {
  9. u32 CRL; //*
  10. u32 CRH; //*
  11. u32 IDR; //*
  12. u32 ODR; //*
  13. u32 BSRR;
  14. u32 BRR; //*
  15. }GPIOG_TypeDef;
  16. #define GPIOG ((GPIOG_TypeDef *)GPIOG_BASE)
  17. #endif

3.外设库的使用

3.1了解基本框架

打开工程模板
image.png

image.png
注意define:这里预先进行了宏定义~~~~
在代码里定义和这里定义功能上是相同的
USE_STDPERIPH_DRIVER, 外设驱动
STM32F10X_HD_VL, 芯片的选择
USE_STM32100E_EVAL 工程实例

如果打开stm3210x.h
这里同上,需要哪个启动代码,打开哪个,也可在工程中配置,如上图。

  1. #if !defined (STM32F10X_LD) && !defined (STM32F10X_LD_VL) && !defined (STM32F10X_MD) && !defined (STM32F10X_MD_VL) && !defined (STM32F10X_HD) && !defined (STM32F10X_HD_VL) && !defined (STM32F10X_XL) && !defined (STM32F10X_CL)
  2. /* #define STM32F10X_LD */ /*!< STM32F10X_LD: STM32 Low density devices */
  3. /* #define STM32F10X_LD_VL */ /*!< STM32F10X_LD_VL: STM32 Low density Value Line devices */
  4. /* #define STM32F10X_MD */ /*!< STM32F10X_MD: STM32 Medium density devices */
  5. /* #define STM32F10X_MD_VL */ /*!< STM32F10X_MD_VL: STM32 Medium density Value Line devices */
  6. /* #define STM32F10X_HD */ /*!< STM32F10X_HD: STM32 High density devices */
  7. /* #define STM32F10X_HD_VL */ /*!< STM32F10X_HD_VL: STM32 High density value line devices */
  8. /* #define STM32F10X_XL */ /*!< STM32F10X_XL: STM32 XL-density devices */
  9. /* #define STM32F10X_CL */ /*!< STM32F10X_CL: STM32 Connectivity line devices */
  10. #endif

上面两个都可以使用

头文件包含:
因此只要包含了stm3210x.h,就包含了所有的头文件

  1. #ifdef USE_STDPERIPH_DRIVER
  2. #include "stm32f10x_conf.h" //包含所有外设头文件
  3. #endif
  4. #include "stm32f10x_adc.h"
  5. #include "stm32f10x_bkp.h"
  6. #include "stm32f10x_can.h"
  7. #include "stm32f10x_cec.h"
  8. #include "stm32f10x_crc.h"
  9. #include "stm32f10x_dac.h"
  10. #include "stm32f10x_dbgmcu.h"
  11. #include "stm32f10x_dma.h"
  12. #include "stm32f10x_exti.h"
  13. #include "stm32f10x_flash.h"
  14. #include "stm32f10x_fsmc.h"
  15. #include "stm32f10x_gpio.h"
  16. #include "stm32f10x_i2c.h"
  17. #include "stm32f10x_iwdg.h"
  18. #include "stm32f10x_pwr.h"
  19. #include "stm32f10x_rcc.h"
  20. #include "stm32f10x_rtc.h"
  21. #include "stm32f10x_sdio.h"
  22. #include "stm32f10x_spi.h"
  23. #include "stm32f10x_tim.h"
  24. #include "stm32f10x_usart.h"
  25. #include "stm32f10x_wwdg.h"
  26. #include "misc.h" /* High level functions for NVIC and SysTick (add-on to CMSIS functions) */

断言配置
如果定义了USE_FULL_ASSERT 就会使用

  1. #ifdef USE_FULL_ASSERT
  2. /**
  3. * @brief The assert_param macro is used for function's parameters check.
  4. * @param expr: If expr is false, it calls assert_failed function which reports
  5. * the name of the source file and the source line number of the call
  6. * that failed. If expr is true, it returns no value.
  7. * @retval None
  8. */
  9. #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
  10. /* Exported functions ------------------------------------------------------- */
  11. void assert_failed(uint8_t* file, uint32_t line);
  12. #else
  13. #define assert_param(expr) ((void)0)
  14. #endif /* USE_FULL_ASSERT */

3.2标准库配置

image.png
库移植成功后,我们原来的代码也可以直接使用

  1. #include "stm32f10x.h"
  2. void led_init(void);
  3. void Delay(void);
  4. void flash(void);
  5. int main(void)
  6. {
  7. led_init();
  8. while(1)
  9. {
  10. flash();
  11. };
  12. return 0;
  13. }
  14. void led_init(void)
  15. {
  16. RCC->APB2ENR = 0x00000100;
  17. GPIOG->CRL = (0x33 << 24);
  18. }
  19. void Delay(void)
  20. {
  21. unsigned int i = 0, j = 0;
  22. for( i = 0; i < 2000; i++)
  23. {
  24. for( j = 0; j < 2000; j++);
  25. }
  26. }
  27. void flash(void)
  28. {
  29. GPIOG->BSRR = 0x000000080;
  30. Delay();
  31. GPIOG->BSRR = 0x00000040;
  32. Delay();
  33. GPIOG->BSRR = 0x00ff0000;
  34. Delay();
  35. }