☰
瑞萨RL78串口配置实战:SAU寄存器解析与波特率计算
2026/10/4 1:29:52 网站建设 项目流程

最近在调试瑞萨RL78系列芯片的串口功能时,发现很多朋友对这套外设的理解还停留在“对着寄存器抄代码”的阶段。尤其是从STM32阵营转过来的工程师,习惯了CubeMX图形化配置,一碰到瑞萨的SAU(串行阵列单元)和CS+的代码生成器,整个人都是懵的。今天我就基于RL78芯片,把串口使用配置这件事从头到尾捋一遍,不仅讲怎么配,也把背后的计算逻辑和踩坑点讲清楚。

RL78的串口模块和传统MCU的UART外设有很大区别。它内部叫SAU,全称Serial Array Unit,是一个可以灵活配置成UART、CSI(SPI)、简易I2C的多功能串行单元。这种设计的初衷是让同一套硬件资源在不同产品中复用,但对第一次接触的人来说,光是理解通道和单元的关系就需要花不少时间。这篇文章适合正在用RL78系列做项目开发的嵌入式工程师,也适合从其他平台转过来想快速上手的同学。

1. 先搞懂RL78串口模块的整体架构,避免后面配置一头雾水

RL78的SAU模块在设计上和传统独立UART外设有本质区别。传统MCU的UART是一个独立外设,有自己独立的波特率发生器、移位寄存器和状态标志,你只需要配置对应的寄存器就能工作。而RL78的SAU是一个单元化的结构,它把多个串行通道整合在一起,每个通道本身不带独立的时钟源,而是共用单元时钟。

以RL78/G13为例,SAU0包含4个通道(通道0到通道3),SAU1也包含4个通道(通道0到通道3)。每个通道都可以独立配置为UART、CSI或简易I2C模式,但同一单元下的通道共享一个基础时钟源。这意味着,你在配置串口之前,第一件事是先确定用的是哪个单元、哪个通道,然后根据该单元提供的时钟频率去计算波特率分频值。

从实际使用角度来说,大多数项目中我们会用SAU0的通道0和通道1作为两路UART,比如一路调试串口、一路通信串口。这种用法在硬件设计上也是合理的,因为SAU0的几个通道对应的引脚分配通常更灵活。选好单元和通道后,下一步就是理解SAU的时钟树,这是整个配置的起点,也是很多人最容易出错的地方。

提到时钟树,就要说到RL78的fCLK。fCLK是RL78内部的高速系统时钟频率,很多型号默认配置在32MHz或16MHz,具体看芯片型号和外部晶振。SAU单元的工作时钟来源于fCLK的分频结果。寄存器SPS0用来设置SAU0的分频系数,SPS1用来设置SAU1的分频系数。分频系数可以取2、4、8、16、32、64、128、256等,具体取决于寄存器位设置。

真正进入通道层之后,每个通道还有自己独立的预分频器,它在单元时钟的基础上再做一次分频。这个两级分频的结构,就是RL78实现不同通道不同波特率的底层机制。也就是说,同一单元下的不同通道可以配置成不同的波特率,只要它们各自通道内分频值不同。理解了这两个层级,后续的波特率寄存器SDR值计算就水到渠成了。

2. 时钟和引脚配置是串口工作的前提,先处理这两块“地基”

2.1 fCLK和单元时钟的选择

在配置串口之前,我强烈建议先把项目的时钟系统梳理清楚。RL78的时钟源有高速内部时钟、高速外部晶振、低速内部时钟等,通过寄存器CMC、CKC、MCM等配置。对于串口应用,主要关注fCLK和fSUB。fCLK用于跑主逻辑和SAU单元时钟,fSUB是低速时钟,一般用于RTC或看门狗,和串口关系不大。

实际操作中,我用得最多的组合是外部8MHz晶振配合PLL倍频到32MHz作为fCLK。为什么不直接使用内部高速时钟?因为内部时钟在全温度范围内的精度偏差比较大,而串口通信对波特率误差有严格要求,尤其是多字节连续传输时,累积误差会造成帧错误。使用外部晶振可以显著降低时钟源误差,给波特率计算留出更大余量。

SPS0寄存器决定SAU0的基础时钟分频,比如设置SPS0 = 0x04,表示分频系数为16。假设fCLK为32MHz,那么SAU0的单元时钟fMCK就是32MHz / 16 = 2MHz。这个单元时钟再进入通道预分频器,最终生成通道时钟fMCKk(k表示通道编号)。例如通道0的预分频系数设为4,那么通道工作时钟就是2MHz / 4 = 500kHz。这个500kHz就是后续波特率计算的基准时钟。

2.2 引脚复用模式切换,RL78的PMxx和PMCxx

RL78引脚功能复用比很多MCU要复杂一点,因为它的复用级别是通过PMC(端口模式控制寄存器)、PM(端口模式寄存器)和P(端口输出锁存寄存器)组合实现的。串口引脚不仅要配置为输入输出方向,还要切换到片上外设功能模式,否则引脚永远是普通GPIO。

例如使用P02作为TXD0、P03作为RXD0时,需要把PMC0的第2位和第3位设置为0,表示选择数字I/O模式而非模拟输入模式。然后设置PM0第2位为0(输出模式)用于TXD0,PM0第3位为1(输入模式)用于RXD0。这还没完,还需要通过P0寄存器和外围引脚复用配置寄存器把引脚切换到UART功能。

在实际项目里,我见过太多人只配置了PM和PMC,忘了检查引脚是否被其他外设复用寄存器抢占,结果串口怎么也调不通。RL78有一个专门的寄存器组用于管理外设输入输出重定向,具体名称和型号有关,在G13里是P0、P1等端口锁存和SPM(外围引脚复用寄存器)。调试时如果发现波形不出来,优先检查这个引脚是否同时被定时器PWM或比较器占用了。

此外,如果使用外部中断或ADC功能复用在同一引脚组,也会冲突。建议拿到新芯片型号后,先把该型号的引脚功能分配表打印出来贴在工位上,配串口时对照表格逐项检查。这比对着数据手册翻半天效率高得多。

3. 核心配置环节:SMR、SCR、SDR寄存器逐位拆解

3.1 SMR串行模式寄存器的配置逻辑

SMR寄存器是每个通道独立拥有的模式寄存器,它的作用是把通道配置为UART模式、CSI模式还是简易I2C模式。对于UART应用,SMR需要设置以下几个关键位段。

SMR的低两位用于选择操作模式,设置为00表示UART模式。接着是SCCS位,它决定通道时钟源是来自单元时钟还是外部输入时钟,一般UART应用选0,即使用内部单元时钟。接下来是CMS位,用于选择操作时钟分频系数,这直接影响波特率基准。

我在配置SMR时习惯先把整个寄存器写成二进制再翻译成十六进制,避免看位段说明书看到眼花。例如系统要求UART模式、内部时钟、时钟分频系数为4,那么SMR的配置值就是0x0022左右,具体还要看型号手册上各位的偏移位置。这里提醒一点,不同RL78系列型号,寄存器位定义可能有细微差别,配置前务必以对应型号的用户手册为准。

3.2 SCR串行控制寄存器的收发方向和停止位设置

SCR寄存器负责控制通道的发送接收开关、停止位长度、数据位长度和奇偶校验类型。RL78的UART支持7位或8位数据,1位或2位停止位,无校验、奇校验、偶校验。需要注意,当选择带有奇偶校验时,数据位长度寄存器的设置包含校验位本身,实际有效数据和存储时占用的长度并不一致,这个细节会在通信协议层造成数据解析错误。

我建议在初学阶段把SCR配置简化:数据位8位、停止位1位、无校验。这是最通用的串口参数组合,也最好调试。等系统跑通了,再根据实际协议需求增加校验配置。设置过程中特别留意DIR位段,它控制数据传输方向优先级,这个位段配置不对,会出现发送正常但接收中断一直不触发,或者反过来。

SCR的TXE和RXE位段是发送和接收使能开关。这是一个很重要的控制位,因为RL78的UART收发使能是独立控制的,这就为半双工和全双工工作模式提供了灵活切换的可能。在实际代码中,我不会把这两个位一直置1,而是在需要接收时才打开RXE,发送完成后可以保留TXE打开,方便下一次发送。

3.3 SDR串行数据寄存器:波特率计算与收发缓冲

SDR寄存器是一个16位寄存器,高9位用于波特率配置,低8位用于数据缓冲。这个寄存器在初始化阶段写入波特率计算值,在发送阶段写入要发送的数据,在接收完成后读出的就是收到的数据。理解这个寄存器的双重作用,是RL78串口配置和普通MCU最大不同的地方。

波特率计算的核心公式是:波特率 = fMCKk / (2 × (SDR[15:9] + 1)),其中fMCKk是经过通道预分频后的时钟频率。以我之前配置一个115200波特率为例,假设SAU0单元时钟fMCK为2MHz,通道预分频系数设为1,那么fMCKk就是2MHz。代入公式反推:SDR[15:9] = 2MHz / (2 × 115200) - 1 = 7.68 - 1 = 6.68,取整为7。实际波特率 = 2MHz / (2 × (7 + 1)) = 125000,误差大约8.5%。这个误差在UART通信标准里是偏大的,会导致通信不稳定。

所以在选择分频系数时,不能随手取,要根据波特率倒推。如果我把通道预分频系数调整为2,也就是fMCKk = 1MHz,那么SDR[15:9] = 1MHz / (2×115200) - 1 = 4.34 - 1 = 3.34,取整3,实际波特率 = 1MHz / (2×(3+1)) = 125000,误差依然是8.5%,没有改善。再尝试预分频系数8,fMCKk = 250kHz,SDR[15:9] = 250000 / 230400 - 1 ≈ 0.085,取整0,实际波特率 = 250kHz / 2 = 125000。到这里你应该发现了,115200这个波特率在2MHz整数倍时钟下,无法得到低误差的分频组合。

实际解决思路有两种。第一种,调整SPS0的单元分频,让fMCK尽量变为目标波特率的整数倍。比如希望得到115200且误差控制在1%以内,需要fMCKk大约是115200的整数倍再乘以2。我用115200×16 = 1.8432MHz,如果fCLK是32MHz,SPS0分频系数设为16得到fMCK=2MHz,再某些型号上支持更细化的分频,有可能得到接近1.8432MHz的值。第二种,直接选择9600或38400这类波特率,它们在常见晶振频率下误差更小。

这里分享一个经验值:fCLK=32MHz时,配置9600波特率用fMCK=2MHz、分频系数12;配置38400波特率用同样fMCK、分频系数2。这些组合误差都在可接受范围内。我实际调试中经常先用逻辑分析仪抓波形,读测实际波特率,再反推寄存器参数,效率反而比手算更高。

4. 从寄存器配置到完整驱动:收发中断的设计与代码实现

4.1 初始化函数的顺序和注意事项

RL78的串口驱动初始化顺序是有讲究的,顺序错乱可能导致寄存器被复位覆盖或中断触发异常。我的推荐顺序是:先关总中断,再配置时钟和引脚,接着初始化SAU单元(SPS寄存器),随后配置通道SMR、SCR、SDR,最后使能相关中断,打开接收使能,打开总中断。

为什么要先关总中断?因为SAU初始化过程中,寄存器状态不确定,此时如果接收到数据,中断标志可能置位,导致一开总中断就误入接收中断。这在产品上电瞬间非常常见,表现为系统启动后莫名其妙进入串口中断然后卡死。先关总中断,等所有配置完成后统一打开,可以完美规避这个问题。

对于引脚配置,我建议在系统初始化函数的早期完成,因为在有些RL78型号上,端口复用寄存器会同时影响多个外设,太晚配置可能影响其他模块初始化。尤其在一个项目里同时使用UART和I2C时,两者共用SPM寄存器的高低位,配置顺序还会影响彼此的引脚映射。

4.2 发送:轮询发送与中断发送的选择

RL78 UART发送有两种常见方式:轮询模式和中断模式。轮询模式适合发送频率低、数据量小、主循环不繁忙的场景。实现方法是把待发送数据写入SDR寄存器,然后等待串行状态寄存器SSR的TXIF标志置1,再写入下一字节。

而中断模式适合大数据量或需要释放CPU的场景。发送中断的触发条件是SDR寄存器空,也就是说每发送完一个字节,硬件把TXIF置位,同时产生发送中断。在中断服务函数里,从发送缓冲区取下一个字节写入SDR,直到缓冲区为空时关闭发送中断。

我在实际项目中用的是轮询和中断结合的方式。初始化阶段用轮询发送调试信息,等到系统进入正常运行状态后,把大数据帧交给中断发送。这种做法既保证了启动阶段的简单可靠,又兼顾了运行阶段的高效。至于发送缓冲区,建议用环形缓冲区,长度根据协议最大帧长而定,我通常取512字节,实际上大多数业务帧都不到100字节,512字节已经留出足够余量。

4.3 接收:接收中断和服务函数的状态机处理

串口接收这块是整个驱动中最容易出bug的地方。RL78的接收中断有两种:接收完成中断和接收错误中断。接收完成中断在SDR寄存器收到完整字节时触发,这没什么好说的。需要注意的是接收错误中断,它包含奇偶校验错误、帧错误和溢出错误三种来源。

一套健壮的接收逻辑应该分为两层。第一层,中断服务函数只负责把SDR数据搬到环形缓冲区,同时记录当前发生的错误状态。第二层,业务层的解析函数从环形缓冲区取数据,按照协议帧格式进行解析和校验。这种分层设计的优势在于,即使上层解析逻辑写得再烂,也不会影响底层继续接收数据,不容易造成数据丢失。

我处理接收错误的方式是:在中断服务函数中读取SSR寄存器,判断错误类型,如果是溢出错误,直接把接收缓冲区清空,重新开始接收;如果是帧错误或奇偶校验错误,把错误计数加1,丢弃当前字节。同时,用一个软件标志通知主循环,表明最近一次通信存在异常。这个错误计数器对定位通信链路质量问题很有用,比如我可以据此判断是波特率偏差过大还是外部干扰严重。

5. 波特率误差分析和实际调试经验分享

5.1 误差的工程可接受范围

很多初学者会纠结波特率误差必须无限接近于0,其实在UART异步通信机制下,只要总误差在可接受范围内,通信就能正常工作。UART采样的容错范围取决于收发双方的时钟误差,以及一帧数据的位数。以一个8位数据、无校验、1位停止位的帧为例,总共有10位(起始位+8数据+停止位),在停止位采样点处的累积误差不能超过半个位宽,换算成百分比大约是5%。

但是,这个5%是整个通信链路的预算,它包含了发送端的时钟误差、接收端的时钟误差以及线路误码裕量。所以工程上通常要求单端时钟误差控制在2%以内比较稳妥。我在实际产品中一般要求1%以内,这样在温度变化和芯片批次差异下还有足够余量。

以RL78的外部晶振方案来说,晶振初始误差通常在几十ppm,温度漂移也在几十ppm范围内,所以真正影响波特率误差的还是分频取整误差。这也是为什么我在前面强调要仔细选择分频系数组合,尽量让实际波特率接近目标值。

5.2 实际调试中的波形测量

串口调不通时,别急着怀疑芯片,先拿示波器或逻辑分析仪抓波形。我把逻辑分析仪接到TXD和RXD引脚上,抓一段已知的发送数据,比如发送字符串“RL78UART”,然后看分析仪解码出来的波特率是否和目标一致。

有一次调试,我把目标波特率设成57600,逻辑分析仪解码出来却是62500,误差达到8.5%。后来分析发现,原因是SPS0分频没生效,我以为配置了分频系数16,但实际寄存器写入时把值写到了SPS1,等于SAU0用的还是默认分频。这种案例说明,仅靠读寄存器回读值验证正确性是不够的,必须通过实际波形确认时钟树每个环节真正生效。

在抓波形时还有一个技巧,先发0x55(二进制01010101)这个字节,它在波形上呈现为01010101的方波形态,非常容易肉眼判断每个位的宽度。测量一个位宽的时间,比如位宽为8.68us,用1除以它得到115207波特率,与目标115200几乎一致。这种验证方法比直接看解码数据更直观,也能更早暴露时钟配置问题。

5.3 常用波特率推荐配置速查表

为了方便参考,我把常见波特率在fCLK=32MHz、SPS0分频16得到2MHz单元时钟条件下,计算得到的SDR高9位值整理成一张表。注意这里通道预分频系数按2配置,也就是fMCKk = 1MHz。不同预分频系数会产生不同结果,这张表只是提供一个参考思路。

目标波特率通道时钟 fMCKk计算值SDR[15:9]取整实际波特率误差
96001MHz5.2158333313.2%
96001MHz,预分频12需要单独算---
384001MHz0.300500000大
384002MHz,预分频12.602333333大

从这张表能直观看到,在不调整预分频的情况下,单靠SDR取整很难实现9600和38400这类低波特率的精确匹配。所以实际项目里,我通常是把SPS0分频系数放大,把单元时钟降为几百kHz,从而让SDR计算值变大、取整误差占比缩小。

以9600为例,如果我把fMCK调成307200Hz,那么SDR[15:9] = 307200 / (2×9600) - 1 = 15。实际波特率就是307200 / (2×(15+1)) = 9600,分毫不差。需要注意的是,fMCK的取值不是随意定的,它必须能由fCLK通过SPS0分频和无级分频组合得到。在配置时,我会先用Excel把常用分频组合全部算一遍,找出误差最小的几组直接抄作业,省去反复试错的麻烦。

6. 常见串口异常问题的排查思路和修复案例

6.1 发送正常、接收全乱码的定位流程

这个问题很典型,也是串口调试里频率最高的故障。我总结的排查链路是:先用示波器测RXD引脚有没有波形,确认外部设备真的在发数据。如果波形正常,接着查引脚复用配置,确认RXD没有被别的功能占用。然后看波特率误差,把接收到的乱码和错误计数结合起来判断。

有一次遇到一个情况,发送正常、接收乱码,而且错误计数一直在增加。量波形发现RXD引脚有完整的数据帧,但高低电平幅值只有1.8V左右。查电路发现对方设备的串口电平是1.8V的,没有做电平转换直接连到了RL78的3.3V引脚。虽然信号逻辑上可能勉强识别,但已经处在输入阈值边缘,抗干扰能力极差,稍微有一点噪声就会造成帧错误。后来加了一颗电平转换芯片,问题彻底消失。

6.2 一上电就误进接收中断

这个问题在带有RXE接收使能的初始化流程里比较常见。芯片刚上电,RXD引脚电平不确定,如果恰好是一个下降沿或者处于低电平状态,接收电路就会被触发,在中断还没来得及初始化之前产生一个接收完成标志。如果代码里没有在初始化时清除这个标志,一开总中断就会立刻跳进中断服务函数,然后读取到一个垃圾数据。

我的修复方式是在SAU初始化函数末尾、使能接收中断之前,先把SSR寄存器的接收相关标志位全部清零,然后延时几十微秒,再次清零一次,最后才打开接收使能和总中断。这个双次清零的写法虽然看起来有些冗余,但在实际工业环境中确实能有效降低上电误触发概率,尤其是那些电源启动波形比较恶劣的场合。

6.3 高波特率通信偶发丢字节

当波特率大于115200时,RL78的接收中断频率非常高,每个字节间隔不到10微秒。如果中断服务函数里做了太多数据处理,比如做协议解析、打印日志,主循环还没返回,下一个字节已经到来,硬件溢出标志被置位,当前字节丢失。

解决思路是把中断服务函数瘦身到极致。中断里只做三件事:读SDR、写环形缓冲区、更新状态标志。所有协议解析和业务处理全部挪到主循环里。如果中断还是来不及,再考虑用RL78的DTC(数据传输控制器)或者DMA方式把接收数据自动搬运到内存缓冲区,彻底减轻CPU负担。我在一个需要921600波特率的现场总线上就是这么干的,用DTC之后CPU负载率从38%降到了4%。

6.4 休眠唤醒后串口不工作

低功耗产品经常遇到这个问题。RL78进入STOP模式后,SAU外设时钟被关闭,所有寄存器状态保持,但内部时钟重新启动后,某些通道状态可能没有恢复到正常。从STOP模式唤醒后,单纯重新初始化SAU寄存器是不够的,因为复用引脚的输入输出缓冲器在低功耗模式下被关掉了,需要把涉及串口的引脚重新初始化一遍。

我的做法是编写一个专门的串口唤醒恢复函数,它执行完整的引脚配置、SAU初始化、波特率重载和中断恢复流程,相当于把整个串口驱动初始化函数再调用一次。虽然代码上有一些重复,但对于低功耗产品的稳定性来说,这点冗余是完全值得的。

7. 从一个实际项目出发,完整走一遍RL78串口配置流程

拿之前做过的一个工业传感器数据采集节点举例。主控用的是RL78/G13,需要外接一个RS485收发器,通过Modbus RTU协议上报数据。串口参数是9600、8位数据、无校验、1位停止位。fCLK配置为32MHz,SPS0分频系数选2,得到fMCK为16MHz,再设置通道预分频系数52,最终fMCKk为16MHz/52 = 307692Hz,SDR计算后取整,实际波特率非常接近9600。

RS485应用有个特殊点,就是收发方向控制。RL78的串口本身没有方向控制引脚,需要用一个普通GPIO控制RS485收发器的DE/RE引脚。发送前置高电平,发送完成后置低电平。这里有个细节,置低电平的时机必须等最后一个字节完全发送出去,否则会截断末尾数据。

我用SSR寄存器的TXIF标志和BFF标志配合实现。TXIF置1表示SDR寄存器空,可以写入下一字节,但此时移位寄存器可能还在发送最后一位。所以我等BFF标志变0,表示发送移位寄存器也已经空,才把DE引脚拉低。这个细节在多字节连续发送时尤其重要,控制不好会导致RS485总线上最后一个字节的停止位被切掉,对方设备解析时出现帧错误。

代码实现大致如下:

void UART_SendString(unsigned char *buf, unsigned int len) { // 拉高DE引脚,进入发送模式 DE_PIN = 1; for (unsigned int i = 0; i < len; i++) { // 等待SDR寄存器可写入 while ((SSR0 & 0x0001) == 0); // TXIF判断 SDR0L = buf[i]; } // 等待最后一个字节完全发送完成,BFF标志清零 while ((SSR0 & 0x0004) != 0); // BFF判断 // 拉低DE引脚,回到接收模式 DE_PIN = 0; }

这段代码简洁且稳定,实际跑了一年多没有出现数据被截断的情况。核心就是那句BFF标志判断,这是很多教科书和参考代码里都忽略的细节。

接收侧,我用中断处理,把数据放到环形缓冲区。Modbus RTU协议要求判断3.5个字符时间的静默间隔来切分报文。实现方式是定时器中断里每1ms检查一次接收时间戳,如果距离上次接收超过3.5个字符时间,就认为一帧报文结束,置位协议解析标志。主循环检测到标志后,从环形缓冲区取出完整一帧,解析CRC和执行寄存器读写操作。

这个架构看着简单,其实涵盖了RL78串口应用中最关键的几个点:时钟分频的选择、SDR寄存器的波特率计算、RS485方向控制的精细时序、中断加缓冲区的数据流设计、以及协议层的超时判断。任何一个环节做不好,整个系统都会出现通信不稳定问题。

8. 对比STM32CubeMX配置方式,给迁移开发者几条实用建议

最近网上关于STM32CubeMX配置串口的内容很多,很多从STM32转过来的工程师习惯先在CubeMX里点点点,然后生成代码直接跑。RL78这边对应的工具是瑞萨的CS+或e2 studio,配合Code Generator插件,也能实现类似图形化配置生成代码的功能。虽然使用体验上确实不如CubeMX顺手,但这个工具用好之后,生成的代码框架可以直接基于它进行二次开发,比纯手写寄存器要快很多。

我建议迁移开发者先别急着依赖代码生成器,而是手写一遍寄存器配置,把整个SAU的时钟树、波特率计算流程过一遍。因为Code Generator生成的代码虽然能跑,但它会把所有可能的配置选项都初始化一遍,导致代码臃肿、排查问题困难。真正理解了底层原理之后,你会更清楚哪些初始化代码可以删、哪些配置位段和你的应用无关、哪些寄存器在运行时需要额外操作。

另一个实际建议是,RL78的调试工具和STM32有差异。RL78常用的调试器是E2 emulator或E20,烧录调试速度相对较慢。在线调试时,如果开了串口中断,在断点处停下来后,串口数据会因为没有及时读取而触发溢出中断,回到运行状态后可能出现缓冲区一堆错误数据。所以我调试串口协议时,很少在中断服务函数里下断点,而是在协议解析的主循环代码里下断点,这样可以避免中断被暂停引起的时序错乱。

至于仿真器连接不上、下载失败这类基础问题,多半是调试器配置和电源时序的问题,和串口外设本身无关,这里就不展开了。

最后分享一个个人习惯。我在做RL78串口驱动时,会在代码里给每个串口通道起一个很明确的名字,比如UART_DEBUG和UART_RS485,而不是直接叫UART0和UART1。配合清晰的注释说明每个通道对应的硬件引脚、波特率、中断优先级和用途,三个月之后再回来看代码,依然能快速定位问题。这个习惯看上去不起眼,但在多串口项目里真的能省下大量时间。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询