库函数皱形

图为  储存器对应控制GPIO 以及时钟外设等地址函数

编写库函数时  使用到了C语言的强制转换,将指针指向向对应的GPIO外设和时钟等地址,避免了相似寄存器学要多个定义每一个特有功能的寄存器。ui

比较以下:指针

库函数原理

#ifndef stm32__H__
#define stm32__H__
#define PERIPH_BASE ((unsigned int)0x40000000)  //stmf103外设总基地址
#define AHBPERIPH_BASE  (PERIPH_BASE+0x20000)
#define APB1PERIPH_BASE (PERIPH_BASE)
#define APB2PERIPH_BASE (PERIPH_BASE+0x10000)
#define RCC_BASE        (AHBPERIPH_BASE+0x1000)
#define GPIOB_BASE      (APB2PERIPH_BASE+0x0c00)
#define uint_32t  unsigned int 
#define uint_16t  unsigned short
#define uint_8t   unsigned char
typedef struct{
    uint_32t CRL;
    uint_32t CRH;
    uint_32t IDR;
    uint_32t ODR;
    uint_32t BSRR;
    uint_32t BRR;
    uint_32t LCKR;
}GPIO_Typedef;
typedef struct{
 uint_32t RCC_CR;
 uint_32t    RCC_CFGR;
 uint_32t RCC_CIR;
 uint_32t RCC_APB2RSTR;
 uint_32t RCC_APB1RSTR;
 uint_32t RCC_AHBENR;
 uint_32t RCC_APB2ENR;
 uint_32t RCC_APB1ENR;
 uint_32t RCC_BDCR;
 uint_32t RCC_CSR;
 uint_32t RCC_AHBRSTR;
}RCC_Typedef;im

#define  GPIOB ((GPIO_Typedef*)(GPIOB_BASE))
#define  RCC   ((RCC_Typedef*)(RCC_BASE))img

#endif
 语言

寄存器di

#ifndef  STM32_H
#define  STM32_H
#define  PERIPH_BASE   ((unsigned int)0x40000000)
#define  APB1PERIPH    PERIPH_BASE
#define  AHBPERIPH_BASE (PERIPH_BASE+0x20000)
#define  APB2PERIPH_BASE   (PERIPH_BASE+0x10000)
#define  RCC_BASE      (AHBPERIPH_BASE+0x1000)
//基地址
#define  GPIOA_BASE  (APB2PERIPH_BASE+0x0800)
#define  GPIOB_BASE  (APB2PERIPH_BASE+0x0c00)
#define  GPIOC_BASE  (APB2PERIPH_BASE+0x1000)
#define  GPIOD_BASE  (APB2PERIPH_BASE+0x1400)
#define  GPIOE_BASE  (APB2PERIPH_BASE+0x1800)
#define  GPIOF_BASE  (APB2PERIPH_BASE+0x2c00)
#define  GPIOG_BASE  (APB2PERIPH_BASE+0x3000)工作

#define  RCC_APB2ENR *(unsigned int*)(RCC_BASE+0x18)结构体

//低位寄存器
#define  GPIOA_CRL   *(unsigned int*)(GPIOA_BASE+0x00)
#define  GPIOB_CRL   *(unsigned int*)(GPIOB_BASE+0x00)
#define  GPIOC_CRL   *(unsigned int*)(GPIOC_BASE+0x00)
#define  GPIOD_CRL   *(unsigned int*)(GPIOD_BASE+0x00) 
#define  GPIOE_CRL   *(unsigned int*)(GPIOE_BASE+0x00)
#define  GPIOF_CRL   *(unsigned int*)(GPIOF_BASE+0x00)
#define  GPIOG_CRL   *(unsigned int*)(GPIOG_BASE+0x00)
//高位寄存器
#define  GPIOA_CRH   *(unsigned int*)(GPIOA_BASE+0x04)
#define  GPIOB_CRH   *(unsigned int*)(GPIOB_BASE+0x04)
#define  GPIOC_CRH   *(unsigned int*)(GPIOC_BASE+0x04)
#define  GPIOD_CRH   *(unsigned int*)(GPIOD_BASE+0x04)
#define  GPIOE_CRH   *(unsigned int*)(GPIOE_BASE+0x04)
#define  GPIOF_CRH   *(unsigned int*)(GPIOF_BASE+0x04)
#define  GPIOG_CRH   *(unsigned int*)(GPIOG_BASE+0x04)
    //输出寄存器
#define  GPIOA_ODR   *(unsigned int*)(GPIOA_BASE+0x0c)
#define  GPIOB_ODR   *(unsigned int*)(GPIOB_BASE+0x0c)
#define  GPIOC_ODR   *(unsigned int*)(GPIOC_BASE+0x0c)
#define  GPIOD_ODR   *(unsigned int*)(GPIOD_BASE+0x0c)
#define  GPIOE_ODR   *(unsigned int*)(GPIOE_BASE+0x0c)
#define  GPIOF_ODR   *(unsigned int*)(GPIOF_BASE+0x0c)
#define  GPIOG_ODR   *(unsigned int*)(GPIOG_BASE+0x0c)

 //输入寄存器
#define  GPIOA_IDR   *(unsigned int*)(GPIOA_BASE+0x08)
#define  GPIOB_IDR   *(unsigned int*)(GPIOB_BASE+0x08)
#define  GPIOC_IDR   *(unsigned int*)(GPIOC_BASE+0x08)
#define  GPIOD_IDR   *(unsigned int*)(GPIOD_BASE+0x08)
#define  GPIOE_IDR   *(unsigned int*)(GPIOE_BASE+0x08)
#define  GPIOF_IDR   *(unsigned int*)(GPIOF_BASE+0x08)
#define  GPIOG_IDR   *(unsigned int*)(GPIOG_BASE+0x08)

 //置位寄存器
#define  GPIOA_BSRR  *(unsigned int*)(GPIOA_BASE+0x10)
#define  GPIOB_BSRR  *(unsigned int*)(GPIOB_BASE+0x10)
#define  GPIOC_BSRR  *(unsigned int*)(GPIOC_BASE+0x10)
#define  GPIOD_BSRR  *(unsigned int*)(GPIOD_BASE+0x10)
#define  GPIOE_BSRR  *(unsigned int*)(GPIOE_BASE+0x10)
#define  GPIOF_BSRR  *(unsigned int*)(GPIOF_BASE+0x10)
#define  GPIOG_BSRR  *(unsigned int*)(GPIOG_BASE+0x10)
 //复位寄存器
#define  GPIOA_BRR   *(unsigned int*)(GPIOA_BASE+0x14)
#define  GPIOB_BRR   *(unsigned int*)(GPIOB_BASE+0x14)
#define  GPIOC_BRR   *(unsigned int*)(GPIOC_BASE+0x14)
#define  GPIOD_BRR   *(unsigned int*)(GPIOD_BASE+0x14)
#define  GPIOE_BRR   *(unsigned int*)(GPIOE_BASE+0x14)
#define  GPIOF_BRR   *(unsigned int*)(GPIOF_BASE+0x14)
#define  GPIOG_BRR   *(unsigned int*)(GPIOG_BASE+0x14)
#endif

 

进过比较会发现   每一个GPIO 都须要定义   指定的寄存器并且每一个都不同,可是当咱们用库函数时会发现咱们的工做量少了,只须要把GPIO的基地址映射出来,而后在定义结构体 GPIO_Typdef  ,在强制转换为GPIO_Typdef  。而后经过指针操做,相比之下工做轻松多了。

下面咱们来说他的原理 :

寄存器之间偏移地址为0x04  (注意是十六进制,在编写过程当中若是用十进制的话会访问不到指定地址)

当我 们进行强转时:  

#define  GPIOB ((GPIO_Typedef*)(GPIOB_BASE))   至关于把 GPIOB_BASE 的地址 做为 指针GPIOB的首地址

GPIOB_BASE 的地址是 :0x40010c00 

寄存器

GPIOB_CRL    地址   GPIOB_BASE +偏移地址(0x00) 0x40010c00 

GPIOB_CRH  地址   GPIOB_BASE +偏移地址(0x04) 0x40010c04

库函数

结构体 GPIO_Typdef 结构 的成员均为int_32T  ,偏移地址为4

当咱们 访问  GPIOB ->CRL    (首个成员就是结构体指针的地址) 那么 地址为:0x40010c00 

                  访问GPIOB->CRH  就是首个成员地址加上偏移地址   那么  地址为:0x40010c04

会发现本质就是地址的访问

相关文章
相关标签/搜索