理论概念-常见嵌入式岗位面试题

一、问题一:

       通过这两篇blog:1、51单片机流水灯程序的Proteus设计和仿真_-HSheng的博客-CSDN博客;2、stm32通过寄存器方式利用GPIO端口点亮LED_-HSheng的博客-CSDN博客的实践,结合阅读ARM、STM32技术手册,深入思考STM32F103系列芯片的地址映射和寄存器映射原理,GPIO端口的初始化设置的一般步骤。回答:

1)嵌入式C程序代码对内存(RAM)中的各变量的修改操作,与对外部设备(寄存器--->对应相关管脚)的操作有哪些相同与差别?

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

二、问题二:

       与PC平台上的一般程序不同,嵌入式C程序经常会看见 register和volatile 关键字,请解释这两个变量修饰符的作用,并用C代码示例进行说明。

三、问题解决: 

3.1、问题一解决:

3.1.1、第一小问:

相同点:

1. 都可以通过变量名或地址访问,进行读写操作

2. 读取操作都需要将数据从内存/寄存器加载到CPU的寄存器或缓存中  

3. 写操作都需要将CPU的数据写入内存/寄存器中

4. 都需要注意数据同步,例如通过volatile关键字

5.都可以使用相同的数据类型来定义内存中的变量和表示寄存器中的数据。同时意味着可以使用相同的数据类型来处理它们。

差异点:

1. 内存变量直接通过变量名访问,外部寄存器需要知道它的地址

2. 内存变量修改直接生效,寄存器需要根据时序要求才能生效

3. 内存变量可以直接读取/修改,寄存器可能需要设置控制位才能访问

4. 同一内存变量可以被多个任务随时访问,寄存器可能存在访问冲突或优先级问题

5. 内存变量的大小灵活,寄存器大小固定  

6. 内存变量不需关心电平电压,寄存器需要匹配芯片的逻辑电平

7. 内存变量不需考虑存储保留的问题,寄存器的某些位可能有特殊使用限制

总结:寄存器操作更复杂,需要参考芯片手册,注意访问时序、电平控制、优先级等因素;对内存中的变量进行修改操作和对外部设备的操作有一些相同的地方,但也存在一些差异。在编写嵌入式C程序时,需要根据具体的需求和硬件平台来选择合适的操作方式,并注意处理数据的有效性和正确性。

3.1.2、第二小问:

1. 51单片机GPIO端口与外部管脚连接更直接,不需要复用设置,可以直接访问端口寄存器控制LED。STM32的GPIO需要先配置复用才能映射到管脚。

2. 51单片机中文资料丰富,例程多,上手容易。STM32资料相对较少,学习门槛更高。

3. 51单片机系统结构简单,编程模型直观。STM32系统复杂,需要理解编程框架。

4. 51单片机GPIO单一功能,只能设置输入输出,不需要另选功能。STM32的GPIO多功能可配置,需要选定要使用的功能。

5. 51单片机中断响应快速,不需考虑响应时间和优先级问题。STM32需要注意中断优先级和抢占。

6. 51单片机GPIO电压转换直接,不需要考虑电平匹配问题。STM32的GPIO需要注意输入输出电压匹配。

7. 51单片机可以直接对GPIO寄存器操作,STM32需要初始化配置GPIO才能使用。

综上所述:51单片机设计更简单,上手更容易。但STM32硬件功能更强大完善。51能比较简单完成的LED点灯,在STM32中就需要更复杂的配置。

3.2、问题二解决:

3.2.1、第一小问:

    在C语言中,register是一个变量修饰符,它建议编译器将某个变量存储在处理器的寄存器中,而不是RAM中。这样做的目的是为了提高访问速度,因为寄存器的访问速度比RAM快得多。然而,这只是一个建议,编译器可以选择忽略它。此外,寄存器的数量有限,因此不能将所有变量都声明为register。在嵌入式C编程中,register关键字可能会更常见,因为在这些系统中,性能优化尤为重要。以下是一个使用register关键字的示例:

#include<stdio.h>

int main() {
   register int i;
   for(i=0; i<10000; i++) {
      printf("%d\n", i);
   }
   return 0;
}

       在这个例子中,我们将变量i声明为register变量。由于i在循环中频繁使用,所以将其存储在寄存器中可以提高程序的运行速度。但请注意,这只是一个建议,编译器可能会选择忽略它。如果你的程序没有运行得更快,那可能就是这个原因。总的来说,现代编译器通常能够自动确定哪些变量应该存储在寄存器中,因此在大多数情况下,你可能不需要显式地使用register关键字。但在某些特定的、对性能要求极高的情况下,显式使用register关键字可能会有所帮助。

 3.2.2、第二小问:

       在C语言中,volatile是一个变量修饰符,它告诉编译器该变量可能会在任何时候被意外地修改。这可能是由于操作系统、硬件或其他并发线程的操作。当一个变量被声明为volatile时,编译器将生成代码,确保对该变量的每次读取都将从其所在的内存地址中获取,每次写入都将直接写入其所在的内存地址。

       在嵌入式C编程中,volatile关键字尤其重要,因为这些系统通常会有硬件寄存器或其他可以随时改变的外部因素。例如,如果你正在编写一个需要读取硬件寄存器状态的程序,那么你可能需要将该寄存器地址映射到一个volatile变量。以下是一个使用volatile关键字的示例:

#include <stdio.h>

int main() {
   volatile int i = 10;
   while(i==10) {
      // 这是一个空循环
   }
   printf("i changed to %d\n", i);
   return 0;
}

     在这个例子中,我们将变量i声明为volatile。如果没有volatile关键字,编译器可能会认为在循环中i的值不会改变,并优化掉对i的检查,导致无限循环。但由于我们使用了volatile关键字,编译器会正确地生成代码来检查i的值。

    总的来说,当你认为一个变量可能会被程序之外的因素改变时(例如:硬件寄存器、操作系统或其他线程),就应该使用volatile关键字。

四、总结(结束语)

    通过这两个问题的解决,我了解并学习了关于register与volatile这两个关键字的知识点以及在C程序和嵌入式发挥的作用。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值