使用寄存器点亮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的时钟使能端
二、配置IO口输出,确定输出模式
先将对应的控制位清零,再根据自己的需要进行设置。
*(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小灯)
👇将原来写在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外设时钟使能寄存器