(十四)嵌入式面试题收集:13道

问题:如 STM32IO 内部框图中 A、B、C、D 4 个信号点哪个是 GPIO 作为 AD 采样时输入的信号端?理由是?

答案C 点。理由:AD 采样是 "模拟信号输入",需经过施密特触发器前的模拟通道(C 点对应模拟输入路径,而 A/B/D 对应数字 I/O 或输出路径)。


问题:以下有关 SPI 说法正确的是()选项:A.SPI 有 3 中工作模式;B.MOSI 是主机的通信输入引脚;C.MISO 是从机通信输入引脚;D. 在工作方式一中,时钟下降沿数据有效

答案无正确选项(若题目存在表述误差,实际 SPI 有 4 种工作模式;MOSI 是主机输出 / 从机输入;MISO 是主机输入 / 从机输出;方式一下时钟上升沿采样)

SPI 的 4 种工作模式由 **CPOL(时钟极性)CPHA(时钟相位)** 两个参数组合决定:

工作模式 CPOL(时钟空闲电平) CPHA(数据采样时刻) 通信逻辑
模式 0 0(空闲时 SCLK 为低) 0(第 1 个时钟沿采样) SCLK 空闲低→第 1 个上升沿采样数据,第 1 个下降沿更新数据
模式 1 0(空闲时 SCLK 为低) 1(第 2 个时钟沿采样) SCLK 空闲低→第 1 个下降沿更新数据,第 2 个上升沿采样数据
模式 2 1(空闲时 SCLK 为高) 0(第 1 个时钟沿采样) SCLK 空闲高→第 1 个下降沿采样数据,第 1 个上升沿更新数据
模式 3 1(空闲时 SCLK 为高) 1(第 2 个时钟沿采样) SCLK 空闲高→第 1 个上升沿更新数据,第 2 个下降沿采样数据

简单记:CPOL 决定空闲时钟的高低,CPHA 决定 "第 1 个沿是采样还是更新"。


问题:关于中断嵌套,以下说法正确的是()选项:A. 中断嵌套会增加栈空间的使用;B. 中断嵌套不会影响程序执行效率;C. 所有单片机都支持中断嵌套;D. 中断嵌套与优先级无关

答案A。解析:中断嵌套时,每次中断都会压栈保存现场,因此会增加栈空间占用;B(嵌套会降低效率)、C(并非所有单片机支持)、D(嵌套依赖优先级)均错误。


问题:以下代码在单片机中运行,可能导致什么问题?

复制代码
void func(){
    int large_array[1024*1024];
    //其他操作
}

选项:A. 栈溢出;B. 堆溢出;C. 内存泄漏;D. 无问题

答案A。解析:局部变量(large_array)存储在栈中,1024*1024 的 int 数组(约 4MB)远超单片机栈的默认大小,会导致栈溢出。


问题:在单片机中,以下哪种方式可以确保中断服务程序 (ISR) 的原子性?选项:A. 使用全局变量;B. 使用 volatile 关键字;C. 禁用中断;D. 使用动态内存分配

答案C。解析:原子性指操作不可被打断,禁用中断可避免 ISR 执行时被其他中断打断;A(全局变量不保证原子性)、B(volatile 仅保证内存可见性)、D(动态分配与原子性无关)均错误。


1. 宏定义表达式

问题#define HW_KEY_Y (0x01 << 4),HW_KEY_Y 的十六进制值 =?十进制值 =?计算0XC3 & (0X80)=?答案

  • 十六进制:0x100x01<<41×16=16,对应十六进制 0x10)
  • 十进制:16
  • 0XC3 & 0X80:0xC3 是11000011,0X80 是10000000,按位与结果为10000000,即0X80(十进制 128)

2. 宏定义运算

问题#define MAX(x,y) x>y?x:yint a=3,b=2时,执行MAX(a++,++b)后,结果、a、b 分别是?答案 :宏展开为a++>++b?a++:++b

  • 先算a++>++b:a=3(后自增),b 先自增为 3 → 3>3不成立;
  • 执行++b:b 变为 4;
  • 最终:结果 = 4,a=4(a++ 执行后),b=4。

3. 数组与指针

问题int *p[10]中 p 表示?int (*q)[10]中 q 表示?答案

  • int *p[10]:p 是指针数组(存储 10 个 int 类型指针的数组);
  • int (*q)[10]:q 是数组指针(指向 "包含 10 个 int 元素的数组" 的指针)。

指针与数组输出

问题:代码输出是?

复制代码
int main(){
  int arr[]={1,2,3,4,5};
  int *p=(int*)(&arr+1);
  printf("arr=%d,%d\n",*(arr+1),*(p-1));
}

答案

  • *(arr+1):arr 是数组首地址,arr+1指向元素 2 → 输出 2;
  • &arr+1:指向数组 arr 的 "下一个数组",p-1指向 arr 最后一个元素 5 → 输出 5;最终输出:arr=2,5

结构体大小与输出

问题

复制代码
typedef struct{
  char a;
  unsigned short b;
}test_t;
int i;
test_t test={0x01,0x02};
char *p=(char*)&test;
for(i=0;i<sizeof(test_t);i++){
  printf("%x,",p[i]);
}
  • 结构体 test_t 大小是?
  • printf 输出是?
  • 题目条件不足的点是?

答案

  • 结构体大小:受内存对齐 影响,char 占 1 字节,unsigned short 占 2 字节,对齐后总大小为4 字节(a 占 1 字节,补 1 字节对齐,b 占 2 字节);
  • 输出:依赖内存字节序 (小端 / 大端),若小端对齐:a=0x01,b=0x02(占 2 字节,小端存储为 0x02、0x00),补 1 字节为 0x00 → 输出1,0,2,0,
  • 条件不足:未说明内存对齐规则处理器字节序(小端 / 大端)。

1. 按键控制 LED 翻转

问题 :编写程序,通过按键输入控制 LED 状态翻转(按下按键时,LED 从亮变灭 / 从灭变亮)。已知函数:api_gpio_in()(读取按键 IO)、api_set_led_on()(亮灯)、api_set_led_off()(灭灯),补全代码:

复制代码
void main(void){
    //do thing....
    While(1){
        // 补全逻辑
    }
}

答案 :需增加按键消抖状态变量,代码如下:

复制代码
void main(void){
    // 定义LED状态(0=灭,1=亮)
    uint8_t led_state = 0;
    // 按键状态(0=未按下,1=按下)
    uint8_t key_state = 0;
    // 初始化LED为灭
    api_set_led_off();

    While(1){
        // 读取按键状态(假设按键按下时返回1)
        key_state = api_gpio_in();
        
        // 按键按下(消抖:简单延时后再确认)
        if(key_state == 1){
            // 消抖延时(比如10ms,根据实际需求调整)
            delay_ms(10);
            // 再次确认按键按下
            if(api_gpio_in() == 1){
                // 翻转LED状态
                if(led_state == 0){
                    api_set_led_on();
                    led_state = 1;
                }else{
                    api_set_led_off();
                    led_state = 0;
                }
                // 等待按键释放(避免重复触发)
                while(api_gpio_in() == 1);
            }
        }
    }
}

2. n×n 矩阵顺时针旋转 90 度

问题 :编写 C 函数rotateMatrix,将 n×n 二维矩阵顺时针旋转 90 度(如示例:3×3 矩阵旋转后行列交换并逆序)。

答案 :思路:先转置矩阵 ,再反转每一行,代码如下:

复制代码
#define N 100
void rotateMatrix(int matrix[N][N]){
    // 步骤1:转置矩阵(行变列,列变行)
    for(int i = 0; i < N; i++){
        for(int j = i + 1; j < N; j++){
            // 交换matrix[i][j]和matrix[j][i]
            int temp = matrix[i][j];
            matrix[i][j] = matrix[j][i];
            matrix[j][i] = temp;
        }
    }

    // 步骤2:反转每一行的元素
    for(int i = 0; i < N; i++){
        for(int j = 0; j < N/2; j++){
            // 交换matrix[i][j]和matrix[i][N-1-j]
            int temp = matrix[i][j];
            matrix[i][j] = matrix[i][N-1-j];
            matrix[i][N-1-j] = temp;
        }
    }
}

示例验证:原矩阵:

复制代码
1 2 3
4 5 6
7 8 9

转置后:

复制代码
1 4 7
2 5 8
3 6 9

反转每一行后(即旋转 90 度结果):

复制代码
7 4 1
8 5 2
9 6 3

3. 不均匀绳子计时问题

问题:粗细不均匀的绳子,烧完 1 根需 1 小时,如何用这批绳子计时 15 分钟、30 分钟、45 分钟?

答案 :利用 "绳子可以从两端同时点燃(烧完时间为原时间的 1/2)" 的特性:

  • 30 分钟 :取 1 根绳子,从两端同时点燃,烧完即为 30 分钟。
  • 15 分钟 :取 2 根绳子(记为 A、B):
    1. 同时点燃 A 的两端 + B 的一端;
    2. A 烧完时(30 分钟),立即点燃 B 的另一端;
    3. B 剩余部分从两端烧,烧完即为 15 分钟。
  • 45 分钟 :取 3 根绳子(记为 A、B、C):
    1. 同时点燃 A 的两端 + B 的一端 + C 的一端;
    2. A 烧完时(30 分钟),立即点燃 B 的另一端;
    3. B 烧完时(额外 15 分钟),总时间为 30+15=45 分钟。
相关推荐
NULL指向我3 小时前
STM32F407VET6学习笔记14:Bootloader程序笔记
笔记·stm32·学习
别了,李亚普诺夫3 小时前
定时器与输出比较-学习笔记
笔记·stm32·学习
mastercoder--3 小时前
速通51单片机————按键控制LED流水灯与定时器闹钟
单片机·嵌入式硬件·51单片机
西城微科方案开发3 小时前
智能打气泵方案开发设计
单片机·嵌入式硬件·方案公司推荐
硅农深芯4 小时前
ARM Cortex-M系列的内核型号有什么区别,该怎么选择
arm开发·单片机·芯片
Y unes5 小时前
《uboot基础命令记录①》
linux·驱动开发·嵌入式硬件·mcu·ubuntu·uboot
Dillon Dong6 小时前
从C到Simulink: 使用 `simulation_stubs`(仿真存根)处理MBD中的硬件依赖
c语言·stm32·matlab
jencepan6 小时前
【3C拓展坞】40V20A同步四开关升降压控制器 太矽TX9575
单片机·嵌入式硬件
墨辰JC8 小时前
STM32架构基于调度器的非阻塞按键状态机设计
stm32·microsoft·架构·状态机·调度器
qq_411262429 小时前
用MCU一个GPIO自锁PMOS就能实现按键开关机
单片机·嵌入式硬件