单片机学习日记 - 详解
上拉电阻:上拉电阻(pull-up):把引脚“默认拉高”,也就是空闲时稳定在高电平。
常见场景:按键检测(按下接地,松开通过上拉变成 1)。
下拉电阻:下拉电阻(pull-down):把引脚“默认拉低”,也就是空闲时稳定在低电平。
常见场景:需要信号空闲为 0 的情况,比如某些输入检测。
上/下拉电阻 → 给输入口稳定的默认电平。
输入捕获(Input Capture):
输入捕获是定时器的一种模式。
定时器本身在计数,就像一个秒表不停跑。输入捕获的作用就是:
当某个外部事件(比如引脚电平变化)到来时,把此时定时器的值记录下来。
测量高电平持续时间(脉宽测量)。
测量两次脉冲的间隔(频率/转速测量)。
记录事件发生的精确时间,用来算频率、脉宽。
定时器(Timer):
__HAL_TIM_GET_COUNTER用于获取计数器的值。
__HAL_TIM_SET_COUNTER用于设置计数器的值。
__HAL_TIM_GET_AUTORELOAD获取重装载寄存器的值。
__HAL_TIM_SET_AUTORELOAD设置重装载寄存器的值
__HAL_TIM_SET_PRESCALER设置预分频器的值
定时器是 MCU 里的“电子秒表”,它的作用远远不止计时:
基本模式:定时中断(比如 1ms 触发一次,用于心跳、操作系统节拍)。
输入捕获:前面说的,测量外部信号的时间特征。
输出比较(PWM):比如产生 PWM 波,控制电机、舵机、LED 亮度。
外部计数模式:用来直接计数外部脉冲(红外传感器输出的方波)。
MCU 的时间和脉冲工具,能计时、捕获、PWM、计数。定时器就是计数器
串口(USART/UART)
串口就是 MCU 的“嘴巴”,负责和外部世界说话(发数据)或者听别人说话(收数据)。
UART:异步串口(常见,常用 TX/RX 两根线,最常用波特率 9600、115200)。
USART:在 UART 基础上多了同步模式,但大多数情况下我们就当 UART 用。
串口的特点是一边一位地传输,速度适中,调试方便。MCU 和外界交流的嘴巴。
DMA,全称 Direct Memory Access(直接存储器访问)
1.DMA 的基本作用
平常情况:
没有 DMA 时,CPU 要负责数据搬运,比如把 ADC 采集结果读出来,再写到内存;或者从内存取数据,一点点写到串口发送寄存器里。这样 CPU 就很累,浪费算力。
有了 DMA:
CPU 只要配置好 源地址、目的地址、数据长度,DMA 控制器就会自动在后台搬运数据,不需要 CPU 参与。
CPU 可以专注于计算和逻辑,效率提升非常大。
比喻:
没有 DMA 时 → CPU 是老板又是搬运工。
有了 DMA → 老板只要说“把仓库 A 搬到仓库 B,数量 1000”,然后搬运工(DMA)自动干活。
2. DMA 的常见用途
ADC + DMA
连续采集传感器数据,DMA 自动把结果写到内存数组里。
CPU 只需要在需要时读取内存,不用一条一条等数据。
USART/SPI/I²C + DMA
串口发一大串数据(比如调试信息),DMA 自动把内存的数据推到发送寄存器。
接收数据时,DMA 可以直接把收到的数据放到数组里。
存储器到存储器
复制一大块数据,不用 CPU 循环拷贝。
定时器触发 DMA
定时器溢出时自动触发 DMA,比如定时更新 DAC 输出波形,形成正弦波/三角波。
3. DMA 的核心特性
源地址:数据从哪里来(寄存器/内存)。
目的地址:数据搬到哪里去(内存/寄存器)。
数据量:要搬多少。
传输方向:寄存器到内存,内存到寄存器,或内存到内存。
自动递增:搬运时地址能否自动递增(比如存到数组里)。
触发源:谁来启动传输(外设事件、软件触发)。
5. 总结
DMA = MCU 的自动搬运工,减少 CPU 负担。
用途:ADC 自动采集、串口高速通信、波形发生器、数据搬移。
优点:快、省 CPU,适合大数据量场景。
缺点:配置比普通外设复杂一些,调试要小心(地址、长度、溢出)。
一句话:知而不行,是为不知;行而不知,可以致知。
中断(Interrupt)
中断就是 MCU 的“紧急插队机制”。
平时 MCU 在顺序执行代码,比如主循环在跑任务。
当某个事件发生(定时器溢出、串口收到数据、外部按键按下),MCU 会立刻“打断”当前任务,跳到对应的中断服务程序(ISR)去处理。
中断的好处:
响应速度快,不用在主循环里死等。
节省 CPU 资源,MCU 可以忙别的事。
但要小心:
中断里代码要尽量短,不要做耗时操作。
要注意优先级,避免高频中断卡死系统。
事件驱动的插队机制,提高效率。
NVIC嵌套向量中断控制器
NVIC 的位置和作用
MCU 的中断分两步走:
外设产生中断请求:比如定时器溢出、串口收到数据、外部 IO 引脚电平变化。
NVIC 处理调度:NVIC 决定是不是要响应、什么时候响应、响应谁。
可以把 NVIC 想象成一个 中断信号的交通指挥员:
哪个中断能过马路(使能/屏蔽)。
哪辆车优先(优先级管理)。
多辆车同时到路口,谁先走(仲裁)。
NVIC 的核心功能
中断使能/禁止
通过寄存器(
NVIC_ISER
/NVIC_ICER
)来打开或关闭某个中断。类似“开关闸门”。
中断优先级
每个中断都有一个优先级(Priority)。
数字越小优先级越高,比如
0
比3
更急。NVIC 会根据优先级来决定先响应谁。
中断嵌套
如果 A 中断在执行时,来了一个更高优先级的 B 中断,B 可以打断 A,先执行完再返回继续 A。
这就是“嵌套”的由来。
向量表管理
每个中断都有对应的入口地址(ISR 函数入口)。
NVIC 根据“中断号”去查向量表,找到对应的服务函数。
举个例子
假设系统里有两个中断:
定时器 1 溢出中断(优先级 2)
串口接收中断(优先级 1)
运行时:
MCU 在跑主循环。
定时器溢出 → 触发中断 → NVIC 查表 → 执行
TIM1_IRQHandler
。正在执行时,串口突然收到了一个字节(优先级更高)。
NVIC 立刻暂停定时器中断,跳去执行
USART_IRQHandler
。串口 ISR 结束 → 返回 → 继续执行定时器 ISR。
这样就保证了重要事件优先处理,次要事件稍后处理。
// 开启定时器中断 nvic_irq_enable(TIMER1_IRQn, 2); // 中断号,优先级 // 中断服务函数 void TIMER1_IRQHandler(void) {if (timer_interrupt_flag_get(TIMER1, TIMER_INT_UP) != RESET) {timer_interrupt_flag_clear(TIMER1, TIMER_INT_UP);// 在这里写你的定时任务,比如LED翻转} }
总结
NVIC = 中断的大脑,负责使能、优先级、仲裁。
它让 MCU 在“多任务”里有序地响应各种外设。
嵌套特性保证高优先级事件能插队,保证实时性。
手册关键信息
手册里的FT便是5V容忍引脚
这就是推挽输出的能力:具有一定的电压与电流驱动的能力。
开漏输出:不具备主动驱动的能力,必须依靠外部电压来进行驱动。使用开漏输出的时候需要选择支持5V容忍的IO口。
施密特触发器的作用:稳定电平,给电平一个参考电压,高于这个参考电压就输出高电平,低于就输出低电平。
数字信号比模拟信号更加稳定。
用数字信号模拟模拟信号,就是采用占空比。
定时器的两种作用:1.输入捕获模式:测量脉冲宽度。2.输出比较模式:输出脉冲宽度。
PWM模式:
输出控制器:一个可以开启关闭的电平反相器(非门)
通过调节比较寄存器的大小就可以调节PWM的占空比:
外设需要推挽输出时,需要使用复用推挽输出模式。
增量式旋转编码器:
IIC
时钟源&时钟树
一、时钟源(Clock Sources)
STM32 常见的几个基础时钟源:
HSI(High Speed Internal Clock,高速内部时钟)
固定频率:8 MHz
优点:上电即有,不需要外部晶振,启动快
缺点:精度一般,用在对精度要求不高的场景
HSE(High Speed External Clock,高速外部时钟)
需要外部晶振/时钟源(常见 8 MHz 晶振)
优点:稳定、精度高,适合对串口、USB 等有严格时钟要求的应用
缺点:需要外接晶振,成本和电路复杂度增加
PLL(Phase Locked Loop,锁相环)
作用:倍频(×2 ~ ×16)
比如你图里:HSE 8 MHz → PLL ×9 → 72 MHz
这是 STM32 最经典的配置(72 MHz 主频)
小结:时钟源 = HSI、HSE、PLL,系统一般选 HSE+PLL 来得到 72 MHz 主频。
二、系统时钟(SYSCLK)
SYSCLK 是整个系统的“根时钟”,CPU 直接使用它。
在图中你能看到:
选择器(Mux)可以选择 HSI、HSE、PLL
你的例子中,选择的是 PLL 输出 72 MHz 作为 SYSCLK
三、AHB 总线和 HCLK
SYSCLK 再经过 AHB 分频器,得到 HCLK。
HCLK = AHB 总线时钟 = 内核、DMA、内存的工作频率
一般情况下设为 72 MHz(不分频,/1)
你图里也标了:
SYSCLK 72 MHz → HCLK 72 MHz
四、APB 总线时钟(外设时钟)
STM32 有两个外设总线:
APB1 总线
低速外设(USART2~5、I2C、CAN、SPI2/3…)
最大频率 36 MHz
所以常见配置是:HCLK / 2 = 36 MHz
定时器有加倍功能(×2),所以 APB1 定时器可以跑到 72 MHz
APB2 总线
高速外设(USART1、SPI1、ADC、GPIO…)
最大频率 72 MHz
一般设为 /1,不分频
五、外设时钟举例
SysTick:HCLK / 8 = 9 MHz
ADC:HCLK / 6 = 12 MHz
USART1(APB2):72 MHz
USART2(APB1):36 MHz
定时器(APB1):72 MHz(因为 ×2)
定时器(APB2):72 MHz(直接用)
六、总结成一句话
STM32 的时钟树逻辑是:
时钟源 (HSI/HSE) → PLL 倍频 → SYSCLK → AHB 分频 → HCLK → APB1/APB2 分频 → 外设时钟也就是说:
你用 HSE 8 MHz + PLL ×9 → SYSCLK 72 MHz
HCLK = 72 MHz
APB1 = 36 MHz(定时器再×2 = 72 MHz)
APB2 = 72 MHz
这样整个芯片的 CPU、总线、外设、定时器就都有了合适的时钟。
外部声明
1.
extern
的本质作用它告诉编译器:
“这个变量/函数不是在本文件里定义的,它在别的地方已经定义了,我这里只是引用一下。”换句话说:
定义:变量的真正创建地(占用内存)。
声明:只是告诉编译器“有这么个东西”,不分配空间。
外部声明(一般写在 .h 头文件里)
注意:函数的 定义 在
.c
文件里,声明 一般写在.h
文件里供别人包含。注意事项
只能有一个定义:
全局变量只能在一个.c
文件里真正定义,其它文件只能用extern
引用。否则会报“重定义错误”。初始化只能出现在定义里:
int x = 5; // 定义并初始化 extern int x; // 声明,不能再写 = 5
推荐做法:
在
.c
文件里定义变量。在
.h
文件里写extern
声明。需要的地方
#include
头文件。
extern
= 外部声明,告诉编译器“变量/函数在别处定义”。它不分配内存,只做“引用”。
在嵌入式里主要用于 模块间变量/函数共享,尤其是多文件工程。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/935250.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!