您的位置 首页 分销

s3c2440的DMA使用

DMA(DirectMemoryAccess,直接内存访问)是一种不经过CPU而直接从内存存取数据的数据交换模式。在需要进行大量数据交换的场合,用好DM…

DMA(Direct Memory Access,直接内存拜访)是一种不经过CPU而直接从内存存取数据的数据交换形式。在需求进行很多数据交换的场合,用好DMA,能够大大进步体系的功能,由于DMA操作几乎不占用CPU资源。

s3c2440供给了4个通道的DMA,它们不只能够完成内存之间的数据交换,还能够完成内存与外设,以及外设与外设之间的数据交换。要用好s3c2440的DMA,关键是装备好它的源、意图寄存器,和必要的操控寄存器。寄存器DISRCn是初始DMA源寄存器,它是用于设置DMA数据传输的源基址,而寄存器DIDSTn是初始DMA意图寄存器,它是用于设置DMA数据传输的意图基址。初始DMA源操控寄存器DISRCCn的第1位用于挑选源的总线(体系总线AHB仍是外设总线APB),第0位用于设置源基址在数据传输过程中是递加仍是固定不变。初始DMA意图操控寄存器DIDSTCn的低两位与寄存器DISRCCn相识,但它是用来设置意图基址,而第2位用于设置是在传输完数据之后中止仍是在主动重载后中止。DMA操控寄存器DCONn用于操控数据的DMA传输,第31位用于设置传输协议是需求形式仍是握手形式,第30位用于挑选同步时钟是PCLK仍是HCLK,第29位用于设置DMA中止是否产生,第28位用于挑选传输巨细是单元传输仍是突发传输,第27位用于挑选服务形式是单步形式仍是彻底形式,第24位到第26位用于设置DMA的恳求源,第23位用于设置DMA的源是软件仍是硬件,第22位用于设置是否需求重载传输的意图和源基址,第20位和第21位用于设置数据传输的数据巨细(字节、半字仍是字),低20位用于初始化传输数据的个数。而经过读取DMA状况寄存器DSTATn的低20位能够获悉当时的传输的计数。DMA掩码触发寄存器DMASKTRIGn的第2位能够中止当时DMA操作,第1位能够用于舱位DMA通道,第0位则一共在软件恳求形式下触发DMA通道。

下面咱们就用DMA的方法来完成音频的播映。由所以用DMA的方法,因而在播映的过程中不占用体系资源,咱们能够很简单的完成声响的各种操作而一点点不影响播映的作用,如音量的进步和下降、静音、暂停等。在这儿,还需求着重一点,使用DMA传输数据,一次最多能够传输的字节巨细为:DSZ×TSZ×TC,DSZ一共的是数据巨细(字节、半字仍是字,便是1、2仍是4),TSZ一共的是传输巨细(单元传输仍是突发传输,即1仍是4),TC一共传输计数值(即寄存器DCONn的低20位寄存的数据),因而假如需求传输的字节巨细超出了这三个参数乘积的巨细,则还要进一步处理,在咱们给出的程序中,咱们就考虑了这方面的问题。下面便是具体的程序,其间咱们是使用UART来完成音频信号的播出、中止、暂停、静音、音量的进步和下降的。

…………
//一段纯音频数据数组
unsigned char music[] = {
0xF9, 0xFF, 0xF5, 0xFF, 0xF8, 0xFF, 0xF8, 0xFF, 0xF6, 0xFF, 0xFF, 0xFF, 0xF5, 0xFF, 0xF9, 0xFF,
0xF6, 0xFF, 0xF6, 0xFF, 0xFA, 0xFF, 0xFD, 0xFF, 0xFA, 0xFF, 0xFA, 0xFF, 0xF7, 0xFF, 0xF6, 0xFF,
…………
};

int result;
int remainder;
char flag;
char cmd;
char play_state;

void __irq uartISR(void)
{
char ch;
rSUBSRCPND |= 0x1;
rSRCPND |= 0x1<<28;
rINTPND |= 0x1<<28;
ch=rURXH0;

switch(ch)
{
case 0x55://播映
cmd = 1;
break;
case 0x1://静音
cmd = 0x11;
break;
case 0x2://音量进步
cmd = 0x12;
break;
case 0x3://音量下降
cmd = 0x13;
break;
case 0x66://中止
cmd = 0x2;
break;
case 0x77://暂停
cmd = 0x3;
break;
}
rUTXH0=ch;
}

//放音子程序
void playsound(unsigned char *buffer,int length)
{
//用于核算音频数据的长度是否超越DMA所能传输的字节数规模
//这儿音频数据的通道位数为16位,因而需求length除以2
remainder = (length>>1) & 0xfffff;//余数
result = (length>>1) / 0x100000;//商

play_state = 1;//置播映标志

rGPBDAT = rGPBDAT & ~(L3M|L3C|L3D) |(L3M|L3C);

//装备1341,具体解说请看上一篇文章
WriteL3(0x14 + 2,1);
WriteL3(0x60,0);

WriteL3(0x14 + 2,1);
WriteL3(0x10,0);

WriteL3(0x14 + 2,1);
WriteL3(0xc1,0);

//装备IIS
rIISPSR= 3<<5|3;
rIISCON= (1<<5)|(0<<4)|(0<<3)|(1<<2)|(1<<1);//发送IIS的DMA使能
rIISMOD= (0<<9)|(0<<8)|(2<<6)|(0<<5)|(0<<4)|(1<<3)|(1<<2)|(1<<0);
rIISFCON = (1<<15)|(1<<13); //发送FIFO为DMA //装备DMA
rDISRC2 = (U32)buffer;//DMA的源基址为音频数据数组的首地址
rDISRCC2 = (0<<1)|(0<<0);//AHB,源地址递加
rDIDST2 = (U32)IISFIFO;//DMA的意图基址为IIS的FIFO
rDIDSTC2 = (0<<2)| (1<<1)|(1<<0);//当传输计数值为0时中止,APB,意图地址不变
if (result == 0)//所传输的字节数没有超出DMA的最大传输规模
{
flag = 0;//清标志,一共没有超出规模,进入DMA中止后结束DMA操作
//握手形式,PCLK同步,传输计数中止,单元传输,单步服务形式,IISSDO,
//硬件恳求形式,非主动重载,半字,
rDCON2 = (1<<31) | (0<<30) | (1<<29) | (0<<28) | (0<<27) | (0<<24) | (1<<23) | (1<<22) | (1<<20) | (remainder); }
else//所传输的字节数超出了DMA的最大传输规模
{
flag = 1;//置标志,一共超出规模
rDCON2 = (1<<31) | (0<<30) | (1<<29) | (0<<28) | (0<<27) | (0<<24) | (1<<23) | (1<<22) | (1<<20) | (0xfffff);
}
rDMASKTRIG2=(0<<2)|(1<<1)|0;//不中止DMA,DMA通道舱位,非软件触发 //发动IIS
rIISCON |= 0x1;
}

void __irq DMA_end(void)
{
rSRCPND |= 0x1<<19;
rINTPND |= 0x1<<19; if (flag == 0)//DMA传输结束
{
rIISCON = 0x0;//封闭IIS
rIISFCON = 0x0;//清IIS的FIFO
rDMASKTRIG2=1<<2;//中止DMA
play_state = 0;//清播映标志
}
else//DMA没有传输结束,持续传输
{
result –;//商递减
rDISRC2 += 0x200000;//DMA源基址递加。由于传输的数据是半字,所以这儿递加0x200000
if (result == 0 )//只剩下余数部分需求传输
{
rDCON2=(rDCON2&(~0xfffff))|(remainder);//需求从头设置传输计数值
flag=0;//清标志
}
rDMASKTRIG2=(0<<2)|(1<<1)|0;//需求从头设置DMA通道的舱位
}
}

void Main(void)
{

char mute;
char volume;

…………

rSRCPND = (0x1<<19)|(0x1<<28);
rSUBSRCPND = 0x1;
rINTPND = (0x1<<19)|(0x1<<28);
rINTSUBMSK = ~(0x1);
rINTMSK = ~((0x1<<19)|(0x1<<28));//舱位DMA2中止屏蔽
pISR_UART0 = (U32)uartISR;
pISR_DMA2=(U32)DMA_end;

result=0;
remainder=0;
flag=0;
cmd=0;
play_state =0;

while(1)
{
switch(cmd)
{
case 0x1://播映
if (play_state==0)
{
volume = 0;//音量清零
mute=0xa0;//初始化静音
playsound(music,sizeof(music));
}
else
{
while(!(rUTRSTAT0 & 0x2))
;
rUTXH0=0xff;
}
cmd = 0;
break;
case 0x2://中止
if (play_state==1)
{
rIISCON = 0x0;//中止IIS
rIISFCON = 0x0;//清IIS的FIFO
rDMASKTRIG2=1<<2;//中止DMA2
flag = 0;
play_state = 0;
}
else
{
while(!(rUTRSTAT0 & 0x2))
;
rUTXH0=0xff;
}
cmd = 0;
break;
case 0x3://暂停,
if(play_state == 1)
{
rIISCON ^= 0x1;//异或
}
else
{
while(!(rUTRSTAT0 & 0x2))
;
rUTXH0=0xff;
}
cmd = 0;
break;
case 0x11://静音
if (play_state==1)
{
mute ^= 0x4;
WriteL3(0x14 + 0,1);//DATA0 (000101xx+00)
WriteL3(mute,0);//10,1,00,x,00:x,静音
}
else
{
while(!(rUTRSTAT0 & 0x2))
;
rUTXH0=0xff;
}
cmd = 0;
break;
case 0x12://音量递加
if (play_state==1)
{
if(volume>0)
{
volume –;
WriteL3(0x14 + 0,1);//DATA0 (000101xx+00)
WriteL3(volume,0);//音量进步
}
}
else
{
while(!(rUTRSTAT0 & 0x2))
;
rUTXH0=0xff;
}
cmd = 0;
break;
case 0x13://音量递减
if (play_state==1)
{
if(volume<61)
{
volume++;
WriteL3(0x14 + 0,1);//DATA0 (000101xx+00)
WriteL3(volume,0);//音量下降
}
}
else
{
while(!(rUTRSTAT0 & 0x2))
;
rUTXH0=0xff;
}
cmd = 0;
break;
}
}
}

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/bandaoti/fenxiao/265507.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部