前言:本文章部分代码参考自野火的例程
有纰漏请指出,转载请说明。
学习交流请发邮件 [email protected]
1 硬件分析
1.1 GPIOB 基地址
例如:点亮红灯,即GPIOB_5输出低电平
1.2 开启GPIOB所在的APB2的RCC时钟
寄存器偏移地址
1.3 配置GPIOB的CRL寄存器,设置GPIO模式
1.4 配置GPIOB的ODR寄存器,PB5输出低电平
2 软件分析
2.1 直接对寄存器地址赋值
//RCC_APB2ENR bit3置1,即GPIOB端口时钟使能
*(unsigned int*)(0x40021018) |= (1<<3);
//清空GPIOx_CRL 的bit20~bit23
//*(unsigned int*)(0x40010c00) &= ~( 0x0F<< (4*5));
//向GPIOx_CRL 的bit20~bit23 写入3,即PB5以50MHz通用推挽输出
*(unsigned int*)(0x40010c00) |= (3<<4*5);
//GPIOx_ODR 的 bit5 置0,即PB5输出低电平
*(unsigned int*)(0x40010c0c) |= ~(0x20);
2.2 用宏 定义寄存器地址
#define GPIOB_CRL *(unsigned int*)(0x40010c00)
#define GPIOB_ODR *(unsigned int*)(0x40010c0c)
#define RCC_APB2ENR *(unsigned int*)(0x40021018)
//RCC_APB2ENR bit3置1,即GPIOB端口时钟使能
RCC_APB2ENR |= (1<<3);
//清空GPIOx_CRL 的bit20~bit23
//GPIOB_CRL &= ~( 0x0F<< (4*5));
//向GPIOx_CRL 的bit20~bit23 写入3,即PB5以50MHz通用推挽输出
GPIOB_CRL |= (3<<4*5);
//GPIOx_ODR 的 bit5 置0,即PB5输出低电平
GPIOB_ODR |= ~(0x20);
2.3 用固件库方法
/* stm32f10x.h */
#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)
typedef unsigned int uint32_t;
typedef unsigned short 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)
/* stm32f10x_gpio.h */
#ifndef __STM32F10X_GPIO_H
#define __STM32F10X_GPIO_H
#include "stm32f10x.h"
#define GPIO_Pin_0 ((uint16_t)0x0001) /*!< 选择Pin0 */ //(00000000 00000001)b
#define GPIO_Pin_1 ((uint16_t)0x0002) /*!< 选择Pin1 */ //(00000000 00000010)b
#define GPIO_Pin_2 ((uint16_t)0x0004) /*!< 选择Pin2 */ //(00000000 00000100)b
#define GPIO_Pin_3 ((uint16_t)0x0008) /*!< 选择Pin3 */ //(00000000 00001000)b
#define GPIO_Pin_4 ((uint16_t)0x0010) /*!< 选择Pin4 */ //(00000000 00010000)b
#define GPIO_Pin_5 ((uint16_t)0x0020) /*!< 选择Pin5 */ //(00000000 00100000)b
#define GPIO_Pin_6 ((uint16_t)0x0040) /*!< 选择Pin6 */ //(00000000 01000000)b
#define GPIO_Pin_7 ((uint16_t)0x0080) /*!< 选择Pin7 */ //(00000000 10000000)b
#define GPIO_Pin_8 ((uint16_t)0x0100) /*!< 选择Pin8 */ //(00000001 00000000)b
#define GPIO_Pin_9 ((uint16_t)0x0200) /*!< 选择Pin9 */ //(00000010 00000000)b
#define GPIO_Pin_10 ((uint16_t)0x0400) /*!< 选择Pin10 */ //(00000100 00000000)b
#define GPIO_Pin_11 ((uint16_t)0x0800) /*!< 选择Pin11 */ //(00001000 00000000)b
#define GPIO_Pin_12 ((uint16_t)0x1000) /*!< 选择Pin12 */ //(00010000 00000000)b
#define GPIO_Pin_13 ((uint16_t)0x2000) /*!< 选择Pin13 */ //(00100000 00000000)b
#define GPIO_Pin_14 ((uint16_t)0x4000) /*!< 选择Pin14 */ //(01000000 00000000)b
#define GPIO_Pin_15 ((uint16_t)0x8000) /*!< 选择Pin15 */ //(10000000 00000000)b
#define GPIO_Pin_All ((uint16_t)0xFFFF) /*!< 选择全部引脚*/ //(11111111 11111111)b
void GPIO_SetBits(GPIO_TypeDef *GPIOx,uint16_t GPIO_Pin);
void GPIO_ResetBits( GPIO_TypeDef *GPIOx,uint16_t GPIO_Pin );
#endif //__STM32F10X_GPIO_H
/* 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;
}
/* main.c */
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
int main(void)
{
RCC->APB2ENR |= ( (1) << 3 );
GPIOB->CRL |= ( (3) << (4*1) );
GPIO_ResetBits(GPIOB,GPIO_Pin_1);
while(1);
}