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);
}
}
感谢你的帮助。