拓冰建站拓冰建站
首页 / 资讯中心 / 正文

C6748 UART例程详解:从CCS工程到串口通信实战

简介针对TI C6748 DSP的UART串行通信开发需求这份rar资源包提供了官方参考例程适合嵌入式工程师、学生及正在使用StarterWare库进行C6748外设开发的开发者。压缩包体积仅3KB内含1个C语言源文件聚焦UART核心操作方便快速定位和复用目前已有209人学习/下载具备一定的实用参考价值。代码展示了基于StarterWare库的UART初始化、波特率设置及发送接收流程采用简洁的设计思路可帮助读者理解中断或轮询方式下的串口数据交互。配合CCS调试环境开发者可以运行并验证回环通信掌握C6748 UART模块的寄存器配置与状态判断方法进一步了解波特率、数据位与停止位的组合方式为后续扩展更复杂的串口协议或对接外部设备打下基础。这份rar包以极小的代码体量呈现完整的UART初始化与收发逻辑是快速上手C6748串口开发的实用参考。 如果你是从单片机转过来学DSP的第一次打开C6748的资料包大概率会和我一样愣住光盘里文件多到让人头皮发麻但是真正能直接跑起来验证开发环境的例程翻来翻去就那一个——uart.rar。这个压缩包解压出来是个CCS工程工程名多半叫uartExample对应官方StarterWare里C6748的UART串口通信例程。别小看这个几十KB的工程它就是C6748上的“Hello World”。把它完整跑通一次CCS环境配置、仿真器连接、外设时钟初始化、串口工具调试这些最基础的环节就全部打通了。这篇文章我就把这个例程从硬件原理到软件流程完整拆一遍再把我调试过程中踩过的坑和排查思路一并写出来给后来的人省点时间。1. 拿到uart.rar之后先搞清楚这个例程到底在演示什么1.1 它其实就是C6748上的“Hello World”很多人拿到开发板的第一反应是点灯但点灯只能证明GPIO能用证明不了内核时钟、外设总线、串口链路这些都正常工作。UART例程的意义在于它把DSP的主频配置、外设时钟使能、引脚复用、串口控制寄存器、以及PC端的串口工具全部串在了一起。当你在串口助手里看到板子发出来的字符时等于这整条链条已经全部打通了。C6748这个芯片的主频通常工作在456MHz部分板子配置为300MHz内部外设挂在不同的时钟域上。UART模块本身并不复杂但是要让它转起来首先要保证两层东西都正确第一层是DSP全局时钟和UART模块时钟得配好第二层是UART控制寄存器得按协议要求配置。官方例程恰好把这两层都覆盖到了。代码里第一步是初始化PLL和DDR很多板子的platform初始化里带DDR配置第二步就是配置UART引脚复用和UART寄存器然后循环往串口发送数据、接收数据。这一步通了后面你想做串口打印调试、和上位机通信、甚至跑操作系统都有了一个可靠的基础设施。1.2 工程里每个核心文件是干什么的打开uart.rar里的工程你会看到一组目录结构初看很唬人其实核心就那几类文件。搞清楚每个文件的职责后面改代码的时候就不会迷路。main.c程序入口里面完成平台初始化和UART配置然后进入发送/接收循环。uart.c/uart.hStarterWare外设库里的UART驱动源码封装了初始化、收发、中断使能等API。这部分官方已经写好正常情况不需要改动。hw_uart.hUART模块的寄存器位域定义头文件。驱动库里读写寄存器全靠它如果你想自己直接操作寄存器从这个文件查位域最权威。evmC6748.c/board.c开发板级初始化代码主要负责把引脚复用配置成UART功能、初始化电源和睡眠控制PSC。platform.c平台相关代码里面包含DSP主频配置、时钟树初始化。这里有个关键信息UART模块时钟频率就是在这个文件里确定的稍后讲波特率计算时你还会遇到它。如果你用的是StarterWare完整包而不是单独解压的uart.rar例程路径一般在C:/ti/StarterWare/binary/c674x/c6748/evmC6748/uart/uartExample附近。确认工程路径时留意一下别把evmC6748和lcdkC6748两个boards目录搞混虽然芯片一样但开发板引脚和外设布局有差异选错了编译出来往往是能编译但板子跑不起来或者引脚对不上。1.3 先能在CCS里把它编译出来编译这一步很多人会卡在CCS版本和编译器的选择上。以我自己的经验用CCS 6.x到CCS 8.x都能顺利打开这个工程关键是导入工程后要确认两件事。第一工程属性里的目标器件是否正确识别为TMS320C6748。第二编译器版本要和工程自带的ccsproject配置匹配。如果工程是用老版本CCS创建的新版本CCS打开后通常会弹窗询问是否自动转换工程格式我一般点自动转换转换完成后重新编译一次大部分问题都能解决。如果你的C6748板子用的是XDS100V2仿真器连接时还需要注意目标配置target configuration里选对仿真器型号测试连接能通过再Load Program。加载程序后先让DSP跑起来F8然后在串口助手观察数据。正常情况板子上电后UART使能并初始化完成程序就会向串口发送预定义的字符串板子在调试器里单步、全速状态下这个行为都是稳定的。2. 动手前必须弄明白的UART硬件细节2.1 C6748的UART模块底子是16550兼容C6748的UART模块不是TI另起炉灶设计的它兼容经典的16550 UART标准。这意味着如果你以前玩过PC串口编程或者STM32的USART看到这套寄存器会有一种熟悉的陌生感有THR/RBR收发保持寄存器、IER中断使能寄存器、IIR中断标识寄存器、LCR线路控制寄存器、LSR线路状态寄存器还有波特率除数锁存器DLL/DLH。唯一不太一样的是C6748把寄存器基地址映射在了内存空间直接通过地址访问没有x86那套IO端口的操作方式。16550标准给C6748带来的好处是它自带16字节发送FIFO和16字节接收FIFO。你可以把FIFO理解为邮局门口的信箱发送的时候先把信投进信箱邮递员硬件移位器按顺序取走逐位发出去接收的时候来信先放在信箱里CPU有空了再来取。没有FIFO的老式UART则像邮递员每来一封信就敲你门你必须放下手里的活在下一个字符到之前取走否则就丢数据。有了FIFOCPU的处理压力一下就小多了这也是中断方式能够可靠运行的基础。2.2 引脚与电平3.3V TTL和RS232之间差一个芯片C6748的UART引脚输出的是3.3V TTL电平TXD空闲时为高电平发送数据时在0V和3.3V之间跳变。而老式电脑的COM口用的是RS232电平空闲为负电压-3V到-15V逻辑1也是负电压逻辑0才是正电压。这两种电平互不兼容直接接上去不仅通信不了还很可能烧掉DSP引脚。所以连接串口之前先看清你的板子上有没有板载的电平转换芯片。如果用USB转TTL工具比如FT232、CH340、CP2102这类那就是把USB信号转成3.3V TTL可以直接和DSP的TXD/RXD引脚相连注意TXD接RXD、RXD接TXD、GND接GND三者缺一不可。如果板子自带DB9接口通常板上已经放了MAX3232或SP3232这类RS232收发器那就用DB9线连电脑原生串口或USB转RS232线不要再额外加转TTL工具。有人会拿5V的USB转TTL模块去接C6748我强烈不建议这么干。C6748的IO口是3.3V供电5V电平直接灌进来轻则通信异常重则损伤引脚。选工具的时候确认一下模块侧面跳线和芯片型号输出的是3.3V还是5V。另外C6748有些IO bank的电压也可以通过电源配置调整虽然开发板基本固定成3.3V但如果你的板子单独改了某组IO电压还要额外注意。2.3 波特率不是想设多少就设多少UART波特率本质上由模块时钟经分频产生C6748的UART内部有一个波特率除数寄存器16位宽。波特率计算公式是波特率 UART模块时钟 / (16 × 除数)换个写法除数 UART模块时钟 / (16 × 波特率)。这个除数必须是整数但实际除出来往往带小数硬件会直接截断取整这就产生了波特率误差。以常见的24MHz UART模块时钟来算要得到115200bps除数 24000000 / (16 × 115200) 13.02取整为13实际波特率 24000000 / (16 × 13) 115384.6bps误差只有0.16%完全没问题。但如果模块时钟是20MHz除数 20000000 / (16 × 115200) 10.85取整为10实际波特率 20000000 / (16 × 10) 125000bps误差达到8.5%这种波特率下PC和DSP收发基本就是乱码了。所以想搞清楚为什么乱码先确认代码里传入UART配置函数的那个时钟频率到底是不是你的板子实际生成的UART模块时钟。3. 官方例程的核心代码逐段拆解3.1 初始化三步走引脚复用、模块时钟、复位C6748的引脚大部分是多功能的同一个物理引脚既可以当GPIO也可以当UART_TXD还可以当其它外设信号。你必须在PINMUX寄存器里告诉芯片这个引脚当前要干什么。官方例程里通常会直接在main开头调用GPIOBank0Pin12PinMuxSetup()这类board层函数名字听起来像是在配GPIO实际上它内部把UART0相关的TXD/RXD引脚复用也一并配置好了。如果你不看代码直接把这行注释掉串口就会悄无声息地没输出因为引脚还停在默认的GPIO模式上。第二步是使能UART模块时钟。C6748的电源和睡眠控制器PSC管理着所有外设的时钟开关默认状态下大部分外设时钟是关闭的目的是省电。如果你跳过这一步直接操作UART寄存器写进去的值不会生效程序逻辑上看着对就是串口没反应。例程里platform初始化会统一把需要用到的外设时钟打开这块逻辑通常在main里的platform_init()或EvM6748_init()中体现。第三步是复位UART模块并等待复位完成。StarterWare的UARTInit()函数做的就是这件事它会设置UART的全局控制寄存器里的复位位再轮询等待硬件完成复位状态清0。这一步的作用是把UART内部状态机恢复到一个确定的初始态防止上电乱序导致寄存器状态不可预期。3.2 UARTConfigSetExpClk到底做了什么官方UART例程里最核心的配置就一行调用UARTConfigSetExpClk(SOC_UART_0_REGS, 24000000, 115200, UART_DATA8, UART_PARITY_NONE, UART_STOP1);这行代码的参数从左到右分别是UART寄存器基地址、UART模块时钟频率、目标波特率、8位数据长度、无校验、1位停止位。函数内部做了几件事先把线路控制寄存器LCR的波特率除数锁存位DLAB置1这样后续写入DLL和DLH才会被解释成波特率除数然后按公式算出分频除数写入DLL/DLH最后把DLAB位清0同时把数据位、校验位、停止位这些参数写入LCR。这里最容易被坑的是第一个时钟参数。它既不是DSP主频456MHz也不是某个固定值而是UART模块实际获得的时钟频率。如果你的platform代码里PLL配置和官方不同有人为了低功耗把主频配成300MHz同时把外设时钟配成了不同的分频值那么这里写死的话就要跟着改。官方例程里直接写的是24000000但更稳妥的做法是从平台层动态获取UART时钟例如用PlatformGetUARTClk()避免因platform配置调整导致波特率失真。官方代码之所以能跑是因为platform配置里UART时钟恰好是24MHz这也在侧面说明看代码不能只看收发逻辑还得顺藤摸瓜确认时钟树。3.3 轮询收发和中断收发官方例程为什么两种都给了如果打开完整的StarterWare UART例程通常能看到两套收发逻辑一套是简单的轮询polling另一套是中断interrupt方式。轮询方式的代码极其简单核心就是两个API// 发送一个字符阻塞直到发送保持寄存器/发送FIFO有空位 UARTCharPut(SOC_UART_0_REGS, A); // 接收一个字符若没有数据则返回-1 int ch UARTCharGetNonBlocking(SOC_UART_0_REGS);轮询的特点就是CPU死等发送前循环等待THR为空接收时不断查询接收FIFO里有没有数据。这在只有一个外设任务的场景下完全够用但是如果你在DSP上还要跑控制算法、做AD采样或者和DDR交互数据任何一次串口等待都会浪费大量CPU时间。中断方式的配置流程会多一些步骤核心思路是使能UART接收中断 → 注册中断服务函数到C6748的高级中断控制器AINTC→ 服务函数里读UARTIntStatus()判断中断源 → 如果是接收中断则从RBR读取数据 → 完成读取后中断标志自动清掉。C6748的中断控制器比ARM Cortex-M的NVIC复杂一些没有现成的HAL的话初始化时序要从IntRegister、IntEnable这些StarterWare API配对使用注意不要漏掉IntGlobalEnable()这个全局中断使能。官方例程两种方式都给目的就是让你先跑通最简单的轮询再渐进式理解C6748的中断系统。4. 跑通例程后最容易踩的四个坑4.1 USB转串口驱动FT231X这类芯片到底该装哪个热搜词里“ft231x usb uart驱动”、“ft232r usb uart驱动”反复出现说明很多人卡在了USB转串口这一环上。FT231X和FT232R都是FTDI公司的USB转UART桥接芯片区别是FT231X较新、封装小FT232R是经典款。Windows 10以上系统通常会自动安装FTDI的VCP驱动识别成功后设备管理器里会出现“USB Serial Port (COMx)”。如果系统没有自动识别务必去FTDI官网下载对应VCP驱动不要用第三方驱动精灵类工具。另外注意一个容易混淆的点FT231X/FT232R驱动装好之后设备管理器里显示的设备名和芯片型号有关有的直接显示芯片型号有的只显示一个COM口号。有些开发板上的USB转串口芯片还集成了复位控制也就是DTR/RTS信号参与DSP的启动模式选择。下载程序时如果发现板子连不上仿真器先复位一下板子再尝试这可能不是驱动问题而是启动模式被串口工具的电平影响了。4.2 波特率误差导致乱码别急着调寄存器先复算一遍时钟串口乱码的排查顺序我建议是先把PC端软件串口参数波特率、数据位、停止位、校验位和代码设置对齐然后用示波器或逻辑分析仪看TXD引脚实际波形数一下一位的宽度算出真实波特率最后反推UART模块时钟和除数的匹配关系。如果确认实际波特率比目标值偏大或偏小比如目标115200、实测大约是115385那就是官方24MHz时钟配套13除数属于正常误差范围乱码概率极低。可如果你把PLL配置改了UART时钟变成了30MHz却仍然在UARTConfigSetExpClk里传入24000000实际算出来的波特率会偏差20%以上这种情况必然乱码。调试的时候不要想当然认为时钟树配置“差不多就行”C6748的PLL配置有固定的分频倍频关系最好打印或单步查看SYSCLK相关寄存器值逐项核对。4.3 一收就死或者丢字节FIFO和中断标志的处理顺序把官方例程改成中断接收后很多人会遇到“发一个字节程序就跑飞”或者“接收偶尔丢字节”。这类问题十有八九出在两个地方。第一个是FIFO触发阈值。C6748 UART的接收FIFO默认阈值是1字节也就是每收到一个字节就触发一次中断。如果你在中断服务函数里一次性读多个字节而数据其实还没收全就会读到空数据。官方库UARTFIFOLevelSet()可以调整阈值比较常用的是4字节或8字节。这个阈值要根据你的实际数据量和中断响应延迟来定阈值设得太低会让CPU频繁进中断太高则可能等不到阈值导致数据积压。第二个是中断服务函数里读取RBR后要正确地清中断标志。16550架构下读RBR这个动作本身就会清除接收中断标志但有经验的开发者会先UARTIntStatus()读出中断标识再根据标识决定是否读取数据防止同一中断被误处理。C6748的AINTC还要求你在退出中断前正确响应中断控制器否则会出现中断嵌套异常或同一次中断被反复触发。4.4 板子接上电脑没反应先按这个顺序排查链路板子连上电脑完全没有数据输出这是最让人头大的情况但也是最容易排查的情况。按这个顺序一步步来能省很多时间。先看电源和指示灯DSP核心电压、IO电压、LED状态是否正常。再看串口工具连接的是不是板子标注的那组串口引脚TXD/RXD是否接反同一块开发板如果引出多组串口选错引脚组合也是常见问题。然后确认仿真器是否连接成功如果代码还没烧进去或者DSP没运行串口自然不会有输出。最后检查PC设备管理器里的COM口号和串口助手选的是不是同一个端口COM口号在重新插拔USB之后可能变化。如果以上都没问题但依然没输出下一步用示波器量TXD引脚。如果DSP全速运行且代码正确TXD上应该有连续的电平翻转波形没有波形则说明程序大概率没跑到UART发送代码这时候回到CCS里看程序计数器停在哪个函数基本就能定位是初始化卡住还是发送逻辑没执行。5. 从官方例程再往前走一步5.1 立刻把轮询改成中断收发官方例程跑通后我建议第一件事就是把收发逻辑从轮询改成中断别拖。轮询看似简单但一旦你的工程里加了一个延时循环或者一个耗时计算串口响应就会立即变得不可靠。中断收发的改造步骤并不复杂上面已经提过初始化时注册中断服务函数使能UART接收中断服务函数里读取接收字符并放入一个环形缓冲区主循环从缓冲区取数据解析即可。这里想强调一个工程习惯中断服务函数里不要做复杂的协议解析只做数据搬运解析放到主循环或者任务里。中断里做解析一旦协议复杂度上来很容易导致中断耗时太长反而丢新数据。5.2 帧协议设计从发裸数据到定义自己的通信格式官方例程只是收发裸数据真正做项目时必须自己定义帧格式。我常用的帧设计是帧头两个固定字节比如0xAA 0x55 长度字节 命令字 数据域 校验字节。校验建议用CRC8或者简单的和校验千万不要在项目里裸发纯数据。原因很现实串口是异步通信没有帧边界概念接收端不知道一串字节从哪里开始到哪里结束。串口调试时用“发送新行”能凑合看文本但机器对接时必须有一个能区分帧边界、能发现错误的机制。我的经验是帧头尽量选不容易在数据里出现的字节序列如果要更可靠还可以在帧头前加一段静默时间作为帧间隔判断。5.3 后续还能扩展什么等UART中断收发跑通以后C6748的外设学习之路就算真正开始了。串口之后可以依次去碰SPI、I2C、McBSP、uPP这些接口会发现C6748外设的学习方法论是通用的先看引脚复用再开时钟再配置控制寄存器最后处理中断或DMA。UART例程就是这套方法论的最小闭环。另外如果你的工程里串口数据量很大比如持续接收传感器数据可以研究一下用EDMA把UART接收FIFO的数据自动搬到内存缓冲区这样CPU只在缓冲区满或达到阈值时才被通知一次能省下大量中断开销。虽然第一次配EDMA的link和param会花不少时间但配通之后你会对整个C6748的数据搬运机制理解深一大截。我自己的体会是uart.rar这个压缩包虽然小但它是一把钥匙。每次有新同事上手C6748我都建议他先别急着翻PDF先把官方UART例程完整跑一遍把串口助手调通。这一步完成之后CCS的工程配置、仿真器连接、外设时钟初始化、串口工具使用这些最基础也最琐碎的环境问题全部在一开始就解决了后面的路上你会省下大量“怀疑人生”的时间。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门