概念理解:寄存器与地址

本文章描写一些对STM32寄存器与地址的概念理解以及在嵌入式编程中register和volatile 变量的区别与示例说明。


一、STM32F103系列芯片的地址映射和寄存器映射原理

(一)什么是寄存器

寄存器是CPU内部用来存放数据的一些小型存储区域,用来暂时存放参与运算的数据和运算结果。寄存器是一种常用的时序逻辑电路,但这种时序逻辑电路只包含存储电路。寄存器的存储电路是由锁存器或触发器构成的,因为一个锁存器或触发器能存储1位二进制数,所以由N个锁存器或触发器可以构成N位寄存器。寄存器是中央处理器内的组成部分,是有限存储容量的高速存储部件,可以用来暂存指令、数据和位址。
举个例子,寄存器顾名思义,就是存东西的地方,可以把寄存器想作超市的购物车,客户可以将商品放入寄存器下暂存。这个例子仅仅说明寄存器的部分功能,寄存器不仅是存放数据,也可以存放指令和位址。而区分不同的寄存器,就引入了第二个主角:地址。不同的寄存器,有不同的地址。就像不同的储物柜有着不同的编号。

(二)地址映射和寄存器映射原理

STM32F103系列芯片的地址映射和寄存器映射原理是将芯片内部的各种资源(如GPIO、UART、SPI等)映射到特定的地址空间和寄存器中,以便程序可以通过读写这些地址和寄存器来访问这些资源。

对于STM32F103系列芯片,每个资源(例如GPIOA)都有一个特定的地址(例如0x40010800),以及一组与之相关的寄存器(例如GPIOA_CRL、GPIOA_CRH、GPIOA_IDR、GPIOA_ODR等)。这些寄存器用于对相应资源进行配置和控制,例如设置GPIOA的输出高/低电平等。

通过地址映射和寄存器映射,我们可以更加方便地访问和控制STM32F103芯片的各种资源,从而实现特定的功能和应用。具体而言,可以使用C语言等编程语言,通过访问特定的地址和寄存器来读写和控制资源,从而实现如LED闪烁、按键检测、串口通信等特定功能。

(三)怎样找到某个寄存器地址?

找到某个寄存器地址的方法主要是通过查阅相关的数据手册。

  1. 找到对应设备的硬件手册或数据手册,这些手册通常会提供寄存器的地址信息。
  2. 在手册中寻找与所需寄存器相关的章节或表格,这些章节或表格通常会以寄存器的名称或功能作为关键字进行标记。
  3. 在相关章节或表格中,可以查找寄存器的地址,通常会以十六进制或二进制的形式表示。
  4. 确定寄存器的地址后,可以在程序中使用该地址进行读写操作。

二、GPIO端口的初始化设置步骤

单个GPIO口的初始化配置为例
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA时钟

GPIO_InitTypeDef GPIO_InitStructure;                      
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;          //设置GPIO口工作模式 ,推挽模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;                 //设置GPIO口的引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;         //设置GPIO口的速度
GPIO_Init(GPIOA, &GPIO_InitStructure);                     
                                                          //初始化完成

三、对RAM中的各变量的修改操作,与对外部设备寄存器的操作有哪些相同与差别?

(1)相同点:

  1. 语法:在C语言中,无论是对内存变量还是对外部设备的操作,语法上都是相同的。都是通过使用指针或者直接访问变量的方式来进行读写操作。

  2. 访问方式:对内存变量和外部设备的访问都需要知道其地址。对内存变量的地址通常由编译器自动分配,而对外部设备的地址通常由硬件或系统提供。

(2) 不同点:

  1. 物理位置:内存变量存储在RAM中,而外部设备存储在硬件设备的寄存器中。RAM是处理器的临时存储区域,当电源关闭时,其内容会丢失。而寄存器的内容即使电源关闭也会保留。

  2. 访问速度:对内存变量的访问速度通常比对外部设备的访问速度快得多。内存访问通常在几个CPU时钟周期内完成,而外部设备的访问可能需要几百个或更多的CPU时钟周期。

  3. 并发性:多个线程或进程可以同时访问内存变量,但需要适当的同步机制来防止数据竞争。然而,对外部设备的访问通常是串行的,因为硬件设备通常不能同时处理多个请求。

  4. 安全性:对内存变量的访问如果存在越界或者非法访问,可能会导致程序崩溃或者数据破坏。而对外部设备的非法访问可能会损坏硬件设备或者导致系统不稳定。

  5. 映射方式:对外部设备的操作通常需要特定的硬件知识,并且需要知道设备寄存器和内存地址之间的映射关系。而对内存变量的操作则相对简单,只需知道变量的地址即可。

(3)为什么51单片机的LED点灯编程要比STM32的简单

51单片机的硬件结构相对简单,其内部资源较少,外部引脚也较少,因此控制LED的方式相对单一。而STM32具有更多的内部资源和外部引脚,可以进行更多复杂的操作,因此需要更复杂的编程

四、register和volatile变量修饰符作用

(1)概念
register:使用register修饰的变量,在编译时请求编译器尽可能的将变量存储在CPU内部寄存器,以提高访问速度。这主要适用于频繁使用的变量。register变量必须是CPU能接受的单值且长度小于等于int类型的变量,它直接存储于寄存器,因此无法取得该变量的地址。

volatile:volatile是易变的,不稳定的意思,用它修饰的变量表示可以被某些编译器未知的因素更改,比如操作系统、硬件或者其他线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码不再进行优化,从而可以提供对特殊地址的稳定访问。
(2)程序示例

#include <stdio.h>    
int main() {  
    register int i; // 使用register修饰i变量  
    i = 10;  
    while(i--) {  
        printf("%d ", i);  
    }  
    printf("\n");  
  
    volatile int j; // 使用volatile修饰j变量  
    j = 10;  
    while(j--) {  
        printf("%d ", j);  
        j = j - 1; // 在循环中更改j的值,以展示volatile的作用  
    }  
    printf("\n");  
    return 0;  
}

在上面的代码中,定义了两个变量i和j,并分别使用register和volatile修饰符。对于i变量,我们使用register修饰符请求编译器将其存储在CPU内部寄存器中,以提高访问速度。在循环中,我们使用i–操作符来减少i的值,并打印每个值。对于j变量,我们使用volatile修饰符表示它可能被某些编译器未知的因素更改。在循环中,我们使用j–操作符减少j的值,并在每次循环中显式地更改j的值。这样做是为了展示volatile修饰符的作用,即告诉编译器不要对访问该变量的代码进行优化,以确保每次循环中都能获得正确的值。

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值