ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

英飞凌TC264串口通信实战:ASCLIN波特率计算与中断收发避坑指南

英飞凌TC264串口通信实战:ASCLIN波特率计算与中断收发避坑指南 英飞凌TC264这颗芯片在智能车竞赛和嵌入式控制圈子里出镜率极高但真正上手串口通信时很多人会卡在一个尴尬的位置例程能跑但换个波特率就乱码中断能进但数据一多就丢包代码抄来了却说不清每一行在干什么。我见过太多队伍在调车阶段被串口问题拖住进度明明传感器数据已经采到了就是传不出来或者传出来一堆乱码排查半天发现是时钟配置差了那么一点点。这篇内容就是冲着这些实际问题来的。我会把TC264的ASCLIN串口模块从寄存器层面拆开讲清楚然后一步步带你完成从工程创建、引脚配置、波特率计算到中断收发、环形缓冲区设计的完整流程。代码全部基于实际可编译运行的版本不是伪代码。无论你是刚接触英飞凌平台的新手还是从STM32转过来想快速上手TC264的老手都能从中找到可以直接复用的配置和避坑经验。1. 先搞清楚TC264的串口到底特殊在哪1.1 ASCLIN不是普通的UART外设如果你之前用的是STM32或者GD32串口配置无非就是选引脚、开时钟、设波特率、开中断几行标准库或者HAL库调用就完事了。但TC264的串口模块叫ASCLIN全称是Asynchronous/Synchronous Interface它跟传统MCU的USART在设计哲学上有本质区别。ASCLIN是一个高度可配置的串行通信引擎它内部有独立的波特率发生器、移位寄存器、FIFO缓冲区和协议状态机。关键差异在于ASCLIN的波特率不是简单地从系统时钟分频得到的而是通过一个分数分频器Fractional Divider配合过采样机制来产生的。这意味着你在配置波特率时需要同时考虑过采样率、分频系数和小数分频值三个参数而不是像STM32那样直接写一个BRR寄存器就完事。这个设计带来的好处是波特率精度更高可以支持非标准波特率坏处是配置起来更复杂算错一个参数就会导致通信失败。我在第一次配置TC264串口时就因为忽略了过采样率的设置导致115200波特率下误码率极高数据十帧能错三帧。1.2 TC264的串口资源分布TC264有多路ASCLIN模块通常标记为ASCLIN0到ASCLIN3甚至更多具体数量取决于封装型号。每一路ASCLIN都可以独立配置为UART模式、SPI模式或者LIN模式。在智能车和嵌入式控制场景中我们主要用的是UART模式。每一路ASCLIN的引脚映射不是固定的需要通过端口控制模块Port Control将特定引脚的功能选择为ASCLIN的TX或RX。这一点跟STM32的GPIO复用功能类似但TC264的引脚复用配置更加底层需要操作P00_IOCR这样的寄存器来设置引脚的工作模式。实际项目中我通常会把ASCLIN0分配给调试串口接USB转串口模块ASCLIN1分配给无线通信模块ASCLIN2留给摄像头或者IMU传感器。这样分配的好处是各路互不干扰调试信息不会和传感器数据混在一起。1.3 为什么很多人从STM32转过来会踩坑STM32的串口配置思维是填参数TC264的串口配置思维是算参数。这个差异导致的最典型问题就是直接照搬STM32的波特率配置逻辑结果TC264上通信失败。举个例子STM32F103在72MHz系统时钟下配置115200波特率只需要设置USART_BRR寄存器的值为0x0271这个值是芯片参考手册直接给出的。但TC264在200MHz时钟下配置115200波特率你需要自己计算分频系数和过采样参数公式涉及多个变量算错了不会报错只会默默产生错误的数据。另一个坑是中断向量表的差异。STM32的中断向量表是固定的每个外设中断有固定的入口地址。TC264使用的是中断路由器Interrupt Router机制外设的中断请求需要通过SRC寄存器路由到具体的CPU中断节点上然后才能在中断向量表中找到对应的服务函数。这个机制更灵活但也更容易配错。2. 动手之前必须理清的时钟与波特率计算2.1 时钟树对串口的影响TC264的ASCLIN模块时钟来源可以配置为系统时钟或者外部时钟具体取决于你用的是哪个时钟源。在大多数应用场景中ASCLIN的时钟来自SPB总线时钟System Peripheral Bus这个时钟又是由PLL从外部晶振倍频得到的。假设你的TC264开发板用的是20MHz外部晶振PLL配置为倍频到200MHz作为系统时钟SPB总线时钟通常设置为系统时钟的一半也就是100MHz。这个100MHz就是ASCLIN模块的输入时钟f_ASCLIN。注意不同开发板的晶振频率和PLL配置可能不同务必先确认你的工程中SPB时钟的实际频率否则后续波特率计算全部会错。2.2 波特率计算公式拆解TC264的ASCLIN波特率计算公式如下BaudRate f_ASCLIN / ( Oversampling × ( Prescaler 1 ) × ( 1 FractionalDivider / 1024 ) )其中f_ASCLINASCLIN模块输入时钟频率Oversampling过采样率可选值为4到16通常取16Prescaler预分频系数整数范围0到1023FractionalDivider小数分频值范围0到1023这个公式看起来复杂但实际配置时有简化的方法。当Oversampling取16时公式可以变形为Prescaler 1 f_ASCLIN / ( 16 × BaudRate × ( 1 FractionalDivider / 1024 ) )实际配置时我们通常先令FractionalDivider为0计算出一个近似的Prescaler值然后再微调FractionalDivider来逼近目标波特率。2.3 以115200波特率为例的完整计算过程假设f_ASCLIN 100MHz目标波特率115200Oversampling取16第一步计算理想分频值Divider 100000000 / ( 16 × 115200 ) 54.2535第二步取整数部分作为PrescalerPrescaler 54 - 1 53第三步计算小数部分对应的FractionalDivider小数部分 0.2535 FractionalDivider 0.2535 × 1024 ≈ 260第四步验证实际波特率实际波特率 100000000 / ( 16 × 54 × ( 1 260 / 1024 ) ) 100000000 / ( 864 × 1.2539 ) 100000000 / 1083.37 ≈ 92305等等这个结果明显不对。问题出在哪里让我重新算一下。实际上公式中的Prescaler和FractionalDivider是组合在一起作为一个整体分频器的。正确的理解是总的分频比 ( Prescaler 1 ) × ( 1 FractionalDivider / 1024 )我们需要的是总的分频比等于54.2535。如果Prescaler取53那么( 53 1 ) × ( 1 FractionalDivider / 1024 ) 54.2535 54 × ( 1 FractionalDivider / 1024 ) 54.2535 1 FractionalDivider / 1024 1.00469 FractionalDivider / 1024 0.00469 FractionalDivider ≈ 4.8 ≈ 5验证实际波特率 100000000 / ( 16 × 54 × ( 1 5 / 1024 ) ) 100000000 / ( 864 × 1.00488 ) 100000000 / 868.22 ≈ 115178误差约为0.02%完全在可接受范围内。这个计算过程说明了一个关键点FractionalDivider是用来微调分频比的它的值通常很小。如果你算出来的FractionalDivider超过100那说明Prescaler的取值需要调整。2.4 常见波特率对应的参数速查为了方便实际配置我整理了一份常用波特率在f_ASCLIN100MHz、Oversampling16条件下的参数表目标波特率PrescalerFractionalDivider实际波特率误差9600650096060.06%192003250192300.16%384001620384610.16%576001080578700.47%1152005351151780.02%2304002652303570.02%4608001354607140.02%921600659214280.02%提示这张表的前提是f_ASCLIN100MHz。如果你的工程中SPB时钟不是100MHz需要重新计算。另外波特率误差控制在2%以内通常都能正常通信但为了稳定性建议尽量控制在1%以内。3. 从零搭建串口工程引脚、寄存器与初始化代码3.1 工程创建与基础配置在AURIX Development Studio或者Tasking中创建TC264工程时第一步是确认芯片型号和时钟配置。如果你用的是智能车竞赛常见的TC264D型号默认的时钟配置通常是外部晶振20MHzPLL倍频到200MHzSPB时钟100MHz。工程创建完成后需要包含以下头文件#include Ifx_Types.h #include IfxCpu.h #include IfxScuWdt.h #include IfxAsclin_Asc.h #include IfxPort.h #include IfxCpu_Irq.h这些头文件分别对应基础类型定义、CPU控制、看门狗、ASCLIN驱动、端口控制和中断控制。如果你使用的是iLLD库Infineon Low Level Driver大部分底层寄存器操作已经被封装好了可以直接调用库函数。3.2 引脚配置把物理引脚变成串口引脚假设我们使用ASCLIN0TX引脚为P14.0RX引脚为P14.1。配置代码如下// 配置P14.0为ASCLIN0 TX输出 IfxPort_setPinModeOutput(MODULE_P14, 0, IfxPort_OutputMode_pushPull, IfxPort_OutputIdx_alt2); // 配置P14.1为ASCLIN0 RX输入 IfxPort_setPinModeInput(MODULE_P14, 1, IfxPort_InputMode_pullUp);这里的关键是IfxPort_OutputIdx_alt2这个参数它表示将引脚功能切换到复用功能2也就是ASCLIN0的TX。不同的引脚对应的复用功能编号不同具体需要查阅TC264的数据手册中的引脚定义表。注意如果引脚复用配置错误串口不会有任何输出而且不会报错。这是新手最容易踩的坑之一。建议先用示波器或者逻辑分析仪确认TX引脚上有没有波形。3.3 ASCLIN模块初始化ASCLIN的初始化可以分为以下几个步骤// 定义ASCLIN配置结构体 IfxAsclin_Asc_Config ascConfig; IfxAsclin_Asc_initModuleConfig(ascConfig, MODULE_ASCLIN0); // 设置波特率 ascConfig.baudrate.prescaler 53; ascConfig.baudrate.fractionalDivider 5; ascConfig.baudrate.oversampling IfxAsclin_OversamplingFactor_16; // 设置数据格式8位数据位1位停止位无校验 ascConfig.frame.dataLength IfxAsclin_DataLength_8; ascConfig.frame.stopBit IfxAsclin_StopBit_1; ascConfig.frame.parityBit FALSE; ascConfig.frame.parityType IfxAsclin_ParityType_even; // 配置TX和RX引脚 ascConfig.pins.txMode IfxPort_OutputMode_pushPull; ascConfig.pins.rxMode IfxPort_InputMode_pullUp; ascConfig.pins.txPin IfxAsclin0_TX_P14_0_OUT; ascConfig.pins.rxPin IfxAsclin0_RX_P14_1_IN; // 配置中断 ascConfig.interrupt.txPriority 10; ascConfig.interrupt.rxPriority 11; ascConfig.interrupt.typeOfService IfxSrc_Tos_cpu0; // 初始化模块 IfxAsclin_Asc_initModule(g_ascHandle, ascConfig);这段代码中IfxAsclin_Asc_initModuleConfig函数会先填充一份默认配置然后我们在此基础上修改需要定制的参数。这种默认配置覆盖的模式在iLLD库中很常见可以避免遗漏必要的配置项。3.4 中断路由配置TC264的中断需要经过中断路由器Interrupt Router才能到达CPU。在iLLD库中IfxAsclin_Asc_initModule函数会自动处理中断路由的配置但如果你使用的是寄存器直接操作的方式就需要手动配置SRC寄存器// 手动配置ASCLIN0 RX中断路由到CPU0 IfxSrc_init(MODULE_SRC.ASCLIN0.RX, IfxSrc_Tos_cpu0, 11); IfxSrc_enable(MODULE_SRC.ASCLIN0.RX);这里的IfxSrc_Tos_cpu0表示中断服务类型为CPU0处理数字11是中断优先级。TC264的中断优先级范围是1到255数值越大优先级越高。在实际项目中串口接收中断的优先级不宜设置过高否则可能影响其他关键中断的响应。4. 数据收发实战中断、缓冲区与协议设计4.1 阻塞式发送与中断式接收的搭配在实际项目中我通常采用阻塞发送中断接收的组合。发送数据时调用发送函数后等待发送完成再返回接收数据时通过中断将数据存入环形缓冲区主循环从缓冲区中读取。这种搭配的理由是发送操作通常是我们主动发起的数据量可控阻塞等待的时间很短115200波特率下发送10个字节约0.87ms不会对系统实时性造成明显影响。而接收操作是被动的数据什么时候来不确定必须用中断来保证不丢数据。发送函数的实现void UART_SendByte(uint8 data) { // 等待TX FIFO有空闲空间 while (IfxAsclin_getTxFifoFillLevel(g_ascHandle.asclin) 16); IfxAsclin_write8(g_ascHandle.asclin, data, 1); } void UART_SendBuffer(uint8 *buffer, uint32 length) { for (uint32 i 0; i length; i) { UART_SendByte(buffer[i]); } }4.2 环形缓冲区的设计与实现环形缓冲区是串口接收的核心数据结构。它的原理很简单一块固定大小的内存一个写指针中断中更新一个读指针主循环中更新。写指针追上读指针表示缓冲区满读指针追上写指针表示缓冲区空。#define UART_RX_BUFFER_SIZE 256 typedef struct { uint8 buffer[UART_RX_BUFFER_SIZE]; volatile uint32 writeIndex; volatile uint32 readIndex; } RingBuffer; RingBuffer g_rxBuffer; // 中断中调用写入一个字节 void RingBuffer_Write(RingBuffer *rb, uint8 data) { uint32 nextWrite (rb-writeIndex 1) % UART_RX_BUFFER_SIZE; if (nextWrite ! rb-readIndex) { rb-buffer[rb-writeIndex] data; rb-writeIndex nextWrite; } // 如果缓冲区满丢弃数据 } // 主循环中调用读取一个字节 boolean RingBuffer_Read(RingBuffer *rb, uint8 *data) { if (rb-readIndex rb-writeIndex) { return FALSE; // 缓冲区空 } *data rb-buffer[rb-readIndex]; rb-readIndex (rb-readIndex 1) % UART_RX_BUFFER_SIZE; return TRUE; } // 查询可读数据长度 uint32 RingBuffer_Available(RingBuffer *rb) { if (rb-writeIndex rb-readIndex) { return rb-writeIndex - rb-readIndex; } else { return UART_RX_BUFFER_SIZE - rb-readIndex rb-writeIndex; } }这里有几个细节值得注意。writeIndex和readIndex都声明为volatile因为它们在中断和主循环中都会被访问编译器不能对它们做优化。缓冲区大小取256是为了让取模运算可以用位与运算替代% 256等价于 255提高执行效率。4.3 接收中断服务函数IFX_INTERRUPT(ASCLIN0_RX_ISR, 0, 11) { // 清除中断标志 IfxAsclin_clearRxEvent(g_ascHandle.asclin); // 读取所有可用数据 while (IfxAsclin_getRxFifoFillLevel(g_ascHandle.asclin) 0) { uint8 data; IfxAsclin_read8(g_ascHandle.asclin, data, 1); RingBuffer_Write(g_rxBuffer, data); } }IFX_INTERRUPT宏定义了中断服务函数第一个参数是函数名第二个参数是CPU编号第三个参数是中断优先级。这个宏会自动将函数注册到中断向量表中。注意在中断服务函数中一定要先清除中断标志再读取数据否则可能丢失后续中断。另外读取数据时要循环读取直到FIFO为空因为一次中断可能对应多个字节的数据到达。4.4 主循环中的数据解析主循环中我们不断从环形缓冲区读取数据然后根据自定义的协议进行解析void UART_ProcessData(void) { uint8 data; while (RingBuffer_Read(g_rxBuffer, data)) { // 协议解析逻辑 switch (g_parseState) { case STATE_HEADER: if (data 0xAA) { g_parseState STATE_LENGTH; } break; case STATE_LENGTH: g_expectedLength data; g_parseIndex 0; g_parseState STATE_PAYLOAD; break; case STATE_PAYLOAD: g_payloadBuffer[g_parseIndex] data; if (g_parseIndex g_expectedLength) { g_parseState STATE_CHECKSUM; } break; case STATE_CHECKSUM: if (data CalculateChecksum(g_payloadBuffer, g_expectedLength)) { ProcessPayload(g_payloadBuffer, g_expectedLength); } g_parseState STATE_HEADER; break; } } }这个状态机解析逻辑可以处理变长数据帧帧头为0xAA第二字节为数据长度后面是有效载荷最后是校验和。这种设计在实际项目中非常实用可以灵活应对不同长度的数据包。5. 那些让我调了半天的坑与排查思路5.1 乱码问题的排查链路串口乱码是最常见的问题排查思路应该从信号源头开始逐级向后检查第一步确认TX引脚有波形输出。用示波器或者逻辑分析仪接在TX引脚上看是否有数据发送时的波形。如果没有波形说明引脚复用配置错误或者ASCLIN模块没有使能。第二步测量波特率是否准确。如果有波形但接收端乱码用示波器测量一个位的宽度。115200波特率下一个位的理论宽度是8.68微秒。如果实测偏差超过5%说明波特率配置有问题需要重新计算Prescaler和FractionalDivider。第三步检查数据格式是否匹配。确认发送端和接收端的数据位、停止位、校验位设置一致。TC264默认是8N1如果你的USB转串口模块设置的是7E1就会乱码。第四步检查电平匹配。TC264的串口是3.3V电平如果你的USB转串口模块是5V电平需要确认模块是否支持3.3V。虽然大多数模块兼容3.3V但有些老模块可能不行。我遇到过一次特别隐蔽的乱码问题TX引脚波形正常波特率也准确但接收端就是乱码。最后发现是USB转串口模块的驱动有问题换了一个模块就好了。所以排查到后面不要忽略PC端工具的问题。5.2 中断不触发的几种可能中断配置好了但就是不进中断服务函数这种情况通常有以下几个原因中断优先级配置错误。TC264的中断优先级需要同时配置SRC寄存器和中断服务函数的优先级参数两者必须一致。如果SRC中配置的优先级是11但中断服务函数中写的是10中断就不会被正确响应。中断使能遗漏。除了配置SRC寄存器还需要调用IfxSrc_enable使能中断。有些开发者只配置了优先级但忘记使能导致中断一直不触发。全局中断未开启。TC264的CPU有全局中断使能位需要调用IfxCpu_enableInterrupts()开启。这个函数通常在初始化完成后调用一次。中断标志未清除。如果中断标志没有被正确清除中断只会触发一次后续不再触发。在中断服务函数中务必先清除标志再处理数据。5.3 数据丢包的根因分析数据丢包通常发生在高速通信或者大数据量场景下。根本原因无非两个中断响应不及时或者缓冲区溢出。中断响应不及时的解决办法是提高中断优先级但要注意不要影响到其他关键中断。另一个办法是使用DMA来搬运数据彻底解放CPU。TC264的ASCLIN模块支持DMA请求配置好DMA通道后接收到的数据会自动搬运到内存中CPU只需要处理完整的数据帧即可。缓冲区溢出的解决办法是增大缓冲区或者加快数据读取速度。如果主循环处理速度跟不上数据接收速度可以考虑在中断中做初步的协议解析只将有效数据存入缓冲区减少主循环的处理负担。5.4 实际项目中的经验参数经过多个项目的验证我总结了一套比较稳妥的参数配置参数推荐值说明过采样率16精度和抗噪性的平衡点RX缓冲区大小256或512根据数据量调整RX中断优先级10-20不宜过高避免影响其他中断TX发送超时10ms防止死循环帧头0xAA或0x55选择不容易与数据混淆的值校验方式累加和或CRC8根据可靠性要求选择这些参数不是绝对的但可以作为起点根据实际项目需求微调。6. 进阶玩法DMA与多路串口的协同6.1 用DMA解放CPU当串口波特率达到460800甚至921600时中断方式的CPU开销会变得不可忽略。每接收一个字节就进一次中断在921600波特率下每秒最多可以接收92160个字节也就是每秒最多9万多次中断。这个中断频率对CPU来说是很大的负担。TC264的ASCLIN模块支持DMA请求可以将接收和发送操作交给DMA控制器处理。配置DMA的基本流程是// 配置DMA通道用于ASCLIN0 RX IfxDma_Dma_Config dmaConfig; IfxDma_Dma_initModuleConfig(dmaConfig, MODULE_DMA); IfxDma_Dma_ChannelConfig chConfig; IfxDma_Dma_initChannelConfig(chConfig, dmaConfig); chConfig.channelId IfxDma_ChannelId_1; chConfig.requestMode IfxDma_ChannelRequestMode_completeTransactionPerRequest; chConfig.transferCount UART_RX_BUFFER_SIZE; chConfig.sourceAddress (uint32)MODULE_ASCLIN0.RXDATA; chConfig.destinationAddress (uint32)g_rxBuffer.buffer; chConfig.sourceAddressIncrement IfxDma_ChannelIncrementMode_disabled; chConfig.destinationAddressIncrement IfxDma_ChannelIncrementMode_incr1;DMA配置的核心是设置源地址、目标地址、传输数量和地址增量模式。对于串口接收源地址是ASCLIN的RXDATA寄存器地址不递增目标地址是内存缓冲区地址递增。6.2 多路串口的中断优先级分配当项目中同时使用多路串口时中断优先级的分配就变得很重要。我的原则是数据率越高、实时性要求越高的串口优先级越高。假设一个项目中使用三路串口ASCLIN0调试串口115200波特率数据量小优先级设为10ASCLIN1无线通信模块115200波特率实时性要求中等优先级设为15ASCLIN2IMU传感器921600波特率数据量大且实时性要求高优先级设为20这样的分配可以保证高速传感器数据优先被处理同时调试信息不会因为优先级过高而影响系统实时性。6.3 串口通信协议的通用设计模板在多路串口协同工作的场景中统一的通信协议设计可以大大简化代码维护。我通常采用以下协议格式| 帧头(1B) | 源地址(1B) | 目标地址(1B) | 命令字(1B) | 数据长度(1B) | 数据(NB) | 校验(1B) |帧头固定为0xAA源地址和目标地址用于区分不同的串口通道命令字标识数据类型数据长度指明有效载荷的字节数校验采用累加和。这种协议格式的优点是结构清晰、扩展性强增加新的数据类型只需要定义新的命令字即可。缺点是有一定的协议开销对于极低延迟的场景可能不太适合。7. 调试工具与实用技巧7.1 串口调试助手的选型PC端的串口调试工具选择很多我常用的有以下几个SSCOM功能全面支持HEX显示、定时发送、多条发送指令预设适合日常调试。串口猎人界面简洁支持波形显示适合观察传感器数据的变化趋势。MinicomLinux命令行工具适合在Linux环境下调试支持脚本自动化。选择工具的原则是能稳定接收数据、支持HEX和ASCII切换、能保存日志。不要小看日志保存功能很多偶发问题就是靠长时间日志分析才找到根因的。7.2 用逻辑分析仪抓串口波形当串口通信出现问题时逻辑分析仪是最直接的排查工具。将逻辑分析仪的通道接到TX引脚上设置采样率为波特率的10倍以上115200波特率建议至少2MHz采样率然后触发一次数据发送就可以看到完整的波形。逻辑分析仪的串口解码功能可以直接将波形翻译成字节数据非常直观。如果解码出来的数据和你发送的数据一致说明TC264的发送没有问题问题在接收端如果不一致说明TC264的配置有问题。7.3 代码调试中的printf重定向在TC264上调试时将printf重定向到串口可以大大提高调试效率。重定向的方法是实现_write函数#include stdio.h int _write(int fd, char *buffer, int length) { for (int i 0; i length; i) { UART_SendByte(buffer[i]); } return length; }实现这个函数后就可以在代码中直接使用printf(Value: %d\n, value)来输出调试信息了。注意要在工程设置中开启对printf的支持并且确保堆栈空间足够。提示printf重定向会占用一定的CPU时间在高速数据采集场景中要谨慎使用避免影响实时性。可以在调试阶段开启正式运行时关闭。7.4 常见问题速查表现象可能原因排查方法完全无输出引脚复用错误检查IOCR寄存器配置输出乱码波特率不匹配测量位宽度重新计算参数偶尔丢数据缓冲区溢出增大缓冲区或提高读取频率中断不触发优先级或使能配置错误检查SRC寄存器和全局中断只能收到第一个字节中断标志未清除在ISR中先清标志再读数据高速通信时丢包中断响应不及时改用DMA方式接收这张表覆盖了我实际项目中遇到的大部分串口问题遇到问题时可以按表排查通常能快速定位根因。8. 写在最后的几点实操体会TC264的串口配置确实比STM32要复杂一些但一旦理解了ASCLIN的工作原理和波特率计算方法后续的配置就是按部就班的操作了。我在多个项目中反复使用同一套初始化代码模板只需要根据实际需求修改波特率和引脚配置即可稳定性很好。关于波特率计算我的建议是不要手算写一个简单的计算脚本或者Excel表格输入目标波特率和时钟频率自动算出Prescaler和FractionalDivider的值。这样既快又不容易出错。我自己的Excel表格里还加了误差计算列可以直观地看到实际波特率和目标波特率的偏差。环形缓冲区的大小需要根据实际数据量来定。如果只是传输调试信息256字节足够了如果是高速传感器数据建议至少512字节甚至1024字节。缓冲区大一点不会有什么坏处最多浪费一点内存但缓冲区太小导致丢数据排查起来就很痛苦了。中断优先级的分配是一个需要权衡的问题。优先级设高了会影响其他中断的响应设低了又可能丢数据。我的经验是先用一个中间值比如15然后根据实际运行情况调整。如果发现丢数据就提高优先级如果发现其他中断响应变慢就降低优先级。最后说一个容易被忽略的细节TC264的串口引脚在复位后的默认状态是高阻态需要在初始化时明确配置为推挽输出或者上拉输入。如果忘记配置TX引脚可能没有输出能力RX引脚可能浮空导致误触发。这个细节在数据手册中写得很清楚但很容易被忽略。
返回列表