电控---基础篇

一、 时钟

时钟控制器(Reset Clock Control,RCC):

1.有低速高速两种(high speed,HS与Low Speed,LS)
  • 低速用于实时时钟(Real Time Clock,RTC)
  • 高速用于定时器,UART,ADC等多种外设

2.有内外部两种(Internal,I与External,E)

  • (1)Disable

    • 不用外部时钟,则自启动(强制)使用MCU核心内部时钟
    • 一般是不准的代名词
  • (2)Crystal/ceramic resonator(晶体、陶瓷振荡器)

    • 使用开发板上的某个元件产生,该元件俗称晶振
    • 可以接受一定激励产生时钟信号,经过MCU内部时钟电路驱动后可以作为单片机的驱动

3.Bypass clock source(旁路时钟源)

  • 由外部其他设备主动给出
  • 该时钟信号不经过MCU内部时钟电路驱动可直接作为单片机的时钟
    电控---基础篇_第1张图片

时钟树

  • 基本时钟信号会经过单片机MCU内部电路的处理,通过倍频分频实现不同频率的子时钟
  • 不同的子时钟作用到不同的设备上,适配不同设备的工作环境
  • 按需配置,一般性能拉满

二、通用输入输出端口

四种输入

1.下拉输入

  • 数字信号输入,只有高低电平两种
  • 等效在MCU内对引脚接一个电阻,这个电阻叫下拉电阻
  • 阻值具体多少不重要,反正比较大
  • 电阻另一端接MCU的低电平
  • 引脚没有任何输入时,此时读取引脚则是低电平

2.上拉输入

  • 数字信号输入,只有高低电平两种
  • 等效在MCU内对一个引脚接一个电阻,这个电阻叫上拉电阻
  • 阻值具体多少不重要,反正比较大
  • 电阻另一端接MCU的高电平
  • 引脚没有任何输入时,此时读取引脚则是高电平

3.浮空输入:

  • 数字信号输入,只有高低电平两种
  • 不接入任何上拉下拉电阻
  • 引脚没有任何输入时,此时读取引脚电平未定,即悬而不定的状态,浮空
  • 万用表检测可能出现0到3.3V之间的任意值

4.模拟输入:

  • 前三个输入均是离散时间的数字信号,也就是只有低电平和高电平,模拟输入当然可以对连续时间连续值的模拟信号进行读取
  • 可以在单片机中转化成可以被处理的离散时间离散值的数字信号

输出

1.推挽输出

  • 高低电平驱动能力都强
  • 宁折不弯,推挽高低电平相遇会烧坏

2.开漏输出

  • 低电平驱动能力强
  • 高电平驱动能力弱
  • 高电平通过自己主动外接上拉电阻实现输出
  • 输出跳变速度取决于上拉电阻,电阻越小越快
  • 开漏高低电平相遇会变低(类似于C语言的与运算&&)

3.复用***输出
用于外设等需要对引脚绑定某特定MCU内功能输出情况

推挽输出、开漏输出的补充讲解


1. 推挽输出(Push-Pull Output)

基本结构
  • 推挽输出内部有两个晶体管(或MOS管):
    • 上管(P型):连接到电源(VCC),负责将输出拉高(高电平)。
    • 下管(N型):连接到地(GND),负责将输出拉低(低电平)。
  • 两个管子像“推”和“拉”一样协同工作,但同一时间只能有一个导通,避免短路。
工作方式
  • 输出高电平:上管导通,电流从电源通过上管流向输出引脚。
  • 输出低电平:下管导通,电流从输出引脚通过下管流向地。
  • 特点
    • 可以主动输出高电平或低电平,驱动能力强(无需外部电路)。
    • 高低电平切换速度快,适合高速信号。
    • 多个推挽输出不能直接并联(可能短路)。
应用场景
  • 普通GPIO控制(如点亮LED)。
  • PWM信号输出(控制电机、LED亮度)。
  • 需要高速切换的场合(如SPI通信、UART的TX引脚)。

2. 开漏输出(Open-Drain Output)

基本结构
  • 开漏输出只有一个下管(N型)连接到地,上管被省略
  • 输出引脚需要通过外部上拉电阻连接到电源(VCC)才能输出高电平。
工作方式
  • 输出低电平:下管导通,电流通过外部上拉电阻流向地,输出被拉低。
  • 输出高电平:下管关闭,输出通过外部上拉电阻被拉高到电源电压。
  • 特点
    • 高电平依赖外部上拉电阻,驱动能力较弱。
    • 多个开漏输出可以并联(实现“线与”逻辑)。
    • 支持不同电压的系统(通过改变上拉电源电压)。
应用场景
  • I2C总线:多个设备共享同一总线,避免电平冲突。
  • 中断信号线:多个设备可以通过拉低同一中断线触发中断。
  • 电平转换:通过外部上拉不同电压的电源,实现不同电压系统的兼容。

3. 两者的核心区别

特性 推挽输出 开漏输出
结构 有上下两个晶体管 只有下管,需外部上拉电阻
高电平驱动 主动输出高电平(内部驱动) 依赖外部上拉电阻
低电平驱动 主动输出低电平(内部驱动) 主动输出低电平(内部驱动)
总线兼容性 不能直接并联(可能短路) 可并联(实现“线与”逻辑)
电平兼容性 只能输出VCC或GND 可通过外部上拉适配不同电压
速度 较慢(受上拉电阻影响)

4. 生活中的比喻

  • 推挽输出:像一辆车有两个司机,一个专门踩油门(拉高),一个专门踩刹车(拉低),能快速切换方向。
  • 开漏输出:像一辆车只有刹车(拉低),想加速(拉高)需要靠外部力量(比如用绳子拉)。

5. 总结

  • 选推挽:需要快速切换、独立驱动高/低电平的场景(如普通IO、PWM)。
  • 选开漏:需要总线共享、电平转换或避免冲突的场景(如I2C、中断线)。

工程配置

基础设备配置
1.打开CubeMX,选择MCU芯片,选择单片机MCU型号,双击
2.配置复位时钟控制器(Reset Clock Control,RCC)
Crystal/ceramic resonator
3.配置时钟树

  • 根据开发板晶振频率设置HSE的频率
  • 让主频通过HSE
  • 主频配置成50MHz

4.根据不同的烧写器,选择不同的调试模式

  • ST-Link调试器—调试模式: Serial Wire Debug (SWD)
  • J-Link调试器—调试模式: JTAG 或 Serial Wire Debug (SWD)
  • 如果用其他烧写器,请对应配置好

工程管理设置中

  • 1.命名工程,不要有中文等非ASCII码的字符,最好以C语言变量要求
  • 2.修改IDE为MDK-ARM,对应Keil这一套工具
  • 3.代码生成中:配置每个外设生成一个单独的头文件,便于管理
    生成代码

必要的开发前的Keil配置
1.编译优化不好,取消编译优化
2.打开C99模式,添加–cpp11
3.烧写即运行,选择Reset and run


Cortex-M3/M4处理器通俗结构

处理器系统

1.处理器
2.唤醒中断控制器
3.调试与跟踪子系统(调试用)
4.指令、数据码存储器专用传输接口(获取指令编码,数据内容)
5.外设传输接口(各种外部设备,如通信模块,存储器)

存储器

指令存储,数据存储(有地址,just like point)
对存储器的抽象认识:

  • 按一定地址编排,像C语言指针访问内存一样可以被访问。
  • 能存指令
  • 能存数据
  • 有些地址保存给寄存器,用于存储其他外部设备,如通信模块、调试组件、附加存储器等。

处理器可以通过访问存储器来获取指令编码和数据内容
搭配一些电路,对指令编码和数据内容进行运算与操作,输出出来

中断

1.处理器系统在执行代码的时候,会从存储器依次取出指令和数据,这种能力需要在处理器里保存一个存储器地址,就是所谓的程序计数器(Program Counter,PC),也叫程序指针
2.当外部中断(Extern Interrupt,EXTI)事件发生的时候,单片机有一定的策略保护好当前执行的状态,将PC跳转到中断服务函数(即回调函数),然后执行相应的用户自定义编写的处理策略
3.完成中断后,恢复原有执行
上述过程依赖嵌套中断向量控制器(Nested Vectored Interrupt Controller,NVIC)

中断事件有两类优先级

  • 抢占优先级:高的可以直接中断掉低优先级的中断服务函数直接处理
  • 子优先级:在多中断事件发生时 ,高的可以插队到低的前面先处理

嵌套中断向量控制器(Nested Vectored Interrupt Controller, NVIC)是 ARM Cortex-M 系列处理器的核心组件,负责管理中断和异常的优先级、嵌套和调度。其设计目标是实现低延迟、高灵活性的中断处理,满足实时系统的需求。以下从架构、寄存器、优先级机制、中断处理流程及优化技术等方面进行专业级分析。


NVIC补充讲解

1. NVIC 架构与核心特性

(1) 硬件架构
  • 集成于 Cortex-M 内核:与处理器紧耦合,直接控制中断响应逻辑。
  • 向量中断机制:每个中断/异常有唯一的向量地址(存储在向量表中),支持快速跳转。
  • 优先级动态配置:支持软件实时修改中断优先级。
  • 抢占与尾链优化:硬件自动处理中断嵌套时的现场保存与恢复,减少延迟。
(2) 关键特性
  • 支持 1~240 个外部中断(具体数量由芯片厂商定义)。
  • 4~256 级可编程优先级(优先级位数由芯片实现决定,如 Cortex-M3/M4 支持 8 级优先级,即 3 位)。
  • 优先级分组:将优先级分为抢占优先级(Preemption)和子优先级(Subpriority)。
  • 中断屏蔽:通过 PRIMASKFAULTMASKBASEPRI 寄存器实现中断全局或条件屏蔽。

2. NVIC 寄存器详解

NVIC 通过内存映射寄存器配置,关键寄存器如下(以 Cortex-M3/M4 为例):

(1) 中断使能寄存器
  • ISERx (Interrupt Set Enable Register):写 1 到某位使能对应中断。
  • ICERx (Interrupt Clear Enable Register):写 1 到某位禁用对应中断。
(2) 中断挂起寄存器
  • ISPRx (Interrupt Set Pending Register):手动触发中断挂起。
  • ICPRx (Interrupt Clear Pending Register):清除挂起状态。
(3) 优先级寄存器
  • IPRx (Interrupt Priority Register):配置中断优先级,每个中断占用 8 位(实际使用位数由芯片决定)。
    示例:若使用 4 位优先级(高 4 位有效),优先级字段格式为:
    Priority = (Preemption Priority << (8 - Priority_Width)) | Subpriority
(4) 系统异常寄存器
  • SHPRx (System Handler Priority Register):配置系统异常(如 SysTick、PendSV)的优先级。

3. 优先级分组与抢占机制

(1) 优先级分组寄存器 (AIRCR)
  • AIRCR[10:8] (PRIGROUP):定义优先级分组方式,将优先级位划分为抢占和子优先级。
    分组规则:
    抢占优先级位数 = PRIGROUP[2:0]
    子优先级位数 = Total_Priority_Bits - 抢占优先级位数

    示例:若总优先级位数为 4(即 16 级优先级),设置 PRIGROUP=5(二进制101),则:
    抢占优先级位数 = 3(高3位为抢占优先级),
    子优先级位数 = 1(低1位为子优先级)。

(2) 抢占规则
  • 若新中断的抢占优先级高于当前执行中断的抢占优先级,则发生抢占。
  • 子优先级仅在多个中断同时挂起且抢占优先级相同时决定执行顺序。

4. 中断处理流程

(1) 中断触发
  1. 中断源激活:外设触发中断信号(如定时器溢出)。
  2. 挂起状态设置:NVIC 将中断标记为挂起(Pending)。
  3. 优先级裁决:NVIC 比较当前执行任务的优先级与新中断的抢占优先级。
(2) 响应阶段
  1. 抢占判断:若允许抢占,CPU 暂停当前任务,保存现场(自动压栈:PC, PSR, R0-R3, R12, LR)。
  2. 向量表跳转:根据中断号从向量表获取 ISR 入口地址。
  3. ISR 执行:执行用户编写的中断服务程序。
(3) 中断返回
  1. 尾链优化 (Tail-Chaining):若挂起中断的优先级高于当前 ISR,直接跳转到新 ISR,跳过恢复现场。
  2. 现场恢复:通过 BX LRPOP {PC} 指令触发异常返回,硬件自动恢复现场。

5. 中断延迟与优化

(1) 关键延迟指标
  • 中断响应时间:从中断触发到 ISR 第一条指令执行的时间(Cortex-M 典型值为 12 周期)。
  • 上下文切换时间:现场保存/恢复的周期数(通常 12~20 周期)。
(2) 优化技术
  • 尾链优化:避免不必要的现场恢复/保存,减少连续中断的延迟。
  • 晚到中断处理 (Late Arrival):高优先级中断在保存现场期间到达时,优先处理高优先级中断。
  • 优先级压缩:合理分配优先级,避免过多抢占导致堆栈溢出。

6. 高级功能

(1) 动态优先级修改
  • 通过写 NVIC_IPRx 寄存器实时修改中断优先级。
  • 应用场景:动态调整任务重要性(如实时任务优先级提升)。
(2) 中断屏蔽
  • PRIMASK:全局关闭中断(CPSID I)。
  • BASEPRI:屏蔽优先级低于某阈值的中断(如 BASEPRI = 0x40 屏蔽优先级 ≥ 4 的中断)。
(3) 软件触发中断
  • 通过写 NVIC_STIR 寄存器(Software Trigger Interrupt Register)触发中断。

7. 调试与问题排查

(1) 常见问题
  • 优先级配置错误:导致预期外的中断嵌套或阻塞。
  • 中断服务程序过长:引发其他高优先级中断的响应延迟。
  • 共享资源冲突:未使用临界区保护导致数据竞争。
(2) 调试工具
  • CMSIS-Core 函数:如 __get_IPSR() 获取当前中断号。
  • 调试器监控:通过 IDE 查看 NVIC 寄存器状态和中断挂起情况。

8. 实际代码示例(基于寄存器操作)

(1) 配置外部中断 EXTI0
// 使能 EXTI0 中断(假设 EXTI0 对应中断号 6)
NVIC_ISER0 |= (1 << 6); // ISER0 对应中断 0-31

// 设置优先级(抢占优先级 2,子优先级 1,优先级位数为 4)
uint8_t priority = (2 << (8 - 4)) | 1; // 假设优先级位数为 4
NVIC_IPR6 = priority << 4; // IPR6 对应中断号 6,优先级值左移 4 位(高4位有效)

// 设置优先级分组(抢占3位,子1位)
SCB->AIRCR = (0x5FA << 16) | (0x5 << 8); // PRIGROUP=5
(2) 临界区保护
#define ENTER_CRITICAL()  __asm volatile ("cpsid i")
#define EXIT_CRITICAL()   __asm volatile ("cpsie i")

9. 总结

NVIC 是 Cortex-M 实时性的核心保障,其设计在硬件层面实现了:

  • 低延迟中断响应:通过向量化跳转和尾链优化。
  • 灵活的优先级管理:支持动态调整和分组配置。
  • 安全的嵌套机制:硬件自动处理现场保存与恢复。

深入掌握 NVIC 需结合芯片手册(如 STM32 参考手册)和 ARMv7-M 架构文档,重点关注寄存器操作、优先级策略及调试技巧。

虚函数

函数声明的前缀有_weak,表示该函数是虚函数

__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	UNUSED(GPIO_Pin);
}
_weak

本质上是一个宏定义,实际上的文本对应的是编译指令_attribute((weak))

  • 虚函数
    • 有虚函数指令——weak的函数声明
    • 虚函数可以有很多个
  • 实函数
    • 没有虚函数指令_weak的函数声明,也就是普通的函数,都是实函数
    • 实函数至多只有一个,多了会编译报错(如果是C++可以兼容函数重载)
    • 如果实函数不存在,则随机选取一个幸运的虚函数(对我们而言是随机的。但对编译器而言有一定的选取规则)

工程配置

1.根据原理图或者PCB图,找到开发板上按键开关对应的单片机引脚。
2.将单片机开关引脚设置为外部中断0号通道
3.检测模式选择下降沿
4.输入模式选择上拉输入,用于维持平时的高电平
5.使能嵌套中断向量控制器
6.中断的两种优先级默认配置即可

按键消抖方法:

1.通过延迟10ms,略过了不稳定的时间,等稳定下来之后再检测状态
缺点:不能同时调用多个,否则会事与愿违;
2.硬件上再按键两端并联一个电容器,滤除高频率的杂波
缺点:要重新设计电路板
3.不用外部中断,定时直接读取引脚信息,用定时器中断(充分利用了人类的反应时间比计算机慢得多的特点。只需要十几毫秒查询一次即可,同样节省了计算性能)

定时器

TIM定时器分类:

  • 基本定时器:
    • 预分频、自动装载值、自定义计数方向、自定义触发事件
    • 单个脉冲输出
    • 可以产生DMA请求定期搬运数据
  • 通用定时器:
    • 具有基本定时器的全部功能
    • 四个独立的GPIO通道可以进行输入捕获、输出比较、PWM生成、编码模式等
  • 高级定时器
    • 通用定时器的全部功能
    • 八个GPIO通道可以支持反向或互补PWM输出
    • 一个GPIO通道可以支持外部输入信号引入刹车重启等功能

你可能感兴趣的:(嵌入式,单片机,嵌入式硬件)