MPC8272 SCC控制器:从寄存器配置到UART通信的嵌入式开发实战
1. MPC8272 SCC控制器:从寄存器到通信链路的核心解析
在嵌入式系统开发,尤其是工业控制、网络通信和车载电子领域,串行通信的可靠性与效率是系统稳定运行的基石。飞思卡尔(现恩智浦)的MPC8272 PowerQUICC II处理器,其内置的串行通信控制器(SCC)模块,正是为应对这类高要求场景而设计的硬件利器。它不是一个简单的UART串口,而是一个高度可配置、支持多协议、并能通过DMA与内存高效交互的通信引擎。很多工程师在初次接触其数百页的数据手册时,往往会被密密麻麻的寄存器位和复杂的初始化序列所困扰。实际上,只要理清其“寄存器配置驱动硬件状态机,DMA描述符管理数据流,中断事件反馈通信状态”这一核心逻辑,就能将其强大的能力为己所用。本文将深入SCC的腹地,不仅解读功能寄存器(RFCR/TFCR)的配置奥秘、拆解中断处理的完整流程,更会聚焦于最常用的UART模式,结合DPLL时钟恢复等底层机制,为你呈现一套从原理到实践的嵌入式串行通信实现方案。
2. SCC核心架构与功能寄存器深度剖析
要驾驭SCC,首先必须理解其与系统其他部分的交互方式,特别是它如何访问内存。这其中的关键,就在于功能代码寄存器(Function Code Registers)。
2.1 RFCR与TFCR:定义DMA访问的“交通规则”
SCC模块通过SDMA(串行DMA)通道与外部内存交换数据,分别用于接收(Rx)和发送(Tx)。对于MPC8272的三个SCC通道,各有三对接收/发送功能代码寄存器(RFCR1-4, TFCR1-4)。这些寄存器并不存储数据,而是为每一次DMA访问定义“事务规范”,告诉系统以何种方式、通过哪条“路”去存取数据。
查看寄存器格式(如图19-8所示),其每一位都至关重要。我们结合表19-6,对关键字段进行实战化解读:
GBL(位2): 全局监听使能
- 0: 禁用监听。这是最常用的设置,适用于SCC与专属内存区域(如参数RAM、数据缓冲区)通信,无需保持与其他处理器缓存的一致性。
- 1: 使能监听。当SCC访问的内存区域可能被其他主设备(如另一个CPU核)缓存时,必须开启此位,以确保DMA写入的数据能立即被其他处理器看到,或DMA读取能获取最新的缓存数据。在多核或共享内存系统中,此配置关乎数据正确性。
- 实操心得:在单核MPC8272系统中,如果为SCC分配的内存区域在初始化后通常不被核心频繁访问,禁用监听(GBL=0)可以获得更简单、更确定的DMA性能。若你使用了带缓存的内存区域作为缓冲区,则必须设置为1。
BO(位3-4): 字节序
- 01: Munged little endian。这是一种经过“处理”的小端模式,通常用于与某些特定外设或协议适配,在通用UART通信中较少使用。
- 1x: 大端序或纯小端序。这是最关键的设置。MPC8272的e300核心本身支持大端和小端模式,但SCC的DMA引擎对缓冲区数据的解释方式由此位决定。通常,为了与处理器默认的内存视图保持一致,在为大端系统(如多数PowerPC架构)编程时,应设置为
10(大端);若系统运行在小端模式,则需设置为11(小端)。设置错误会导致接收到的数据字节顺序颠倒。 - 避坑指南:务必与你的编译器和系统内存视图的字节序保持一致。一个简单的验证方法是,在内存中定义一个16位变量
0x1234,然后通过SCC发送该变量指向的缓冲区。如果接收端收到的是0x34, 0x12,则说明字节序设置反了。
TC2(位5): 传输代码
- 此位与TC[0-1]共同构成一个3位的传输类型标识。对于SCC的SDMA访问,TC[0-1]被硬件固定为
11,表示这是一次DMA类型的访问。TC2位则可由软件配置,用于在复杂的系统总线架构中区分不同的访问属性或优先级,但在大多数标准应用中可以保持默认值。
- 此位与TC[0-1]共同构成一个3位的传输类型标识。对于SCC的SDMA访问,TC[0-1]被硬件固定为
DTB(位6): 数据总线指示器
- 0: 使用60x总线进行SDMA操作。这是MPC8272的标准配置,SCC通过60x系统总线访问内存。
- 1: 保留。必须设置为0。
- 配置示例:假设我们配置SCC1的接收功能寄存器,期望使用大端字节序且禁用总线监听,则向
RFCR1寄存器写入的值应为:0x0000(保留位清0)|0x0000(GBL=0)|0x0010(BO=10,大端)|0x0000(TC2=0)|0x0000(DTB=0) =0x0010。
2.2 参数RAM基地址:SCC的专属“控制中心”
除了功能寄存器,SCC的另一个核心是参数RAM(Parameter RAM)。如表19-5所示,每个SCC在CPM(通信处理器模块)的内部RAM中都有256字节的专属区域。这个区域是SCC的“软件控制中心”,存放了协议相关的所有动态参数、缓冲区描述符表指针以及各种状态计数器。
- SCC1 基地址:
RAM_Base + 0x8000 - SCC3 基地址:
RAM_Base + 0x8200 - SCC4 基地址:
RAM_Base + 0x8300(注:SCC2在MPC8272上通常分配给其他功能如FEC,故地址保留)
重要提示:RAM_Base是CPM内部RAM的起始地址,需要在系统初始化时从IMMR(内部内存映射寄存器)的特定寄存器中获取。对参数RAM的任何读写操作,都必须基于这个正确的基地址进行偏移。
3. SCC中断处理机制与实战流程
中断是SCC与CPU协同工作的核心机制。CPU无需轮询状态,SCC在完成一帧数据发送、接收到数据、或发生错误时,通过中断主动通知CPU进行处理,极大提高了系统效率。
3.1 中断相关寄存器:事件、掩码与状态
如表19-7所示,每个SCC都有三个关键的中断寄存器:
- SCCEx(事件寄存器):这是一个“状态”寄存器。当SCC内部发生任何预设的事件(如发送完成
TX、发送错误TXE、接收完成RX、接收缓冲区满RXB、特定控制字符匹配等),无论该事件是否被允许产生中断,其对应的位都会被硬件置1。清除中断标志的方法是对该位写1,写0无效。这是许多硬件寄存器常见的“写1清0”(W1C)机制,务必注意。 - SCCMx(掩码寄存器):这是一个“开关”寄存器。其位定义与SCCE一一对应。只有当某事件的掩码位为1,且CPM和SIU(系统接口单元)的全局中断掩码也相应开启时,该事件发生时才会触发核心中断。通常,在初始化完成后,我们需要使能关心的中断事件,例如使能
TX和RX。 - SCCSx(状态寄存器):一个只读寄存器,用于实时监控RXD引脚的电平状态,在调试硬件连接或排查起始位/停止位错误时非常有用。
3.2 中断服务程序(ISR)标准操作流程
手册第19.3.3节给出了处理SCC中断的标准步骤,这是编写稳定可靠ISR的黄金准则:
确定并清除中断源:进入ISR后,首先读取
SCCE寄存器,判断是哪个事件触发了中断。然后,立即向读取到的值为1的位写入1,以清除这些中断标志。这一步必须在处理业务逻辑前完成,防止中断标志未清除导致中断重复触发或丢失。处理发送完成:如果
SCCE[TX]或SCCE[TXE]被置位,说明有发送缓冲区(TxBD)已使用完毕。ISR需要遍历发送缓冲区描述符链表,回收那些R(Ready)位已被硬件清零的BD,以便应用程序可以填充新的数据并重新提交。关键技巧:由于中断响应可能存在延迟,在高速通信时,SCC可能已经连续处理了多个缓冲区。因此,ISR不能只处理一个BD就返回,而应该使用一个循环,持续检查并回收所有R=0的BD,直到遇到一个R=1的BD(表示该缓冲区尚未发送或正在发送)为止。处理接收数据:如果
SCCE[RX]、SCCE[RXB]或SCCE[RXF]被置位,说明有数据到达。同样地,ISR需要遍历接收缓冲区描述符链表,提取那些E(Empty)位已被硬件清零的BD中的数据。处理逻辑与发送类似:循环读取所有E=0的BD中的数据,并重新初始化这些BD(将E位置1,并更新数据长度等),交还给SCC硬件用于下一次接收,直到遇到一个E=1的BD。中断返回:执行
rfi(中断返回)指令,退出ISR。
实操心得与常见陷阱:
- 中断嵌套与重入:确保SCC中断的优先级设置合理,并在ISR开头做好关键数据的保护(如果ISR和主程序共享数据),防止重入导致数据错乱。
- 缓冲区管理:BD链表的管理是SCC编程的核心。务必确保在回收和重新提交BD时,正确更新数据指针和长度,并严格按照手册顺序设置
R/E位和W(Wrap)位(表示链表结束)。 - 性能考量:对于极高波特率的通信,中断频率会很高。可以考虑使用BD的
I(中断)位进行优化,只为最后一个BD启用中断,从而将多个数据包合并为一次中断处理,降低CPU负载。
4. SCC的初始化、重配置与协议切换
SCC的初始化是一个精细的过程,任何步骤错序或遗漏都可能导致通信失败。
4.1 上电初始化标准流程
无论SCC最终用于何种协议(UART, HDLC, 透明传输等),其基础初始化流程是通用的(手册19.3.4节):
- 配置并行I/O(PIO):MPC8272的引脚功能是复用的。首先需要将对应的TxD、RxD、RTS、CTS、CD等引脚通过PIO控制器配置为SCC功能,而非通用GPIO。
- 配置串行接口:如果使用时分复用(TSA)模式,需要配置SI2模块;如果使用非复用串行接口(NMSI)模式,则需要初始化CMXSCR寄存器。
- 配置通用模式寄存器(GSMR):这是SCC的主配置寄存器,分为高16位(GSMR_H)和低16位(GSMR_L)。特别注意:此时先不要设置
GSMR_L[ENT](发送使能)和GSMR_L[ENR](接收使能)。 - 配置协议特定模式寄存器(PSMR):根据选择的协议(如UART),设置字符长度、奇偶校验、停止位等。
- 配置数据同步寄存器(DSR):用于某些同步协议的同步模式。
- 初始化参数RAM:填写该SCC通道参数RAM区域的所有必要字段,如波特率发生器分频值、缓冲区描述符表基地址(TBPTR/RBPTR)、UART模式下的MAX_IDL(最大空闲字符)等。
- 发送CP命令:通过写CP命令寄存器(CPCR),发送
INIT TX PARAMETERS和INIT RX PARAMETERS命令,让CPM根据当前配置初始化SCC的内部状态。 - 清除事件寄存器:向SCCE写入
0xFFFF,清除所有可能残留的事件位。 - 使能中断:根据需求,向SCCM寄存器写入相应的位掩码,使能所需的中断源。
- 最后使能收发器:设置
GSMR_L[ENT]和GSMR_L[ENR],启动SCC的发送和接收功能。
4.2 动态重配置与协议切换
在实际系统中,可能需要动态改变SCC的波特率、协议甚至禁用某个通道以节能。手册19.3.7节详细描述了安全的重配置序列。
核心原则:在修改任何可能影响SCC正在进行的帧处理的参数(如GSMR中除ENT/ENR外的某些位、波特率、编码方式等)前,必须首先平滑停止当前的收发活动。
重配置发送器:
- 如果正在发送,通过CPCR发送
STOP TRANSMIT命令。 - 清除
GSMR_L[ENT],禁用发送器。 - 修改发送参数或参数RAM。如需切换协议,发送
INIT TX PARAMETERS命令。 - 如果第3步没有发送初始化命令,则发送
RESTART TRANSMIT命令。 - 重新设置
GSMR_L[ENT]。
- 如果正在发送,通过CPCR发送
重配置接收器:
- 清除
GSMR_L[ENR],禁用接收器。 - 修改接收参数或参数RAM。如需切换协议,发送
INIT RX PARAMETERS命令。 - 如果第2步没有发送初始化命令,则发送
ENTER HUNT MODE命令(使接收器重新开始搜索同步字或起始位)。 - 重新设置
GSMR_L[ENR]。
- 清除
完整协议切换:流程是上述两者的结合:先同时禁用发送和接收(
ENT=0, ENR=0),修改GSMR和PSMR切换到新协议,发送INIT TX AND RX PARAMETERS命令,最后再同时使能(ENT=1, ENR=1)。
重要警告:对并行I/O引脚配置或串行通道物理接口(如从NMSI切换到TDM)的动态修改,必须在SCC完全禁用(
ENT=0且ENR=0)的情况下进行,修改完成后需要执行完整的初始化流程(包括发送CP命令)才能重新使能。直接修改可能导致不可预测的行为。
5. SCC UART模式详解与DPLL时钟恢复
UART是SCC最常用的模式之一,它实现了标准的异步串行通信。
5.1 UART模式的特有功能
如手册第20章所述,SCC的UART模式不仅支持基本的串行数据收发,还提供了许多高级功能:
- 多机通信(Multidrop):支持通过地址字节唤醒特定从机,实现一主多从网络。
- 接收器唤醒:可配置为在检测到线路空闲(Idle Line)或地址位(Address Bit)时唤醒。
- 硬件流控:支持RTS/CTS和DTR/DSR等硬件握手信号,由SCC自动管理。
- 丰富的错误检测:帧错误、奇偶校验错误、噪声错误和Break信号检测,并有独立的计数器(PAREC, FRMEC, NOSEC, BRKEC)。
- 可编程字符格式:数据位(5-8位)、停止位(9/16, 1, 1.5, 2位)、奇偶校验(奇/偶/强制/无)。
- 控制字符插入:可以在发送流中插入如XON/XOFF这样的特殊控制字符,而无需打断当前正在发送的数据缓冲区。
5.2 参数RAM在UART模式下的映射
UART模式使用了参数RAM中从偏移0x30开始的特定区域(表20-1)。几个关键参数需要仔细配置:
- MAX_IDL (0x38): 最大空闲字符数。这是一个极为有用的帧界定工具。当接收器收到一个字符后,开始对线路上的“空闲”(持续高电平)状态进行计数。如果连续的空闲时间超过了
MAX_IDL个字符的长度,则触发“空闲超时”中断,并自动关闭当前的接收缓冲区。这允许你将一长串不定长的数据,在接收端自动分割成以空闲时间为间隔的“帧”。计算方式:空闲字符长度 = 1(起始位) + 数据位长度(5-9) + 奇偶校验位(0或1) + 停止位长度(1-2)。例如,对于8N1格式,一个字符是10位。若设置MAX_IDL=5,则线路空闲50个位时间后,会触发超时。 - BRKCR (0x3C): 断点计数寄存器。当发送
STOP TRANSMIT命令时,发送器会持续发送BRKCR个“Break”字符(全0)。每个Break字符的长度与当前配置的字符格式相同。 - UADDR1/UADDR2 (0x48/0x4A): 在多机模式下,用于存储本机需要响应的两个地址。
- CHARACTER1-8 (0x50-0x5E): 八个控制字符寄存器。当接收到的数据与其中任何一个匹配时,可以产生特定中断,用于实现软件流控或自定义协议。
5.3 DPLL:异步通信的时钟恢复引擎
在异步UART模式下,接收端没有独立的时钟线,必须从数据流中恢复出时钟。这是通过数字锁相环(DPLL)实现的(手册19.3.6节)��
DPLL工作原理:
- 参考时钟:DPLL需要一个高频参考时钟(HSRCLK),通常由波特率发生器(BRG)提供,其频率是目标波特率的8倍、16倍或32倍(由
GSMR_L[RDCR]选择)。16倍是最常用的设置。 - 搜索与锁定:初始时,DPLL处于搜索模式。当在RXD上检测到第一个下降沿(起始位开始)时,DPLL内部计数器复位并开始工作。
- 跟踪与调整:DPLL持续监视数据线上的边沿。每当检测到边沿(对于NRZ编码,就是0/1变化),它就与内部计数器的预期位置进行比较,并微调计数器的相位和频率,使产生的采样时钟(RCLK)的中心点对准数据位的中间。
- 采样:接收器使用DPLL恢复出的RCLK,在每个数据位周期内采样三次(通常是位周期的第7、8、9个脉冲),采用“三取二”的多数表决法确定该位的值。如果三次采样值不一致,则
NOSEC(噪声错误计数器)加一。
编码方式:DPLL支持多种编码(表19-9),在UART中我们使用最简单的NRZ(不归零)编码。其他如NRZI、曼彻斯特编码等用于特定总线标准(如Profibus, MIL-STD-1553)。
配置要点:
- 通过
GSMR_L[RENC]和GSMR_L[TENC]选择编码方式,UART通常为000(NRZ)。 - 通过
GSMR_L[RDCR]和GSMR_L[TDCR]选择DPLL的倍率(8x, 16x, 32x)或旁路(1x模式)。旁路模式仅在外部提供同步时钟时使用。 - 在发送前,DPLL可以自动发送特定格式的前导码(Preamble),帮助接收端快速锁定时钟,这在一些同步协议中很重要。
6. 实战:配置MPC8272 SCC1为115200 8N1 UART
下面我们以一个具体的例子,将MPC8272的SCC1配置为最常用的115200波特率、8位数据、无校验、1位停止位的异步UART接口。
6.1 硬件与软件准备
假设使用SCC1的TxD(引脚C15)和RxD(引脚C16),工作在NMSI模式,使用BRG1产生时钟。核心时钟频率CLKIN为66MHz。
6.2 详细配置步骤与代码片段
步骤1:引脚复用配置首先,将对应引脚的功能设置为SCC1。
/* 假设IMMR基地址已定义为 immr */ volatile uint16_t *papcr = (uint16_t*)(immr + 0xE00); // PORTC引脚分配寄存器 *papcr = (*papcr & ~0x000F) | 0x0005; // 将PC15, PC16配置为SCC1的TXD, RXD (具体值需查手册)步骤2:禁用SCC并配置GSMR在修改任何配置前,先确保SCC被禁用。
volatile uint32_t *gsmr_h = (uint32_t*)(immr + 0x11A00); // SCC1 GSMR_H volatile uint32_t *gsmr_l = (uint32_t*)(immr + 0x11A04); // SCC1 GSMR_L *gsmr_l &= ~0x00000003; // 清除ENT和ENR,禁用收发 // 配置GSMR_H:选择UART模式,8位接收FIFO,其他默认 *gsmr_h = 0x00000000; // 具体位域需根据需求设置,例如RFW=1使能8位FIFO // 配置GSMR_L:选择UART协议,16倍时钟模式,使能RTS/CTS(如果需要) *gsmr_l = 0x00000000; // 先清空 *gsmr_l |= (0x0A << 20); // 协议选择: 0b1010 = UART *gsmr_l |= (0x02 << 14); // RDCR/TDCR: 0b10 = 16x DPLL模式 // 不设置ENT/ENR,稍后使能步骤3:配置PSMR(UART特定模式)
volatile uint16_t *psmr = (uint16_t*)(immr + 0x11A0E); // SCC1 PSMR *psmr = 0x0000; // 清空 *psmr |= (0x3 << 12); // 数据长度: 0b11 = 8位 // *psmr |= (1 << 11); // 使能奇偶校验(此处禁用) // *psmr |= (1 << 10); // 偶校验(如果使能) *psmr |= (0x0 << 8); // 停止位长度: 0b00 = 1位停止位步骤4:配置波特率发生器(BRG1)BRG分频公式:BRG Clock = CLKIN / (((BRG分频值) + 1) * 16)对于115200波特率,且DPLL使用16x模式,BRG需要输出115200 * 16 = 1.8432 MHz。 假设CLKIN=66MHz,则分频值DIV = (CLKIN / (1.8432M * 16)) - 1 = (66M / 29.4912M) - 1 ≈ 1.238 - 1 = 0.238。 显然不是整数,这意味着66MHz无法精确产生115200波特率。我们需要选择一个最接近的分频值。 计算:DIV = round(66M / (115200*16*16)) - 1? 这里注意:BRG输出的是DPLL的参考时钟HSRCLK,而HSRCLK = BRG输出。对于16x模式,HSRCLK = 波特率 * 16。 所以:DIV = (CLKIN / (波特率 * 16 * 16)) - 1 = (66M / (115200 * 256)) - 1 = (66M / 29.4912M) - 1 ≈ 1.238 - 1 = 0。 取整后DIV=0,实际波特率 =66M / (16*16*(0+1)) = 66M / 256 ≈ 257.8125 kHz,再除以16得到实际数据波特率约为16.113 kHz,误差极大。
这说明时钟配置是关键。通常,我们需要选择一个能产生标准波特率的参考时钟。MPC8272的BRG也可以使用外部时钟或另一个更灵活的时钟源。在实践中,往往会使用一个专门的晶振或PLL输出作为CPM的时钟源,以便精确分频。这里为了示例,我们假设经过PLL配置后,CPM的时钟频率CPM_CLK为47.0016 MHz(这是许多UART芯片的基准频率,因为它能被115200整除)。 则:DIV = (47.0016M / (115200 * 256)) - 1 = (47.0016M / 29.4912M) - 1 = 1.594 - 1 = 0.594,取整为1。 实际波特率 =47.0016M / (256 * (1+1)) = 47.0016M / 512 = 91800,仍有误差。更好的分频值是DIV=0,波特率=47.0016M/256=183600,然后设置GSMR_L[RDCR/TDCR]=001(8x模式),这样DPLL参考时钟为183600*8=1.4688M,数据波特率=1.4688M/16=91.8k,仍然不准。
结论:精确的波特率生成需要仔细计算系统时钟和分频器。很多项目会直接使用手册推荐的时钟频率,或者接受一个较小的误差(通常<2%在异步通信中是可接受的)。配置代码:
volatile uint16_t *brgc1 = (uint16_t*)(immr + 0xE90); // BRG1配置寄存器 *brgc1 = (1 << 15) | (0 << 14) | (31 << 0); // 使能BRG1,使用CPM_CLK,分频值设为31(示例) // 分频值需要根据实际CPM_CLK频率计算步骤5:初始化参数RAM首先获取参数RAM基地址。
uint32_t cpm_ram_base = ...; // 从IMMR中的CPCRAM基址寄存器获取 uint32_t scc1_param_base = cpm_ram_base + 0x8000; // SCC1参数RAM基址 volatile uint16_t *max_idl = (uint16_t*)(scc1_param_base + 0x38); *max_idl = 10; // 设置空闲超时为10个字符长度,用于帧分隔 volatile uint32_t *rbptr = (uint32_t*)(scc1_param_base + 0x8); // 接收BD表基址 volatile uint32_t *tbptr = (uint32_t*)(scc1_param_base + 0x10); // 发送BD表基址 *rbptr = (uint32_t)rx_bd_table; // 指向你定义的接收BD数组 *tbptr = (uint32_t)tx_bd_table; // 指向你定义的发送BD数组 // 初始化你的BD表,设置数据缓冲区和控制字(R=1/E=1, ...)步骤6:发送CP初始化命令并配置中断
// 通过CPCR发送初始化命令 volatile uint16_t *cpcr = (uint16_t*)(immr + 0xE00); // CP命令寄存器 // 发送 INIT RX PARAMETERS 命令 (SCC1, 命令码0x0001) // 发送 INIT TX PARAMETERS 命令 (SCC1, 命令码0x0002) // 具体操作需要轮询CPCR的FLG位,等待命令完成。这是一个标准流程,代码略。 // 清除SCC1事件寄存器 volatile uint16_t *scce1 = (uint16_t*)(immr + 0x11A10); *scce1 = 0xFFFF; // 使能SCC1中断(例如,使能接收完成和发送完成中断) volatile uint16_t *sccm1 = (uint16_t*)(immr + 0x11A14); *sccm1 = 0x0003; // 假设位0为RX,位1为TX(具体需查手册位定义) // 在系统中断控制器中使能SCC1中断(配置SIMR, CIMR等,此处略)步骤7:最后使能SCC
*gsmr_l |= 0x00000003; // 设置ENT和ENR,使能发送器和接收器6.3 调试技巧与常见问题排查
无数据收发:
- 检查引脚复用:确认PAPCR寄存器是否正确配置,用示波器或逻辑分析仪测量TxD引脚是否有波形。
- 检查时钟:确认BRG已使能并输出正确频率。测量BRGCLK引脚或使用内部时钟探测功能。
- 检查使能位:确认
GSMR_L[ENT]和GSMR_L[ENR]已置1。 - 检查BD状态:确认发送BD的
R位已置1,接收BD的E位已置1,且数据缓冲区指针有效。
数据错误(乱码):
- 检查波特率:计算误差是否在允许范围内(通常<2%)。用示波器测量位宽度。
- 检查字节序(BO位):这是最常见的原因之一。如果收到的是反向字节,请检查RFCR/TFCR的BO位设置是否与你的数据内存布局一致。
- 检查数据位/停止位/奇偶校验:确认PSMR寄存器配置与对端设备完全一致。
- 检查DPLL配置:在异步模式下,确保
GSMR_L[RDCR/TDCR]设置为8x、16x或32x,而不是1x(旁路模式)。
中断不触发:
- 检查SCCE:在ISR中首先打印或读取SCCE值,看事件位是否被置起。
- 检查SCCM:确认你关心的中断事件位已被使能。
- 检查CPM和SIU中断掩码:SCC中断需要经过CPM和系统中断控制器的多层使能。
- 检查BD的中断位:每个缓冲区描述符(BD)都有一个
I(中断)位。只有当前BD的I位为1,且该BD操作完成时,才会触发中断。如果你只为最后一个BD设置了I位,那么只有在处理完最后一个缓冲区时才会产生一次中断。
只能收发一次数据:
- 没有回收和重新提交BD:在中断服务程序中,处理完一个BD后,必须将其状态重置(对于发送BD,清除
R位并填充新数据后重新置R=1;对于接收BD,清除L位和错误位,并置E=1),并将其重新链接到BD链表中(或使用环形链表)。如果BD链表没有正确闭环(W位),SCC在处理完最后一个BD后会停止。
- 没有回收和重新提交BD:在中断服务程序中,处理完一个BD后,必须将其状态重置(对于发送BD,清除
通过以上步骤和问题排查指南,你应该能够成功地在MPC8272上配置并驱动SCC模块进行可靠的UART通信。记住,理解寄存器每一位的含义、遵循严格的初始化和重配置序列、并善用缓冲区描述符机制,是驾驭这款强大通信控制器的关键。在实际项目中,建议将SCC的初始化、BD管理和中断服务程序封装成独立的驱动层,以提高代码的复用性和可维护性。
