外设库价值
- 外设库即以前芯片公司提供的示例代码的标准化产物
- 外设库简化了我们开发产品的工作量
- 外设库以源码方式提供,且可以用作学习素材
学习和使用重点
- 规范化编程的意识和能力
- C语言要求
- 对框架和层次认识
- 掌握没有外设库时直接C语言操作寄存器的方式(看原理图、查数据手册、位操作等)
外设库只是帮助我们简化编程,简化的主要是劳动量,一定程度上降低编程难度,但不应停留在只会库的情况上。
外设库结构介绍
我是从官网上下载的最新库函数(下载时间:2020.07.05)
-
CMSIS(STM32内部ARM核心相关内容)
Core 内核相关的一些设置的寄存器集合及其封装
Device 重要! -
STM32F10x_StdPeriph_Driver(外设驱动)
inc(include,头文件.h)
src(source,源文件.c)
标准库对硬件信息的封装方式
- 寄存器地址封装
- 寄存器位定义的封装
- 外设操作的封装
使用结构体方式访问寄存器
- C语言访问寄存器的本质是C语言访问内存
实现:定义一个指针(临时变量)指向这块内存,然后*p = xx这种方式去解引用指针从而向目标内存中写入内容 - 缺陷:麻烦
- 解决思路:用结构体的方式定义。
实现:把整个模块的所有寄存器(地址连续)写在一个结构体中,每个寄存器对应结构体中的一个元素,结构体基地址对应寄存器组的基地址,通过结构体的各个元素来访问各个寄存器。 - 结构体方式来访问寄存器和指针式访问寄存器,本质一样,但C语言封装不同。
代码练习
#define GPIOB_BASE 0x40010C00
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_init(void)
{
GPIO_Typedef *pGPIOB = (GPIO_Typedef *)GPIOB_BASE;
rRCC_APB2ENR = 0x00000008;
pGPIOB->CRH = 0x33333333;
pGPIOB->ODR = 0x0000AA00; //结构体方式访问内存
}
RCC模块标准库分析
(在rcc.c文件中定义宏是防止被其他文件调用)
//定义RCC各个位地址
/* ------------ RCC registers bit address in the alias region ----------- */
#define RCC_OFFSET (RCC_BASE - PERIPH_BASE)
/* --- CR Register ---*/
/* Alias word address of HSION bit */
#define CR_OFFSET (RCC_OFFSET + 0x00)
#define HSION_BitNumber 0x00
#define CR_HSION_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (HSION_BitNumber * 4))
/* Alias word address of PLLON bit */
#define PLLON_BitNumber 0x18
#define CR_PLLON_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (PLLON_BitNumber * 4))
#ifdef STM32F10X_CL
/* Alias word address of PLL2ON bit */
#define PLL2ON_BitNumber 0x1A
#define CR_PLL2ON_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (PLL2ON_BitNumber * 4))
/* Alias word address of PLL3ON bit */
#define PLL3ON_BitNumber 0x1C
#define CR_PLL3ON_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (PLL3ON_BitNumber * 4))
#endif /* STM32F10X_CL */
/* Alias word address of CSSON bit */
#define CSSON_BitNumber 0x13
#define CR_CSSON_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (CSSON_BitNumber * 4))
/* --- CFGR Register ---*/
/* Alias word address of USBPRE bit */
#define CFGR_OFFSET (RCC_OFFSET + 0x04)
#ifndef STM32F10X_CL
#define USBPRE_BitNumber 0x16
#define CFGR_USBPRE_BB (PERIPH_BB_BASE + (CFGR_OFFSET * 32) + (USBPRE_BitNumber * 4))
#else
#define OTGFSPRE_BitNumber 0x16
#define CFGR_OTGFSPRE_BB (PERIPH_BB_BASE + (CFGR_OFFSET * 32) + (OTGFSPRE_BitNumber * 4))
#endif /* STM32F10X_CL */
/* --- BDCR Register ---*/
/* Alias word address of RTCEN bit */
#define BDCR_OFFSET (RCC_OFFSET + 0x20)
#define RTCEN_BitNumber 0x0F
#define BDCR_RTCEN_BB (PERIPH_BB_BASE + (BDCR_OFFSET * 32) + (RTCEN_BitNumber * 4))
/* Alias word address of BDRST bit */
#define BDRST_BitNumber 0x10
#define BDCR_BDRST_BB (PERIPH_BB_BASE + (BDCR_OFFSET * 32) + (BDRST_BitNumber * 4))
/* --- CSR Register ---*/
/* Alias word address of LSION bit */
#define CSR_OFFSET (RCC_OFFSET + 0x24)
#define LSION_BitNumber 0x00
#define CSR_LSION_BB (PERIPH_BB_BASE + (CSR_OFFSET * 32) + (LSION_BitNumber * 4))
#ifdef STM32F10X_CL
/* --- CFGR2 Register ---*/
/* Alias word address of I2S2SRC bit */
#define CFGR2_OFFSET (RCC_OFFSET + 0x2C)
#define I2S2SRC_BitNumber 0x11
#define CFGR2_I2S2SRC_BB (PERIPH_BB_BASE + (CFGR2_OFFSET * 32) + (I2S2SRC_BitNumber * 4))
/* Alias word address of I2S3SRC bit */
#define I2S3SRC_BitNumber 0x12
#define CFGR2_I2S3SRC_BB (PERIPH_BB_BASE + (CFGR2_OFFSET * 32) + (I2S3SRC_BitNumber * 4))
#endif /* STM32F10X_CL */
//定义RCC寄存器的位掩码
/* ---------------------- RCC registers bit mask ------------------------ */
/* CR register bit mask */
#define CR_HSEBYP_Reset ((uint32_t)0xFFFBFFFF)
#define CR_HSEBYP_Set ((uint32_t)0x00040000)
#define CR_HSEON_Reset ((uint32_t)0xFFFEFFFF)
#define CR_HSEON_Set ((uint32_t)0x00010000)
#define CR_HSITRIM_Mask ((uint32_t)0xFFFFFF07)
/* CFGR register bit mask */
#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) || defined (STM32F10X_CL)
#define CFGR_PLL_Mask ((uint32_t)0xFFC2FFFF)
#else
#define CFGR_PLL_Mask ((uint32_t)0xFFC0FFFF)
#endif /* STM32F10X_CL */
#define CFGR_PLLMull_Mask ((uint32_t)0x003C0000)
#define CFGR_PLLSRC_Mask ((uint32_t)0x00010000)
#define CFGR_PLLXTPRE_Mask ((uint32_t)0x00020000)
#define CFGR_SWS_Mask ((uint32_t)0x0000000C)
#define CFGR_SW_Mask ((uint32_t)0xFFFFFFFC)
#define CFGR_HPRE_Reset_Mask ((uint32_t)0xFFFFFF0F)
#define CFGR_HPRE_Set_Mask ((uint32_t)0x000000F0)
#define CFGR_PPRE1_Reset_Mask ((uint32_t)0xFFFFF8FF)
#define CFGR_PPRE1_Set_Mask ((uint32_t)0x00000700)
#define CFGR_PPRE2_Reset_Mask ((uint32_t)0xFFFFC7FF)
#define CFGR_PPRE2_Set_Mask ((uint32_t)0x00003800)
#define CFGR_ADCPRE_Reset_Mask ((uint32_t)0xFFFF3FFF)
#define CFGR_ADCPRE_Set_Mask ((uint32_t)0x0000C000)
/* CSR register bit mask */
#define CSR_RMVF_Set ((uint32_t)0x01000000)
#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) || defined (STM32F10X_CL)
/* CFGR2 register bit mask */
#define CFGR2_PREDIV1SRC ((uint32_t)0x00010000)
#define CFGR2_PREDIV1 ((uint32_t)0x0000000F)
#endif
#ifdef STM32F10X_CL
#define CFGR2_PREDIV2 ((uint32_t)0x000000F0)
#define CFGR2_PLL2MUL ((uint32_t)0x00000F00)
#define CFGR2_PLL3MUL ((uint32_t)0x0000F000)
#endif /* STM32F10X_CL */
/* RCC Flag Mask */
#define FLAG_Mask ((uint8_t)0x1F)
/* CIR register byte 2 (Bits[15:8]) base address */
#define CIR_BYTE2_ADDRESS ((uint32_t)0x40021009)
/* CIR register byte 3 (Bits[23:16]) base address */
#define CIR_BYTE3_ADDRESS ((uint32_t)0x4002100A)
/* CFGR register byte 4 (Bits[31:24]) base address */
#define CFGR_BYTE4_ADDRESS ((uint32_t)0x40021007)
/* BDCR register base address */
#define BDCR_ADDRESS (PERIPH_BASE + BDCR_OFFSET)
static __I uint8_t APBAHBPrescTable[16] = {0, 0, 0, 0, 1, 2, 3, 4, 1, 2, 3, 4, 6, 7, 8, 9};
static __I uint8_t ADCPrescTable[4] = {2, 4, 6, 8};
//RCC_DeInit函数,去初始化(无参数,无返回值)
void RCC_DeInit(void)
{
/* Set HSION bit */
RCC->CR |= (uint32_t)0x00000001;
/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
#ifndef STM32F10X_CL
RCC->CFGR &= (uint32_t)0xF8FF0000;
#else
RCC->CFGR &= (uint32_t)0xF0FF0000;
#endif /* STM32F10X_CL */
/* Reset HSEON, CSSON and PLLON bits */
RCC->CR &= (uint32_t)0xFEF6FFFF;
/* Reset HSEBYP bit */
RCC->CR &= (uint32_t)0xFFFBFFFF;
/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
RCC->CFGR &= (uint32_t)0xFF80FFFF;
#ifdef STM32F10X_CL
/* Reset PLL2ON and PLL3ON bits */
RCC->CR &= (uint32_t)0xEBFFFFFF;
/* Disable all interrupts and clear pending bits */
RCC->CIR = 0x00FF0000;
/* Reset CFGR2 register */
RCC->CFGR2 = 0x00000000;
#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL)
/* Disable all interrupts and clear pending bits */
RCC->CIR = 0x009F0000;
/* Reset CFGR2 register */
RCC->CFGR2 = 0x00000000;
#else
/* Disable all interrupts and clear pending bits */
RCC->CIR = 0x009F0000;
#endif /* STM32F10X_CL */
}
//配置HSE模块,通过传递要求的三个宏对此模块操作
void RCC_HSEConfig(uint32_t RCC_HSE)
{
/* Check the parameters */
assert_param(IS_RCC_HSE(RCC_HSE)); //检查用户调用时传参是否正确
/* Reset HSEON and HSEBYP bits before configuring the HSE ------------------*/
/* Reset HSEON bit */
RCC->CR &= CR_HSEON_Reset;
/* Reset HSEBYP bit */
RCC->CR &= CR_HSEBYP_Reset;
/* Configure HSE (RCC_HSE_OFF is already covered by the code section above) */
switch(RCC_HSE)
{
case RCC_HSE_ON:
/* Set HSEON bit */
RCC->CR |= CR_HSEON_Set;
break;
case RCC_HSE_Bypass: //通过查找数据手册,了解Bypass
/* Set HSEBYP and HSEON bits */
RCC->CR |= CR_HSEBYP_Set | CR_HSEON_Set;
break;
default:
break;
}
}
assert(断言):C语言里用来判断使用是否正确,正确则忽略,错误则显示提示(warrning error)
断言机制常用于检查用户调用该库函数时传参是否符合要求
推荐详细描述1
推荐详细描述2
/* Exported macro ------------------------------------------------------------*/
#ifdef USE_FULL_ASSERT
/**
* @brief The assert_param macro is used for function's parameters check.
* @param expr: If expr is false, it calls assert_failed function which reports
* the name of the source file and the source line number of the call
* that failed. If expr is true, it returns no value.
* @retval None
*/
#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
/* Exported functions ------------------------------------------------------- */
void assert_failed(uint8_t* file, uint32_t line);
#else
#define assert_param(expr) ((void)0)
#endif /* USE_FULL_ASSERT */
//此函数实现需用户自定义
void assert_failed(uint8_t* file, uint32_t line)
{
//断言错误报错方法可用户自定义
//用户可使用#error等方式在编译时报错(报错前提断言表达式在预处理是有结果)
//常见方式是用户在运行时用printf打印调试信息方式报错
printf(“Wrong parameters value: file %s on line %d\r\n”, file, line) / / Infinite loop */
}