stm32的GPIO编程之寄存器操作

直接寄存器操作

编程思路
① 找到控制LED灯连接的GPIO口PB5和PE5
② 确定GPIO口工作模式:推挽输出,高电平灯灭,低电平灯亮
③ 确定端口寄存器映射地址
④ 编程,读写相应的寄存器
3种方式:
• 直接写寄存器ODR
• 写BSRR
• 位带操作
⑤ 编译、下载、调试
1. ODR直写方式:
PB的基地址0x40010C00
PE的基地址0x40011800
PB5设置:
• CRL:地址0x4001 0C00 + 0x00。值:CNF5[1:0]=00、
MODE5[1:0]=11,故CRL[23:20]=0x3,其他位保持不变。
• ODR: 地址0x4001 0C00 + 0x0C。值:ODR[5]=0亮或1灭,
其他位保持不变
PE5设置:
• CRL:地址0x4001 1800 + 0x00。值:CNF5[1:0]=00、
MODE5[1:0]=11,故CRL[23:20]=0x3,其他位保持不变。
• ODR: 地址0x4001 1800 + 0x0C。值:ODR[5]=0亮或1灭,
其他位保持不变

#include "sys.h"
#include "delay.h"
#define GPIOB_BASE (0x40010C00);
#define GPIOB_CRL *(unsigned int*)(GPIOB_BASE + 0X00);
#define GPIOB_ODR *(unsigned int*)(GPIOB_BASE + 0X0C);
#define GPIOE_BASE (0x40011800);
#define GPIOE_CRL *(unsigned int*)(GPIOE_BASE + 0X00);
#define GPIOE_ODR *(unsigned int*)(GPIOE_BASE + 0X0C);
int main(void)
{
Stm32_Clock_Init(9);//系统时钟设置
delay_init(72); //延时初始化
RCC->APB2ENR|=1<<3; //使能PORTB时钟
RCC->APB2ENR|=1<<6; //使能PORTE时钟
GPIOB_CRL&=0xFF0F_FFFF;
GPIOB_CRL|=0x0030_0000;
GPIOB_ODR|=0x0000_0020; //0010_0000b,led0灭
GPIOE_CRL&=0xFF0F_FFFF;
GPIOE_CRL|=0x0030_0000;
GPIOE_ODR|=0x0000_0020; //0010_0000b,led1灭
while(1)
{
GPIOB_ODR&=0xFFFF_FFDF; //1101_1111b,led0亮
GPIOE_ODR|=0x0000_0020; //0010_0000b,led1灭
delay_ms(300);
GPIOB_ODR|=0x0000_0020; //1101_1111b,led0灭
GPIOE_ODR&=0xFFFF_FFDF; //0010_0000b,led1亮
delay_ms(300);
}
}

2. BSRR写方式:
PB的基地址0x4001 0C00
PE的基地址0x4001 1800
PB5设置:
• CRL:地址0x4001 0C00 + 0x00。值:CNF5[1:0]=00、
MODE5[1:0]=11,故CRL[23:20]=0x11,其他位保持不变。
• BSRR: 地址0x4001 0C00 + 0x10。值:BSRR[5]=1灭或
BSRR[21]=1亮 ,其他位为0
PE5设置:
• CRL:地址0x4001 1800 + 0x00。值:CNF5[1:0]=00、
MODE5[1:0]=11,故CRL[23:20]=0x11,其他位保持不变。
• BSRR: 地址0x4001 1800 + 0x10。值:BSRR[5]=1灭或
BSRR[21]=1 亮,其他位为0

#include "sys.h"
#include "delay.h"
#define GPIOB_BASE (0x40010C00);
#define GPIOB_CRL *(unsigned int*)(GPIOB_BASE + 0x00);
#define GPIOB_BSRR *(unsigned int*)(GPIOB_BASE + 0x10);
#define GPIOE_BASE (0x40011800);
#define GPIOE_CRL *(unsigned int*)(GPIOE_BASE + 0x00);
#define GPIOE_BSRR *(unsigned int*)(GPIOE_BASE + 0x10);
int main(void)
{
Stm32_Clock_Init(9);//系统时钟设置
delay_init(72); //延时初始化
RCC->APB2ENR|=1<<3; //使能PORTB时钟
RCC->APB2ENR|=1<<6; //使能PORTE时钟
GPIOB_CRL&=0xFF0F_FFFF;
GPIOB_CRL|=0x0030_0000;
GPIOB_BSRR =0x0000_0020; //0010_0000b,led0灭
GPIOE_CRL&=0xFF0F_FFFF;
GPIOE_CRL|=0x0030_0000;
GPIOE_BSRR =0x0000_0020; //0010_0000b,led0灭
while(1)
{
GPIOB_BSRR = 0x0020_0000; //0010_0000b,led0亮
GPIOE_BSRR = 0x0000_0020; //0010_0000b,led1灭
delay_ms(300);
GPIOB_BSRR = 0x0000_0020; //0010_0000b,led0灭
GPIOE_BSRR = 0x0020_0000; //0010_0000b,led1亮
delay_ms(300);
}
}

3. BSRR+BRR写方式:
PB的基地址0x40010C00
PE的基地址0x40011800
PB5设置:
• CRL:地址0x4001 0C00 + 0x00。值:CNF5[1:0]=00、
MODE5[1:0]=11,故CRL[23:20]=0x11,其他位保持不变。
• BSRR: 地址0x4001 0C00 + 0x10。值:BSRR[5]=1灭。BRR:
地址0x4001 0C00 + 0x14.。值:BRR[5]=1亮 ,其他位为0
PE5设置:
• CRL:地址0x4001 1800 + 0x00。值:CNF5[1:0]=00、
MODE5[1:0]=11,故CRL[23:20]=0x11,其他位保持不变。
• BSRR: 地址0x4001 1800 + 0x10。值:BSRR[5]=1灭。BRR:
地址0x4001 1800 + 0x14,BRR[5]=1 亮,其他位为0

#include "sys.h"
#include "delay.h"
#define GPIOB_BASE (0x40010C00);
#define GPIOB_CRL *(unsigned int*)(GPIOB_BASE + 0x00);
#define GPIOB_BSRR *(unsigned int*)(GPIOB_BASE + 0x10);
#define GPIOE_BASE (0x40011800);
#define GPIOE_CRL *(unsigned int*)(GPIOE_BASE + 0x00);
#define GPIOE_BSRR *(unsigned int*)(GPIOE_BASE + 0x10);
int main(void)
{
Stm32_Clock_Init(9);//系统时钟设置
delay_init(72); //延时初始化
RCC->APB2ENR|=1<<3; //使能PORTB时钟
RCC->APB2ENR|=1<<6; //使能PORTE时钟
GPIOB_CRL&=0xFF0F_FFFF;
GPIOB_CRL|=0x0030_0000;
GPIOB_BSRR =0x0000_0020; //0010_0000b,led0灭
GPIOE_CRL&=0xFF0F_FFFF;
GPIOE_CRL|=0x0030_0000;
GPIOE_BSRR =0x0000_0020; //0010_0000b,led0灭
while(1)
{
GPIOB_BRR = 0x0000_0020; //0010_0000b,led0亮
GPIOE_BSRR = 0x0000_0020; //0010_0000b,led1灭
delay_ms(300);
GPIOB_BSRR = 0x0000_0020; //0010_0000b,led0灭
GPIOE_BRR = 0x0000_0020; //0010_0000b,led1亮
delay_ms(300);
}
}

4. 位带操作方式:
PB的基地址0x40010C00
PE的基地址0x40011800
PB5设置:
• CRL:地址0x4001 0C00 + 0x00。值:CNF5[1:0]=00、
MODE5[1:0]=11,故CRL[23:20]=0x3,其他位保持不变。
• ODR: 地址0x40010C00 + 0x0C。
• ODR别名地址:0x42000000+ 0x10C0032+54
PE5设置:
• CRL:地址0x4001 1800 + 0x00。值:CNF5[1:0]=00、
MODE5[1:0]=11,故CRL[23:20]=0x3,其他位保持不变。
• ODR: 地址0x40011800 + 0x0C。
• ODR别名地址:0x42000000+ 0x10C0032+54

#include "sys.h"
#include "delay.h"
#define GPIOB_BASE (0x40010C00);
#define GPIOB_CRL *(unsigned int*)(GPIOB_BASE + 0x00);
#define GPIOB_ODR_ADDRESS (GPIOB_BASE + 0x0C);
#define GPIOE_BASE (0x40011800);
#define GPIOE_CRL *(unsigned int*)(GPIOE_BASE + 0x00);
#define GPIOE_ODR_ADDRESS (GPIOE_BASE + 0x0C);
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
#define PBout(n) BIT_ADDR(GPIOB_ODR_ADDRESS,n) //输出
#define PEout(n) BIT_ADDR(GPIOE_ODR_ADDRESS,n) //输出
int main(void)
{
Stm32_Clock_Init(9);//系统时钟设置
delay_init(72); //延时初始化
RCC->APB2ENR|=1<<3; //使能PORTB时钟
RCC->APB2ENR|=1<<6; //使能PORTE时钟
GPIOB_CRL&=0xFF0F_FFFF;
GPIOB_CRL|=0x0030_0000;
PBout(5)=1;//led0灭
GPIOE_CRL&=0xFF0F_FFFF;
GPIOE_CRL|=0x0030_0000;
PEout(5)=1;//led1灭
while(1)
{
PBout(5)=0;//led0亮
PEout(5)=1;//led1灭
delay_ms(300);
PBout(5)=1;//led0灭
PEout(5)=0;//led1亮
delay_ms(300);
}
}

猜你喜欢

转载自blog.csdn.net/qq_46523260/article/details/106883285