一、定义外设的各基地址,参考存储器映射
#define PERIPH_BASE ((unsigned int)0x4000000)
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000)
#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 + 0x1C00)
#define GPIOG_BASE (APB2PERIPH_BASE + 0x2000)
#define RCC_BASE (AHBPERIPH_BASE + 0x1000)
F103系统框图
F103存储器映射
二、定义GPIO与RCC寄存器结构体
#define __IO volatile
typedef unsigned int uint32_t
typedef unsigned short uint16_t
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 APR2ENR;
__IO uint32_t ApR1ENR:
__IO uint32_t BDCR;
__IO uint32_t CSR;
}RCC_TypeDef;
在stm32中,程序的存储器,数据存储器,寄存器和输入输出端口被组织在一个4GB(4294967296)的线性空间中,即从地址0x0000 0000 到 地址0xFFFF FFFF。且被分为8个block。一个block的大小为512MB,注意,这里的存储单位是一个字节。而GPIO中一个寄存器的存储空间是4个字节,上面的七个寄存器的存储空间是连续的。一个uint32_t刚好也为4个字节。因此只需要给结构体传入GPIO的基地址即可。
#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE)
#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE)
#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE)
#define GPIOE ((GPIO_TypeDef *) GPIOE_BASE)
#define GPIOF ((GPIO_TypeDef *) GPIOF_BASE)
#define GPIOG ((GPIO_TypeDef *) GPIOG_BASE)
#define RCC ((RCC_TypeDef *) RCC_BASE)
三、利用寄存器使PB0输出低电平
int main(void)
{
RCC -> APB2ENR |= (1<<3);
GPIO -> CRL &= ~( 0x0F << (4*0));
GPIOB -> CRL |= (1<<4*0);
GPIOB -> ODR |= (0<<0);
while(1);
}
四、构造库函数
定义GPIO初始化结构体
typedef struct{
uint16_t GPIO_Pin;
uint16_t GPIO_Speed;
uint16_t GPIO_Mode;
} GPIO_InitTypeDef;
枚举类型定义
typedef enum{
GPIO_Speed_10MHz = 1,
GPIO_Speed_2MHz,
GPIO_Speed_50MHz
} GPIOSpeed_TypeDef;
typedef enum{
GPIO_Mode_AIN = 0x0,
GPIO_Mode_IN_FLOATING = 0x04,
GPIO_Mode_IPD = 0x28,
GPIO_Mode_IPU = 0x48,
GPIO_Mode_Out_OD = 0x14,
GPIO_Mode_Out_PP = 0x10,
GPIO_Mode_AF_OD = 0x1C,
GPIO_Mode_AF_PP = 0x18
} GPIOMode_TypeDef;
定义引脚号
#define GPIO_Pin_0 (uint16_t)0x0001)
#define GPIO_Pin_1 ((uint16_t)0x0002)
#define GPIO_Pin_2 ((uint16_t)0x0004)
#define GPIO_Pin_3 ((uint16_t)0x0008)
#define GPIO_Pin_4 ((uint16_t)0x0010)
#define GPIO_Pin_5 ((uint16_t)0x0020)
#define GPIO_Pin_6 ((uint16_t)0x0040)
#define GPIO_Pin_7 ((uint16_t)0x0080)
#define GPIO_Pin_8 ((uint16_t)0x0100)
#define GPIO_Pin_9 ((uint16_t)0x0200)
#define GPIO_Pin_10 ((uint16_t)0x0400)
#define GPIO_Pin_11 ((uint16_t)0x0800)
#define GPIO_Pin_12 ((uint16_t)0x1000)
#define GPIO_Pin_13 ((uint16_t)0x2000)
#define GPIO_Pin_14 ((uint16_t)0x4000)
#define GPIO_Pin_15 ((uint16_t)0x8000)
#define GPIO_Pin_All ((uint16_t)0xFFFF)
GPIO初始化函数
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
{
uint32_t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00;
uint32_t tmpreg = 0x00, pinmask = 0x00;
currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F);
if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00)
{
currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed;
}
if (((uint32_t)GPIO_InitStruct->GPIO_Pin & ((uint32_t)0x00FF)) != 0x00)
{
tmpreg = GPIOx->CRL;
for (pinpos = 0x00; pinpos < 0x08; pinpos++)
{
pos = ((uint32_t)0x01) << pinpos;
currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;
if (currentpin == pos)
{
pos = pinpos << 2;
pinmask = ((uint32_t)0x0F) << pos;
tmpreg &= ~pinmask;
tmpreg |= (currentmode << pos);
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
{
GPIOx->BRR = (((uint32_t)0x01) << pinpos);
}
else
{
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
{
置 1
GPIOx->BSRR = (((uint32_t)0x01) << pinpos);
}
}
}
}
GPIOx->CRL = tmpreg;
}
if (GPIO_InitStruct->GPIO_Pin > 0x00FF)
{
tmpreg = GPIOx->CRH;
for (pinpos = 0x00; pinpos < 0x08; pinpos++)
{
pos = (((uint32_t)0x01) << (pinpos + 0x08));
currentpin = ((GPIO_InitStruct->GPIO_Pin) & pos);
if (currentpin == pos)
{
pos = pinpos << 2;
pinmask = ((uint32_t)0x0F) << pos;
tmpreg &= ~pinmask;
tmpreg |= (currentmode << pos);
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
{
GPIOx->BRR = (((uint32_t)0x01) << (pinpos + 0x08));
}
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
{
GPIOx->BSRR = (((uint32_t)0x01) << (pinpos + 0x08));
}
}
}
GPIOx->CRH = tmpreg;
}
}
GPIO引脚工作模式真值表
- 当bit4为1时,工作模式为输出,为0时,工作模式为输入。而输入不需要设置速率
- 配置上下拉的工作模式是通过写BSRR或者BRR寄存器来实现的
端口输出函数
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
GPIOx->BSRR = GPIO_Pin;
}
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
GPIOx->BRR = GPIO_Pin;
}
用库函数实现端口输出
#define RCC_APB2ENR *(unsigned int*)(RCC_BASE+0x18)
int main(void) {
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2ENR |= (1<<3);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_ResetBits(GPIOB,GPIO_Pin_0);
while (1)
{
GPIO_ResetBits(GPIOB,GPIO_Pin_0);
Delay(0xFFFF);
GPIO_SetBits(GPIOB,GPIO_Pin_0);
Delay(0xFFFF);
}
}
void Delay(int i)
{
i--;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)