<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > s3c2440的DMA應用

s3c2440的DMA應用

作者: 時(shí)間:2016-11-19 來(lái)源:網(wǎng)絡(luò ) 收藏
DMA(Direct Memory Access,直接內存訪(fǎng)問(wèn))是一種不經(jīng)過(guò)CPU而直接從內存存取數據的數據交換模式。在需要進(jìn)行大量數據交換的場(chǎng)合,用好DMA,可以大大提高系統的性能,因為DMA操作幾乎不占用CPU資源。

s3c2440提供了4個(gè)通道的DMA,它們不僅可以實(shí)現內存之間的數據交換,還可以實(shí)現內存與外設,以及外設與外設之間的數據交換。要用好s3c2440的DMA,關(guān)鍵是配置好它的源、目的寄存器,和必要的控制寄存器。寄存器DISRCn是初始DMA源寄存器,它是用于設置DMA數據傳輸的源基址,而寄存器DIDSTn是初始DMA目的寄存器,它是用于設置DMA數據傳輸的目的基址。初始DMA源控制寄存器DISRCCn的第1位用于選擇源的總線(xiàn)(系統總線(xiàn)AHB還是外設總線(xiàn)APB),第0位用于設置源基址在數據傳輸過(guò)程中是遞增還是固定不變。初始DMA目的控制寄存器DIDSTCn的低兩位與寄存器DISRCCn相識,但它是用來(lái)設置目的基址,而第2位用于設置是在傳輸完數據之后中斷還是在自動(dòng)重載后中斷。DMA控制寄存器DCONn用于控制數據的DMA傳輸,第31位用于設置傳輸協(xié)議是需求模式還是握手模式,第30位用于選擇同步時(shí)鐘是PCLK還是HCLK,第29位用于設置DMA中斷是否發(fā)生,第28位用于選擇傳輸大小是單元傳輸還是突發(fā)傳輸,第27位用于選擇服務(wù)模式是單步模式還是完全模式,第24位到第26位用于設置DMA的請求源,第23位用于設置DMA的源是軟件還是硬件,第22位用于設置是否需要重載傳輸的目的和源基址,第20位和第21位用于設置數據傳輸的數據大?。ㄗ止?、半字還是字),低20位用于初始化傳輸數據的個(gè)數。而通過(guò)讀取DMA狀態(tài)寄存器DSTATn的低20位可以獲知當前的傳輸的計數。DMA掩碼觸發(fā)寄存器DMASKTRIGn的第2位可以終止當前DMA操作,第1位可以用于開(kāi)啟DMA通道,第0位則表示在軟件請求模式下觸發(fā)DMA通道。

下面我們就用DMA的方式來(lái)實(shí)現音頻的播放。由于是用DMA的方式,因此在播放的過(guò)程中不占用系統資源,我們可以很容易的實(shí)現聲音的各種操作而絲毫不影響播放的效果,如音量的提高和降低、靜音、暫停等。在這里,還需要強調一點(diǎn),利用DMA傳輸數據,一次最多可以傳輸的字節大小為:DSZ×TSZ×TC,DSZ表示的是數據大?。ㄗ止?、半字還是字,即是1、2還是4),TSZ表示的是傳輸大?。▎卧獋鬏斶€是突發(fā)傳輸,即1還是4),TC表示傳輸計數值(即寄存器DCONn的低20位存放的數據),因此如果需要傳輸的字節大小超出了這三個(gè)參數乘積的大小,則還要進(jìn)一步處理,在我們給出的程序中,我們就考慮了這方面的問(wèn)題。下面就是具體的程序,其中我們是利用UART來(lái)實(shí)現音頻信號的播出、停止、暫停、靜音、音量的提高和降低的。


…………
//一段純音頻數據數組
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)
{
//用于計算音頻數據的長(cháng)度是否超過(guò)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);//發(fā)送IIS的DMA使能
rIISMOD= (0<<9)|(0<<8)|(2<<6)|(0<<5)|(0<<4)|(1<<3)|(1<<2)|(1<<0);
rIISFCON = (1<<15)|(1<<13); //發(fā)送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時(shí)中斷,APB,目的地址不變
if (result == 0)//所傳輸的字節數沒(méi)有超出DMA的最大傳輸范圍
{
flag = 0;//清標志,表示沒(méi)有超出范圍,進(jìn)入DMA中斷后結束DMA操作
//握手模式,PCLK同步,傳輸計數中斷,單元傳輸,單步服務(wù)模式,IISSDO,
//硬件請求模式,非自動(dòng)重載,半字,
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通道開(kāi)啟,非軟件觸發(fā)

//啟動(dòng)IIS
rIISCON |= 0x1;
}


void __irq DMA_end(void)
{
rSRCPND |= 0x1<<19;
rINTPND |= 0x1<<19;

if (flag == 0)//DMA傳輸完畢
{
rIISCON = 0x0;//關(guān)閉IIS
rIISFCON = 0x0;//清IIS的FIFO
rDMASKTRIG2=1<<2;//停止DMA
play_state = 0;//清播放標志
}
else//DMA沒(méi)有傳輸完畢,繼續傳輸
{
result --;//商遞減
rDISRC2 += 0x200000;//DMA源基址遞增。因為傳輸的數據是半字,所以這里遞增0x200000
if (result == 0 )//只剩下余數部分需要傳輸
{
rDCON2=(rDCON2&(~0xfffff))|(remainder);//需要重新設置傳輸計數值
flag=0;//清標志
}
rDMASKTRIG2=(0<<2)|(1<<1)|0;//需要重新設置DMA通道的開(kāi)啟
}
}

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));//開(kāi)啟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;
}
}
}


關(guān)鍵詞: s3c2440DMA應

評論


技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>