main.c
#include "stm32f10x.h"
#if 0
int main(void)
{
//打开GPIOB时钟
*(unsigned int*)0X40021018 |= ((1)<<(3));
//端口配置低寄存器CRL,输出模式,最大速度10MHz
*(unsigned int*)0X40010C00 |= (1<<(4*0));
//端口输出寄存器ODR设置PB0输出数据0
*(unsigned int*)0X40010C0C &=~(1<<0);
}
#endif
#if 0
int main(void)
{
//打开GPIOB时钟
*(unsigned int*)0X40021018 |= ((1)<<(3));
//端口配置低寄存器CRL,输出模式,最大速度10MHz
*(unsigned int*)0X40010C00 |= (1<<(4*5));
//端口输出寄存器ODR设置PB5输出数据0
*(unsigned int*)0X40010C0C &=~(1<<5);
}
#endif
int main(void)
{
#if 0
//打开GPIOB时钟
*(unsigned int*)0X40021018 |= ((1)<<(3));
//端口配置低寄存器CRL,输出模式,最大速度10MHz
*(unsigned int*)0X40010C00 |= (1<<(4*1));
//端口输出寄存器ODR设置PB1输出数据0
*(unsigned int*)0X40010C0C &=~(1<<1);
#else
RCC_APB2ENR |= ((1)<<(3));
GPIOB_CRL |= (1<<(4*1));
GPIOB_ODR&=~(1<<1);
#endif
}
//置位 |=,清零 &=~
void SystemInit()
{
}
stm32f10x.h
//用来存放STM32寄存器映射代码
#define PERIPH_BASE ((unsigned int)0x40000000)
#define APB1PERIPH_BASE PERIPH_BASE
#define APB2PERIPH_BASE (PERIPH_BASE+0x10000)
#define AHBPERIPH_BASE (PERIPH_BASE+0x20000)
#define RCC_BASE (AHBPERIPH_BASE+0x1000)
#define GPIOB_BASE (APB2PERIPH_BASE+0x0C00)
#define RCC_APB2ENR *(unsigned int*)(RCC_BASE +0x18)
#define GPIOB_CRL *(unsigned int*)(GPIOB_BASE +0x00)
#define GPIOB_CRH *(unsigned int*)(GPIOB_BASE +0x04)
#define GPIOB_ODR *(unsigned int*)(GPIOB_BASE +0x0C)
代码从寄存器点亮LED到逐渐封装点亮LED。
main.c
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#define LED_GPIO_PORT GPIOB
#define LED_GPIO_CLK (RCC->APB2ENR |=((1)<<(3)))
#define LED_GPIO_PIN GPIO_Pin_1
#if 0
int main(void)
{
//打开GPIOB时钟
*(unsigned int*)0X40021018 |= ((1)<<(3));
//端口配置低寄存器CRL,输出模式,最大速度10MHz
*(unsigned int*)0X40010C00 &= ~((0x0f)<<(4*0));
*(unsigned int*)0X40010C00 |= (1<<(4*0));
//端口输出寄存器ODR设置PB0输出数据0
*(unsigned int*)0X40010C0C &=~(1<<0);
}
#endif
#if 0
int main(void)
{
//打开GPIOB时钟
*(unsigned int*)0X40021018 |= ((1)<<(3));
//端口配置低寄存器CRL,输出模式,最大速度10MHz
*(unsigned int*)0X40010C00 |= (1<<(4*5));
//端口输出寄存器ODR设置PB5输出数据0
*(unsigned int*)0X40010C0C &=~(1<<5);
}
#endif
#if 0
int main(void)
{
//打开GPIOB时钟
*(unsigned int*)0X40021018 |= ((1)<<(3));
//端口配置低寄存器CRL,输出模式,最大速度10MHz
*(unsigned int*)0X40010C00 |= (1<<(4*1));
//端口输出寄存器ODR设置PB1输出数据0
*(unsigned int*)0X40010C0C &=~(1<<1);
RCC_APB2ENR |= ((1)<<(3));
GPIOB_CRL |= (1<<(4*1));
GPIOB_ODR&=~(1<<1);
}
#endif
#if 0
int main(void)
{
RCC->APB2ENR |= ((1)<<(3));
GPIOB->CRL |= (1<<(4*5));
//GPIOB->ODR &=~(1<<5);
//GPIO_SetBits(GPIOB,GPIO_Pin_5);
GPIO_ResetBits(GPIOB,GPIO_Pin_5);
}
#endif
int main(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//RCC->APB2ENR |=((1)<<(3));
LED_GPIO_CLK ;
GPIO_InitStructure.GPIO_Pin=LED_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(LED_GPIO_PORT,&GPIO_InitStructure);
GPIO_SetBits(LED_GPIO_PORT,LED_GPIO_PIN);
GPIO_ResetBits(LED_GPIO_PORT,LED_GPIO_PIN);
}
void SystemInit()
{
}
stm32f10x_gpio.c
#include "stm32f10x_gpio.h"
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;
}
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;
/*---------------- GPIO 模式配置 -------------------*/
// 把输入参数 GPIO_Mode 的低四位暂存在 currentmode
currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F);
// bit4 是 1 表示输出, bit4 是 0 则是输入
// 判断 bit4 是 1 还是 0,即首选判断是输入还是输出模式
if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) &
((uint32_t)0x10)) != 0x00)
{
// 输出模式则要设置输出速度
currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed;
}
/*-----GPIO CRL 寄存器配置 CRL 寄存器控制着低 8 位 IO- ----*/
// 配置端口低 8 位,即 Pin0~Pin7
if (((uint32_t)GPIO_InitStruct->GPIO_Pin &
((uint32_t)0x00FF)) != 0x00)
{
// 先备份 CRL 寄存器的值
tmpreg = GPIOx->CRL;
// 循环,从 Pin0 开始配对,找出具体的 Pin
for (pinpos = 0x00; pinpos < 0x08; pinpos++)
{
// pos 的值为 1 左移 pinpos 位
pos = ((uint32_t)0x01) << pinpos;
// 令 pos 与输入参数 GPIO_PIN 作位与运算
currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;
//若 currentpin=pos,则找到使用的引脚
if (currentpin == pos)
{
//pinpos 的值左移两位(乘以 4),因为寄存器中 4 个位配置一个引脚
pos = pinpos << 2;
//把控制这个引脚的 4 个寄存器位清零,其它寄存器位不变
pinmask = ((uint32_t)0x0F) << pos;
tmpreg &= ~pinmask;
// 向寄存器写入将要配置的引脚的模式
tmpreg |= (currentmode << pos);
// 判断是否为下拉输入模式
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
{
// 下拉输入模式,引脚默认置 0,对 BRR 寄存器写 1 对引脚置 0
GPIOx->BRR = (((uint32_t)0x01) << pinpos);
}
else
{
// 判断是否为上拉输入模式
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
{
// 上拉输入模式,引脚默认值为 1,对 BSRR 寄存器写 1 对引脚置 1
GPIOx->BSRR = (((uint32_t)0x01) << pinpos);
}
}
}
}
// 把前面处理后的暂存值写入到 CRL 寄存器之中
GPIOx->CRL = tmpreg;
}
/*--------GPIO CRH 寄存器配置 CRH 寄存器控制着高 8 位 IO- -----*/
// 配置端口高 8 位,即 Pin8~Pin15
if (GPIO_InitStruct->GPIO_Pin > 0x00FF)
{
// // 先备份 CRH 寄存器的值
tmpreg = GPIOx->CRH;
// 循环,从 Pin8 开始配对,找出具体的 Pin
for (pinpos = 0x00; pinpos < 0x08; pinpos++)
{
pos = (((uint32_t)0x01) << (pinpos + 0x08));
// pos 与输入参数 GPIO_PIN 作位与运算
currentpin = ((GPIO_InitStruct->GPIO_Pin) & pos);
//若 currentpin=pos,则找到使用的引脚
if (currentpin == pos)
{
//pinpos 的值左移两位(乘以 4),因为寄存器中 4 个位配置一个引脚
pos = pinpos << 2;
//把控制这个引脚的 4 个寄存器位清零,其它寄存器位不变
pinmask = ((uint32_t)0x0F) << pos;
tmpreg &= ~pinmask;
// 向寄存器写入将要配置的引脚的模式
tmpreg |= (currentmode << pos);
// 判断是否为下拉输入模式
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
{
// 下拉输入模式,引脚默认置 0,对 BRR 寄存器写 1 可对引脚置 0
GPIOx->BRR = (((uint32_t)0x01) << (pinpos + 0x08));
}
// 判断是否为上拉输入模式
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
{
// 上拉输入模式,引脚默认值为 1,对 BSRR 寄存器写 1 可对引脚置 1
GPIOx->BSRR = (((uint32_t)0x01) << (pinpos + 0x08));
}
}
}
// 把前面处理后的暂存值写入到 CRH 寄存器之中
GPIOx->CRH = tmpreg;
}
}
stm32f10x_gpio.h
#ifndef _STM32F10X_GPIO_H
#define _STM32F10X_GPIO_H
#include "stm32f10x.h"
#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)0x0001)
typedef enum
{
GPIO_Speed_10MHz = 1, // 10MHZ (01)b
GPIO_Speed_2MHz, // 2MHZ (10)b
GPIO_Speed_50MHz // 50MHZ (11)b
} GPIOSpeed_TypeDef;
typedef struct
{
uint16_t GPIO_Pin; /*!< 选择要配置的 GPIO 引脚 */
uint16_t GPIO_Speed; /*!< 选择 GPIO 引脚的速率 */
uint16_t GPIO_Mode; /*!< 选择 GPIO 引脚的工作模式 */
} GPIO_InitTypeDef;
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;
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
void GPIO_SetBits(GPIO_TypeDef *GPIOx,uint16_t GPIO_Pin);
void GPIO_ResetBits(GPIO_TypeDef *GPIOx,uint16_t GPIO_Pin);
#endif
stm32f10x.h
//用来存放STM32寄存器映射代码
#ifndef _STM32F10X_H
#define _STM32F10X_H
#define PERIPH_BASE ((unsigned int)0x40000000)
#define APB1PERIPH_BASE PERIPH_BASE
#define APB2PERIPH_BASE (PERIPH_BASE+0x10000)
#define AHBPERIPH_BASE (PERIPH_BASE+0x20000)
#define RCC_BASE (AHBPERIPH_BASE+0x1000)
#define GPIOB_BASE (APB2PERIPH_BASE+0x0C00)
#define RCC_APB2ENR *(unsigned int*)(RCC_BASE +0x18)
/*
#define GPIOB_CRL *(unsigned int*)(GPIOB_BASE +0x00)
#define GPIOB_CRH *(unsigned int*)(GPIOB_BASE +0x04)
#define GPIOB_IDR *(unsigned int*)(GPIOB_BASE +0x08)
#define GPIOB_ODR *(unsigned int*)(GPIOB_BASE +0x0C)
#define GPIOB_BSRR *(unsigned int*)(GPIOB_BASE +0x10)
#define GPIOB_BRR *(unsigned int*)(GPIOB_BASE +0x14)
#define GPIOB_LCKR *(unsigned int*)(GPIOB_BASE +0x18)
*/
typedef unsigned int uint32_t;
typedef unsigned int uint16_t;
typedef struct
{
uint32_t CRL;
uint32_t CRH;
uint32_t IDR;
uint32_t ODR;
uint32_t BSRR;
uint32_t BRR;
uint32_t LCKR;
}GPIO_TypeDef;
typedef struct
{
uint32_t CR;
uint32_t CFGR;
uint32_t CIR;
uint32_t APB2RSTR;
uint32_t APB1RSTR;
uint32_t AHBENR;
uint32_t APB2ENR;
uint32_t APB1ENR;
uint32_t BDCR;
uint32_t CSR;
}RCC_TypeDef;
#define GPIOB ((GPIO_TypeDef*)GPIOB_BASE)
#define RCC ((RCC_TypeDef*)RCC_BASE)
#endif