STM32常用外设面试题

GPIO

什么是GPIO?如何配置GPIO?

GPIO是 通用输入输出端口(General Purpose Input/Output) 的缩写,是一种可以通过程序灵活配置为输入或输出模式的数字信号引脚。

GPIO有哪些常用寄存器?

  1. 端口配置寄存器(GPIOx_CRL 和 GPIOx_CRH)
    端口配置寄存器
    对于stm32f1系列的单片机,输出的上下拉是通过设置ODR寄存器来配置的,1为上拉,0为下拉。而f4等更高级别的不一样,由GPIOx_PUPDR配置。

  2. 端口数据寄存器(IDR 和 ODR)
    下面是ODR的说明,IDR类似。
    端口数据寄存器

  3. 端口置位/复位寄存器(BSRR)
    端口置位/复位寄存器

为什么有了 ODR 寄存器,还要这个 BSRR 寄存器呢?我们先看看 BSRR 的寄存器描述,首先 BSRR 是只写权限,而 ODR 是可读可写权限。BSRR 寄存器 32 位有效,对于低 16 位(0-15),我们往相应的位写 1(BSy=1),那么对应的 IO 口会输出高电平,往相应的位写 0(BSy=0),对 IO 口没有任何影响,高 16 位(16-31)作用刚好相反,对相应的位写 1(BRy=1)会输出低电平,写 0(BRy=0)没有任何影响,y=0~15。

也就是说,对于 BSRR 寄存器,你写 0 的话,对 IO 口电平是没有任何影响的。我们要设置某个 IO 口电平,只需要相关位设置为 1 即可。而 ODR 寄存器,我们要设置某个 IO 口电平,我们首先需要读出来 ODR 寄存器的值,然后对整个 ODR 寄存器重新赋值来达到设置某个或者某些 IO 口的目的,而 BSRR 寄存器直接设置即可,这在多任务实时操作系统中作用很大。BSRR寄存器还有一个好处,就是 BSRR 寄存器改变引脚状态的时候,不会被中断打断,而 ODR 寄存器有被中断打断的风险。

GPIO有哪些工作模式?

  1. 输入浮空
  2. 输入上拉
  3. 输入下拉
  4. 模拟输入
  5. 开漏输出
  6. 推挽输出
  7. 开漏式复用功能
  8. 推挽式复用功能

具体见寄存器说明

如何使用GPIO点亮一个LED灯?

#include "main.h"
#include "stm32f1xx_hal.h"

int main(void) {
    HAL_Init();                     // 初始化HAL库
    SystemClock_Config();           // 配置系统时钟(由CubeMX生成)
    
    // 初始化GPIO(由CubeMX生成的MX_GPIO_Init函数)
    MX_GPIO_Init();

    while (1) {
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);   // 点亮LED
        HAL_Delay(500);                                       // 延时500ms
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET); // 熄灭LED
        HAL_Delay(500);
    }
}

什么是GPIO的复用功能?在STM32中如何配置GPIO复用功能?

GPIO复用功能的概念
GPIO(General Purpose Input/Output)是单片机用于输入/输出信号的通用引脚。但在实际应用中,GPIO引脚不仅仅用作普通的输入/输出引脚,很多引脚具有复用功能,即可以通过配置将其用作特定的外设功能,例如串口(USART)、定时器(TIM)、I2C、SPI等。这样可以最大化地利用有限的引脚资源。

STM32中GPIO复用功能的配置方法
对于stm32f1系列的单片机,根据外设的需要将GPIO配置为复用推挽输出、复用开漏输出或者其他的输入模式,然后开启外设的时钟并初始化即可。

如何配置GPIO中断?

  1. 开启 GPIO 时钟(使能 GPIO 端口的时钟)。
  2. 配置 GPIO 为输入模式,并选择中断触发方式(上升沿、下降沿或双边沿)。
  3. 使能并配置外部中断(EXTI),将 GPIO 连接到中断控制器。
  4. 配置 NVIC(嵌套向量中断控制器),设置中断优先级并使能中断。
  5. 编写中断服务函数(ISR),在中断发生时执行所需的操作。

什么是GPIO的输出速度?有哪些选项?如何选择合适的速度?

GPIO(通用输入输出)输出速度指的是 GPIO 引脚的开关速率,即它们从高电平切换到低电平或从低电平切换到高电平的速率。输出速度通常影响信号的上升时间、下降时间以及驱动能力,主要用于匹配不同外设或负载的需求。

对于stm32来说,有低速、中速和高速三种模式,对不同的外设选择不同的速度。如控制LED的亮灭就可以选择低速,I2C通信可以选择中速,SDIO、ETH可以选择高速。速度越快功耗越高。

如何处理GPIO引脚复用资源冲突的问题?

  1. 查看手册,看看是否有其他相同外设可以使用,比如如果USART1冲突了,看看USART2能不能用。
  2. 重映射冲突的外设。

定时器

STM32定时器有哪些类型?它们的主要区别是什么?

stm32定时器种类及区别
除此之外,高级定时器还有重复计数器寄存器 RCR,通过设置这个寄存器为N可以在定时器发生N次溢出之后才触发中断,利用这个寄存器可以输出指定个数的PWM。

重复计数器寄存器用于设置重复计数器值,因为它具有影子寄存器,所以它本身只是起缓冲作用。当更新事件发生时,该寄存器的值会转移到其影子寄存器中,从而真正起作用。TIMx_ RCR 寄存器描述如图所示:
重复计数器寄存器 RCR

STM32定时器的基本作用是什么?

对于基本定时器,其主要功能是产生定时的中断或事件。

对于通用定时器和高级定时器,其主要功能除了定时中断或事件之外,还有产生PWM、测量脉冲宽度等功能。

什么是定时器的预分频器(Prescaler)?

定时器的预分频器(Prescaler, PSC) 是 STM32 定时器中的一个重要参数,它的作用是对定时器输入时钟进行分频,从而控制计数器(CNT)的计数速率。
在这里插入图片描述

什么是定时器的自动重装载寄存器(ARR)?它如何影响定时器的周期?

自动重装载寄存器(ARR) 是 STM32 定时器中的一个关键参数,它决定了 定时器计数的最大值,并影响定时中断、PWM 频率等功能。对于递增计数模式,当计数寄存器的值与自动重装载寄存器相等的时候,在下一个时钟到来时会变成0;对于递减计数模式,当计数寄存器的值与0相等的时候,在下一个时钟到来时会变成自动重装载寄存器的值。

T=(ARR+1)×(PSC+1)×1fclkT = (ARR + 1) \times (PSC + 1) \times \frac{1}{f_{\text{clk}}}T=(ARR+1)×(PSC+1)×fclk1

ARR可以由 控制寄存器的APRE位设置是否进行缓冲。如果ARPE为1,设置的ARR值不会立刻刷新到它的影子寄存器中,也就是说不会立刻起作用,而是要等到定时器发生溢出才会刷新到影子寄存器中。

在这里插入图片描述自动重装载寄存器:
自动重装载寄存器(ARR)
计数寄存器:
计数寄存器

什么是定时器的计数模式?有哪些常用模式?

STM32定时器有哪些类型?它们的主要区别是什么?这一问题。

如何启用和关闭STM32定时器?

控制寄存器TIMx_CR1的CEN位置1开启,0关闭。

如何使用STM32定时器生成PWM?

想要用定时器输出PWM,需要用到通用计时器或者高级计时器的比较输出功能。

在这里插入图片描述
在这里插入图片描述
该寄存器的模式设置位OC2M[2:0]就是对应着通道2的模式设置,此部分由3位组成。总共可以配置成8种模式,我们使用的是 PWM模式,所以这 3 位必须设置为 110 或者 111,分别对应 PWM 模式1和 PWM 模式2。这两种 PWM模式的区别就是输出有效电平的极性相反。位OC2PE控制输出比较通道2的预装载使能,实际就是控制CCR2寄存器是否进行缓冲。因为CCR2寄存器也是有影子寄存器的,影子寄存器才是真正起作用的寄存器。CC2S[1:0]用于设置通道2的方向(输入/输出)默认设置为0,就是设置通道作为输出使用。

在这里插入图片描述
CCxE使能相对应的通道,CCxP设置相应通道的极性。CCxP与OC2M[2:0]所选择的PWM1或者PWM2模式共同决定了PWM的输出极性,具体查看下面的图示。
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
当CCxP=0(有效电平为1)且OCxM[2:0]=110(PWM1)的时候,计数寄存器CNT小于CCRx输出高电平,大于等于CCRx的时候输出低电平,因此占空比为
D=CCRARR+1×100%D = \frac{CCR}{ARR + 1} \times 100\%D=ARR+1CCR×100%
PWM频率为
fPWM=fclk(PSC+1)×(ARR+1)f_{PWM} = \frac{f_{clk}}{(PSC + 1) \times (ARR + 1)}fPWM=(PSC+1)×(ARR+1)fclk

因此,使用定时器输出PWM需要下面几步:

  1. 确定需要的PWM频率和占空比,计算相应的PSC、ARR、CCR的值。
  2. 选择某个定时器的某个通道作为输出端口,进行相应配置,包括开启对应端口的GPIO时钟和复用模式,开启定时器时钟,设置通道的模式为比较输出模式,选择PWM1模式,设置CCxP为0(为了占空比公式正确,如果相反则需要用1减去计算结果)。开启通道对应的TIMx_CCER的使能位,使能通道。
  3. 将计算好的值设置到相应的寄存器中去。
  4. 将TIMx_CR1的CEN位置1,使能定时器。

STM32定时器捕获/比较功能的典型应用是什么?

  1. 产生PWM输出。
  2. 测量脉冲宽度

什么是定时器重载中断?

就是定时器溢出中断。

如何配置STM32的定时器从模式(Slave Mode)和主模式(Master Mode)?

通过TIMx_CR2的MMS选择主模式,设置为010在定时器溢出的时候产生触发信号。通过TIMx_SMCR的SMS选择从模式,设置为111使用触发输入的上升沿驱动计数器。通过设置TIMx_SMCR的TS可以选择触发源,具体设置什么数值对应什么触发源不同的定时器有不同的结果,可通过查表得知。TS的改变必须在SMS为000或者定时器未运行的情况下进行。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


DMA

什么是DMA?在STM32中DMA的作用是什么?

DMA是一种计算机系统中的数据传输技术,它允许外设或存储设备在不经过CPU干预的情况下,直接在存储器和外设之间或在存储器之间传输数据。DMA的主要特点是高效地进行大批量数据传输,减少CPU的负担,提高系统性能。

DMA的传输方向:

  1. 存储器到存储器(如复制大块数据)
  2. 存储器到外设(如从内存发送数据到UART、SPI等)
  3. 外设到存储器(如从ADC采集数据存入内存)

DMA传输的主要配置项有哪些?

  1. 传输方向(Direction)
  2. 源地址(Peripheral Address)
  3. 目标地址(Memory Address)
  4. 数据传输长度(Number of Data)
  5. 数据宽度(Data Width)
  6. 地址自增模式(Increment Mode)
  7. DMA模式(Mode)
    • 普通模式:传输完成后DMA停止,需要重新启动
    • 循环模式:数据传输完成后自动重启(适用于持续数据采集,如ADC)
  8. 传输优先级(Priority Level)
  9. DMA中断(Interrupts)

什么是DMA的循环模式(Circular Mode)?它的典型应用是什么?

DMA 循环模式(Circular Mode) 是指 DMA 传输完成后不会自动停止,而是自动从头开始重新执行传输,无需 CPU 重新配置 DMA 传输参数。这样,数据可以持续不断地进行传输,非常适合需要连续数据采集或流式数据处理的应用。

典型应用如ADC采集等。

如何启用STM32 DMA?需要配置哪些寄存器?

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

当DMA方向是外设到内存或内存到外设的时候,按照寄存器的说明填写地址;当内存到内存的时候外设地址寄存器存储源地址,存储器地址寄存器存储目标地址。


SDIO

什么是SDIO?STM32中SDIO的主要用途是什么?

SDIO支持哪些类型的卡?

SDIO在STM32中使用哪些引脚?

SDIO的时钟频率是多少?如何调整?

SDIO通信协议的基本步骤是什么?

如何使用STM32的HAL库初始化SDIO接口?

SDIO中单块传输和多块传输的区别是什么?

如何检测SD卡的插入和拔出?

如何区分SDIO的命令传输和数据传输?

如何通过SPI连接SD卡?


RTC

什么是RTC?

STM32F103的实时时钟(RTC)是一个独立的定时器。STM32的RTC模块拥有一组连续计数的计数器,在相对应的软件配置下,可提供时钟日历的功能。修改计数器的值可以重新设置系统的当前时间和日期。

STM32的RTC模块需要哪些外部硬件支持?

  1. 外部晶振(LSE - 低速外部晶振)
  2. 备用电池(VBAT引脚)

STM32中RTC的主要寄存器有哪些?它们的作用是什么?

在这里插入图片描述

RTC_CRL:
在这里插入图片描述

RTC 预分频装载寄存器(RTC_PRLH/RTC_PRLL):
如果输入时钟是32.768kHz,这个预分频寄存器中写入7FFFF可获得周期1秒钟的信号。
在这里插入图片描述
在这里插入图片描述

还有一个与RTC预分频装载寄存器类似的RTC预分频余数寄存器(RTC_DIVH/RTC_DIVL),也是20个有效位,用来获得比秒钟更加准确的时钟,比如可以得到0.1秒,甚至0.01秒等,该寄存器的值自减的,用于保存还需要多少时钟周期获得一个秒信号。在一次秒钟更新后,由硬件重新装载。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

stm32f103zet6复位之后想要修改RTC寄存器的值,需要以下步骤:

  1. 使能电源和备份接口时钟: 设置寄存器 RCC_APB1ENRPWRENBKPEN 位,以使能电源控制器(PWR)和备份接口(BKP)的时钟。
  2. 解除备份域写保护: 设置寄存器 PWR_CRDBP 位,允许对备份寄存器和RTC的访问。
  3. 等待RTC寄存器同步: 在使能RTC时钟后,需要等待RTC寄存器与APB1总线的同步完成,也就是等待RTC_CRLRSF由硬件置1。
  4. 进入RTC配置模式: 设置 RTC_CRL 寄存器的 CNF 位,使RTC进入配置模式。
  5. **等待RTC寄存器操作完成:**在每次对RTC寄存器进行写操作后,需要等待操作完成。可以通过检查 RTC_CRL 寄存器的 RTOFF 位来确认。

如何在STM32中初始化RTC并设置时间和日期?

先按照上面的复位之后修改RTC寄存器需要的步骤配置好,然后通过修改备份域控制寄存器 (RCC_BDCR)的RTCSEL[1:0]选择时钟源,再按照时钟源频率配置RTC预分频装载寄存器,使得分频后的时钟频率为1秒,最后修改RTC计数器寄存器,设置时间。

在配置之前,可以判断备份数据寄存器BKP_DR的标志位(自己选择和设置)来确定是不是第一次配置,如果配置过就不再次配置;如果首次配置,在完成之后就将备份数据寄存器的相应位置1。

在这里插入图片描述
在这里插入图片描述

如何读取STM32 RTC当前的时间和日期?

直接读取RTC计数寄存器即可,根据公式换算成时间和日期。

什么是RTC的备用域?备用域有什么作用?

在STM32微控制器中,备份域(Backup Domain) 是一个特殊的区域,主要用于在主电源(VDD)断电的情况下,仍能保持关键数据的完整性。该区域由备用电源(VBAT)供电,确保其中的数据在掉电或系统复位后不丢失。

如何在STM32中实现RTC的闹钟功能?

先按照上面的复位之后修改RTC寄存器需要的步骤配置好,然后将需要闹钟的日期换算成秒,写入RTC闹钟寄存器。使能闹钟中断并配置相应的优先级,编写中断处理函数。


<think>嗯,用户想准备STM32相关的面试题,需要常见问题及答案。首先,我得回忆一下STM32的基础知识,比如启动流程、时钟配置、中断处理这些基本点。然后,可能涉及到外设的使用,比如GPIO、定时器、USART、SPI、I2C等,这些都是面试常问的内容。 用户提供的引用里有关于51单片机STM32的对比,特别是启动过程和内存大小的差异,这可能是一个重点。比如启动过程中F1和F4的不同,或者内存管理的问题。此外,引用3提到硬件问题排查,说明调试和故障处理也是常见考点。 接下来,我需要整理常见的问题,比如STM32启动流程、时钟树配置、中断优先级、GPIO模式选择、DMA的作用、低功耗模式、看门狗使用、固件库结构、IAP实现、RTOS整合等。每个问题需要简明扼要的解答,并且结合引用中的例子,比如启动过程分哪几个步骤,或者时钟配置的重要性。 还要注意用户提到的系统级指令,比如数学公式的格式,不过这里可能用不上。但需要确保回答结构清晰,分点列出问题和解答,便于用户理解。同时,生成的相关问题要覆盖更多潜在考点,比如外设区别、调试方法、RTOS整合挑战等。 可能还要考虑用户的实际需求,作为面试准备,问题需要涵盖基础到中级,可能涉及项目经验和实际应用场景。比如如何优化代码效率,或者如何实现OTA升级,这些实际应用中的问题。 需要检查引用内容,确保引用标识正确,比如引用[^1]提到启动过程和资源分配,引用[^2]关于内存大小,引用[^3]的调试案例。在解答中适当引用这些内容,增强答案的可信度。 最后,确保语言口语化,避免技术术语堆砌,但又要准确。例如解释中断嵌套时,用优先级分组的方式来描述,而不是直接复制术语。同时,问题要覆盖全面,帮助用户系统性地准备面试。</think>### STM32单片机面试常见问题与解答 --- #### **1. STM32启动过程是怎样的?** STM32启动过程分为以下步骤: 1. **复位向量初始化**:从`0x00000000`地址读取栈顶指针(SP)和程序计数器(PC)。 2. **系统初始化**:执行`SystemInit()`函数,配置时钟树(如HSI、HSE、PLL)、Flash预取和等待周期。 3. **跳转到主程序**:执行`main()`函数,进入用户代码。 - **注意**:F1和F4系列在内存大小和时钟配置上有差异,例如F4的SRAM更大(192K)。 --- #### **2. STM32时钟树配置的关键点是什么?** 时钟树是STM32的核心,配置需关注: - **时钟源选择**:HSI(内部高速)、HSE(外部高速)、LSE(外部低速)。 - **PLL配置**:通过倍频/分频生成系统主频(如72MHz for F1,168MHz for F4)。 - **外设时钟使能**:通过RCC寄存器开启GPIO、USART等外设时钟。 - **关键代码示例**: ```c RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); ``` --- #### **3. 如何配置STM32的中断优先级?** STM32使用NVIC(嵌套向量中断控制器)管理中断优先级: - **优先级分组**:通过`NVIC_PriorityGroupConfig()`设置抢占优先级和子优先级的位数(如分组2:2位抢占,2位子优先级)。 - **中断服务函数**:需在启动文件中声明中断向量,并在代码中实现。 - **示例**:外部中断配置: ```c EXTI_InitTypeDef EXTI_InitStruct; EXTI_InitStruct.EXTI_Line = EXTI_Line0; EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising; EXTI_Init(&EXTI_InitStruct); ``` --- #### **4. GPIO的输入/输出模式如何选择?** - **输出模式**: - 推挽输出(PP):驱动能力强,适合LED、继电器。 - 开漏输出(OD):需外接上拉电阻,适合I2C总线。 - **输入模式**: - 浮空输入(Floating):用于按键检测(需外部上拉/下拉)。 - 模拟输入(Analog):用于ADC采样。 - **注意**:STM32的I/O操作需先使能外设时钟,与51单片机直接操作不同。 --- #### **5. DMA的作用及配置步骤?** DMA(直接内存访问)用于外设与内存间高效数据传输,减少CPU负载。 - **配置步骤**: 1. 开启DMA时钟。 2. 配置DMA通道、传输方向(外设↔内存)、数据宽度。 3. 设置源地址和目的地址。 4. 使能DMA中断(可选)。 - **应用场景**:ADC多通道采样、SPI/I2S数据传输。 --- #### **6. 如何实现STM32的低功耗模式?** STM32支持多种低功耗模式: - **睡眠模式(Sleep)**:CPU停止,外设运行。 - **停止模式(Stop)**:所有时钟关闭,保留RAM内容。 - **待机模式(Standby)**:最低功耗,需复位或外部中断唤醒。 - **关键代码**: ```c PWR_EnterStopMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI); ``` --- #### **7. STM32的看门狗(WWDG/IWDG)有什么区别?** - **独立看门狗(IWDG)**:基于LSI时钟,用于防止软件死锁,需定期“喂狗”。 - **窗口看门狗(WWDG)**:基于APB1时钟,需在指定时间窗口内喂狗,否则复位。 - **典型应用**:IWDG用于系统级监控,WWDG用于关键任务超时检测。 --- #### **8. 如何调试STM32外设驱动问题?** 调试步骤: 1. **检查时钟配置**:确认外设时钟已使能。 2. **验证引脚复用**:使用`GPIO_PinAFConfig()`配置复用功能。 3. **排查时序问题**:如I2C的起始/停止信号、SPI的时钟极性。 4. **使用逻辑分析仪**:抓取总线信号分析波形。 --- #### **9. STM32的固件库(HAL/LL/标准库)有什么区别?** - **标准库(Standard Peripheral Library)**:直接操作寄存器,代码效率高。 - **HAL库(Hardware Abstraction Layer)**:跨系列兼容,但代码体积大。 - **LL库(Low-Layer)**:轻量级,兼顾效率和易用性。 - **建议**:HAL库适合快速开发,LL库适合资源敏感场景[^1]。 --- #### **10. 如何实现STM32的IAP(在应用编程)?** IAP步骤: 1. **Bootloader设计**:通过串口/USB接收固件,写入Flash指定地址。 2. **跳转机制**:从Bootloader跳转到用户程序(需设置向量表偏移)。 3. **校验机制**:添加CRC校验确保固件完整性。 - **关键代码**: ```c typedef void (*pFunction)(void); pFunction JumpToApp = (pFunction)(*(__IO uint32_t*)(APP_ADDRESS + 4)); __set_MSP(*(__IO uint32_t*)APP_ADDRESS); JumpToApp(); ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值