使用寄存器点亮跑马灯

使用寄存器点亮跑马灯

寄存器

其实不管用库函数法还是位操作,其本质都是操作STM32单片机的寄存器。那什么是寄存器呢?先来给寄存器下个定义
寄存器就是给特定的内存单元取一个别名,这个别名就是我们常说的寄存器。这里的重点是"内存单元"如下栗子
使用寄存器点亮跑马灯_第1张图片
上图来自于STM32官方数据手册,左边是地址,右边是相对应的外设。而寄存器就是,给这些地址取的一个别名。那为什么要这么做?如果我要给GPIOB的端口全部输出1,不用寄存器,即直接对地址进行操作:
在这里插入图片描述
每次这么操作很麻烦有木有。如果使用寄存器就会方便很多。
在这里插入图片描述
说白了,就是将端口的地址用宏定义定义好了。我们直接使用宏定义后的名称就好。当然,对于地址的宏定义是不需要我们操作的,我们直接操作相关的寄存器就好了。在每个引脚里面,很多的寄存器,可以看到这些寄存器相对于基地址的偏移。以GPIOB为例。
使用寄存器点亮跑马灯_第2张图片

明白了什么是寄存器,再来看看怎么通过寄存器点亮跑马灯。

步骤:

1. 时钟使能
2. GPIO配置
3. 点亮

步骤和库函数法一样,不过操作内容有区别。

1) 时钟使能

还是以PA8和PD2为例,时钟使能操作如下

RCC->APB2ENR|=1<<2;  //使能GPIO.A时钟
RCC->APB2ENR|=1<<5;   //使能GPIO.D时钟

怎么实现的?通过查阅芯片数据手册,我们可以看到GPIO的端口,都是挂载在APB2总线上的
使用寄存器点亮跑马灯_第3张图片
APB2是由RCC时钟进行控制的,因此,我们要进行时钟使能,就是要配置其寄存器。还是查阅数据手册,可以看到RCC_APB2RSTR寄存器,这是16位寄存器
在这里插入图片描述
使用寄存器点亮跑马灯_第4张图片
可以看到,我们需要配置的PA和PD分别位该寄存器的第2位和第5位
直接给其写入1即可。所以有了这一步。

RCC->APB2ENR|=1<<2;  //使能GPIO.A时钟
RCC->APB2ENR|=1<<5;   //使能GPIO.D时钟

**2)**GPIO配置

接下来,配置GPIO相关的寄存器。GPIO的寄存器在上面有展示,
端口配置低寄存器(GPIOx_CRL) (x=A…E)
端口配置高寄存器(GPIOx_CRH) (x=A…E)
端口输入数据寄存器(GPIOx_IDR) (x=A…E)
端口输出数据寄存器(GPIOx_ODR) (x=A…E)
端口位设置/清除寄存器(GPIOx_BSRR) (x=A…E)
端口位清除寄存器(GPIOx_BRR) (x=A…E)
端口配置锁定寄存器(GPIOx_LCKR) (x=A…E)

我们需要使用的端口配置寄存器和端口输出寄存器。端口配置寄存器分为高8位CRH和低8位CRL,根据输出引脚而定。例如输出引脚是PA15,则用高八位寄存器CRH配置,同样,若输出引脚为PA2,则用低八位寄存器CRL配置。我们这里引脚为PA8和PD2,因此用高八位配置和低八位配置。以低八位PD2配置为例

使用寄存器点亮跑马灯_第5张图片
这里我们需要做的工作是:

1. 找准引脚口
2. 配置正确的输出模式、速度

在这里插入图片描述
上图的四位为一个引脚,该寄存器32位一共对应8个引脚。PD2为第三个引脚,因此为8、9、10、11位。配置PA8也参考此方法,不过是在CRH寄存器中。
CNFy[1:0]:用于配置输出模式。MODEy[1:0]:用于配置输出速度。

00:通用推挽输出模式                   
01:通用开漏输出模式
10:复用功能推挽输出模式
11:复用功能开漏输出模式
00:输入模式(复位后的状态)
01:输出模式,最大速度10MHz
10:输出模式,最大速度2MHz
11:输出模式,最大速度50MHz

选择输出模式为推挽输出模式,速度为50Mhz。因此配置为0011,16进制表示为03

GPIOD->CRL&= 0xFFFFF0FF;    //PD2  第二位清零
GPIOD->CRL|= 0x00000300;   //设置输出模式、输出速度。这两步就配置好了CRL

配置时需要先对寄存器数据与运算进行清零,然后进行或运算写入

端口配置好以后,再配置数据输出寄存器:
使用寄存器点亮跑马灯_第6张图片
这是低16位寄存器,根据引脚直接写入1即可,简单粗暴

GPIOD->ODR|=1<<2;      //ODR寄存器给PTD.2第二个口高位.

这样就配置好了关于PD2的寄存器,PA8同样是使用该寄存器写入数据。

3) 点亮


    GPIOA->ODR|=1<<8;   //ODR是数据输出寄存器
    GPIOD->ODR=~(1<<2);   //取非运算 
  
    delay_ms(300);
    
    GPIOD->ODR|=1<<2; 
    GPIOA->ODR=~(1<<8);
	delay_ms(300);

通过取非运算,操作ODR寄存器,来控制灯的熄灭。

你可能感兴趣的:(STM32,嵌入式,stm32)