大插曲
我一开始检查了时钟,接口,发现怎么都跑不通,调试了两天。不是代码卡在某个函数里面,就是代码可以运行,但是没有现象。
直摇人,同事调出来了,我才发现
是我搞错接口了???? 但是不对啊!IAR 代码文件的注释上写的串口是 PTD13/PTD14
而且用 IAR 的例程也跑的通,从来没想过是串口初始化的问题。我反向定位为什么 IAR 的历程可以把串口跑通,发现。。。。


好好好,你用 if/else 初始化是吧
这个故事告诉我们不要随意相信代码注释,请以原理图为准。。。。
正文开始:
基本配置
根据自己板子的接口
进行 pin 配置,我的板子是 PTC8 和 PTC9

在lpuart模块里进行配置,设置波特率;device那里,有的时候默认的是错的,注意校对
![]()


在 main.c 中编辑代码
- 打开时钟,初始化pin口

- 初始化串口

- 发送
![]()
![]()
- 结果

S32K144 的 lpuart 相关信息(待完善)

S32K144可以有三个 LPUART 实例,发送、接收数据缓存区为 4 字节
LPUART 发射器框图

LPUART 接收器框图

寄存器定义


波特率生成

AI 生成的 lpuart_driver
前置知识
串口的三种工作模式:
- 轮询:CPU 不停的查询串口状态标志(如 “是否有数据待接收”“发送缓冲区是否为空”),只有满足状态时才执行收发操作。
- 中断:串口硬件主动触发中断,CPU 在 ISR 里面处理收发逻辑,在没有触发中断的时间里,CPU 可以执行其他任务。
- 阻塞:调用收发函数后,函数不返回,直到操作完成,对调用者呈现“阻塞等待”的效果。通过信号量,把任务切换到等待队列,CPU 去执行其他任务,等信号量释放,任务由等待队列切换到就绪队列,等待 CPU 调度继续运行。适用于单任务场景下的确定性收发(如发送配置指令后,必须等确认才能继续)。
ISR 是如何安装的
回调函数
回调函数是啥:
普通的函数调用

回调函数 callback:

红色函数的就是callback,需要用户自己定义。它可以让代码更好的复用(你需要用什么函数,你就定义成什么函数)。回调函数往往依赖函数指针实现。
关于函数指针可以看 C语言指针进阶(一)——深入详解“函数指针”与“指针函数”-优快云博客
- 用途:
- 加快UI的相应速度
- 提高系统的实时性
- 高效分配各个线程的线程栈
- 本程序中:接收回调函数的安装函数。
| C |
| Plain Text |
Q:如果我们要实现接收一个以 ‘\0’ 结尾的字符串,我们该怎么办?
A:我们需要开辟(定义)一个 buffer 用于存储字符串和一个指向 buffer 的指针 bufferIdx,然后通过 LPUART_DRV_ReceiveData(INST_LPUART1, buffer[0], 1U) 接收一个字节存入buffer,然后我们通过接收回调函数,判断那个buffer是否填入了一个字节(事件UART_EVENT_RX_FULL),如果是,就判断被填入被填入的是不是结束符还有是不是要超出 buffer 大小了,如果都不是就移动指针,并使用 LPUART_DRV_SetRxBuffer 配置串口接收的缓冲区信息(告诉硬件 “下一次收到的数据应该存到哪里,以及接收多少字节”),然后串口的工作模式,有数据传来时就触发下一次的接收
'\0' 和 '0' 的区别

结尾交付物提议
要不要我帮你整理一份LPUART 驱动核心结构体与函数速查表?表格会包含 “结构体成员说明”“函数功能 + 参数 + 返回值”,方便你后续开发时快速查阅,不用反复翻看驱动代码。
-
Ipuart_driver.h解析
-
一、重要结构体(驱动的 “数据骨架”)
结构体名
核心作用
核心成员
成员类型
成员说明
使用场景
lpuart_user_config_t存储用户配置参数
transferType枚举
传输方式:
LPUART_USING_INTERRUPTS(中断)/LPUART_USING_DMA(DMA)初始化前,用户配置通信参数(波特率、校验等),作为
LPUART_DRV_Init参数baudRateuint32_t
波特率(如 9600、115200)
parityMode枚举
校验模式:
LPUART_PARITY_DISABLED(无校验)/ 奇校验 / 偶校验stopBitCount枚举
停止位:
LPUART_ONE_STOP_BIT(1 位)/2 位bitCountPerChar枚举
数据位:
LPUART_8_BITS_PER_CHAR(8 位)/9 位 / 10 位rxDMAChannel/txDMAChanneluint32_t
DMA 传输的通道号(仅 DMA 模式有效)
lpuart_state_t存储驱动运行时状态
transferType枚举
当前传输方式(从
lpuart_user_config_t复制)初始化时传入空实例,驱动内部跟踪传输状态(如是否忙碌、剩余字节数)
txBuff/rxBuffuint8_t*
发送 / 接收缓冲区指针
txSize/rxSizeuint32_t
剩余待发送 / 待接收字节数
isTxBusy/isRxBusybool
发送 / 接收是否忙碌(
true= 忙碌)transmitStatus/
receiveStatus枚举
传输状态:
STATUS_SUCCESS(成功)/STATUS_TIMEOUT(超时)/ 错误rxCallback/
txCallback函数指针
接收 / 发送回调函数(事件触发时调用)
rxCallbackParam/
txCallbackParamvoid*
回调函数的用户自定义参数
rxComplete/
txComplete信号量
阻塞传输时,用于等待传输完成
rxDMAChannel/
txDMAChanneluint32_t
DMA 通道号(仅 DMA 模式有效)
uart_event_t定义 UART 事件类型(枚举)
UART_EVENT_RX_FULL枚举值
接收缓冲区满(单次接收完成,如 1 字节)
回调函数中判断事件类型,执行对应逻辑(如继续接收 / 处理错误)
UART_EVENT_TX_EMPTY枚举值
发送缓冲区空(可写入下一字节)
UART_EVENT_END_TRANSFER枚举值
整个传输完成(所有字节发送 / 接收完毕)
UART_EVENT_ERROR枚举值
通信错误(校验错 / 帧错误 / 溢出错误)
uart_callback_t定义回调函数签名(函数类型)
函数原型:
void (*)(void* driverState, uart_event_t event, void* userData)函数指针类型
driverState:lpuart_state_t指针;event:事件类型;userData:用户参数上层通过
LPUART_DRV_InstallRxCallback安装回调,响应传输事件二、核心函数功能(按 “功能模块” 分类)
代码中的函数按 “初始化→配置→发送→接收→中断处理→辅助操作” 划分,以下是各模块的关键函数解析:
模块 1:初始化与反初始化(驱动 “启动 / 关闭”)
这是使用 LPUART 的第一步,负责 “硬件初始化、状态复位、中断配置”。
函数名
核心功能
关键逻辑
LPUART_DRV_GetDefaultConfig
获取默认配置
给lpuart_user_config_t填充默认值(波特率 9600、无校验、8 位数据位、1 位停止位、中断传输),避免用户手动填充所有参数。
LPUART_DRV_Init
初始化 LPUART
1. 校验参数合法性(如实例号、状态结构体非空);2. 配置 LPUART 硬件(波特率、校验位、数据位等,调用LPUART_DRV_SetBaudRate);3. 创建同步信号量(rxComplete/txComplete,用于阻塞传输);4. 安装中断处理函数(INT_SYS_InstallHandler)并使能中断;5. 保存状态结构体指针(s_lpuartStatePtr),标记驱动已初始化。
LPUART_DRV_Deinit
反初始化 LPUART
1. 等待发送完成(避免数据残留);2. 销毁同步信号量;3. 禁用中断并恢复默认中断处理函数;4. 清空状态结构体指针,标记驱动未初始化。
模块 2:通信参数配置(动态调整硬件参数)
用于初始化后修改 LPUART 的核心通信参数(如波特率)。
函数名
核心功能
关键逻辑
LPUART_DRV_SetBaudRate
设置波特率
1. 校验当前无传输(isTxBusy/isRxBusy为false);2. 计算波特率分频系数(sbr)和过采样率(osr),确保实际波特率与期望偏差最小;3. 配置 LPUART 硬件寄存器(写入osr和sbr)。
LPUART_DRV_GetBaudRate
获取当前波特率
读取硬件寄存器的osr和sbr,结合 LPUART 时钟频率,计算当前实际波特率并返回。
模块 3:数据发送(三种传输方式:阻塞、轮询、非阻塞)
驱动提供三种发送接口,适配不同场景(如 “需要等待发送完成”“不允许阻塞”)。
函数名
传输方式
核心功能
适用场景
LPUART_DRV_SendDataBlocking
阻塞
发送数据后,阻塞等待传输完成(通过osSemWait等待txComplete信号量),函数返回即表示传输结束(成功 / 超时 / 错误)。
需确保数据发送完成后再执行后续逻辑(如发送指令后等待响应)。
LPUART_DRV_SendDataPolling
轮询
不依赖中断,通过循环查询 “发送缓冲区空” 标志(LPUART_TX_DATA_REG_EMPTY),直到所有数据发送完成。
不允许使用中断的场景(如裸机、低功耗场景),但会占用 CPU 资源。
LPUART_DRV_SendData
非阻塞
启动发送后立即返回,传输过程由中断 / DMA 完成;上层需通过LPUART_DRV_GetTransmitStatus查询状态,或通过回调函数获取结果。
不希望阻塞 CPU 的场景(如多任务系统、实时性要求高的应用)。
LPUART_DRV_GetTransmitStatus
-
查询发送状态(成功 / 忙碌 / 错误),并返回剩余待发送字节数。
非阻塞发送时,上层判断传输是否完成。
LPUART_DRV_AbortSendingData
-
终止正在进行的非阻塞发送,标记状态为STATUS_UART_ABORTED。
紧急情况下需要停止发送(如超时、错误)。
模块 4:数据接收(三种传输方式:阻塞、轮询、非阻塞)
与发送对应,接收也提供三种接口,核心逻辑是 “将硬件接收的数据存入缓冲区”。
函数名
传输方式
核心功能
适用场景
LPUART_DRV_ReceiveDataBlocking
阻塞
启动接收后,阻塞等待接收完成(通过osSemWait等待rxComplete信号量),函数返回即表示数据接收完毕。
需等待数据接收后再处理(如接收传感器数据后解析)。
LPUART_DRV_ReceiveDataPolling
轮询
不依赖中断,通过循环查询 “接收缓冲区满” 标志(LPUART_RX_DATA_REG_FULL),直到所有数据接收完成;同时检测接收错误(校验错、帧错误等)。
不允许使用中断的场景,需手动处理错误。
LPUART_DRV_ReceiveData
非阻塞
启动接收后立即返回,接收过程由中断 / DMA 完成;上层通过LPUART_DRV_GetReceiveStatus查询状态,或通过回调函数获取接收结果。
不希望阻塞 CPU 的场景(如多任务系统)。
LPUART_DRV_GetReceiveStatus
-
查询接收状态(成功 / 忙碌 / 错误),并返回剩余待接收字节数。
非阻塞接收时,上层判断接收是否完成。
LPUART_DRV_AbortReceivingData
-
终止正在进行的非阻塞接收,标记状态为STATUS_UART_ABORTED。
紧急情况下需要停止接收(如超时、错误)。
模块 5:回调函数管理(上层与驱动的 “事件通知”)
通过回调函数,驱动可在 “数据接收满、传输完成、出错” 时主动通知上层,无需上层轮询。
函数名
核心功能
关键逻辑
LPUART_DRV_InstallRxCallback
安装接收回调
将用户实现的接收回调函数(uart_callback_t)和参数存入lpuart_state_t,接收事件触发时调用该函数。
LPUART_DRV_InstallTxCallback
安装发送回调
类似接收回调,发送事件(如发送空、发送完成)触发时调用用户函数。
模块 6:中断处理(驱动的 “核心事件响应”)
中断是 “非阻塞传输” 的核心,代码中通过中断处理函数实现 “实时响应硬件事件”,所有中断函数均为static(内部调用,不对外暴露)。
函数名
核心功能
关键逻辑
LPUART_DRV_IRQHandler
总中断入口
LPUART 中断触发时,首先调用该函数;它会分类型处理:
1. 错误中断(调用LPUART_DRV_ErrIrqHandler);
2. 接收满中断(调用LPUART_DRV_RxIrqHandler);
3. 发送空中断(调用LPUART_DRV_TxEmptyIrqHandler);
4. 发送完成中断(调用LPUART_DRV_TxCompleteIrqHandler)。
LPUART_DRV_RxIrqHandler
接收满中断处理
1. 调用LPUART_DRV_GetData,将硬件接收的数据存入rxBuff;
2. 更新接收进度(rxBuff指针后移,rxSize递减);
3. 若接收完成(rxSize == 0),调用接收回调(如UART_EVENT_RX_FULL),并终止接收(LPUART_DRV_CompleteReceiveDataUsingInt)。
LPUART_DRV_TxEmptyIrqHandler
发送空中断处理
1. 调用LPUART_DRV_PutData,将txBuff的数据写入硬件发送缓冲区;
2. 更新发送进度(txBuff指针后移,txSize递减);
3. 若发送完成(txSize == 0),禁用发送空中断,启用发送完成中断。
LPUART_DRV_ErrIrqHandler
错误中断处理
检测错误类型(溢出错误、帧错误、校验错误、噪声错误),标记接收状态,终止接收,并调用回调(UART_EVENT_ERROR)。
模块 7:辅助函数(驱动内部工具)
这些函数是static修饰的内部函数,用于封装重复操作,简化核心逻辑。
函数名
核心功能
LPUART_DRV_SetTxBuffer
LPUART_DRV_SetRxBuffer
设置发送 / 接收缓冲区指针和长度,支持 “连续传输”(如接收满后,通过回调调用该函数配置下一个缓冲区)。
LPUART_DRV_PutData
根据数据位长度(8/9/10 位),将txBuff的数据写入 LPUART 硬件发送寄存器。
LPUART_DRV_GetData
根据数据位长度,从 LPUART 硬件接收寄存器读取数据,存入rxBuff。
LPUART_DRV_StartSendDataUsingInt
LPUART_DRV_CompleteSendDataUsingInt
中断发送的 “启动 / 终止”:启动时初始化发送状态、使能发送中断;终止时禁用中断、更新状态、释放信号量。
三、驱动整体工作流程(以 “中断接收” 为例)
结合之前你关注的 “逐字节连续接收”,用一个实际场景串联驱动的核心操作:
-
初始化:上层调用LPUART_DRV_GetDefaultConfig获取默认配置,修改后调用LPUART_DRV_Init初始化硬件和驱动状态;
-
安装回调:调用LPUART_DRV_InstallRxCallback,安装自定义的rxCallback(如你之前的 “接收满则配置下一次接收” 函数);
-
启动接收:调用LPUART_DRV_ReceiveData(非阻塞),传入接收缓冲区buffer和长度(如 1 字节);
-
中断触发:硬件接收 1 字节后,触发UART_EVENT_RX_FULL中断,调用LPUART_DRV_RxIrqHandler;
-
回调处理:中断处理函数调用rxCallback,在回调中判断 “是否收到\n或缓冲区满”,若未满足则调用LPUART_DRV_SetRxBuffer配置下一次接收;
-
接收完成:当收到\n或缓冲区满时,回调中不再配置下一次接收,接收过程终止。
1806

被折叠的 条评论
为什么被折叠?



