1. 映射即将内存的某段地址与某一寄存器对应,单片机对函数的操作底层是操作寄存器,而寄存器最终是操作内存上对应的单元,
2. 各个寄存器对应的地址都是在ST定义的起始地址上层层偏移得到
3. 想要实现某功能可直接对此段内存写进相应的值,即可赋予某一功能
4. STM32底层实际是先定义出外设基地址,然后由基地址进行偏移得到不同的外设地址
5. 因为STM32的寄存器大多数是32bit位,且某一功能外设的寄存器地址常常是连贯的,因此只需要定义出寄存器基地址,然后强制转 换为某一结构体类型,此结构体内包含一组寄存器,即可定义一组外设的功能
6. 库函数内部调用寄存器
7. STM32库函数解析:
定义内存基地址 -> 将内存基地址转换为想要的指针类型,如GPIO结构体类型
8. 操作内存,操作寄存器,操作库函数实现GPIO输出低示例
main文件:
include "stm32f10x.h"
#include "stm32f10x_gpio.h"
int main(void)
{
#if 0
/*
采用存储器直接操作
GPIOB Pin3输出低
*/
*((uint32_t *)0X40021018) |= 1 << 3;//时钟使能
*((uint32_t *)0X40010C00) &= ~( 0X0F << (4 * 3 ));//将GPIOB的PIN3 CRL寄存器清0
*((uint32_t *)0X40010C00) |= 0X01 << (4 * 3);//配置为输出模式
*((uint32_t *)0X40010C14) &= ~(0X01 << 3);//控制BRR寄存,将Pin位设置为0
#elif 0
/*
采用寄存器操作
GPIOB Pin3输出低
*/
RCC->APB2ENR |= 1 << 3;//时钟使能
GPIOB->CRL &= ~( 0X0F << (4 * 3 ));//将GPIOB的PIN3 CRL寄存器清0
GPIOB->CRL |= 0X01 << (4 * 3);//配置为输出模式
GPIOB->BRR &= ~(0X01 << 3);//控制BRR寄存,将Pin位设置为0
#else
/*
采用库函数操作
GPIOB Pin3输出低
*/
GPIO_InitTypeDef GPIO_InitStructe;
RCC_APB2CLK_ENR;//时钟使能
GPIO_InitStructe.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructe.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructe.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructe);
GPIO_ResetBit(GPIOB,GPIO_Pin_3);
#endif
}
void SystemInit(void)
{
// 函数体为空,目的是为了骗过编译器不报错
}
内存地址映射文件:
#ifndef __STM32F10X_H
#define __STM32F10X_H
typedef unsigned int uint32_t;
typedef unsigned short int uint16_t;
#define __IO volatile
typedef struct
{
__IO uint32_t CRL;
__IO uint32_t CRH;
__IO uint32_t IDR;
__IO uint32_t ODR;
__IO uint32_t BSRR;
__IO uint32_t BRR;
__IO uint32_t LCKR;
}GPIO_TypeDef;
typedef struct
{
__IO uint32_t CR;
__IO uint32_t CFGR;
__IO uint32_t CIR;
__IO uint32_t APB2RSTR;
__IO uint32_t APB1RSTR;
__IO uint32_t AHBENR;
__IO uint32_t APB2ENR;
__IO uint32_t APB1ENR;
__IO uint32_t BDCR;
__IO uint32_t CSR;
__IO uint32_t AHBRSTR ;
__IO uint32_t CFGR2;
}RCC_TypedefInit;
#define PERIPH_BASE (0x40000000U)//外设基地址
#define APB1PERIPH_BASE PERIPH_BASE//APB1基地址
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000U)//APB2基地址
#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000U)
#define RCC_BASE (PERIPH_BASE + 0x20000U)
#define GPIOA ((GPIO_TypeDef *)(PERIPH_BASE + 0x10800U))
#define GPIOB ((GPIO_TypeDef *)(PERIPH_BASE + 0x10C00U))
#define GPIOC ((GPIO_TypeDef *)(PERIPH_BASE + 0x11000U))
#define GPIOD ((GPIO_TypeDef *)(PERIPH_BASE + 0x11400U))
#define GPIOE ((GPIO_TypeDef *)(PERIPH_BASE + 0x11800U))
#define RCC ((RCC_TypedefInit *)RCC_BASE)
#define RCC_APB2CLK_ENR (RCC->APB2ENR |= 1 << 3)
#endif
GPIO初始化头文件
#ifndef __STM32F10X_GPIO_H
#define __STM32F10X_GPIO_H
#include "stm32f10x.h"
#define GPIO_Pin_0 ((uint16_t)0x0001U)
#define GPIO_Pin_1 ((uint16_t)0x0002U)
#define GPIO_Pin_2 ((uint16_t)0x0003U)
#define GPIO_Pin_3 ((uint16_t)0x0004U)
#define GPIO_Pin_5 ((uint16_t)0x0005U)
#define GPIO_Pin_6 ((uint16_t)0x0006U)
#define GPIO_Pin_7 ((uint16_t)0x0007U)
#define GPIO_Pin_8 ((uint16_t)0x0008U)
#define GPIO_Pin_9 ((uint16_t)0x0009U)
#define GPIO_Pin_10 ((uint16_t)0x000AU)
#define GPIO_Pin_11 ((uint16_t)0x000BU)
#define GPIO_Pin_12 ((uint16_t)0x000CU)
#define GPIO_Pin_13 ((uint16_t)0x000DU)
#define GPIO_Pin_14 ((uint16_t)0x000EU)
#define GPIO_Pin_15 ((uint16_t)0x000FU)
typedef enum
{
GPIO_Speed_10MHz = 1,
GPIO_Speed_20MHz,
GPIO_Speed_50MHz
}GPIOSpeed_TypeDef;
typedef enum
{ GPIO_Mode_AIN = 0x0, // 模拟输入 (0000 0000)b
GPIO_Mode_IN_FLOATING = 0x04, // 浮空输入 (0000 0100)b
GPIO_Mode_IPD = 0x28, // 下拉输入 (0010 1000)b
GPIO_Mode_IPU = 0x48, // 上拉输入 (0100 1000)b
GPIO_Mode_Out_OD = 0x14, // 开漏输出 (0001 0100)b
GPIO_Mode_Out_PP = 0x10, // 推挽输出 (0001 0000)b
GPIO_Mode_AF_OD = 0x1C, // 复用开漏输出 (0001 1100)b
GPIO_Mode_AF_PP = 0x18 // 复用推挽输出 (0001 1000)b
}GPIOMODE_TypeDef;
typedef struct
{
uint32_t GPIO_Pin;
uint32_t GPIO_Mode;
uint32_t GPIO_Speed;
}GPIO_InitTypeDef;
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
void GPIO_ResetBit(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin);
void GPIO_SetBit(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin);
#endif