嵌入式课堂笔记1月14-15
本文总结了嵌入式开发中RTOS学习路径和关键外设编程要点。RTOS学习需掌握链表、数组等前置知识,分API调用、原理理解和优化修改三个阶段。重点讲解了串口中断编程,包括CubeMX配置方法、HAL库初始化函数解析及中断回调机制实现。同时详细介绍了定时器系统,涵盖SysTick内核定时器工作原理、HAL_Delay实现逻辑,以及TIM外设定时器的配置流程和1秒定时中断案例。文中通过代码示例展示了串口
·
嵌入式学习笔记
一、前置说明
RTOS学习铺垫
学习RTOS需掌握前置知识:链表、数组;
学习分为三个阶段:
- 会调用API
- 熟悉内部工作原理
- 优化修改
二、串口中断程序编写
1. CubeMX配置要点
- 串口(UART)属于内部中断,无需配置EXTI(EXTI仅管理GPIO外部中断)
- 核心配置方向:串口参数(波特率、数据位等)、GPIO引脚、中断优先级与使能
- 具体流程图见飞书笔记
2. 核心代码解析
(1)串口初始化函数
//HAL库的串口初始化函数
void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 9600;
huart1.Init.WordLength = UART_WORDLENGTH_8B;//8bit数据位
huart1.Init.StopBits = UART_STOPBITS_1;//1个停止位
huart1.Init.Parity = UART_PARITY_NONE;//无奇偶校验
huart1.Init.Mode = UART_MODE_TX_RX;//收发模式
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;//无硬件流控
huart1.Init.OverSampling = UART_OVERSAMPLING_16;//16倍过采样
if (HAL_UART_Init(&huart1) != HAL_OK)//初始化校验
{
Error_Handler();//初始化失败进入错误处理
}
/* USER CODE BEGIN USART1_Init 2 */
/* USER CODE END USART1_Init 2 */
}
(2)串口GPIO与中断初始化
//串口的GPIO初始化
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspInit 0 */
/* USER CODE END USART1_MspInit 0 */
/* USART1时钟使能 */
__HAL_RCC_USART1_CLK_ENABLE();//串口使能
__HAL_RCC_GPIOA_CLK_ENABLE();//GPIOA时钟使能
/**USART1 GPIO配置
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;//收发引脚
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;//收发均是复用推挽输出(建议接收配置为浮空/上拉输入)
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;//高速传输
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;//开启复用功能
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USART1中断配置 */
HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);//设置中断优先级
HAL_NVIC_EnableIRQ(USART1_IRQn);//使能中断
/* USER CODE BEGIN USART1_MspInit 1 */
/* USER CODE END USART1_MspInit 1 */
}
}
3. 串口中断关键函数与回调
(1)非阻塞发送函数 HAL_UART_Transmit_IT
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size)
- 功能:启动中断驱动的UART发送,设置发送缓冲区/计数,使能TXE(发送数据寄存器空)中断,由中断逐字节发送
- 特性:非阻塞,调用后立即返回,实际发送由中断完成
- 返回值:
HAL_OK/HAL_ERROR/HAL_BUSY - 调用示例:
HAL_UART_Transmit_IT(&huart1,"xixixi",sizeof("xixixi"));(无超时时间)
(2)发送完成回调函数
//弱函数(用户可重写)
__weak void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
UNUSED(huart);
/* 需自定义逻辑时,在用户文件中重写该函数 */
}
//自定义重写示例
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance==USART1)//判断串口实例
{
i++;
if(i>250){
i=1;
}
}
}
- 注意:串口发送完成后会自动关闭使能,需手动重新使能
三、定时器系统
1. 时钟基础概念
- 时钟信号:有规律、稳定的周期性方波脉冲,用于计时/计数,决定程序运行速度(如F411最高100M,单条指令耗时1/100μs)
- 核心参数:周期(T)、频率(f)、占空比(高电平占比)、上升沿/下降沿
- 时钟源分类:
- 高速:HSE(外部)、HSI(内部)→ 管理主频
- 低速:LSE(外部)、LSI(内部)
- 特殊:SysTick(内核)、TIM(片上外设)
2. SysTick(滴答定时器)
(1)核心特性
-
归属:Cortex-M4内核,ARM官方开发
-
类型:24位递减定时器,最大计数值2^24(16777216)
-
作用:产生时基(通常1ms),为操作系统提供心跳,也可用于基础计时
-
触发机制:设定初值使能后,每来1个时钟信号计数值-1;减至0触发异常,自动重装初值循环

(2)关键寄存器
- CTRL:控制寄存器(使能、时钟源、中断使能、计数标志)
- LOAD:重装载寄存器(存储计数初值)
- VAL:当前值寄存器(存储当前计数值)
(3)HAL_Delay实现原理
#define HAL_MAX_DELAY 0xFFFFFFFFU //最大延时值
typedef enum
{
HAL_TICK_FREQ_10HZ = 100U,
HAL_TICK_FREQ_100HZ = 10U,
HAL_TICK_FREQ_1KHZ = 1U,
HAL_TICK_FREQ_DEFAULT = HAL_TICK_FREQ_1KHZ //默认1KHz(1ms)
} HAL_TickFreqTypeDef;
HAL_TickFreqTypeDef uwTickFreq = HAL_TICK_FREQ_DEFAULT;
__weak void HAL_Delay(uint32_t Delay)
{
uint32_t tickstart = HAL_GetTick();//获取进入延时的初始时间
uint32_t wait = Delay;
/* 保证最小延时(防止Delay=0时无等待) */
if (wait < HAL_MAX_DELAY)
{
wait += (uint32_t)(uwTickFreq);//加1ms,存在1ms误差
}
//死循环等待,直到当前时间-初始时间≥目标延时
while((HAL_GetTick() - tickstart) < wait)
{
}
}
(4)SysTick中断触发周期配置
- 初始化链路:
main()→HAL_Init()→HAL_InitTick()→HAL_SYSTICK_Config() - 配置示例:
SystemCoreClock / (1000U /(uint32_t)uwTickFreq)(如SystemCoreClock=4000000UL时,计算得4000,即每4000个时钟周期触发一次中断,对应1ms)
3. TIM定时器(片上外设)
(1)核心特性
-
类比闹钟,支持定时中断、计数外部脉冲、生成PWM(电机调速/LED调光等)
-
st、其他芯片厂商开发
-
分类:高级定时器、通用定时器、基本定时器(按复杂度/功能扩展)
-
位数决定计数上限

-
关键参数:
- 计数器分辨率:0~65535(16位)
- 计数类型:向上/向下/向上+向下计数
- 预分频因子(PSC):16位寄存器(0~65535),0=不分频,1=2分频,以此类推(如16M时钟分频16得1M)
(2)CubeMX配置要点
- 时钟来源:内部时钟
- 预分频值、自动重装载值配置
- 计数方式选择
- NVIC中断优先级与使能
- 通道选择(如需PWM)
- 从动模式/触发方式(按需配置)
(3)实战:1S串口上报“我来了”
步骤:
- 配置串口(参考第二部分)
- 配置TIM定时器:
- 设置预分频值、自动重装载值(实现1S定时)
- 开启自动重装、NVIC中断使能
- 代码实现:
- 调用函数开启定时器
- 重写定时器中断回调函数
- 在回调函数中调用
HAL_UART_Transmit_IT发送“我来了”
4. 补充知识点
(1)枚举类型赋值规则
typedef enum {
A = 1U //1U:无符号1(减少CPU类型判断开销)
B = 2UL //2UL:无符号长整型
C = B //继承B的值
D //未赋值,为前一个值+1(即3)
} name;
- 系统库常用
U/UL:避免类型转换,提升调用效率
(2)关键外设缩写
- SDIO:安全数字输入输出接口
- SWDIO:串行调试输入输出接口
- EXTI:外部中断控制器
- NVIC:嵌套向量中断控制器
(3)volatile关键字
- 作用:防止编译器优化,确保每次读取变量都从内存中获取(定时器/中断相关变量需加)
(4)总线挂载
- TIM定时器分属APB1(低速)、APB2(高速)总线,可在芯片结构图中查看
- 例:TIM1/TIM10共用一条中断线
四、待深入探究的问题
- 西风的按键消抖方法原理
- 串口硬件流控的具体含义与应用场景,NCOF,回顾飞书笔记
- 串口过采样的原理与作用
huart->Instance的底层实现与作用- HAL_Delay中“防0操作”的必用场景
- SysTick寄存器(CTRL/LOAD/VAL)的详细配置与解析
- TIM定时器不同类型(高级/通用/基本)的功能差异
- 回顾串口的cubemx配置
- 什么是ewarm——IAR
- 外部:SR状态寄存器
- 不定长串口接收
五、GPIO流程图
在05stm32实战的02点灯

在通信笔记

更多推荐
所有评论(0)