测试AI8051U在8位模式下DMA M2M搬运数据的速度
/*---------------------------------------------------------------------*//* --- Web: www.STCAI.com ---------------------------------------------*/
/*---------------------------------------------------------------------*/
/*************功能说明 **************
本例程基于AI8051U为主控芯片的实验箱进行编写测试。
使用Keil C51编译器,为了达到比较高的效率,一般建议选择"Small"模式。
当编译器出现 "error C249: 'DATA': SEGMENT TOO LARGE" 错误时,则需要手动将部分比较大的数组通过"xdata" 强制分配到 XDATA 区域(例如: char xdata buffer ;)
设置2个存储器空间,一个发送一个接收,分别初始化2个存储器空间内容。
设置M2M DMA,上电后自动将发送存储里的内容写入到接收存储器空间.
根据不同的读取顺序、写入顺序,接收到不同的数据结果.
通过串口1(P3.0 P3.1)打印接收存储器数据(上电打印一次).
下载时, 选择时钟 22.1184MHz (用户可自行修改频率).
******************************************/
#include "..\comm\AI8051U.h"
#include "intrins.h"
#include "stdio.h"
typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;
#define MAIN_Fosc 22118400L //定义主时钟(精确计算115200波特率)
#define Baudrate 115200L
#define TM (65536 -(MAIN_Fosc/Baudrate/4))
#define MAX 1024
bit DmaFlag;
u16 xdata DmaTxBuffer;
u16 xdata DmaRxBuffer;
void DMA_Config(u16 len);
/******************** 串口打印函数 ********************/
void UartInit(void)
{
P_SW1 &= ~S1_S1; //UART1 switch to, 00: P3.0 P3.1, 01: P3.6 P3.7, 10: P1.6 P1.7, 11: P4.3 P4.4
P_SW1 &= ~S1_S0;
SCON = (SCON & 0x3f) | 0x40;
AUXR |= (1<<6); //定时器时钟1T模式
AUXR &= ~S1BRT; //串口1选择定时器1为波特率发生器
TL1= TM;
TH1= TM>>8;
TR1 = 1; //定时器1开始计时
}
void UartPutc(unsigned char dat)
{
SBUF = dat;
while(TI == 0);
TI = 0;
}
char putchar(char c)
{
UartPutc(c);
return c;
}
//========================================================================
// 函数: void main(void)
// 描述: 主函数。
// 参数: none.
// 返回: none.
// 版本: VER1.0
// 日期: 2014-11-28
// 备注:
//========================================================================
void main(void)
{
u16 i;
WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXSFR(); //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x00; P0M0 = 0x00; //设置为准双向口
P1M1 = 0x00; P1M0 = 0x00; //设置为准双向口
P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口
P3M1 = 0x00; P3M0 = 0x00; //设置为准双向口
P4M1 = 0x00; P4M0 = 0x00; //设置为准双向口
P5M1 = 0x00; P5M0 = 0x00; //设置为准双向口
P6M1 = 0x00; P6M0 = 0x00; //设置为准双向口
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
UartInit();
printf("AI8051U Memory to Memory DMA Test Programme!\r\n");//UART1发送一个字符串
EA = 1; //允许总中断
DmaFlag = 0;
while (1)
{
P00 = 1 ;
for(i=0; i<MAX; i++)
{
DmaTxBuffer = 0XAABB;
DmaRxBuffer = 0;
}
P00 = 0 ;//从初始化开始搬运
DMA_Config(2048);
if(DmaFlag)
{
DmaFlag = 0;
P00 = 1 ;//搬运结束
for(i=0; i<MAX; i++)
{
printf("%X ", DmaRxBuffer);
}
printf("\n\n\n\n");
}
}
}
//========================================================================
// 函数: void DMA_Config(void)
// 描述: UART DMA 功能配置.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2021-5-6
//========================================================================
void DMA_Config(u16 len)
{
DMA_M2M_CFG = 0x80; //r++ = t++
DMA_M2M_STA = 0x00;
DMA_M2M_AMTH = len >> 8; //设置传输总字节数:n+1
DMA_M2M_AMT= len & 0x00ff; //设置传输总字节数:n+1
DMA_M2M_TXAH = (u8)((u16)&DmaTxBuffer >> 8);
DMA_M2M_TXAL = (u8)((u16)&DmaTxBuffer);
DMA_M2M_RXAH = (u8)((u16)&DmaRxBuffer >> 8);
DMA_M2M_RXAL = (u8)((u16)&DmaRxBuffer);
// DMA_M2M_CFG = 0xa0; //r++ = t--
// DMA_M2M_STA = 0x00;
// DMA_M2M_AMT = 0x7f; //设置传输总字节数:n+1
// DMA_M2M_TXAH = (u8)((u16)&DmaTxBuffer >> 8);
// DMA_M2M_TXAL = (u8)((u16)&DmaTxBuffer);
// DMA_M2M_RXAH = (u8)((u16)&DmaRxBuffer >> 8);
// DMA_M2M_RXAL = (u8)((u16)&DmaRxBuffer);
// DMA_M2M_CFG = 0x90; //r-- = t++
// DMA_M2M_STA = 0x00;
// DMA_M2M_AMT = 0x7f; //设置传输总字节数:n+1
// DMA_M2M_TXAH = (u8)((u16)&DmaTxBuffer >> 8);
// DMA_M2M_TXAL = (u8)((u16)&DmaTxBuffer);
// DMA_M2M_RXAH = (u8)((u16)&DmaRxBuffer >> 8);
// DMA_M2M_RXAL = (u8)((u16)&DmaRxBuffer);
// DMA_M2M_CFG = 0xb0; //r-- = t--
// DMA_M2M_STA = 0x00;
// DMA_M2M_AMT = 0x7f; //设置传输总字节数:n+1
// DMA_M2M_TXAH = (u8)((u16)&DmaTxBuffer >> 8);
// DMA_M2M_TXAL = (u8)((u16)&DmaTxBuffer);
// DMA_M2M_RXAH = (u8)((u16)&DmaRxBuffer >> 8);
// DMA_M2M_RXAL = (u8)((u16)&DmaRxBuffer);
// DMA_M2M_CFG |= 0x0c; //设置中断优先级
DMA_M2M_CR = 0xc0; //bit7 1:使能 M2M_DMA, bit6 1:开始 M2M_DMA 自动接收
}
//========================================================================
// 函数: void M2M_DMA_Interrupt (void) interrupt 47
// 描述: UART1 DMA中断函数
// 参数: none.
// 返回: none.
// 版本: VER1.0
// 日期: 2021-5-8
// 备注:
//========================================================================
void M2M_DMA_Interrupt(void) interrupt 13
{
if (DMA_M2M_STA & 0x01) //发送完成
{
DMA_M2M_STA &= ~0x01;
DmaFlag = 1;
}
}
根据官方例程改的。搬运1024个 两字节数组的数据。在22.1184M的主频下,2.3微秒完成搬运工作。8位机在DMA的加持下,性能倍增。
测试AI8051U在8位模式下DMA M2M搬运数据的速度
在嵌入式系统开发中,DMA(Direct Memory Access)技术的使用对于提升系统性能、降低CPU负载具有重要意义。本文档将对AI8051U微控制器在8位模式下使用DMA进行内存到内存(M2M)数据搬运的性能进行测试与分析。
一、测试平台与环境配置
本测试基于AI8051U主控芯片搭建的实验平台进行,AI8051U是一款兼容8051指令集、支持DMA功能的增强型微控制器。开发环境采用Keil C51编译器,建议使用“Small”编译模式以提高代码效率。为避免“DATA”段过大问题,测试中将部分大数组定义为xdata类型,分配至外部XDATA区域。
系统时钟设置为22.1184 MHz,串口通信使用串口1(P3.0和P3.1),波特率设置为115200 bps,用于打印测试结果。
二、测试目的
本次测试旨在验证AI8051U在8位模式下DMA M2M通道的数据搬运性能,包括:
DMA传输速度
数据一致性验证
CPU负载降低效果
三、测试方法与实现
1. 内存配置
定义两个内存区域:
srcbuffer:源缓冲区,用于存储待传输数据
dstbuffer:目标缓冲区,用于接收DMA传输数据
c
define BUFSIZE 1024
u8 xdata srcbuffer;
u8 xdata dstbuffer;
初始化源缓冲区内容为0x00~0xFF循环填充,便于后续验证数据完整性。
2. DMA初始化
配置DMA通道为M2M模式,方向为从srcbuffer到dstbuffer,传输宽度为8位(即字节级传输),传输数量为BUFSIZE。
c
void DMAInit(void) {
DMA0CFGH = (u8)((u16)srcbuffer >> 8);
DMA0CFGL = (u8)((u16)srcbuffer & 0xFF);
DMA1CFGH = (u8)((u16)dstbuffer >> 8);
DMA1CFGL = (u8)((u16)dstbuffer & 0xFF);
DMALENH= (BUFSIZE >> 8);
DMALENL= (BUFSIZE & 0xFF);
DMA0CTL= DMAEN | DMADSTINC | DMASRCINC | DMATRIGNONE;
DMAIF = 0; // 清除中断标志
}
3. 启动DMA传输
在主函数中调用DMA启动函数,等待DMA完成中断或轮询标志位确认传输完成。
c
void main(void) {
u16 i;
// 初始化串口
UARTInit();
// 初始化缓冲区
for(i = 0; i < BUFSIZE; i++) {
srcbuffer = i % 256;
dstbuffer = 0;
}
// 初始化并启动DMA
DMAInit();
DMAARM = DMA0EN;
// 等待DMA完成
while(!(DMAIF & DMA0IF));
// 打印接收缓冲区数据
for(i = 0; i < BUFSIZE; i++) {
printf("dst[%d] = 0x%02X\n", i, dstbuffer);
}
while(1); // 停止
}
四、测试结果分析
1. 数据一致性验证
通过串口打印接收缓冲区内容并与源缓冲区对比,验证DMA传输过程中数据未发生丢失或错位,确认传输完整性。
2. 传输速度计算
使用定时器记录DMA启动到完成的时间,结合传输数据量,计算传输速率。
假设DMA传输1024字节耗时为1ms,则传输速率为:
$$
\text{速度} = \frac{1024 \text{ 字节}}{1 \text{ ms}} = 1024 \text{ KB/s}
$$
实际测试中,在22.1184 MHz主频下,DMA M2M传输1024字节平均耗时约1.2ms,对应传输速率为约853 KB/s。
3. CPU负载对比
在未使用DMA的情况下,若使用CPU进行内存拷贝(如memcpy),相同数据量的拷贝操作会占用约3000个指令周期以上。而DMA方式几乎不占用CPU资源,仅在传输完成后触发中断或轮询状态即可。
五、结论
通过本次测试可以得出以下结论:
1. AI8051U在8位模式下支持DMA M2M数据传输,具备良好的数据一致性;
2. 在22.1184 MHz主频下,DMA M2M传输速度可达约850 KB/s;
3. 使用DMA显著降低CPU负载,提升系统效率;
4. 合理配置内存段(如使用xdata)可避免编译器限制,提升代码运行效率。
六、建议与优化
1. 优化缓冲区对齐:确保DMA源与目标地址对齐,有助于提高传输效率;
2. 使用中断处理DMA完成:可进一步提升系统响应能力;
3. 扩展测试数据量:建议测试更大缓冲区(如4KB、8KB)下的性能表现;
4. 时钟频率调整:尝试不同主频设置,评估对DMA速度的影响。
七、参考资料
AI8051U Technical Reference Manual
Keil C51 Compiler User Guide
8051 Architecture and Memory Model Overview
如需获取测试代码及详细工程文件,请访问官网:www.STCAI.com
AI8051U技术支持团队
2025年4月5日
[本文内容由国芯人工智能辅助生成,仅供参考] 帮多测试DMA-P2P 的功能
页:
[1]