1、寄存器地址
/*片上外设基地址 */
#define PERIPH_BASE ((unsigned int)0x40000000)
/*APB2 总线基地址 */
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
/* AHB总线基地址 */
#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000)
/*GPIOB外设基地址*/
#define GPIOB_BASE (APB2PERIPH_BASE + 0x0C00)
/* GPIOB寄存器地址,强制转换成指针 */
#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)
/*RCC外设基地址*/
#define RCC_BASE (AHBPERIPH_BASE + 0x1000)
/*RCC的APB2时钟使能寄存器地址,强制转换成指针*/
#define RCC_APB2ENR *(unsigned int*)(RCC_BASE+0x18)c
以#define RCC_APB2ENR (unsigned int)(RCC_BASE+0x18)为例,unsigned int*为指针的基类型,将常数强制转换为无符号整型的指针,即寄存器地址。 *(unsigned int)(RCC_BASE+0x18)为指针的“解引用”,访问(读/写)指针所指向地址的数据。#define RCC_APB2ENR 为后面内容的别名。
2、使能时钟
点亮LED用到GPIOB端口,要使能 STM32F103 系列单片机的 GPIOB 口时钟信号,可以使用 RCC_APB2ENR 或 RCC_AHBENR 寄存器,具体实现方法如下:
方法一:使用 RCC_APB2ENR 寄存器
RCC_APB2ENR |=1<<3; //开启GPIOB时钟
或
RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
其中,RCC_APB2ENR_IOPBEN 是一个宏定义,对应的数值为 0x00000008,表示启用 GPIOB 口的时钟信号。通过将该宏对应的数值写入 RCC_APB2ENR 寄存器,即可启用 GPIOB 口的时钟信号。
需要注意的是,使用位或运算符(|)可以同时保留 RCC_APB2ENR 寄存器的原始值,并将 GPIOB 口时钟信号位置为1,不会影响其它外设时钟的相关配置。
方法二:使用 RCC_AHBENR 寄存器
RCC->AHBENR |= RCC_AHBENR_GPIOBEN;
其中,RCC_AHBENR_GPIOBEN 是一个宏定义,对应的数值为 0x00020000,表示启用 GPIOB 口的时钟信号。同样地,使用位或运算符(|)可以同时保留 RCC_AHBENR 寄存器的原始值,并将 GPIOB 口时钟信号位置为1,不会影响其它外设时钟的相关配置。
需要注意的是,通过 RCC_AHBENR 寄存器启用 GPIOB 口时钟,GPIOB 口的时钟源必须是 AHB 总线,而不是 APB2 总线。在 STM32F103 系列单片机中,GPIOB 口的时钟源默认就是 AHB 总线,因此可以使用该方法来启用 GPIOB 口时钟信号。
3 配置 PB0 引脚为推挽输出模式
查询芯片原理图,可知PB0控制绿色LED灯,寄存器设置如图所示
查询上表可知,需要将寄存器3 2 1 0位设置为0001
GPIOB_CRL |= 1<<0;//设置PB0为推挽输出,速度为10M
4 点亮LED
如下图所示,PB0低电位导通
GPIOB_ODR |= 0<<0;
添加延时函数延时1秒,整体主函数如下
int main()
{
unsigned int delay = 1000000;
RCC_APB2ENR |=1<<3; //开启GPIOB时钟
GPIOB_CRL &= 0xF0<<0;//清除PB0的控制位
GPIOB_CRL |= 1<<0;//设置PB0为推挽输出,速度为10M
while(1)
{
GPIOB_ODR |= 0<<0;
delay =1000000;
while(delay --);
GPIOB_ODR &= ~(0<<0);
delay =1000000;
while(delay --);
}
}
延时似乎没起作用