
瑞萨RL78串口配置这块网上资料其实不少但大部分都是照着数据手册翻译或者官方例程直接贴上来真正把“为什么这么配”讲清楚的很少。我前阵子用一个RL78/G13做项目串口这块从寄存器看到中断从波特率误差算到引脚复用踩了不少坑也总结了一套自己的配置思路。这篇就把完整的配置流程、背后的计算逻辑、以及我实际调试中遇到的问题都梳理一遍给正在用瑞萨芯片做串口通信的朋友做个参考。1. 整体思路先搞懂RL78的串口资源再动手配1.1 瑞萨RL78的串口有什么特殊性RL78系列是瑞萨的16位MCU低功耗是它的强项但串口这块和主流STM32的通用USART不太一样。RL78的串口模块叫“串行阵列单元”Serial Array Unit简称SAU一套SAU里分了多个通道每个通道可以灵活配置为UART、CSISPI、简易I2C三种模式之一。这和ST的USART虽然都是外设但配置思路有明显的差异。STM32用CubeMX点几下就能生成好初始化代码寄存器细节基本不用管。RL78虽然也有e² studio配合Smart Configurator可以图形化配置但实际项目中很多人还是直接写寄存器或者基于官方例程改。原因很简单RL78的寄存器层级深、位定义细而且不同子系列G系列、F系列、L系列之间寄存器和时钟树还有差异完全依赖工具生成代码出了问题反而更难排查。我用的RL78/G13是典型的16位MCU运行频率最高32MHz内部有高速片上振荡器HOCO和低速振荡器。串口这块的时钟源、分频系数、波特率计算都需要自己算清楚否则串口收发会出现乱码甚至完全不通。1.2 选择和确认串口通道前的三个准备工作动手配串口之前我建议你先花十分钟做三件事可以省掉后面大量调试时间。第一确认你手里芯片的具体型号和封装。RL78/G13的引脚分配因封装不同而不同串口通道对应的引脚组合也不一样。比如有的封装UART0只能映射到P20/P21有的还能通过外围引脚重定向功能映射到其他引脚。查数据手册的“引脚功能分配表”和“SAU通道分配表”这两个表是串口配置的根本依据。第二确认串口的时钟源。RL78的SAU时钟来自内部高速时钟经过分频后的时钟具体分频寄存器是SPSSerial Clock Select Register它可以选fCLK/2、fCLK/4、fCLK/8、fCLK/16等。这里的fCLK是CPU外设时钟G13系列默认16MHzHOCO经过寄存器设置后可以跑到32MHz。波特率的精度和这个fCLK直接相关后面计算波特率时要用到。第三确认你需要的串口模式是UART还是Simplified I2C因为SAU通道配置为不同模式时寄存器字段的含义完全不同。本文讲的是UART模式如果你需要I2C不要直接套用本文的寄存器配置。1.3 和STM32开发习惯的类比RL78的“CubeMX时刻”在哪很多从STM32转过来的工程师第一次接触RL78都会找“类似CubeMX的东西”。答案是e² studio里面的Smart Configurator插件它能以图形化方式配置引脚、时钟、外设并生成代码。但说实话我自己的经验是Smart Configurator生成的代码在简单场景很好用一旦涉及中断优先级定制、多串口复用、低功耗唤醒等高级功能它生成的代码反而像个黑盒不如自己手动配置来得清晰。所以我的建议是先用Smart Configurator快速初始化一个最小工程看它帮你配置了哪些寄存器然后在此基础上自己动手修改逐步将寄存器配置吃透。既兼顾了开发效率又能掌握底层细节排查问题时不至于抓瞎。2. 串口配置的三大核心细节时钟、引脚、波特率2.1 时钟树里那条关键的“SAU时钟路径”RL78/G13的时钟系统不算复杂但串口相关的时钟路径一定要理清。芯片上电默认使用内部高速振荡器HOCO频率为16MHz部分型号支持更高。CPU和外设的时钟由HOCO经过系统时钟控制寄存器CMC、CKC设置分频得到。SAU模块本身还有一个独立的时钟分频由SPS寄存器控制。以我常用的配置为例HOCO选择16MHzCPU时钟设为16MHzSPS设置为fCLK/4那么SAU的计数时钟就是4MHz。这个4MHz就是后面计算波特率的基准。记住一条黄金法则SAU的时钟频率必须能够整除目标波特率的整数倍否则波特率必然有误差。误差超过2%就会出现偶发乱码超过5%基本没法通信。注意RL78的HOCO精度大约为±1%对异步串口来说这个误差加上分频取整的误差最好控制在总误差2%以内。我在实际项目里的目标是把误差压到1%以下这样长时间大流量传输才安心。2.2 引脚复用配置不是简单一句“设为UART模式”RL78的引脚配置比STM32多了一步它有两组关键寄存器端口模式控制寄存器PMC和端口模式寄存器PM。PMC决定引脚是数字I/O还是模拟I/OPM决定引脚方向输入还是输出。串口使用的引脚必须保证PMC被设为数字模式才能正常工作的。以RL78/G13的UART0使用P20TXD0和P21RXD0为例// 将P20、P21设置为数字I/O模式 PMC0 0xCF; // PMC0 bit4和bit5清零即PMC04和PMC05对应P20和P21的数字模式 // 设置引脚方向P20为输出TXDP21为输入RXD PM0 0xCF; // PM04清零P20输出PM05置1P21输入如果你用了外部引脚重定向功能还需要额外设置相关重定向寄存器。这一步是RL78常见坑点很多人配置好了UART寄存器但忘了设置引脚复用结果串口完全没反应。调试技巧如果串口不工作先检查引脚配置寄存器再用示波器量TX引脚有没有波形。很多时候问题根本不在UART模块本身而在引脚没有正确配置成复用功能。2.3 波特率计算的完整推导过程RL78 SAU的UART波特率计算本质上就是一个分频器的计算。数据手册给出了标准公式我这里用实际数字走一遍方便你直接套用。波特率时钟fMCK由SPS寄存器选择假设fCLK 16MHzSPS配置为fCLK/4则fMCK 4MHz。UART的传输时钟由SDR寄存器的低8位设定数据手册里用SDRmn表示分频设定值。UART模式下波特率计算公式为波特率 fMCK / (2 × (SDRmn 1))反推SDRmn的值SDRmn fMCK / (2 × 波特率) - 1以波特率9600为例SDRmn 4000000 / (2 × 9600) - 1 4000000 / 19200 - 1 208.33 - 1 207.33取整最接近的整数为207代入公式计算实际波特率实际波特率 4000000 / (2 × (207 1)) 4000000 / 416 9615.38 误差 (9615.38 - 9600) / 9600 0.16%这个误差可以接受。再看波特率115200的情况SDRmn 4000000 / (2 × 115200) - 1 17.36 - 1 16.36取整为16实际波特率实际波特率 4000000 / (2 × 17) 117647.06 误差 (117647.06 - 115200) / 115200 2.12%2.12%的误差已经超过了安全范围通信容易出问题。解决办法有两种一是提高fMCK到8MHz甚至16MHz二是调整fMCK分频找到一个合适的频率让误差降下来。以fMCK 8MHz为例SDRmn 8000000 / (2 × 115200) - 1 33.72 - 1 32.72取整为33实际波特率实际波特率 8000000 / (2 × 34) 117647.06 误差同样是2.12%咦误差一样这说明115200本身和8MHz的公倍数关系决定的需要换一个思路。把fMCK设为12MHz试试SDRmn 12000000 / (2 × 115200) - 1 51.04 - 1 50.04取整为50实际波特率实际波特率 12000000 / (2 × 51) 117647.06误差还是2.12%。这是因为115200 16 × 7200而分频方式的固有特性决定的。实际项目中115200波特率情况下可以把fMCK选为7.3728MHz这样SDRmn 31实际波特率为115200误差为0。但RL78的SPS只支持fCLK的整数分频不一定能分出7.3728MHz所以实际开发中我通常这样做如果通信对象是PC上位机优先用9600或38400误差好压如果必须用115200就逐个尝试SPS分频选误差最小的组合必要时换用外部晶振作为时钟源自定义频率来匹配波特率。实操心得我一般先写个小脚本或者用Excel把所有SPS分频组合下的波特率误差算一遍直接挑最优的配置而不是靠肉眼估算。Renesas官方也提供波特率计算工具但我觉得自己算一遍能加深理解。2.4 帧格式和数据位配置RL78的UART帧格式通过SDR寄存器的相关位和UMR寄存器来配置。寄存器位比较分散我整理了一个速查表配置项寄存器/位说明数据位长度UMRmn的DC位0表示8位数据1表示7位数据停止位长度UMRmn的SC位0表示1位停止位1表示2位停止位奇偶校验UMRmn的PE位0表示无校验1表示有校验校验类型UMRmn的PT位0表示奇校验1表示偶校验波特率设定SDRmn的低8位前面计算出的分频值接收中断触发SCRmn的RIF位等配置实际配置时我用的是8位数据、1位停止位、无校验这是最通用的配置。代码里这样写// UMR0寄存器设置以通道0为例 UMR0 0x03; // 0000 0011 // bit1-0: DC位 11表示8位数据 // bit2: SC位 0表示1位停止位 // bit3: PT位 0表示奇校验PE0时无意义 // bit4: PE位 0表示无校验这个值不同子系列可能略有差异但一般G系列、F系列的UART模式配置基本一致。2.5 发送和接收的寄存器操作序列RL78的UART发送和接收分别由控制寄存器SCR、状态寄存器SSR和串行数据寄存器SDR管理。发送的流程比STM32要“手工作业”一些每个步骤都有因果关系。发送一个字节的标准流程// 1. 确认发送缓冲区为空SSR0的TXE标志发送完成标志/发送数据寄存器空标志为1 while ((SSR0 0x04) 0); // TXE 1说明可以写入下一个数据 // 2. 将数据写入串行数据寄存器 SDR0 data; // 写入后自动启动发送 // 3. 等待发送彻底完成如果需要例如发送后就要休眠 while ((SSR0 0x04) 0); // 等待TXE再次置1注意SDR寄存器是一个“双用途寄存器”写入时它作为发送数据寄存器读取时它是接收数据寄存器。所以写SDR就是发送读SDR就是接收。接收一个字节的标准流程// 1. 等待接收完成标志RXC标志 SSR0 bit0 while ((SSR0 0x01) 0); // RXC 1说明接收到了数据 // 2. 读取数据 uint8_t received SDR0; // 3. 检查接收错误标志 if (SSR0 0xF0) // 检查PE、FE、OVE等错误位 { // 错误处理清除错误标志 SSR0 0x0F; // 清除错误位 }这里有个容易踩的坑SSR0的错误标志位PE、FE、OVE只能写0清除不能写1清除。而且必须先清除错误标志再接收下一帧数据否则错误状态会一直锁存。3. 完整实操从零配置RL78串口收发3.1 基于寄存器方式的完整初始化代码下面这段代码是我在实际项目里用的精简版初始化逻辑基于RL78/G13UART0通道9600波特率8N1帧格式。时钟设置为HOCO 16MHzSPS为fCLK/4也就是4MHz的SAU时钟。void UART0_Init(void) { // 1. 配置引脚P20 TXD0输出P21 RXD0输入 PMC0 0xCF; // P20、P21设为数字模式 PM0 0xEF; // P20设为输出PM04 0 PM0 | 0x10; // P21设为输入PM05 1 // 2. 禁止UART0通道并复位相关寄存器 ST0 | 0x01; // 通道0停止 ST0 0x01; // 确认停止完成实际使用可加超时 // 3. 配置SAU时钟分频SPS寄存器选择fCLK/4 → 4MHz SPS 0x04; // 具体值查手册不同系列位置有差异 // 4. 配置串口模式UART08位数据1停止位无校验 SMR0 0x02; // 操作模式0UART UMR0 0x03; // 8位数据、1停止位、无校验 SCR0 0x20; // 使能发送和接收TXE1RXE1 // 5. 设置波特率分频值 SDR0 207; // 4MHz / (2 * 208) ≈ 9615误差0.16% // 6. 启动通道0 SS0 | 0x01; // 启动通道0 }3.2 发送字符串和接收中断配置串口初始化只是第一步实际项目中收发逻辑才是重头戏。发送字符串的封装void UART0_SendString(uint8_t *str) { while (*str ! \0) { // 等待发送缓冲区空 while ((SSR0 0x04) 0); // 发送当前字符 SDR0 *str; } }接收使用中断方式配置// 中断初始化 void UART0_RxInterrupt_Init(void) { // 配置优先级 PR1 0xFE; // 设置优先级具体位看用户手册 // 清除中断标志 IF1 0xFE; // 清除INTC0标志 // 使能中断 MK1 0xFE; // 取消屏蔽使能串口0接收中断 }中断服务函数__interrupt void UART0_Rx_ISR(void) { uint8_t rx_data; // 读取接收数据 rx_data SDR0; // 检查错误标志 if (SSR0 0xF0) { SSR0 0x0F; // 清除错误 return; } // 处理接收到的数据存入环形缓冲区或直接处理 uart_rx_buffer[uart_rx_index] rx_data; }这个中断函数里读取SDR0这个动作本身就起到了清除接收中断标志的作用这点和很多外设不太一样要特别记住。3.3 实际联调中的硬件连接注意事项软件配置再完美硬件连接出问题一样白搭。我在项目中遇到过几个现象排查了半天发现都是硬件问题第一共地问题。MCU和上位机、传感器模块之间必须共地否则串口信号电平参考点不一致会出现随机乱码。这个问题我之前在调试一款数字传感器时遇到了折腾了好几个小时最后发现是地线虚接。第二电平匹配。RL78工作电压如果是3.3V接5V的USB转串口模块时需要确认模块是3.3V逻辑电平或者加电平转换芯片。直接硬接5V的TX到RL78的RX引脚轻则误码重则烧引脚。这一点经常被忽略因为很多USB转串口模块虽然支持3.3V供电但TX电平还是5V的这时候就需要分压或者电平转换。第三TX/RX交叉连接。这个听起来很简单但实际中我至少有两次把TX接TX、RX接RX结果就是完全没有数据。如果遇到串口完全没反应先用万用表确认TX和RX有没有接反。3.4 一个完整的回环测试验证方法配置完成后我建议先做一个内部回环测试验证MCU串口本身没问题再和外部设备对接。RL78/G13支持串口自检模式也就是把TXD输出内部连接到RXD输入不经过外部引脚。通过设置SCR寄存器的相关位可以进入回环模式。但更简单的做法是把串口初始化好之后写一个循环发送一个字节然后在接收中断里把收到的数据打印出来确认收发链路正常。实际操作中我更习惯直接接USB转串口模块在PC上用串口助手看数据。先让MCU每隔一秒发送一个递增的数字看PC端收到的数据是否连续、是否出现乱码。如果这部分一切正常说明MCU发送链路没问题。然后让PC端向MCU发送数据MCU收到后在中断里把数据回发也就是把接收到的数据再通过发送寄存器送回去在PC端看到原样数据说明接收链路也正常。回环测试通过后再接入真实的传感器或通信模块这样排查问题时就可以快速缩小故障范围。4. 常见问题与排查技巧实录4.1 串口完全无响应的排查清单遇到过串口完全不通的情况按照下面这个顺序排查基本都能定位排查步骤检查点判断标准1电源和复位电压是否正常复位脚是否被拉低2引脚配置PMC和PM是否正确设置复用功能有没有打开3时钟配置HOCO是否起振SPS分频是否正确4通道启动ST0/SS0是否处于启动状态5波特率波特率误差是否过大6硬件连接TX/RX是否交叉共地是否保证7电平标准电平转换是否正确其中最容易遗漏的是第2步因为很多官方例程初始化时已经把引脚配置写在前面了你可能复制代码时漏掉了这部分。RL78的UART不工作十次里有五次是引脚复用没配置对。4.2 乱码问题的四种原因定位乱码这个现象能牵扯出好几种原因从简单到复杂列一下第一种波特率误差过大。这是最常见的按我在第2部分的方法重新计算SDRmn值把误差压到1%以内。第二种时钟源跳动。RL78的HOCO在全温度范围内的精度指标没有晶振那么硬如果你的应用环境温度变化大建议使用外部晶振或者选择低波特率。第三种发送方和接收方的帧格式不一致。比如MCU设置为8数据位1停止位但PC端串口助手默认的是8数据位1停止位无校验一般不会弄错但如果是7位数据带校验这种不常用组合就容易配错。第四种引脚信号质量问题。信号线过长、干扰过大、或者TXD的驱动能力不够都会导致接收端采样到的数据出现误码。这时候用示波器看波形如果边沿不陡、有回勾振荡就需要调整硬件电路比如加上拉电阻、减小布线长度。实际心得调试乱码时先把波特率降到最低比如9600排除一半以上的问题。如果9600下不乱码115200乱码基本就是波特率误差或信号质量问题如果9600都乱码那大概率是帧格式或接线问题。4.3 中断不触发的暗中原因接收中断莫名其妙不触发除了忘记使能中断MK寄存器没清零之外RL78还有一个隐藏特性中断标志IF寄存器必须在使能中断之前先手动清零一次。如果之前中断标志意外置1这时候你使能了中断但该中断一直被挂起看起来就像中断不触发。另外RL78的中断分为可屏蔽中断和不可屏蔽中断串口中断属于可屏蔽中断优先级由PR寄存器控制。如果你把优先级设错了导致串口中断被其他高优先级中断一直阻断同样会出现“中断不触发”的现象。我的排查顺序如下// 1. 确认中断使能位被清零 if (MK1 0x01) { MK1 0xFE; // 使能串口接收中断 } // 2. 确保中断标志被清理干净 IF1 0xFE; // 3. 确认没有更高优先级的中断持续占用CPU // 4. 确认总中断开关IE标志位打开RL78的IE标志位相当于全局中断开关在C语言环境下Renesas的编译器提供了EI()函数来开总中断。很多刚上手的人会忘记这一句导致所有中断都不触发。4.4 休眠模式下串口无法唤醒的处理RL78以低功耗著称我的这个项目里也需要在休眠模式下保持串口监听。这里有个巨坑RL78进入STOP模式后SAU模块如果仍在运行是可以唤醒的但要确保两件事第一SAU的时钟在STOP模式下没有被关闭。RL78的STOP模式可以选择是否保留片上振荡器的运行你需要确认使用的时钟源是否在STOP模式下继续工作。第二串口接收中断在STOP模式下必须配置成可唤醒中断。RL78的中断分为唤醒中断和普通中断通过相关的唤醒控制寄存器来设置。如果串口接收中断没有使能唤醒功能MCU会一直睡下去。实际测试中我甚至遇到过从STOP模式唤醒后SAU模块状态异常的情况。解决办法是在唤醒后重新初始化串口。这种“先停外设再进休眠唤醒后重新配置”的做法在一些低功耗项目里反而是最稳妥的。5. 常见问题速查表问题现象可能原因解决方案完全无输出引脚复用未配置正确设置PMC/PM寄存器完全无输出通道未启动ST00后SS0写入1完全无输出TX/RX接反交叉连接TX/RX乱码波特率误差大重新计算SDRmn分频值乱码帧格式不一致核对数据位、停止位、校验位乱码地线未连接保证共地能发不能收RX引脚未配置为输入PM寄存器方向位检查能发不能收中断未使能或优先级不对检查MK/IF/PR寄存器发送卡死TXE等待条件写死检查SSR寄存器TXE位逻辑偶发一个字节错误接收溢出未处理及时读取SDR和清除错误标志6. 基于经验的几个配置建议最后分享几个基于实操的个人建议不一定每个项目都适用但多数情况下能帮你少走弯路。配置RL78串口时不要迷信官方例程。官方例程为了兼容各种场景代码里带了很多宏定义和条件编译看起来很长反而影响理解。把核心逻辑剥离出来自己从头写一遍对寄存器的理解会提升一个层次。时钟的选择上如果项目对串口稳定性有硬要求直接上外部晶振。内部HOCO虽然方便精度和温漂始终是隐患。晶振频率往标准值靠比如用7.3728MHz可以精确得到常用波特率但RL78的分频链需要仔细验证是否支持。多通道串口使用时每个通道的SPS是共享的。也就是说两个串口必须使用同一个SAU时钟分频值。如果两个串口需要不同的波特率就需要计算它们能否在同一个fMCK下都获得低误差的波特率。如果不行只能把其中一个串口换到另一组SAU单元有些型号有SAU0和SAU1两组或者改变外部时钟配置方案。调试时用逻辑分析仪比示波器方便。逻辑分析仪的协议解码功能能够直接显示一帧UART数据的十六进制值还有波特率误差提示排查问题效率极高。我自从用过一次带协议解码的逻辑分析仪之后就再也没用示波器看过UART波形了——除非怀疑是信号完整性问题才会回到示波器看波形质量。瑞萨的RL78是一颗很扎实的芯片串口虽然配置起来没有STM32那么“一站式”但搞懂原理之后会发现它的灵活性其实很高。希望这篇对你配置RL78串口有所帮助。最后再分享一个小技巧如果你在调试的过程中使用Renesas的E2仿真器在线调试可以实时查看SDR、SSR、SCR等寄存器的值变化这在排查中断不触发、标志位状态异常这类问题上比盲猜代码高效得多。很多人习惯烧录进去直接跑串口助手遇到问题就反复改代码烧录其实用仿真器挂一下很多问题一眼就能看清楚。