主题中讨论的其他器件:TM4C123、 EK-TM4C123GXL
工具/软件:Code Composer Studio
我正在使用 TM4C123 Launchpad 以我想要的方式进行配置。 我的计划是仅将 DMA 用于 UART 传输、并使用简单的 UART 中断处理程序来接收传入数据。 原因是、我不知道数据的长度、我想在数据出现时进行处理。 我以 UDMA_DEMO 的 TIVAARE 工作示例为例。 演示使用 DMA 来发送和接收数据。 它按规定工作。
下面是我修改后的代码、用于运行 UART TX DMA 并使用中断处理程序接收数据。 如您所见、InitUARTTransfer 函数通过将 TX DMA 配置为256字节来开始传输。 使用仅 TX DMA、我只接收30个字节、它们也会被加码。 我尝试了从9600到115200的不同波特率。 突发模式为我提供30个字节、单个字节模式为我提供34个字节。 首次填充 RX FIFO (16字节)始终显示良好的数据、然后剩余的14或18字节来自数据末尾。 帖子末尾的调试器照片显示了30个字节。 我发送的数据是64字节"A"、64字节"B"、64字节"C"和64字节"D"。 我从未收到"B"或"C"。
我在这里错过了什么?
如果您在 udma_demo.c 中注释以下行、则 TIVAWARE UDMA 示例将按原样运行。
#define _NOT_USE_RX_DMA_
//
//
// 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 ()、115200、
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);
}
}
================================================================================
感谢您的帮助。