当前位置: 首页 > news >正文

7.【NXP 号令者RT1052】开发——实战-串口通信

7.【NXP 号令者RT1052】开发——实战-串口通信

本章将实现如下功能:RT1052 通过串口和上位机的对话,RT1052 在收到上位机发过来的字符串后,原原本本的返回给上位机。
做一个简单的回显。

7.1 RT1052 串口简介

关于串口的基础知识这里不做介绍了。下面仅仅分析一下fsl库关于串口的API函数。

初始化函数详解:LPUART_Init

c

status_t LPUART_Init(LPUART_Type *base, const lpuart_config_t *config, uint32_t srcClock_Hz);
  • base:选择具体串口控制器(LPUART1~LPUART8)。每个串口都有独立的寄存器组与时钟根路径;在 RT1052 上通常以 UART_CLK_ROOT(80 MHz)为源。
  • config:串口配置参数结构体指针,类型为 lpuart_config_t(见下文详解)。此结构体决定了波特率、校验、数据位、停止位、收发开关等。
  • srcClock_Hz:串口根时钟频率(单位 Hz)。你的项目中使用 PLL3_SW_CLK/6 = 80 MHz,因此传入 80000000。

你的使用示例(保持原样):

c

lpuart_config_t lpuart1_config;
lpuart1_config.baudRate_Bps=bound;               // 波特率
lpuart1_config.dataBitsCount=kLPUART_EightDataBits; // 8 位数据位
lpuart1_config.stopBitCount=kLPUART_OneStopBit;  // 1 位停止位
lpuart1_config.parityMode=kLPUART_ParityDisabled;// 无奇偶校验
lpuart1_config.enableRx=true;                    // 使能接收
lpuart1_config.enableTx=true;                    // 使能发送
LPUART_Init(LPUART1,&lpuart1_config,80000000);   // 初始化 LPUART1

关键点与注意事项:

  • 不需要单独调用时钟使能:FSL 驱动在 LPUART_Init 内部会调用 CLOCK_EnableClock 打开 LPUART 模块时钟。
  • 配置一致性:波特率的正确性取决于 srcClock_Hz 与 UART CLK 根的真实值一致;若你更改了时钟树或分频,需要同步更新 srcClock_Hz。
  • 复用与根时钟:确保已通过 CLOCK_SetMux/Div 将 UART MUX 指向 PLL3/6 且分频为 1(你之前的代码已设置),否则实际波特率会偏差。

配置结构体逐项解释:lpuart_config_t

c

typedef struct _lpuart_config
{uint32_t baudRate_Bps;                // 波特率lpuart_parity_mode_t parityMode;      // 奇偶校验lpuart_data_bits_t dataBitsCount;     // 数据位bool isMsb;                           // 是否高位先传输#if defined(FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT) && FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORTlpuart_stop_bit_count_t stopBitCount; // 停止位配置
#endif#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFOuint8_t txFifoWatermark;              // 发送 FIFO 水位线uint8_t rxFifoWatermark;              // 接收 FIFO 水位线
#endif#if defined(FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT) && FSL_FEATURE_LPUART_HAS_MODEM_SUPPORTbool enableRxRTS;                     // 使能接收 RTSbool enableTxCTS;                     // 使能发送 CTSlpuart_transmit_cts_source_t txCtsSource; lpuart_transmit_cts_config_t txCtsConfig; 
#endiflpuart_idle_type_select_t rxIdleType; // 接收空闲类型lpuart_idle_config_t      rxIdleConfig; // 接收空闲字符数量bool enableTx;                        // 使能发送bool enableRx;                        // 使能接收
} lpuart_config_t;
  • baudRate_Bps:串口波特率;常用 115200、57600、9600 等。取决于 srcClock_Hz 与内部分频器;FSL 驱动会计算并写入合适的分频值。
  • parityMode(lpuart_parity_mode_t):
    • kLPUART_ParityDisabled:无校验
    • kLPUART_ParityEven:偶校验
    • kLPUART_ParityOdd:奇校验
  • dataBitsCount(lpuart_data_bits_t):
    • kLPUART_EightDataBits:8 数据位
    • kLPUART_SevenDataBits:7 数据位(部分 SoC 支持)
  • isMsb:是否使用高位在前(MSB-first),通常保持 false(LSB-first)。
  • stopBitCount(lpuart_stop_bit_count_t):
    • kLPUART_OneStopBit:1 位停止位(常用)
    • kLPUART_TwoStopBit:2 位停止位(提高容错)
  • FIFO 相关项(若支持):影响中断/ DMA 触发水位;默认 0 意味着尽快触发。
  • Modem(RTS/CTS)相关项(若支持):用于硬件流控;如不接线,保持关闭。
  • rxIdleType/rxIdleConfig:接收空闲检测配置,典型用于多机通信或帧边界判定;默认即可。
  • enableTx/enableRx:打开收发通道;通常两者都为 true。

建议实践:

  • 面向通用串口通信:8N1(8 数据位,无校验,1 停止位),对应你的配置。
  • 若与外设/模块匹配失败:优先检查校验位与停止位是否一致,确保 srcClock_Hz 正确。

默认配置函数:LPUART_GetDefaultConfig

函数原型与作用:

c

void LPUART_GetDefaultConfig(lpuart_config_t *config);
  • 将 config 初始化为默认值:115200 波特率、8N1、关闭收发、关闭 RTS/CTS、默认空闲配置。
  • 常用流程:先调用默认配置,再在此基础上填入实际需求(如开启 Tx/Rx、修改波特率)。

你的原文说明保持不变;这里补充一个典型用法(不修改你的配置写法,仅补充思路):

  • 先默认:LPUART_GetDefaultConfig(&cfg);
  • 再改动:cfg.enableTx = true; cfg.enableRx = true; cfg.baudRate_Bps = bound; 等。

串口中断:使能与关闭

函数与参数保持你的原文:

c

LPUART_EnableInterrupts(LPUART1, kLPUART_RxDataRegFullInterruptEnable); 
LPUART_DisableInterrupts(LPUART1, kLPUART_RxDataRegFullInterruptEnable);

补充说明:

  • kLPUART_RxDataRegFullInterruptEnable:当接收数据寄存器(RDR)非空时触发中断,用于接收。
  • 若使用中断收发:需要在 NVIC 中设置优先级并 EnableIRQ(LPUARTx_IRQn),且在 ISR 内读取 DATA 寄存器清除状态。
  • 与 FIFO/水位线配合:可降低中断频率,建议在大量数据场景中根据硬件支持进行优化。

数据收发:单字节与多字节阻塞

单字节 API:

c

void    LPUART_WriteByte(LPUART_Type *base, uint8_t data);
uint8_t LPUART_ReadByte(LPUART_Type *base);
  • 写一个字节到 DATA 寄存器,或从 DATA 读出一个字节。适合简单测试或中断处理中的字节流。

阻塞式多字节 API:

c

void     LPUART_WriteBlocking(LPUART_Type *base, const uint8_t *data, size_t length);
status_t LPUART_ReadBlocking (LPUART_Type *base,       uint8_t *data, size_t length);
  • WriteBlocking:逐字节发送并等待发送完成,直到 length 发送完毕。
  • ReadBlocking:逐字节等待接收,直到填满 length;若无数据,会阻塞。可在任务型框架或初始化阶段使用,不适合高实时性主循环。

注意事项:

  • 阻塞读在空闲时会卡住线程;若不希望阻塞,改用中断或设置超时策略(自行封装)。
  • 阻塞写会占用 CPU;大量数据发送建议使用中断或 DMA(若驱动支持)。

状态查询:LPUART_GetStatusFlags

c

uint32_t LPUART_GetStatusFlags(LPUART_Type *base);
  • 返回 STAT 寄存器的当前状态位集合。
  • 常见状态位用途(示例):发送完成、发送缓冲空、接收缓冲满、帧错误、噪声错误、溢出等。实际位定义请查看 fsl_lpuart.h 的枚举。
  • 调试策略:在异常时读 STAT,结合错误位(如 Overrun、Framing)定位问题。

7.2 硬件设计

本实验需要用到的硬件资源有:
1) 指示灯 DS0
2) 串口 1
串口 1 之前还没有介绍过,本实验用到的串口 1 与 USB 串口并没有在 PCB 上连接在一起,需要通过跳线帽来连接一下。这里我们把 P4 的 RXD 和 TXD 用跳线帽与 P112(GPIO1_IO12)和 P113(GPIO1_IO13)连接起来。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7.3 软件设计

本章的代码设计,比前两章简单很多,因为我们的串口初始化代码和接收代码就是用我们之前介绍的 SYSTEM 文件夹下的串口部分的内容。
打开上一章的工程,因为本章我们用不到按键的功能,所以先注释掉。
然后在 SYSTEM 组下双击 lpuart.c,我们就可以看到该文件里面的代码,先介绍LPUART1_Init 函数,该函数代码如下:

//初始化IO 串口1 
//bound:波特率
void LPUART1_Init(u32 bound)
{	u32 freq=0;							//串口的时钟源频率CLOCK_EnableClock(kCLOCK_Lpuart1);	//使能LPUART1时钟CLOCK_SetMux(kCLOCK_UartMux,0); 	//设置UART时钟源为PLL3 80Mhz,PLL3/6=480/6=80MHzCLOCK_SetDiv(kCLOCK_UartDiv,0); 	//设置UART时钟1分频,即UART时钟为80Mhz//LPUART1所使用的IO功能配置,即:从ALT0~ALT7选择合适的功能。IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_12_LPUART1_TX,0U);	//GPIO_AD_B0_12设置为LPUART1_TXIOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_13_LPUART1_RX,0U);	//GPIO_AD_B0_13设置为LPUART1_RX//配置IO引脚GPIO_AD_B0_12和GPIO_AD_B0_13的功能//低转换速度,驱动能力为R0/6,速度为100Mhz,关闭开路功能,使能pull/keepr//选择keeper功能,下拉100K Ohm,关闭HystIOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_12_LPUART1_TX,0x10B0u); IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_13_LPUART1_RX,0x10B0u); freq=LPUART_SrcFreqGet();	LPUART_GetDefaultConfig(&lpuart1_config); 				//先设置为默认配置,后面在根据实际情况配置//初始化NXP官方提供的debug console,此函数会重新初始化LPUART1,但是我们后面会//重新显示的初始化一次LPUART1,DbgConsole_Init()主要是给那些想要使用NXP官方//调试功能的开发者使用的,不需要使用的话就可以将下面代码注释掉DbgConsole_Init(BOARD_DEBUG_UART_BASEADDR,bound,BOARD_DEBUG_UART_TYPE,freq);lpuart1_config.baudRate_Bps=bound;						//波特率lpuart1_config.dataBitsCount=kLPUART_EightDataBits;		//8位lpuart1_config.stopBitCount=kLPUART_OneStopBit;			//1位停止位lpuart1_config.parityMode=kLPUART_ParityDisabled;		//无奇偶校验lpuart1_config.enableRx=true;							//使能接收lpuart1_config.enableTx=true;							//使能发送LPUART_Init(LPUART1,&lpuart1_config,freq);				//初始化LPUART1 #if EN_LPUART1_RX									        //是否需要开启中断?	//LPUART中断设置LPUART_EnableInterrupts(LPUART1,kLPUART_RxDataRegFullInterruptEnable); //使能接收中断RT1052_NVIC_SetPriority(LPUART1_IRQn,5,0);				//抢占优先级5,子优先级0EnableIRQ(LPUART1_IRQn);	                            //使能LPUART1中断
#endif
}	

在代码中,原本调用的 CLOCK_EnableClock 用于开启 LPUART1 时钟,但实际上可以省略,因为 LPUART_Init 内部已经会自动完成时钟使能。接着,将串口时钟源配置为 80 MHz,并通过 IOMUXC 将 GPIO_AD_B0_12GPIO_AD_B0_13 分别复用为 LPUART1 的 TX 和 RX 引脚。完成 IO 配置后,调用 LPUART_Init 初始化串口 1。

由于需要使用串口中断接收功能,需要在 lpuart.h 中确保宏 EN_LPUART1_RX 置为 1(默认即为 1)。这样初始化函数会自动配置接收中断并开启 LPUART1 的 NVIC 中断。最后,将串口 1 的中断优先级设置为抢占优先级 5、子优先级 0,并在 LPUART1_IRQHandler 中编写具体的中断服务逻辑。

然后写main.c的代码

#include "sys.h"
#include "lpuart.h"
#include "delay.h"
#include "led.h"
#include "key.h"int main(void)
{u8 key=0;u8 led0sta=1,led1sta=1;     //LED0,LED1的当前状态u8 len;					//接收数据长度u16 times=0;            //延时计数器MPU_Memory_Protection();    //初始化MPURT1052_Clock_Init();	    //配置系统时钟DELAY_Init(600);		    //延时函数初始化LPUART1_Init(115200);       //初始化串口1RT1052_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);//优先级分组4LED_Init();				    //初始化LEDKEY_Init();                 //初始化KEYLED0(0);					//先点亮红灯 while(1){
#ifdef KEY_DEBUGkey=KEY_Scan(0); 		    //得到键值if(key){	switch(key){				 case WKUP_PRES:	//控制LED0,LED1互斥点亮led1sta=!led1sta;led0sta=!led1sta;break;case KEY2_PRES:	//控制LED0翻转led0sta=!led0sta;break;case KEY1_PRES:	//控制LED1翻转	 led1sta=!led1sta;break;case KEY0_PRES:	//同时控制LED0,LED1翻转 led0sta=!led0sta;led1sta=!led1sta;break;}LED0(led0sta);		//控制LED0状态LED1(led1sta);		//控制LED1状态}else delay_ms(10);
#endif // KEY_DEBUGif(LPUART_RX_STA&0x8000){					   len=LPUART_RX_STA&0x3fff;//得到此次接收到的数据长度printf("\r\n发送的消息为:\r\n");LPUART_WriteBlocking(LPUART1,LPUART_RX_BUF,len);//发送接收到的数据printf("\r\n\r\n");//插入换行LPUART_RX_STA=0;}else{times++;if(times%5000==0){printf("\r\nALIENTEK RT1052开发板 串口实验\r\n");}if(times%200==0)printf("请输入数据,以回车键结束\r\n");  if(times%30==0)LED0_Toggle;//闪烁LED,提示系统正在运行.delay_ms(10);   }}
}

一定注意使用GB2312格式编码!!!!
然后编译,下载。
打开串口调试工具。
在这里插入图片描述
数据回显,同时红色小灯闪烁。

总结

这一节比较简单,主要难点是串口接收中断这部分。串口发送相反简单一点,因为我们在新建工程的时候已经有所了解。

http://www.dtcms.com/a/568900.html

相关文章:

  • CANoe学习(二)使用CANdb++制作dbc
  • Node.js Buffer:深入理解与高效使用
  • Prompt Gen Desktop 管理和迭代你的 Prompt!
  • Prompt Composition with LangChain’s PipelinePromptTemplate
  • 【HarmonyOS NEXT】常见的性能优化
  • [Ethernet in CANoe]2--如何在CANoe中去仿真CP版本的SOME/IP通信
  • 优先队列(堆)
  • 基于 TCP 线程池服务器封装 HTTP 服务器:从协议解析到适配落地
  • xargs
  • 据库事务是数据库管理系统 ACID 四大特性
  • 宜昌市住房和城乡建设局网站wordpress后台慢
  • SSM基于HTML5的流浪动物领养平台yww0b(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
  • 网站栏目分类网站开发市场
  • word转Pdf,在window正常,放在linux服务器上就转出来中文是空白
  • 攻防世界-Misc-pdf
  • 开启RN之旅——前端基础
  • 【LeetCode】99. 恢复二叉搜索树
  • 【rhcsa第一次作业】
  • 哪个网站做图找图片上海网络推广公司排名
  • 订单支付后库存不扣减,如何用RabbitMQ来优化?
  • Qt对话框设计
  • 解决 contents have differences only in line separators
  • 无锡建站方案深圳百度总部
  • Docker中安装 redis、rabbitmq、MySQL、es、 mongodb设置用户名密码
  • SAP EXCEL模板下载导入
  • 动态贝叶斯网络物联网应用方式
  • Oracle OCP认证:深度解析与实战指南
  • 帝国建设网站wordpress迅雷插件下载
  • HTTP 请求与数据交互全景指南:Request、GET、POST、JSON 及 curl
  • 如何进一步推动淘宝商品详情API的安全强化与生态协同创新?