使用寄存器点亮LED

使用寄存器点亮LED分为三步:

  • 第一步:打开对应IO口的外设时钟
  • 第二步:配置对应IO口的输出模式
  • 第三步:输出低电平

一、打开对应的外设时钟

通过查询手册可知, 复位和时钟控制(RCC)的基地址为0x4002 1000

控制GPIOC的APB2外设时钟使能寄存器(RCC_APB2ENR)的偏移地址为0x18,即0x4002 0018

接下来需要修改该地址的寄存器的值,接下来就是将0x4002 1018这个数值转换成单片机可识别的地址,即(unsigned int *)0x4002 1018,如果需要修改该地址的值,就在前面再加上一个取值符,即:

*(unsigned int *)0x4002 1018 |=(1<<4);

👆上面的这条语句则打开了GPIOC的时钟使能端

使用寄存器点亮LED-1

二、配置IO口输出,确定输出模式

先将对应的控制位清零,再根据自己的需要进行设置。

使用寄存器点亮LED-2

*(unsigned int*) 0x4001 1004 &=~(0x0F<<(20));
*(unsigned int*) 0x4001 1004 |=(1<<20);

👆其目的是为了将对应位清零的同时,不影响其他位的值。

三、输出低电平

使用端口输出数据寄存器:

*(unsigned int*) 0x4001 100c &=~(1<<(13));   //输出低电平点亮
*(unsigned int*) 0x4001 1004 |=(1<<20);         //输出高电平熄灭

四、完整代码

int main() {
      *(unsigned int*)0x40021018 |=(1<<4);//打开GPIOC时钟
      *(unsigned int*)0x40011004 &=~(0x0F<<(4*5));//配置输出模式
      *(unsigned int*)0x40011004 |=(1<<(4*5));
      *(unsigned int*)0x4001100C &=~(1<<13);//配置输出低电平

      while(1);
}

void SystemInit(void){
}

五、简化代码-使用自定义头文件

👇将原来的指针地址用#define语句单独放在头文件当中引用:

#include "stm32f103c8x.h"
int main(void) {
    RCC_APB2ENR |=1<<4;
    GPIOC_CRH &=~(0x0F<<20);
    GPIOC_CRH |=(1<<20);
    GPIOC_ODR &=~(1<<13);

    while(1);
}

void SystemInit(void) {
} 

👇寄存器的地址分布(针对点亮PC13口的LED小灯)

使用寄存器点亮LED-3

👇将原来写在main函数当中的指针地址用#define语句放入头文件当中:

"stm32f103c8x.h"
#define PERIPH_BASE ((unsigned int)0x40000000) //总线基地址
#define APB1_PERIPH_BASE PERIPH_BASE //APB1总线基地址
#define APB2_PERIPH_BASE (PERIPH_BASE + 0x00010000) //APB2总线基地址
#define AHB_PERIPH_BASE (PERIPH_BASE + 0x00020000) //AHB总线基地址

#define GPIOC_BASE (APB2_PERIPH_BASE + 0x00001000) //GPIOC基地址

#define GPIOC_CRH *(unsigned int*)(GPIOC_BASE + 0x04) //CRH寄存器
#define GPIOC_IDR *(unsigned int*)(GPIOC_BASE + 0x08) //IDR寄存器
#define GPIOC_ODR *(unsigned int*)(GPIOC_BASE + 0x0C) //ODR寄存器

#define RCC_BASE (AHB_PERIPH_BASE + 0x1000) //复位和时钟控制寄存器地址
#define RCC_APB2ENR *(unsigned int*) (RCC_BASE + 0x18) //AHB外设时钟使能寄存器