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

7. TI MSPM0L1306串口通信实战:基于SysConfig与中断的UART0收发配置详解

7. TI MSPM0L1306串口通信实战:基于SysConfig与中断的UART0收发配置详解

最近在TI电赛开发板上做项目,串口通信是调试和与外界交互最常用的功能。很多刚开始接触TI MSPM0系列(比如咱们用的MSPM0L1306)的朋友,可能会对如何使用CCS里的图形化工具SysConfig来配置串口感到陌生。今天,我就手把手带大家走一遍完整的流程,从时钟配置、引脚分配到中断编程,实现一个“收到什么就回发什么”的数据回环实验。只要你跟着步骤做,保证能让开发板上的串口0(UART0)和电脑顺畅地“对话”。

1. 准备工作与核心概念扫盲

在动手配置之前,咱们先快速过一遍几个关键概念,理解它们能让你后面的操作更清晰。

串口通信,简单说就是设备之间一根线发数据,另一根线收数据,按位(bit)来传输。虽然速度比不上并口,但它接线简单,成本低,远距离通信更有优势。要让两个设备能“聊上天”,必须约定好相同的通信参数,主要是这四个:

  • 波特率:通信的速度,比如9600,表示每秒传输9600个比特。
  • 数据位:一个数据帧里实际有效数据的位数,常见的是8位。
  • 停止位:用来表示一个数据帧传输结束,通常是1位。
  • 校验位:用于简单的错误检查,比如奇校验或偶校验,如果不需要可以选“无”。

咱们的MSPM0L1306芯片有两个串口:UART0和UART1。在TI电赛开发板上,UART0的引脚(PA22和PA23)已经连接到了板载的CH340E芯片上。CH340E是一个USB转串口芯片,所以你只需要用一根USB Type-C线连接开发板和电脑,电脑上就会出现一个串口设备(比如COM3),非常方便。

注意:PA23这个引脚比较特殊,它同时是串口0的RX引脚、参考电压引脚和BSL(引导加载程序)串口引脚。开发板默认通过一个0欧姆电阻(R24)将它配置为串口功能。如果你后续项目需要用到参考电压功能,记得把这个电阻去掉。

2. 使用SysConfig图形化配置UART0

TI在Code Composer Studio (CCS)里提供的SysConfig工具非常好用,像搭积木一样配置外设,能自动生成初始化代码,省去了我们手动查手册、算寄存器值的麻烦。

2.1 创建工程与打开SysConfig

首先,在CCS里新建一个空的工程(Empty Project)。工程建好后,在左侧的工程资源管理器里,你会看到一个名为工程名.syscfg的文件,双击打开它,SysConfig的配置界面就出来了。

2.2 配置串口时钟源(MFCLK)

串口要工作,必须有时钟驱动。MSPM0L1306的串口时钟可以从三个来源选:

  • BUSCLK:内部高频振荡器提供的CPU主时钟,默认通常是32MHz。
  • MFCLK:固定的4MHz时钟。我们本次实验就选用这个
  • LFCLK:内部低频振荡器提供的32KHz时钟,用于低功耗场景。

要使用MFCLK,我们需要在SysConfig里先把它“打开”。

  1. 在SysConfig左侧选项卡中找到并点击SYSCTL
  2. 在右侧的选项页中,找到Use Clock Tree并勾选,这样就能配置时钟树了。
  3. 勾选后,左侧会出现三个图标,点击中间那个时钟树图标。
  4. 在展开的时钟树图中,找到SYSOSC_4M这一分支,点击其上的选项块,将其状态设置为Enabled
  5. 设置成功后,你会看到右侧对应位置显示频率为4.0000MHz。这就说明MFCLK时钟源已经准备好了。

2.3 添加并配置UART0外设

时钟搞定,现在来配置串口本身。

  1. 在SysConfig左侧的“Peripherals”或类似选项卡下,找到UART,点击ADD按钮添加一个UART实例。

  2. 添加后,右侧会出现详细的配置页面。我们需要设置以下几项:

    • Instance: 选择UART0
    • Pin Configuration: 配置引脚。根据数据手册,UART0对应PA22和PA23。在配置页中找到引脚设置,将TX选择为PA22,RX选择为PA23。SysConfig会自动帮你配置引脚的复用功能。
    • Basic Settings(基本设置):
      • Baud Rate (波特率):9600
      • Data Length (数据位):8 bits
      • Stop Bits (停止位):1 bit
      • Parity (校验位):None
      • Hardware Flow Control (硬件流控制):Disabled
    • Advanced Settings(高级设置):
      • 这里有个关键参数Oversampling(过采样率)。它有3、8、16三个档位。这个值会影响波特率计算的精度。我们的时钟源是4MHz,为了能正确计算出9600波特率的分频系数而不出错,这里选择16一个简单的原则:只要SysConfig界面底部没有报错(红色错误提示),你的配置就是可行的。
    • Interrupt Settings(中断设置):
      • 因为我们打算用中断方式接收数据,所以需要开启接收中断。找到接收中断相关的选项(如RX Interrupt),将其使能(Enabled)。
  3. 所有配置完成后,记得按Ctrl+S保存这个.syscfg文件。保存后,SysConfig会自动在后台生成对应的C语言初始化代码(在ti_msp_dl_config.c.h文件中),我们等下直接调用就行。

3. 编写代码:实现中断接收与回发

配置工具帮我们做好了硬件初始化,但数据怎么收、怎么发,还得我们写代码来实现。我们要实现的功能是:电脑通过串口调试助手发送一个字符给开发板,开发板收到后,立刻把这个字符再发回给电脑。

3.1 主函数与中断使能

打开包含main()函数的那个C文件(比如main.cempty.c),开始编写代码。

#include "ti_msp_dl_config.h" volatile unsigned char uart_data = 0; // 用于存储接收到的字符 void uart0_send_char(char ch); // 声明发送单个字符的函数 void uart0_send_string(char* str); // 声明发送字符串的函数 int main(void) { // 1. 初始化所有在SysConfig中配置的外设(包括UART0) SYSCFG_DL_init(); // 2. 清除UART0可能已有的中断挂起标志,避免一开中断就误触发 NVIC_ClearPendingIRQ(UART_0_INST_INT_IRQN); // 3. 使能UART0的中断(NVIC是中断控制器) NVIC_EnableIRQ(UART_0_INST_INT_IRQN); // 4. 发送一个启动提示信息 uart0_send_string("uart0 start work\r\n"); // 5. 主循环,这里什么都不做,等待中断发生 while (1) { // 可以在这里添加其他任务 } }

代码解析:

  • SYSCFG_DL_init():这个函数是SysConfig生成的,必须调用,它负责按照我们之前的图形化配置,初始化芯片的时钟、GPIO、UART等所有外设。
  • NVIC_ClearPendingIRQNVIC_EnableIRQ:这是操作中断控制器的标准流程。先清除旧的中断标志,再打开这个中断的“开关”。UART_0_INST_INT_IRQN这个宏定义在ti_msp_dl_config.h里,代表UART0的中断号。
  • volatile关键字:修饰uart_data是因为它会在中断服务函数中被修改,在主循环中可能被读取或判断。volatile告诉编译器不要优化这个变量,确保每次访问都从内存中读取最新值。

3.2 串口发送函数

我们需要两个实用的发送函数:发单个字符和发字符串。

// 串口发送单个字符 void uart0_send_char(char ch) { // 等待串口0发送器空闲(不忙)。这是防止数据覆盖丢失的关键! while( DL_UART_isBusy(UART_0_INST) == true ); // 发送字符 DL_UART_Main_transmitData(UART_0_INST, ch); } // 串口发送字符串 void uart0_send_string(char* str) { // 判断字符串指针有效且未到结尾(C语言字符串以'\0'结尾) while(*str != 0 && str != 0) { // 发送当前字符,然后指针指向下一个字符 uart0_send_char(*str++); } }

提示DL_UART_isBusy这个等待循环非常重要。想象一下,如果你连续调用发送函数,而前一个字节还没从硬件发送出去,后一个字节就写入了发送缓冲区,就会导致数据丢失。这个函数就是检查硬件是否就绪的“哨兵”。

3.3 串口中断服务函数

这是核心部分。当串口收到一个字节的数据时,硬件会自动触发中断,CPU就会跳转到这里来执行。

// UART0的中断服务函数 —— 函数名是固定的,不能改! void UART_0_INST_IRQHandler(void) { // 获取是哪种串口中断触发了本次调用 switch( DL_UART_getPendingInterrupt(UART_0_INST) ) { case DL_UART_IIDX_RX: // 如果是接收中断 // 从接收数据寄存器中读取一个字节 uart_data = DL_UART_Main_receiveData(UART_0_INST); // 将收到的数据原样发送回去 uart0_send_char(uart_data); break; default: // 其他类型的串口中断(如发送完成中断),本例中不处理 break; } }

关键点

  1. 函数名必须准确UART_0_INST_IRQHandler这个名字是芯片启动文件或驱动库定义好的,写错了中断就进不来了。你可以在工程生成的ti_msp_dl_config.h文件里找到这个函数名的宏定义。
  2. 中断类型判断:使用DL_UART_getPendingInterrupt来查询具体的中断源。我们只关心接收中断 (DL_UART_IIDX_RX)。
  3. 读取数据DL_UART_Main_receiveData函数会读取并清除接收缓冲区,同时也会清除相应的中断标志位。

3.4 实验验证

将代码编译、下载到开发板。打开电脑上的串口调试助手(如XCOM、SSCOM等),选择开发板对应的串口号(COMx),设置波特率9600、8数据位、1停止位、无校验。

点击发送一个字符或一串字符,你应该能在接收区看到开发板回送的一模一样的数据。同时,第一次上电或复位时,会收到uart0 start work的启动信息。

4. 进阶技巧:重定向printf函数

每次都调用uart0_send_string来输出调试信息有点麻烦。如果能直接用printf函数,那可就方便多了。这就需要我们“重定向”标准输出到串口。

#include "stdio.h" // 必须包含这个头文件 // 重定向fputc函数,使printf的字符输出到串口 int fputc(int ch, FILE *stream) { while( DL_UART_isBusy(UART_0_INST) == true ); DL_UART_Main_transmitData(UART_0_INST, (char)ch); return ch; } // 重定向fputs函数(可选,但更高效) int fputs(const char* restrict s, FILE* restrict stream) { uint16_t char_len = 0; while(*s != 0) { while( DL_UART_isBusy(UART_0_INST) == true ); DL_UART_Main_transmitData(UART_0_INST, *s++); char_len++; } return char_len; }

把上面这段代码加到你的工程里,之后你就可以在代码中愉快地使用printf(“温度值:%d\r\n”, temperature);了,输出会自动通过UART0发送到串口助手。

踩坑提醒:如果你在printf中使用了浮点数格式(如%f),程序可能会卡死。这是因为默认的工程优化设置可能不支持完整的浮点库。解决方法是在CCS的工程属性中,将优化等级从O2暂时调整为O0(不优化)。具体路径是:右键工程 -> Properties -> CCS Build -> Optimization -> Optimization Level -> None (-O0)。

http://www.cnnetsun.cn/news/1243319.html

相关文章:

  • DownKyi:零基础轻松下载B站高清视频的开源工具
  • FunASR离线时间戳模型实战:从Docker镜像下载到Python客户端调通的避坑指南
  • 【深度学习】Paddle-Lite模型优化实战:从导出到NB格式转换全流程解析
  • 416. 分割等和子集
  • EU104芯片深度评测:无需晶振的UART扩展方案真的靠谱吗?(实测数据+功耗分析)
  • 告别手动排查!用ncdu可视化分析CentOS目录占用(附Docker/Jenkins专项清理指南)
  • OpenTelemetry实战指南——Kubernetes环境下的链路追踪自动化部署
  • 还在为Winget安装发愁?这款工具让Windows包管理部署效率提升90%
  • vue实战:基于快马平台快速构建整合pinia和vue router的商品管理系统
  • 罗技鼠标宏压枪脚本精准控制方案:从原理到实战的系统化配置指南
  • H3C无线网络优化实战指南:从信道调优到频谱导航
  • Python实战:5分钟搞定拉格朗日插值法(附完整代码)
  • Qwen-Image-2512-SDNQ MATLAB集成:科研数据可视化增强
  • 5个超实用的非参考图像质量评估工具:从BRISQUE到PIQE的实战指南
  • 智能标注革命:从繁琐测量到一键生成的工作流革新
  • ESP32-C61 AT命令实战:HTTP/TCP/SSL透传全栈解析
  • 互联网公开数据合规利用:为万象熔炉·丹青幻境构建领域知识库
  • Glyph-OCR效果对比:传统方法 vs Glyph,结果一目了然
  • 效率倍增:用快马AI一键生成模块化全球服务器监控面板
  • ESP32-S3中断矩阵详解:寄存器映射、NMI管理与状态查询
  • CODESYS任务类型全解析:从循环任务到外部事件的实战应用
  • Kook Zimage真实幻想Turbo开发者指南:自定义LoRA注入与权重清洗
  • Qwen3-TTS-12Hz-1.7B-CustomVoice在播客制作中的应用:自动化内容生成方案
  • ESP32-S3 SPI时序补偿与中断机制深度解析
  • 效率倍增:利用快马AI快速适配clawdbot至不同网站结构
  • 3步高效掌握Parse12306:全国列车数据获取实战秘籍
  • 新手教程:nanobot超轻量部署与使用,从安装到QQ机器人配置
  • MiniCPM-V-2_6问题解决指南:常见报错处理,小白避坑手册
  • Qwen3-TTS语音合成参数详解:12Hz采样率设计动机与频响特性分析
  • Fish Speech 1.5企业应用指南:低成本构建私有化语音合成生产环境