This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] CCS/TM4C123GH6PM:TM4C123 UART DMA 问题、仅用于传输

Guru**** 1791630 points
Other Parts Discussed in Thread: EK-TM4C123GXL
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/568126/ccs-tm4c123gh6pm-tm4c123-uart-dma-issue-when-using-dma-for-transmission-only

器件型号:TM4C123GH6PM
Thread 中讨论的其他器件:EK-TM4C123GXL

工具/软件:Code Composer Studio

我将使用 launchpad 和 UDMA_DEMO 示例。 该示例配置为在环回模式下使用 UART1、并在发送和接收时使用 DMA。 在许多应用中、我们只知道传输的数据量、如果没有传入数据长度、则很难使用 DMA 的 UART RX。 我修改了该示例、使用 DMA 进行 UART 传输、使用基于中断的简单例程进行接收。 当 DMA 被设置为发送256字节时、我接收到乱码数据、并且只有30个字节。 代码随附在此处。 我刚才修改了 UDMA_DEMOL.c 文件。

如果您从 C 文件中注释掉以下行、则原始 UDMA 演示将正常工作。

#define _NOT_USE_RX_DMA_

我还在旧的 Stellaris 平台上运行类似的代码、同一代码不在 Tiva 上运行。 我可能缺少一些简单的设置。 是否有人可以花几分钟时间来查看并给我提示?

//
//
// udma_demo.c - uDMA 示例。
//
//版权所有(c) 2012-2013 Texas Instruments Incorporated。  保留所有权利。
//软件许可协议
//
//德州仪器(TI)仅提供和使用此软件
//专门用于 TI 的微控制器产品。 该软件归其所有
// TI 和/或其供应商、受适用版权保护
//法律。 您不能将此软件与"病毒"开源软件结合使用
//软件,以便形成一个更大的程序。
//
//此软件按“原样”提供,且存在所有故障。
//不作任何明示、暗示或法定的保证,包括但
//不限于对适销性和适用性的暗示保证
//此软件的特定用途。 TI 不得以任何方式进行
//情况,对特殊、偶然或从属事件负责
//任何原因造成的损害。
//
//这是 EK-TM4C123GXL 固件包版本2.0.1.11577的一部分。
//
//

#include
#include
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_UART.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "driverlib/SysTick .h"
#include "driverlib/uart.h"
#include "driverlib/udma.h"
#include "utils/cpu_usage.h"
#include "utils/uartstdio.h"
#include "utils/ustdlib.h"

#define _NOT_USE_RX_DMA_
//
//
//! \addtogroup example_list
//!

UDMA (UDMA_DEMO)


//!
//! 此示例应用演示了如何使用 UDMA 控制器
//! 在存储器缓冲区之间传输数据、以及与之间传输数据
//! UART。  测试在退出前运行10秒钟。
//!
//! UART0、连接到 FTDI 虚拟 COM 端口、运行速度为115、200、
//! 8-N-1用于显示来自此应用程序的消息。
//
//

//
//
//用于 SysTick 中断的每秒 SysTick 节拍数。
//
//
#define SYSTICKS_PER_second    100

//
//
//内存传输源和目的缓冲区的大小(以字为单位)。
//
//
#define MEM_buffer_size        1024

//
//
// UART 发送和接收缓冲区的大小。  它们不需要
//大小相同。
//
//
#define UART_TXBUF_SIZE        256
#define UART_RXBUF_SIZE        256

//
//
//用于内存传输的源和目的缓冲区。
//
//
静态 uint32_t g_ui32SrcBuf[MEM_buffer_size];
静态 uint32_t g_ui32DstBuf[MEM_buffer_size];

//
//
//用于 UART 传输的发送和接收缓冲区。  有一个
//发送缓冲器和一对接收乒乓缓冲器。
//
//
静态 uint8_t g_ui8TxBuf[UART_TXBUF_SIZE];
静态 uint8_t g_ui8RxBufA[UART_RXBUF_SIZE];
静态 uint8_t g_ui8RxBufB[UART_RXBUF_SIZE];

#ifdef _NOT_USE_RX_DMA_
静态 uint8_t g_ui8TxBufA[MEM_buffer_size];
#endif

//
//
// UDMA 错误的计数。  此值由 UDMA 错误递增
//处理程序。
//
//
静态 uint32_t g_ui32uDMAErrCount = 0;

//
//
//发生 uDMA 中断但 UDMA 传输没有发生的次数
//完成。  这应该保持为0。
//
//
静态 uint32_t g_ui32BadISR = 0;

//
//
//填充的 UART 缓冲器的计数,每个乒乓缓冲器一个。
//
//
静态 uint32_t g_ui32RxBufACount = 0;
静态 uint32_t g_ui32RxBufBCount = 0;

//
//
//内存 uDMA 传输块的计数。  该值由递增
//内存块传输完成时的 uDMA 中断处理程序。
//
//
静态 uint32_t g_ui32MemXferCount = 0;

//
//
// CPU 使用率,以16.16定点格式表示。
//
//
静态 uint32_t g_ui32CPUUsage;

//
//
//自程序启动以来经过的秒数。  该值是
//由 SysTick 中断处理程序维护。
//
//
静态 uint32_t g_ui32Seconds = 0;

//
//
// UDMA 控制器使用的控制表。  此表必须对齐
//到1024字节边界。
//
//
#IF 定义(ewarm)
#pragma DATA_alignment=1024
uint8_t ui8ControlTable[1024];
#Elif Defined (CCS)
#pragma DATA_ALIGN (ui8ControlTable、1024)
uint8_t ui8ControlTable[1024];
其他
uint8_t ui8ControlTable[1024]__attribute__(aligned (1024)));
#endif

//
//
//驱动程序库遇到错误时调用的错误例程。
//
//
#ifdef 调试
无效
_error__(char * pcFilename、uint32_t ui32Line)

   while (1)
   {
       //
       //运行时挂起错误。
       //
   }

#endif

//
//
// SysTick 计时器的中断处理程序。  此处理程序将使 A 递增
//秒计数器,只要出现适当的节拍数。  它
//还将调用 CPU 使用率节拍函数来查找 CPU 使用率百分比。
//
//
无效
SysTickHandler (空)

   静态 uint32_t ui32TickCount = 0;

   //
   //使 tick 计数器递增。
   //
   ui32TickCount++;

   //
   //如果每秒出现的节拍数,则递增
   //秒计数器。
   //
   if (!(ui32TickCount % SYSTICKS_PER_second))
   {
       G_ui32Seconds ++;
   }

   //
   //调用 CPU 使用节拍函数。  此函数将计算该量
   //自上次调用以来 CPU 使用的周期数,并返回结果
   //定点16.16格式的百分比。
   //
   G_ui32CPUUsage = CPUUsageTick();


//
//
// UDMA 错误的中断处理程序。  如果发生该中断、则会发生该中断
// UDMA 在尝试执行传输时遇到总线错误。  这种情况
//处理程序仅在发生错误时递增计数器。
//
//
无效
uDMAErrorHandler (空)

   uint32_t ui32Status;

   //
   //检查 uDMA 错误位
   //
   ui32Status = ROM_uDMAErrorStatusGet ();

   //
   //如果存在 uDMA 错误,则清除该错误并递增
   //错误计数器。
   //
   if (ui32状态)
   {
       ROM_uDMAErrorStatusClear ();
       G_ui32uDMAErrCount++;
   }


//
//
//内存通道的 uDMA 中断的中断处理程序。  这种情况
//中断将递增计数器,然后重新启动另一个内存
//传输。
//
//
无效
uDMAIntHandler (空)

   uint32_t ui32模式;

   //
   //检查主控制结构体以指示完成。
   //
   ui32Mode = ROM_uDMAChannelModeGet (UDMA_CHANGE_SW);
   if (ui32Mode = uDMA_MODE_STOP)
   {
       //
       //递增已完成传输的计数。
       //
       G_ui32MemXferCount++;

       //
       //为另一个传输配置它。
       //
       ROM_uDMAChannelTransferSet (UDMA_CHANGE_SW、UDMA_MODE_AUTO、
                                    G_ui32SrcBuf、g_ui32DstBuf、
                                    MEM_buffer_size);

       //
       //启动另一个传输。
       //
       ROM_uDMAChannelEnable (UDMA_CHANGE_SW);
       ROM_uDMAChannelRequest (UDMA_CHANGE_SW);
   }

   //
   //如果通道未停止,则说明有问题。
   //
   其他
   {
       G_ui32BadISR++;
   }


uint32_t RxInt = 0;

//
//
// UART1的中断处理程序。  在 DMA 时将发生此中断
//使用 UART1 UDMA 通道完成传输。  它也是如此
//如果外设发出错误信号则触发。  该中断处理程序将会执行
//在接收乒乓缓冲器 A 和 B 之间切换。 它还将重新启动 TX
//如果之前的传输完成,则进行 uDMA 传输。  这将保留 UART
//连续运行(将 TX 数据循环回 RX)。
//
//
无效
UART1 IntHandler (空)

   uint32_t ui32Status;
   uint32_t ui32模式;
   uint32_t recchar;


   //
   //读取 UART 的中断状态。
   //
   ui32Status = ROM_UARTIntStatus (UART1_BASE、1);

   //
   //清除任何挂起状态,即使由于没有 UART,应该没有任何挂起状态
   //中断已启用。  如果启用了 UART 错误中断
   //这些中断可能在这里发生,应该被处理。  UDMA 的影响
   //用于 RX 和 TX、那么这两个中断都不应该
   //已启用。
   //
   ROM_UARTIntClear (UART1_BASE、ui32Status);

#ifdef _NOT_USE_RX_DMA_
   if (ui32Status &(UART_IM_RTIM | UART_IM_RXIM))
   {
      while (ROM_UARTCharsAvail (UART1_base))
      {
          recChar = ROM_UARTCharGetNonBlocking (UART1_base);
          if (RxInt < UART_RXBUF_SIZE)
              G_ui8RxBufA[RxInt]=整数;
          其他
              G_ui32RxBufACount = RxInt/256;
          RxInt++;
      }
   }
其他
   //
   //检查 DMA 控制表以查看乒乓"A"传输是否为
   //完成。  "A"传输使用接收缓冲器"A"和主缓冲器
   //控制结构。
   //
   ui32Mode = ROM_uDMAChannelModeGet (UDMA_CHANGE_UART1RX | UDMA_PRI_SELECT);

   //
   //如果主控制结构体指示停止,则表示"A"
   //接收缓冲完成。  UDMA 控制器仍应接收
   //将数据输入"B"缓冲区。
   //
   if (ui32Mode = uDMA_MODE_STOP)
   {
       //
       //递增计数器以指示数据已接收到缓冲区 A 中  
       //一个实际应用,此应用将用于向主线程发出信号
       //数据已接收,因此主线程可以处理数据。
       //
       G_ui32RxBufACount++;

       //
       //使用主缓冲区为"A"缓冲区设置下一个传输
       //控制结构。  进入"B"缓冲器的持续接收为时
       //完成,UDMA 控制器将切换回这个。  这种情况
       //示例重复使用缓冲区 A,但更复杂的应用可能
       //使用一组旋转的缓冲区来增加该时间
       //主线程必须先处理缓冲区中的数据,然后再处理
       //重复使用。
       //
       ROM_uDMAChannelTransferSet (UDMA_CHANGE_UART1RX | UDMA_PRI_SELECT、
                                  UDMA_MODE_PINGONG、
                                  (void *)(UART1_base + UART_O_DR)、
                                  g_ui8RxBufA、sizeof (g_ui8RxBufA);
   }

   //
   //检查 DMA 控制表以查看乒乓"B"传输是否为
   //完成。  "B"传输使用接收缓冲器"B"和副缓冲器
   //控制结构。
   //
   ui32Mode = ROM_uDMAChannelModeGet (UDMA_CHANGE_UART1RX | UDMA_ALT_SELECT);

   //
   //如果副控制结构体指示停止,则表示"B"
   //接收缓冲完成。  UDMA 控制器仍应接收
   //将数据输入到"A"缓冲区中。
   //
   if (ui32Mode = uDMA_MODE_STOP)
   {
       //
       //递增计数器以指示数据已接收到缓冲区 A 中  
       //一个实际应用,此应用将用于向主线程发出信号
       //数据已接收,因此主线程可以处理数据。
       //
       G_ui32RxBufBCount++;

       //
       //使用替代设置"B"缓冲区的下一个传输
       //控制结构。  接收到"A"缓冲器的时间
       //完成,UDMA 控制器将切换回这个。  这种情况
       //示例重复使用缓冲区 B,但更复杂的应用程序可以
       //使用一组旋转的缓冲区来增加该时间
       //主线程必须先处理缓冲区中的数据,然后再处理
       //重复使用。
       //
       ROM_uDMAChannelTransferSet (UDMA_CHANGE_UART1RX | UDMA_ALT_SELECT、
                                  UDMA_MODE_PINGONG、
                                  (void *)(UART1_base + UART_O_DR)、
                                  g_ui8RxBufB、sizeof (g_ui8RxBufB));
   }

   //
   //如果 UART1 DMA TX 通道被禁用,则表示 TX DMA 传输
   //完成。
   //
   if (!ROM_uDMAChannelIsEnabled (UDMA_CHANGE_UART1TX))
   {
       //
       //开始到 UART1 TX 的另一个 DMA 传输。
       //
       ROM_uDMAChannelTransferSet (UDMA_CHANGE_UART1TX | UDMA_PRI_SELECT、
                                  UDMA_MODE_BASIC、g_ui8TxBuf、
                                  (void *)(UART1_base + UART_O_DR)、
                                  sizeof (g_ui8TxBuf));

       //
       //必须重新启用 uDMA TX 通道。
       //
       ROM_uDMAChannelEnable (UDMA_CHANGE_UART1TX);
   }
#endif


//
//
//初始化 UART1外设并设置 TX 和 RX UDMA 通道。
//将 UART 配置为环回模式,以便在 TX 上发送的任何数据都是如此
//在 RX 上接收。  UDMA 通道的配置使 TX 通道成为可能
//将数据从缓冲区复制到 UART TX 输出。  和 UDMA RX 通道
//将在乒乓模式下将任何传入数据接收到一对缓冲器中。
//
//
无效
InitUART1传输(空)

   unsigned int uIdx;
#ifndef _NOT_USE_RX_DMA_
   //
   //用简单的数据模式填充 TX 缓冲区。
   //
   for (uIdx = 0;uIdx < UART_TXBUF_SIZE;uIdx++)
   {
       G_ui8TxBuf[uIdx]= uIdx;
       G_ui8RxBufA[uIdx]= 0x0;
   }
其他
   for (uIdx = 0;uIdx < UART_TXBUF_SIZE;uIdx++)
   {
       if (uIdx < 64)
           G_ui8TxBuf[uIdx]= 0x41;
       否则、如果(uIdx < 128)
           G_ui8TxBuf[uIdx]= 0x42;
       否则、如果(uIdx < 192)
           G_ui8TxBuf[uIdx]= 0x43;
       其他
           G_ui8TxBuf[uIdx]= 0x44;
       G_ui8RxBufA[uIdx]= 0x0;
   }
#endif
   //
   //启用 UART 外设,并将其配置为即使 CPU 也能正常工作
   //处于睡眠状态。
   //
   ROM_SysCtlPeripheralEnable (SYSCTL_Periph_UART1);
   ROM_SysCtlPeripheralSlepEnable (SYSCTL_Periph_UART1);

#ifdef _NOT_USE_RX_DMA_
   //
   //配置 UART 通信参数。
   //
   ROM_UARTConfigSetExpClk (UART1_base、ROM_SysCtlClockGet ()、115200、
                           UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                           UART_CONFIG_PAR_NONE);
其他
   ROM_UARTConfigSetExpClk (UART1_base、ROM_SysCtlClockGet ()、9600、
                               UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                               UART_CONFIG_PAR_NONE);
#endif

   //
   //将 TX 和 RX 触发阈值设置为4。  这将由使用
   // uDMA 控制器发出信号,指示何时应传输更多数据。  。
   //将配置 uDMA TX 和 RX 通道,以便可以传输4个通道
   当 UART 准备传输更多数据时、//以突发方式传输字节。
   //
   ROM_UARTFIFOLevelSet (UART1_base、UART_FIFO_TX4_8、UART_FIFO_RX4_8);

   //
   //启用 UART 以进行操作,并为两个 TX 启用 UDMA 接口
   //和 RX 通道。
   //
   ROM_UARTEnable (UART1_BASE);
#ifndef _NOT_USE_RX_DMA_
   ROM_UARTDMAEnable (UART1_base、UART_DMA_RX | UART_DMA_TX);
其他
   ROM_UARTDMAEnable (UART1_BASE、UART_DMA_TX);
#endif
   //
   //该寄存器写入将 UART 设置为在环回模式下运行。  任何
   //在 TX 输出上发送的数据将在 RX 输入上接收。
   //
   HWREG (UART1_BASE + UART_O_CTL)|= UART_CTL_LBE;

   //
   //启用 UART 外设中断。  请注意、没有 UART 中断
   //已启用,但 UDMA 控制器将在上引起中断
   uDMA 传输完成时的// UART 中断信号。
   //
   ROM_IntEnable (INT_UART1);
#ifdef _NOT_USE_RX_DMA_
   ROM_UARTIntEnable (UART1_BASE、UART_INT_DMATX | UART_INT_RX | UART_INT_RT);
#endif

#ifndef _NOT_USE_RX_DMA_
   //
   //将 UDMA UART1RX 通道的属性置于已知状态。  这些
   默认情况下、//应已禁用。
   //
   ROM_uDMAChannelAttributeDisable (UDMA_CHANGE_UART1RX、
                                   UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST |
                                   UDMA_ATTR_HIGH_PRIOR|
                                   UDMA_ATTR_REQMASK);

   //
   //为配置主控制结构体的控制参数
   // UART RX 通道。  主控制结构用于"A"
   //部分乒乓接收。  传输数据大小为8位
   //源地址不会递增,因为它将从读取
   //寄存器。  目的地址增量是字节8位字节。  。
   //仲裁大小设置为4以匹配 RX FIFO 触发阈值。
   //如果可能,UDMA 控制器将使用4字节突发传输。  这种情况
   //这种单字节传输会更有效一些。
   //
   ROM_uDMAChannelControlSet (UDMA_CHANGE_UART1RX | UDMA_PRI_SELECT、
                             UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 |
                             UDMA_ARB_4);

   //
   //为的替代控制结构配置控制参数
   // UART RX 通道。  备用控制结构体用于"B"
   //部分乒乓接收。  配置与相同
   //主/A 控制结构。
   //
   ROM_uDMAChannelControlSet (UDMA_CHANGE_UART1RX | UDMA_ALT_SELECT、
                             UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 |
                             UDMA_ARB_4);

   //
   //设置 UART RX 主控件的传输参数
   //结构。  模式设置为乒乓模式、传输源为
   // UART 数据寄存器,目的是接收“A”缓冲区。  。
   //传输大小设置为与缓冲区大小匹配。
   //
   ROM_uDMAChannelTransferSet (UDMA_CHANGE_UART1RX | UDMA_PRI_SELECT、
                              UDMA_MODE_PINGONG、
                              (void *)(UART1_base + UART_O_DR)、
                              g_ui8RxBufA、sizeof (g_ui8RxBufA);

   //
   //设置 UART RX 交替控制的传输参数
   //结构。  模式设置为乒乓模式、传输源为
   // UART 数据寄存器,目的是接收"B"缓冲区。  。
   //传输大小设置为与缓冲区大小匹配。
   //
   ROM_uDMAChannelTransferSet (UDMA_CHANGE_UART1RX | UDMA_ALT_SELECT、
                              UDMA_MODE_PINGONG、
                              (void *)(UART1_base + UART_O_DR)、
                              g_ui8RxBufB、sizeof (g_ui8RxBufB));
#endif
   //
   //将 UDMA UART1TX 通道的属性置于已知状态。  这些
   默认情况下、//应已禁用。
   //
   ROM_uDMAChannelAttributeDisable (UDMA_CHANGE_UART1TX、
                                   UDMA_ATTR_ALTSELECT |
                                   UDMA_ATTR_HIGH_PRIOR|
                                   UDMA_ATTR_REQMASK);

   //
   //设置 UDMA UART TX 通道的 USEBURST 属性。  这将会
   //强制控制器在传输数据时始终使用突发
   //将 TX 缓冲器连接到 UART。  这是比较有效的总线使用
   //不是允许单次或突发传输的默认值。
   //
   ROM_uDMAChannelAttributeEnable (UDMA_CHANGE_UART1TX、UDMA_ATTR_USEBURST);

   //
   //配置 UART TX 的控制参数。  UDMA UART TX
   //通道用于将数据块从缓冲区传输到 UART。
   //数据大小为8位。  源地址增量为8位字节
   //因为数据来自缓冲区。  目的增量为
   //由于数据将被写入 UART 数据寄存器,因此不存在。  。
   //仲裁大小设置为4,与 UART TX FIFO 触发器匹配
   //阈值。
   //
   ROM_uDMAChannelControlSet (UDMA_CHANGE_UART1TX | UDMA_PRI_SELECT、
                             UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE |
                             UDMA_ARB_4);

   //
   //设置 uDMA UART TX 通道的传输参数。  这将会
   //配置传输源和目的以及传输大小。
   //使用基本模式是因为外设正在进行 UDMA 传输
   //请求。  源是 TX 缓冲区、目的是 UART
   //数据寄存器。
   //
   ROM_uDMAChannelTransferSet (UDMA_CHANGE_UART1TX | UDMA_PRI_SELECT、
                              UDMA_MODE_BASIC、g_ui8TxBuf、
                              (void *)(UART1_base + UART_O_DR)、
                              sizeof (g_ui8TxBuf));

   //
   //现在,UDMA UART TX 和 RX 通道都被引脚以启动 A
   //传输。  一旦启用通道、外设将会启动
   //发出传输请求,数据传输将开始。
   //
#ifndef _NOT_USE_RX_DMA_
   ROM_uDMAChannelEnable (UDMA_CHANGE_UART1RX);
#endif
   ROM_uDMAChannelEnable (UDMA_CHANGE_UART1TX);


//
//
//初始化 UDMA 软件通道以执行存储器到存储器的 UDMA
//传输。
//
//
无效
InitSWTransfer (空)

   unsigned int uIdx;

   //
   //用简单的递增模式填充源存储器缓冲区。
   //
   for (uIdx = 0;uIdx < MEM_buffer_size;uIdx++)
   {
       G_ui32SrcBuf[uIdx]= uIdx;
   }

   //
   //启用来自 uDMA 软件通道的中断。
   //
   ROM_IntEnable (INT_UDMA);

   //
   //将 UDMA 软件通道的属性置于已知状态。
   //默认情况下,这些应该已经被禁用。
   //
   ROM_uDMAChannelAttributeDisable (UDMA_CHANGE_SW、
                                   UDMA_ATTR_USEBURST | UDMA_ATTR_ALTSELECT |
                                   (UDMA_ATTR_HIGH_PRIOR|
                                   uDMA_attr_REQMASK);

   //
   //配置 SW 通道的控制参数。  开关通道
   //将用于在两个存储器缓冲区之间传输,每次32位。
   //因此数据大小为32位,地址增量为32位
   //用于源和目的。  仲裁数目将设置为8、
   //这会导致 UDMA 控制器在8个项目后重新比特率
   //已转移。  这可以防止该通道占用 UDMA 控制器
   //一旦传输开始,就允许其他通道循环(如果有)
   //具有更高的优先级。
   //
   ROM_uDMAChannelControlSet (UDMA_CHANGE_SW | UDMA_PRI_SELECT、
                             UDMA_SIZE_32 | UDMA_SRC_INC_32 | UDMA_DST_INC_32 |
                             UDMA_ARB_8);

   //
   //设置软件通道的传输参数。  这将会
   //配置传输缓冲区和传输大小。  必须为自动模式
   //用于软件传输。
   //
   ROM_uDMAChannelTransferSet (UDMA_CHANGE_SW | UDMA_PRI_SELECT、
                              UDMA_MODE_AUTO、g_ui32SrcBuf、g_ui32DstBuf、
                              MEM_buffer_size);

   //
   //现在软件通道被启动一个传输。  通道
   //必须启用。  对于基于软件的传输、必须有一个请求
   //已印发。  之后、UDMA 存储器传输开始。
   //
   ROM_uDMAChannelEnable (UDMA_CHANGE_SW);
   ROM_uDMAChannelRequest (UDMA_CHANGE_SW);


//
//
//配置 UART 及其引脚。  这必须在 UARTprintf()之前调用。
//
//
无效
配置 UART (空)

   //
   //启用 UART 使用的 GPIO 外设。
   //
   ROM_SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA);

   //
   //启用 UART0
   //
   ROM_SysCtlPeripheralEnable (SYSCTL_Periph_UART0);
   ROM_SysCtlPeripheralSlepEnable (SYSCTL_Periph_UART0);

   //
   //为 UART 模式配置 GPIO 引脚。
   //
   ROM_GPIOPinConfigure (GPIO_PA0_U0RX);
   ROM_GPIOPinConfigure (GPIO_PA1_U0TX);
   ROM_GPIOPinTypeUART (GPIO_Porta_base、GPIO_PIN_0 | GPIO_PIN_1);

   //
   //使用内部16MHz 振荡器作为 UART 时钟源。
   //
   UARTClockSourceSet (UART0_BASE、UART_CLOCK_PIOSC);

   //
   //初始化控制台 I/O 的 UART
   //
   UARTStdioConfig (0、115200、16000000);


//
//
//此示例演示了如何使用 uDMA 控制器传输数据
//存储器缓冲区之间以及与外设之间的通信,在本例中为 UART。
// UDMA 控制器被配置为重复传输一个数据块
//从一个内存缓冲区到另一个内存缓冲区。  它还设置为重复复制 A
//从缓冲器到 UART 输出的数据块。  UART 数据是循环的
//返回、以便接收相同的数据、并将 UDMA 受控的配置为
//使用乒乓缓冲器持续接收 UART 数据。
//
//处理器在不执行任何操作时处于睡眠状态,这是允许的
//收集 CPU 使用情况数据以查看在期间使用了多少 CPU
//数据传输正在进行中。
//
//
内部
main (空)

   静态 uint32_t ui32 PrevSeconds;
   静态 uint32_t ui32PrevXferCount;
   静态 uint32_t ui32 PrevUARTCount = 0;
   符合 uint32_t ui32X 标准;
   uint32_t ui32字节首选;

   //
   //为中断处理程序启用怠惰堆栈。  这允许使用浮点
   //在中断处理程序中使用的指令,但代价是
   //额外的堆栈用法。
   //
   ROM_FPULazyStackingEnable();

   //
   //将时钟设置为以50MHz 的频率从 PLL 运行。
   //
   ROM_SysCtlClockSet (SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
                      SYSCTL_XTAL_16MHz);

   //
   //使外设在 CPU 处于睡眠状态时运行。
   //
   ROM_SysCtlPeripheralClockGating (真);

   //
   //启用用于板载 LED 的 GPIO 端口。
   //
   ROM_SysCtlPeripheralEnable (SYSCTL_Periph_GPIOF);

   //
   //为 LED 启用 GPIO 引脚(PF2)。
   //
   ROM_GPIOPinTypeGPIOOutput (GPIO_PORTF_BASE、GPIO_PIN_2);

   //
   //初始化 UART。
   //
   ConfigureUART();

   UARTprintf ("\033[2JuDMA 示例\n");

   //
   //在显示屏上显示时钟频率。
   //
   UARTprintf ("Tiva C 系列@%u MHz\n\n"、ROM_SysCtlClockGet ()/ 1000000);

   //
   //显示统计标题。
   //
   UARTprintf ("CPU   内存    UART      剩余\n");
   UARTprintf ("使用 情况传输  传输时间\n");

   //
   //将 SysTick 配置为每秒发生100次,以用作一次
   //参考。  使能 SysTick 来产生中断。
   //
   ROM_SysTickPeriodSet (ROM_SysCtlClockGet ()/SYSTICKS_PER_second);
   ROM_SysTickIntEnable();
   ROM_SysTickEnable();

   //
   //初始化 CPU 使用情况测量例程。
   //
   CPUUsageInit (ROM_SysCtlClockGet ()、SYSTICKS_PER_second、2);

   //
   //在系统级别启用 uDMA 控制器。  使其继续
   //在处理器处于睡眠状态时运行。
   //
   ROM_SysCtlPeripheralEnable (SYSCTL_Periph_UDMA);
   ROM_SysCtlPeripheralSlepEnable (SYSCTL_Periph_UDMA);

   //
   //启用 uDMA 控制器错误中断。  将发生该中断
   //如果在传输过程中出现总线错误。
   //
   ROM_IntEnable (INT_UDMAERR);

   //
   //启用 UDMA 控制器。
   //
   ROM_uDMAEnable();

   //
   //指向控制表以用于通道控制结构体。
   //
   ROM_uDMAControlBaseSet (ui8ControlTable);

   //
   //初始化 UDMA 内存到内存的传输。
   //
   InitSWTransfer();

   //
   //初始化 UDMA UART 传输。
   //
   InitUART1传输();

   //
   //记住当前 SysTick 秒数。
   //
   ui32 PrevSeconds = g_ui32Seconds;

   //
   //记住内存缓冲区传输的当前计数。
   //
   ui32PrevXferCount = g_ui32MemXferCount;

   //
   //循环、直到按下按钮。  处理器进入休眠状态
   //这样就可以测量 CPU 利用率。
   //
   while (1)
   {
       //
       //检查一秒是否已过去。  如果是、则生成一些
       //更新。
       //
       if (g_ui32Seconds!= ui32PrevSeconds)
       {
           //
           //将 LED 作为心跳信号打开
           //
           GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_2、GPIO_PIN_2);

           //
           //将显示 CPU 使用率百分比的消息打印到显示屏上。
           //忽略百分比值的小数部分。
           //
           UARTprintf ("\r\n3D%%  "、g_ui32CPUUsage >> 16);

           //
           //记住新的秒数。
           //
           ui32 PrevSeconds = g_ui32Seconds;

           //
           //计算自上次传输以来发生的内存传输数
           //秒。
           //
           ui32XfersCompleded = g_ui32MemXferCount - ui32PrevXferCount;

           //
           //记住新的传输计数。
           //
           ui32PrevXferCount = g_ui32MemXferCount;

           //
           //计算内存传输中传输的字节数
           //从最后一秒开始。
           //
           ui32BytesTransfed = ui32XfersCompleded * MEM_buffer_size * 4;

           //
           //打印显示内存传输速率的消息。
           //
           if (ui32字节首选>= 100000000)
           {
               UARTprintf ("%3d Mb/s  "、ui32BytesTranscfp / 1000000);
           }
           否则(ui32BytesTranscfp >= 10000000)
           {
               UARTprintf ("%2d.%01D Mb/s "、ui32BytesTransf/ 1000000、
                          (ui32字节首选% 1000000)/100000);
           }
           否则(ui32字节首选>= 1000000)
           {
               UARTprintf ("%1D.%02d Mb/s "、ui32BytesTransf/ 1000000、
                          (ui32字节首选% 1000000)/10000);
           }
           否则(ui32BytesTranscfp >= 100000)
           {
               UARTprintf ("%3d kb/s  "、ui32 BytesTransfP/1000);
           }
           否则(ui32BytesTranscfp >= 10000)
           {
               UARTprintf ("%2d.%01D kb/s "、ui32 BytesTransf/ 1000、
                          (ui32 BytesTransfer%1000)/100);
           }
           否则(ui32BytesTranscfp >= 1000)
           {
               UARTprintf ("%1D.%02d kb/s "、ui32BytesTransf/ 1000、
                          (ui32 BytesTransfer%1000)/10);
           }
           否则(ui32BytesTranscfp >= 100)
           {
               UARTprintf ("%3D B/s   "、ui32 BytesTranscfred);
           }
           否则(ui32BytesTranscfp >=10)
           {
               UARTprintf ("%2D B/s    "、ui32 BytesTranscfred);
           }
           其他
           {
               UARTprintf ("%1D B/s     "、ui32 BytesTranscfred);
           }

           //
           //计算自上次传输以来发生的 UART 传输数
           //秒。
           //
           ui32XfersCompleded =(g_ui32RxBufACount + g_ui32RxBufBCount -
                                 ui32 PrevUARTCount);

           //
           //记住新的 UART 传输计数。
           //
           ui32PrevUARTCount = g_ui32RxBufACount + g_ui32RxBufBCount;

           //
           //计算 UART 传输的字节数。  数字
           //接收到的字节数乘以2、以便 TX 字节
           //转移也被计算在内。
           //
           ui32BytesTransfed = ui32XfersCompleded * UART_RXBUF_SIZE * 2;

           //
           //打印显示 UART 传输速率的消息。
           //
           if (ui32字节首选>= 1000000)
           {
               UARTprintf ("%1D.%02d Mb/s "、ui32BytesTransf/ 1000000、
                          (ui32字节首选% 1000000)/10000);
           }
           否则(ui32BytesTranscfp >= 100000)
           {
               UARTprintf ("%3d kb/s  "、ui32 BytesTransfP/1000);
           }
           否则(ui32BytesTranscfp >= 10000)
           {
               UARTprintf ("%2d.%01D kb/s "、ui32 BytesTransf/ 1000、
                          (ui32 BytesTransfer%1000)/100);
           }
           否则(ui32BytesTranscfp >= 1000)
           {
               UARTprintf ("%1D.%02d kb/s "、ui32BytesTransf/ 1000、
                          (ui32 BytesTransfer%1000)/10);
           }
           否则(ui32BytesTranscfp >= 100)
           {
               UARTprintf ("%3D B/s   "、ui32 BytesTranscfred);
           }
           否则(ui32BytesTranscfp >=10)
           {
               UARTprintf ("%2D B/s    "、ui32 BytesTranscfred);
           }
           其他
           {
               UARTprintf ("%1D B/s     "、ui32 BytesTranscfred);
           }

           //
           //打印一条旋转线,使其更明显
           //发生的事情。
           //
           UARTprintf ("%2ds"、10 - ui32 PrevSeconds);

           //
           //关闭 LED。
           //
           GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_2、0);
       }

       //
       //如果没有任何操作,请将处理器置于睡眠状态。  这是允许的
       //测量可用 CPU 周期数的 CPU 使用例程。
       //如果处理器经常处于睡眠状态,则可能很难连接到
       //调试器中的目标。
       //
       ROM_SysCtlSleep ();

       //
       //查看我们是否已运行 int32_t enough 并退出循环(如果已运行)。
       //
       if (g_ui32Seconds >= 10)
       {
           中断;
       }
   }

   //
   //在显示屏上指明示例已停止。
   //
   UARTprintf ("\nStopped\n");

   //
   //在 CPU 未休眠的情况下永久循环,因此调试器可以进行连接。
   //
   while (1)
   {
       //
       //打开绿色 LED。
       //
       GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_2、GPIO_PIN_2);

       //
       //延迟一位。
       //
       SysCtlDelay (SysCtlClockGet ()/ 20/3);

       //
       //关闭绿色 LED。
       //
       GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_2、0);

       //
       //延迟一位。
       //
       SysCtlDelay (SysCtlClockGet ()/ 20/3);

   }


感谢你的帮助。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好 Pragnesh

    UART 中断使能的线路在定义范围内

    ROM_UARTIntEnable (UART1_BASE、UART_INT_DMATX | UART_INT_RX | UART_INT_RT);

    因此、基本而言、在读取一个长代码(并在浏览器上混淆)后、注释本身/可能会出现问题