
1. 项目概述与核心价值在嵌入式系统开发尤其是基于Motorola现NXPMC68341这类经典微控制器的项目中直接内存访问DMA和串行通信模块Serial Module是两个决定系统性能与可靠性的核心外设。DMA的本质是“数据搬运工”它允许数据在内存与I/O设备之间直接传输无需CPU逐字节介入。想象一下你正在厨房CPU准备一顿大餐同时需要从仓库内存搬运大量食材到灶台外设。如果没有帮手你得来回跑无数趟灶台上的火都等凉了。DMA就是这个帮手它接管了搬运的苦力活让你CPU能专心炒菜执行核心算法整个厨房的效率和吞吐量自然就上去了。MC68341集成的DMA控制器功能相当强大支持单地址和双地址模式能灵活应对从简单外设数据采集到复杂的内存块初始化等各种场景。而串行通信模块则是系统与外界对话的“嘴巴和耳朵”。MC68341的串行模块是一个双通道全双工UART通用异步收发器它负责将CPU处理的并行数据转换成一位一位的串行比特流发送出去同时也能把接收到的串行数据组装成完整的字节交给CPU。它的价值在于提供了稳定、可配置的通信链路无论是连接调试终端、与传感器通信还是构建简单的设备网络都离不开它。其内部的波特率生成器、多级缓冲以及丰富的中断机制是保证通信可靠、CPU负担轻的关键。本文将深入这两个模块的“内脏”。我不会仅仅罗列用户手册中的寄存器位定义那和读字典没区别。我会结合我十多年在工控和通信设备开发中“踩坑”的经验带你一步步拆解MC68341 DMA通道的配置逻辑从模块配置寄存器MCR的优先级仲裁到通道控制寄存器CCR的传输模式选择再到结合具体场景如外部突发请求、内存到内存拷贝的汇编代码实例分析。对于串行模块我们将从信号引脚的电平特性聊起深入其与经典MC68681的异同并探讨如何正确配置波特率、数据格式以及利用其自动RTS/CTS流控来构建健壮的通信链路。我的目标是让你读完不仅能看懂手册更能写出稳定、高效的驱动代码在面对时序调试、中断冲突等实际问题时心中有谱手里有招。2. DMA通道配置从原理到实战代码配置DMA本质上是在和一堆寄存器“对话”告诉控制器数据从哪里来源地址、到哪里去目的地址、一次搬多少字节数、怎么搬地址递增/递减、传输宽度、什么时候开始以及搬完了怎么办中断。MC68341的DMA控制器有两个独立的通道它们的配置流程有清晰的逻辑顺序。2.1 核心寄存器组详解与配置逻辑DMA的配置并非简单地对寄存器填值每一步背后都有其设计意图。我们需要按照模块级、通道级、传输级的顺序来理解。2.1.1 模块配置寄存器MCR——设定舞台规则MCR是DMA控制器的“总指挥部”它的设置影响两个通道的全局行为。手册里提到的步骤可以任意顺序执行但理解其含义至关重要。停止位STP这是全局的紧急停止按钮。在正常操作前必须将其清零STP0。注意无论你用哪个通道这个位只有一个。在调试时如果DMA行为异常首先检查STP位是否被意外置位。冻结响应FRZ1, FRZ0当CPU32内核进入调试模式FREEZE信号有效时这两个位决定DMA是否继续运行。如果设置忽略FRZx1则DMA在调试时仍可传输这在调试与DMA并发的数据流时非常有用如果设置响应FRZx0则DMA暂停方便你静态查看内存状态。实操心得在开发初期建议设置为响应冻结避免在单步调试时DMA还在后台“捣乱”导致内存数据莫名变化增加调试难度。单地址模式使能SE这是一个关键模式选择。置1启用单地址模式此时DMA通道仅使用一个地址寄存器SAR或DAR在总线上扮演“主设备”角色直接与外设进行读写。清零则为双地址模式DMA作为“中间人”完成内存到内存或内存到外设的搬运。核心原理单地址模式适用于外设具有独立地址空间且支持DMA请求如某些FIFO或DMA控制器外设而双地址模式更通用。中断服务屏蔽ISM[2:0]这是DMA与CPU中断优先级协调的“门槛”。DMA通道只有在CPU状态寄存器SR中的中断优先级I2-I0小于或等于此处设置的ISM值时才会启动传输。为什么需要这个这是为了防止高优先级的中断服务程序ISR执行时被DMA传输打断导致ISR执行时间不可预测。例如设置ISM2那么只有当CPU处于中断优先级0、1或2时DMA才能运行如果CPU正在处理优先级为3的中断DMA会等待。访问权限SUPV决定用户模式下的程序是否可以访问DMA寄存器。出于系统安全考虑通常将此位置1限制为仅超级用户如操作系统内核可配置DMA。主仲裁IDMAID[2:0]与中断仲裁IARB[3:0]这两个是解决资源冲突的“交通警察”。MC68341内部有一条内部模块总线IMBDMA、串行模块等都挂在这条总线上。MAID用于仲裁两个DMA通道之间谁先使用IMB值越大优先级越高。重要提示如果两个通道都使用务必给它们分配不同的MAID值否则通道1默认优先。IARB则用于当DMA模块向CPU发出中断请求时在多个中断源中确定自己的优先级值越大优先级越高。2.1.2 中断寄存器INTR与通道控制寄存器CCR——精细控制中断寄存器INTR配置该通道中断的优先级INTL和向量号INTV。这决定了当DMA传输完成或出错时CPU如何响应。通道控制寄存器CCR这是每个通道的“操作面板”功能繁多中断使能位INTB, INTN, INTE分别控制断点、正常完成、错误发生时是否产生中断。在简单的数据搬运场景可以只使能完成中断INTN在需要高可靠性的场景务必使能错误中断INTE。传输方向/请求源ECO在单地址模式下此位选择传输方向读/写在双地址模式下选择请求源内部定时或外部信号。启动位STR这是一个极易踩坑的地方在配置所有地址、计数等参数之前必须先将STR位写0防止通道意外启动。在所有参数就绪后最后一步才是将STR写1启动传输。很多初学者遇到的“DMA只传了一次就停”或“数据错乱”问题根源就是STR位控制不当。2.2 单地址与双地址模式实战流程理解了寄存器我们来看两种模式的配置流程差异。手册给出了步骤但我想告诉你每个步骤“为什么”要这么做。2.2.1 单地址模式配置精要单地址模式常用于DMA作为主设备从外设读取数据到内存或从内存写数据到外设。假设我们要从某个外设地址$10000读取3个长字12字节到内存使用外部突发请求。预清除STR在CCR中写0清除启动位。目的锁住通道防止在配置过程中因误触发而开始传输。设置地址增量SAPI/DAPI与传输大小SSIZE/DSIZE对于读周期我们设置源地址增量SAPI和源大小SSIZE。这里选长字4字节传输所以SSIZE设为长字SAPI设为4每次传输后地址4。选择请求模式REQ选择外部突发请求REQ10。突发请求意味着外设一旦发出请求DMA会连续传输完BTC指定的所有字节期间不释放总线效率最高。设置单地址模式S/D将S/D位置1声明这是单地址传输。清除通道状态寄存器CSR写入$7C。这个操作清除了DONE完成、BES/BED总线错误、CONF配置错误和BRKP断点状态位。原理这些状态位是“锁存”的只有写1到对应位或写$7C这种特定值才能清除。不清除它们DMA无法启动新的传输。配置功能码寄存器FCR设置总线和访问类型。例如$99表示访问的是DMA空间、用户数据空间。写入源地址SAR和字节计数器BTC将外设地址$10000写入SAR传输字节数$C12写入BTC。最终启动在CCR中将STR位写1。此时DMA开始等待外设的DREQDMA请求信号一旦有效便启动传输。2.2.2 双地址模式配置精要双地址模式是更通用的内存到内存或内存到外设需设备有地址的搬运。假设我们要将内存地址$6000开始的7个字14字节搬移到$8000使用内部请求即DMA自主发起无需外部信号。预清除STR同上安全第一。设置地址增量与传输大小需要同时设置源和目的地址的增量SAPI,DAPI和大小SSIZE,DSIZE。两者都设为字2字节。选择请求模式与带宽BBREQ选择内部请求REQ00。BB字段用于分配DMA占用总线的带宽比例例如100%意味着DMA传输时CPU完全让出总线。这在需要高速、连续搬运时使用。清除双地址模式S/D将S/D位清零。清除CSR写入$7C。配置FCR设置源和目的的功能码。写入源地址SAR、目的地址DAR和BTC。最终启动写STR为1。DMA会立即开始传输按照设定的带宽与CPU交替使用总线。注意事项在双地址模式进行内存初始化如清零一片内存时有一个经典技巧。你可以将源地址设置为一个包含初始化值如0的固定地址并设置源地址不递增SAPI0目的地址递增。这样DMA就会不断地从同一个源地址读取固定值写入递增的目的地址高效完成内存填充。2.3 代码实例深度剖析与避坑指南手册提供了四个例子我们以**例1外部突发请求单地址读和例2内部请求内存到内存**为例深入每一行代码背后的意图。; *********************************************************** ; 例1外部突发请求单地址传输从外设$10000读3个长字 ; *********************************************************** SARADD EQU $10000 ; 源地址外设 NUMBYTE EQU $C ; 传输字节数 (12字节3个长字) LEA MODBASEDMACH1,A0 ; A0指向DMA通道1寄存器基址 ; 初始化MCR: $1271 ; 位分析: STP0(运行), FRZ10(响应冻结), SE1(单地址模式) ; ISM010(优先级2), SUPV1(仅超级用户), MAID111(优先级7), IARB0001(仲裁优先级1) MOVE.W #$1271,(A0) ; 配置模块全局行为 CLR.W DMACCR1(A0) ; 关键清除CCR主要是将STR位清零防止误启动 ; 配置中断: 优先级7向量号$42 MOVE.W #$0742,DMAINT1(A0) ; 清除通道状态寄存器解锁通道 MOVE.B #$7C,DMACSR1(A0) ; 配置功能码: $99 10011001b ; 位分析: 源功能码10(DMA空间), 目的功能码01(用户数据空间) MOVE.B #$99,DMAFCR1(A0) ; 设置源地址和传输计数 MOVE.L SARADD,DMASAR1(A0) MOVE.L NUMBYTE,DMABTC1(A0) ; 最后配置CCR并启动: $1823 ; 位分析: INTB/INTN/INTE000(无中断), ECO0(读周期), SAPI10(增量4-长字) ; SSIZE10(长字), REQ10(外部突发请求), S/D1(单地址), STR1(启动!) MOVE.W #$1823,DMACCR1(A0)代码解读与避坑点顺序很重要MCR、INTR、CSR、FCR、地址/计数寄存器的配置顺序可以灵活但STR位的控制必须严格——先清后设。CLR.W DMACCR1(A0)这行就是用来清零STR的保险操作。ISM与CPU状态例子中ISM2这意味着只有当CPU的SR中中断优先级字段I2-I0的值 ≤ 2时DMA才能启动。如果你的系统主程序运行在中断优先级0这没问题。但如果你在优先级为3的中断服务程序中尝试启动DMA它会卡住。排查DMA不启动时务必检查CPU的SR和DMA的ISM设置是否匹配。字节计数器BTCBTC存放的是要传输的字节数不是传输次数。对于长字4字节传输传输次数 BTC / 4。例子中$C就是12字节。; *********************************************************** ; 例2内部请求内存到内存传输$6000 - $8000, 7个字 ; *********************************************************** SARADD EQU $6000 ; 源地址 DARADD EQU $8000 ; 目的地址 NUMBYTE EQU $E ; 传输字节数 (14字节7个字) LEA MODBASEDMACH1,A0 ; 初始化MCR: $0334 ; STP0, FRZ10, SE0(双地址模式), ISM3, SUPV1, MAID3, IARB4 MOVE.W #$0334,(A0) CLR.W DMACCR1(A0) ; 清除STR MOVE.W #$0742,DMAINT1(A0) ; 中断配置 MOVE.B #$7C,DMACSR1(A0) ; 清除状态 ; 功能码: $DD 11011101b ; 源和目的功能码均为11(监督程序数据空间) MOVE.B #$DD,DMAFCR1(A0) ; 设置源、目的地址和计数 MOVE.L SARADD,DMASAR1(A0) MOVE.L DARADD,DMADAR1(A0) MOVE.L NUMBYTE,DMABTC1(A0) ; 配置CCR并启动: $0E8D ; INTx000, ECO1(写周期), SAPI01(增量2-字), DAPI01(增量2-字) ; SSIZE01(字), DSIZE01(字), REQ00(内部请求), BB10(100%带宽), S/D0(双地址), STR1 MOVE.W #$0E8D,DMACCR1(A0)双地址模式特别关注带宽控制BBBB10表示DMA占用100%总线带宽。这意味着在传输期间CPU完全停止直到DMA完成。这对于需要保证数据连续性的场景如音频流是好的但会完全阻塞CPU。如果系统实时性要求高可以设置为BB0175%或0050%让DMA和CPU分时复用总线。地址对齐例子中是字传输源和目的地址都应是字对齐的地址最低位为0。虽然MC68341可能支持非对齐访问但会降低性能或需要额外周期。最佳实践是确保源和目的地址都按传输数据大小对齐。3. DMA增强功能与信号握手深度解析MC68341的DMA在MC68340基础上增加了RDY1、RDY2、DTC信号和延迟DACKx模式这些增强功能极大地提升了与慢速外设协同工作的灵活性和可靠性。3.1 就绪信号RDYx与延迟应答Delayed DACKx这两个功能通常配合使用用于解决外设与内存速度不匹配时的握手问题。RDYx信号这是一个由外设控制的输入信号。在单地址模式下使能后DMA传输周期的结束不仅需要内存端返回的DSACKx数据传输应答还需要外设端发出的RDYx信号有效。这相当于给外设一个“喊停”的权利。例如一个慢速的ADC正在转换数据当DMA发起读请求时内存快返回DSACKx但ADC数据还没准备好它可以保持RDYx无效DMA就会在S2状态后插入等待周期Sw直到RDYx有效才结束周期。重要限制RDYx不应在双地址模式下启用因为双地址模式是内存到内存的传输不存在外设“准备”的概念。延迟DACKx模式在单地址读操作中标准的DACKxDMA应答在地址选通AS有效后不久就发出用于选通外设。但如果外设需要确保数据在总线上已经稳定有效后才开始操作就需要延迟DACKx。在此模式下DACKx的断言会延迟到内存的DSACKx有效之后确保数据已从内存读出并出现在数据总线上DACKx才通知外设来取数。这对于连接某些需要严格数据建立时间的外设至关重要。配置方法这些增强功能需要通过SIM41模块中的端口C引脚分配寄存器PPARC来启用。例如要启用通道1的RDY1和延迟DACK1功能需要执行OR.B #$50, MODBASEPPARC ; 设置PPARC相应位实操心得在使用RDYx时务必注意其建立时间要求。手册指出RDYx必须比DSACKx提前至少一个时钟周期被识别才能达到相同的总线终止定时。如果RDYx和DSACKx同时或更晚有效总线周期将以RDYx为准并在识别RDYx两个时钟后结束。这意味着如果你的外设逻辑设计不当可能会导致不可预测的额外等待周期。3.2 数据传输完成信号DTCDTC是一个非常有用的状态指示信号。它在所有MC68341总线周期CPU或DMA结束时如果被选中会发出一个时钟周期的脉冲。这个脉冲明确地告诉外部逻辑“当前这个总线传输周期此刻正式结束了”。它的核心价值在于解决“双条件终止”的确定性判断问题。当使用RDYx时一个DMA周期的结束取决于DSACKx和RDYx两者。外部设备或内存控制器无法单独从DSACKx或RDYx的撤销来准确判断周期是否结束因为另一个信号可能还在保持。DTC的出现提供了一个统一的、确定的结束点信号。外部逻辑可以利用DTC的上升沿或下降沿作为触发安全地进行锁存数据或改变状态的操作而无需关心内部是哪个应答信号最终起了作用。注意DTC在总线错误BERR或重试RETRY终止的周期中不会产生但在延迟总线错误或延迟重试终止的周期中会产生。3.3 时序图分析与设计启示手册中的图6-17至6-20是极佳的学习资料。我们以**图6-19单地址读带延迟DACK和RDY**为例分析其波形周期开始AS地址选通有效地址/数据总线输出有效地址。内存响应内存识别地址后在S2周期结束时返回DSACKx假设内存速度匹配为2周期访问。此时数据已从内存读出到总线。延迟DACK生效由于使能了延迟DACKDACKx信号并不在AS后立即有效而是等到DSACKx被识别后的下一个时钟才断言。这给了总线数据稳定的时间。外设响应外设在DACKx有效后知道数据已就绪开始处理。当它准备好接收数据时便拉低RDYx信号。周期结束DMA控制器在识别到RDYx有效且DSACKx已有效后在接下来的时钟周期结束总线周期撤销AS、DS等信号并产生一个DTC脉冲。关键观察整个读周期被RDYx延长了。如果没有RDYx在DSACKx有效后两个时钟周期就会结束。现在周期长度由最慢的设备此处是外设准备数据的速度决定。设计启示在设计带有DMA的慢速外设接口时比如通过CPLD/FPGA实现一个自定义接口RDYx和延迟DACKx给了你极大的灵活性。你可以用DACKx作为外设的片选或使能用RDYx来插入等待状态完美匹配外设的时序要求。而DTC则可以作为一个可靠的“数据有效”或“传输完毕”标志用于触发下一级逻辑。4. 串行通信模块架构、信号与配置实战串行通信模块是MC68341与外界进行字符流通信的桥梁。它是一个高度可编程的双通道UART与经典的MC68681 DUART高度兼容但又有改进。4.1 模块架构与核心功能拆解模块的核心可以看作两个独立的“通信引擎”通道A和B共享一个“心跳发生器”波特率生成器并由一个“调度中心”内部控制与中断逻辑管理。通信通道每个通道都是全双工的包含独立的发送器和接收器。发送器是双缓冲的这意味着它可以保存一个正在发送的字符和一个等待发送的字符提高了连续发送的流畅度。接收器是四重缓冲的FIFO可以连续接收最多4个字符而无需CPU立即读取这极大地降低了因CPU响应不及时而丢失数据的风险特别是在高波特率下。波特率生成器这是串口通信的“节拍器”。它基于一个3.6864MHz的基准时钟来自外部晶体或时钟输入通过分频产生19种标准波特率从50到76800bps。你也可以绕过它直接使用外部时钟SCLK作为收发时钟实现非标准波特率。控制与中断逻辑所有操作都通过读写一系列内存映射的寄存器来控制。中断系统非常完善提供了7种可屏蔽的中断源如接收数据就绪、发送缓存空、错误状态等并且有独立的中断使能寄存器IER和状态寄存器ISR方便程序高效地处理通信事件。4.2 关键信号定义与硬件连接要点理解每个引脚的电平特性和功能是硬件设计的基础。TxDA/TxDB发送数据输出引脚。当发送器空闲或禁用时保持高电平“传号”状态。数据在时钟下降沿移出。硬件连接通常直接或通过电平转换芯片如MAX232连接到对方设备的RxD。RxDA/RxDB接收数据输入引脚。数据在时钟上升沿被采样。注意事项在空闲状态下此引脚应被外部电路保持为高电平。浮空或低电平可能被误判为起始位导致接收错误。RTSA/RTSB请求发送输出低有效。这个信号非常有用可以配置为自动流量控制。例如你可以设置当接收FIFO快满时自动拉低RTS通知对方停止发送。它也可以被软件直接控制作为一个通用的输出引脚OP0/OP1。CTSA/CTSB清除发送输入低有效。通常连接对方设备的RTS。当CTS为低时本地的发送器才能工作为高时发送器会暂停。这是硬件流控的关键。TxRDYA/RxRDYA这两个是“准备好”输出信号低有效。TxRDYA反映发送保持寄存器空可以写入新数据RxRDYA反映接收FIFO中有数据可以读取。它们不能被中断屏蔽寄存器IER屏蔽因此非常适合用于连接至CPU的中断输入引脚或作为DMA请求DREQ信号实现高效的数据搬移。它们也可作为通用输出引脚OP6等。与MC68681的主要差异点寄存器映射中断向量寄存器IVR的位置变了模式寄存器2MR2A/MR2B从隐藏地址移到了固定地址。编程时需要参考MC68341的手册不能完全照搬MC68681的代码。定时器/计数器MC68341的串行模块没有集成MC68681上的那个通用定时器/计数器。如果你的设计依赖于此功能需要寻找其他替代方案如使用独立的定时器模块。RxRTS自动化MC68341的RTS自动断言/取消逻辑更加自动化配置起来更简便。晶体就绪XTAL_RDY这是一个重要的状态位位于ISR中。在初始化波特率生成器尤其是写时钟选择寄存器CSR之前必须轮询此位直到其为0表示晶体振荡已稳定。这是一个必须遵守的步骤否则可能导致波特率严重不准通信完全失败。示例伪代码如下while (ISR XTAL_RDY_MASK) { // 等待晶体振荡稳定 } // 现在可以安全地配置CSR和波特率了4.3 串行模块初始化与通信流程配置一个串行通道进行通信通常遵循以下步骤等待时钟稳定如上所述轮询ISR中的XTAL_RDY位。配置模式寄存器MR1A/B, MR2A/BMR1设置数据位长度5-8位、奇偶校验类型奇校验、偶校验、强制高/低、无校验、错误模式等。MR2设置停止位长度可精确到1/16位、通道模式全双工、自动回波、本地环回、远程环回。本地环回模式是极其有用的自测工具它将发送输出内部连接到接收输入无需外部连线即可测试发送和接收通路是否正常。配置时钟选择寄存器CSRA/B选择时钟源。是使用内部波特率生成器并从19种固定速率中选择还是使用外部SCLK引脚提供的时钟1分频或16分频。配置命令寄存器CR这是一个“动作”寄存器。通过写CR来使能发送器、使能接收器、复位错误状态、发送间隔break信号等。例如写入0x01通常代表“复位接收器”。配置中断设置中断使能寄存器IER开放你需要的中断源如“接收数据就绪”、“发送保持寄存器空”。设置中断向量寄存器IVR。数据收发发送查询状态寄存器SRA/B的“发送保持寄存器空”位TxRDY或等待“发送保持寄存器空”中断。当该位为1时向发送数据寄存器THRA/B写入要发送的字符。接收查询SRA/B的“接收数据就绪”位RxRDY或等待“接收数据就绪”中断。当该位为1时从接收数据寄存器RHRA/B读取字符。务必同时检查SRA/B中的错误位如帧错误FE、溢出错误OE、奇偶错误PE并在读取数据后根据错误类型进行相应处理如丢弃数据、重发请求等。流量控制如果需要硬件流控确保RTS和CTS引脚正确连接并配置。MC68341可以配置为当接收FIFO达到一定阈值时自动拉低RTS。避坑指南处理接收溢出Overrun接收溢出错误OE是串口编程中最常见的错误之一发生在CPU或DMA未及时读取接收FIFO中的数据而新数据又到达时。MC68341的四字符FIFO提供了一定的缓冲但仍需注意中断方式使能“接收数据就绪”中断并在中断服务程序中尽可能快地读取RHR直到RxRDY位为0。避免在中断中进行复杂耗时操作。DMA方式这是更高效的方法。可以将串口的RxRDYA引脚连接到DMA通道的DREQDMA请求输入并配置DMA在双地址模式下将RHR作为一个固定源地址或由外设请求触发的数据自动搬运到内存中的环形缓冲区。这样数据接收完全由DMA接管几乎不占用CPU时间彻底避免溢出。轮询方式如果采用轮询轮询间隔必须小于字符传输时间 × FIFO深度。例如在115200波特率下传输一个10位字符约需87μs。四字符FIFO给你约348μs的响应时间。这意味着你的轮询循环必须保证在348μs内至少执行一次接收检查这对主循环中有其他任务的系统是一个挑战。配置MC68341的DMA和串行模块就像在指挥一个精密的交响乐团。每个寄存器位都是一个乐手的乐器时序图是乐谱而你的代码是指挥棒。理解每个部分的工作原理预见它们之间的交互并在关键点如启动DMA、处理串口中断设置好“保险”才能奏出稳定流畅的系统协奏曲。希望这些从实际项目中沉淀下来的细节和思路能帮助你更自信地驾驭这颗经典的芯片。