(十四)嵌入式面试题收集: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 分钟。
相关推荐
SystickInt4 小时前
32 DMA实现ROM与RAM通信
stm32·单片机·嵌入式硬件
IAR爱亚系统4 小时前
在IAR Embedded Workbench for Renesas RH850中开发和调试Renesas RH850 MCU
嵌入式·嵌入式软件开发·iar·汽车嵌入式
俊昭喜喜里6 小时前
STM32开发板电源设计( DCDC 电路和 LDO 电路 )
stm32·单片机·嵌入式硬件
m0_555762906 小时前
方案再再对比
单片机
路弥行至6 小时前
FreeRTOS任务管理详解中: FreeRTOS任务创建与删除实战教程(动态方法)
c语言·开发语言·笔记·stm32·操作系统·freertos·入门教程
boneStudent7 小时前
Day20:串口基本配置与收发
stm32·单片机·嵌入式硬件
紫阡星影7 小时前
基于Arduino模拟烟雾监测系统
单片机·嵌入式硬件·arduino
HIZYUAN8 小时前
嵌入式开发踩坑记: AG32硬件设计指南(一)
stm32·单片机·嵌入式硬件·fpga开发·硬件设计·最小系统·agm ag32
墨染倾城殇8 小时前
车规级蓝牙模组BT3721V:汽车无钥匙进入系统解决方案
嵌入式·蓝牙模块·汽车电子·车规级蓝牙·飞易通
三佛科技-134163842128 小时前
BP85958D输出12V400MA智能家居电源芯片(典型应用电路、替代型号HN32512)
单片机·嵌入式硬件·物联网·智能家居·pcb工艺