S3c2440A 支持位于系統(tǒng)總線和外設(shè)總線之間的4 個(gè)通道的控制器。每個(gè)DMA 控制器通道 無(wú)限制地執(zhí)行系統(tǒng)總線上的設(shè)備或外設(shè)總線上的設(shè)備之間數(shù)據(jù)搬移。換句話說(shuō),就是每個(gè) 通道都操作一下四種情況: (1)源和目的設(shè)備都在系統(tǒng)總線上 (2)源設(shè)備在系統(tǒng)總線上,目的設(shè)備在外設(shè)總線上 (3)源設(shè)備在外設(shè)總線上,目的設(shè)備在系統(tǒng)總線上 (4)源設(shè)備和目的設(shè)備都在外設(shè)總線上 DMA 的主要有點(diǎn)就是其傳輸數(shù)據(jù)不需要CPU 的干涉。DMA 操作可由軟件或來(lái)自?xún)?nèi)設(shè)或外 部請(qǐng)求引腳來(lái)初始化。 DMA每次傳送2個(gè)字節(jié),放到FIFO中,IIS就播放,F(xiàn)IFO空,導(dǎo)致DMA被再次觸發(fā),直到傳輸計(jì)數(shù)器為0,產(chǎn)生DMA中斷,CPU進(jìn)入中斷處理程序。在DMA傳送的時(shí)候,CPU可以處理其他事情。提高了系統(tǒng)效率。 下面的程序使用IIS播放聲音同時(shí)跑流水燈。如果不用DMA,直接用上一篇的IIS程序,會(huì)發(fā)現(xiàn)聲音斷斷續(xù)續(xù),因?yàn)镮IS和流水燈一起分CPU的時(shí)間。如果使用DMA,則IIS需要的數(shù)據(jù)由DMA負(fù)責(zé)傳送,而CPU可以執(zhí)行流水燈程序,互相不耽誤。當(dāng)傳輸計(jì)數(shù)器為0時(shí),產(chǎn)生DMA中斷,CPU進(jìn)入中斷處理程序。其他時(shí)候,CPU可以執(zhí)行流水燈。這樣就實(shí)現(xiàn)了流水燈和IIS放音同時(shí)執(zhí)行。 #include "2440addr.h" #include "music.h" #define L3MODE 1<<2 #define L3DATA 1<<3 #define L3CLOCK 1<<4 #define _ISR_STARTADDRESS 0x33ffff00 #define U32 unsigned int U32 flag, result, remain; void Delay(){ int i, j, k; for(i = 0; i < 0xff; i++) for(j = 0; j < 0xff; j++) for(k = 0; k < 0xff; k++) ; } void Led(){ int i; for(i = 3; i < 7; i++){ rGPFDAT &= "(1<<i); Delay(); rGPFDAT = 0xff; } } void WriteL3(unsigned char data, unsigned int mode){ //mode = 0,地址模式;mode = 1,數(shù)據(jù)傳輸模式 int i, k; if(mode == 0){ rGPBDAT = rGPBDAT & "(L3MODE|L3DATA|L3CLOCK )|L3CLOCK; } else{ rGPBDAT = rGPBDAT & "(L3MODE|L3DATA|L3CLOCK)|(L3CLOCK|L3MODE); } for(k = 0; k < 5; k++) ; for(i = 0; i < 8; i++){ if(data & 0x1){ rGPBDAT &= "L3CLOCK; rGPBDAT |= L3DATA; for(k = 0; k < 5; k++) ; rGPBDAT |= L3CLOCK; rGPBDAT |= L3DATA; for(k = 0; k < 5; k++) ; } else{ rGPBDAT &= "L3CLOCK; rGPBDAT &= "L3DATA; for(k = 0; k < 5; k++) ; rGPBDAT |= L3CLOCK; rGPBDAT &= "L3DATA; for(k = 0; k < 5; k++) ; } data >>= 1; } rGPBDAT = rGPBDAT & "(L3MODE|L3DATA|L3CLOCK)|(L3CLOCK|L3MODE); } void PlayMusic(unsigned char buffer[], unsigned int length){ result = (length>>1)/0x100000; remain = (length>>1)&0xfffff; //UDA1341 //STATUS模式 rGPBDAT = rGPBDAT & "(L3MODE|L3DATA|L3CLOCK)|(L3CLOCK|L3MODE); WriteL3(0x14+2,0); //復(fù)位 WriteL3(0x60,1); WriteL3(0x14+2,0); //00010000 系統(tǒng)時(shí)鐘頻率384fs WriteL3(0x10,1); WriteL3(0x14+2,0); //11000001 輸出增益,ADC關(guān),DAC開(kāi) WriteL3(0xc1,1); //IIS //DMA開(kāi)啟,在接受空閑狀態(tài),不產(chǎn)生IISLRCK信號(hào),IIS預(yù)分頻使能 rIISCON = (1<<5)|(0<<4)|(0<<3)|(1<<2)|(1<<1); //主設(shè)備時(shí)鐘PCLK,主設(shè)備模式,發(fā)送模式,串行數(shù)據(jù)16位,主時(shí)鐘是384fs,串行位時(shí)鐘32fs rIISMOD = (0<<9)|(0<<8)|(2<<6)|(0<<5)|(0<<4)|(1<<3)|(1<<2)|(1<<0); //預(yù)分頻都是N=3 rIISPSR = (3<<5)|3; //發(fā)送FIFO用DMA模式,發(fā)送FIFO使能 rIISFCON = (1<<15)|(1<<13); //DMA rDISRC2 = (U32)buffer; //DMA2初始源地址 rDISRCC2 = (0<<1)|(0<<0); //源在系統(tǒng)總線上,地址增加 rDIDST2 = (U32)IISFIFO; //DMA2初始目的地址 rDIDSTC2 = (0<<2)|(1<<1)|(1<<0); //當(dāng)TC為0時(shí),中斷發(fā)生,源在外圍總線上,地址固定,一直為IISFIFO的0x55000010(小端) if(result == 0){ flag = 0; //握手模式,與APB時(shí)鐘同步,當(dāng)所有的傳輸結(jié)束,中斷請(qǐng)求生成,單元傳送,單服務(wù)模式,當(dāng)傳輸計(jì)數(shù)器為0時(shí),DMA通道關(guān)閉 rDCON2 = (1<<31)|(0<<30)|(1<<29)|(0<<28)|(0<<27)|(0<<24)|(1<<23)|(1<<22)|(1<<20)|(remain<<0); } else{ flag = 1; rDCON2 = (1<<31)|(0<<30)|(1<<29)|(0<<28)|(0<<27)|(0<<24)|(1<<23)|(1<<22)|(1<<20)|(0xfffff<<0); } rDMASKTRIG2 = (0<<2)|(1<<1)|(0<<0); //DMA通道開(kāi)啟 rIISCON |= 0x1; //IIS開(kāi)啟 } void __irq DMA2_ISR(void){ rSRCPND |= 1<<19; rINTPND |= 1<<19; if(flag == 0){ rIISCON = 0x0; //關(guān)閉IIS rIISFCON = 0x0; //關(guān)閉IISFIFO的DMA模式 rDMASKTRIG2 = 1<<2; //關(guān)閉DMA } else{ result--; rDISRC2 += 0x200000; //因?yàn)槭前胱?nbsp; if(result == 0){ flag = 0; rDCON2 = (rDCON2 & ("0xfffff)) | (remain); } rDMASKTRIG2 = (0<<2)|(1<<1)|(0<<0); } } int Main(){ rGPBUP = rGPBUP & "(0x7<<2) | (0x7<<2); //The pull up function is disabled GPB[4:2] 1 1100 rGPBCON = rGPBCON & "(0x3f<<4) | (0x15<<4); //GPB[4:2]=Output(L3CLOCK):Output(L3DATA):Output(L3MODE) rGPBDAT = 0x1ec; rGPEUP = rGPEUP & "(0x1f) | 0x1f; //The pull up function is disabled GPE[4:0] 1 1111 rGPECON = rGPECON & "(0x3ff) | 0x2aa; //GPE[4:0]=I2SSDO:I2SSDI:CDCLK:I2SSCLK:I2SLRCK rMPLLCON = (150<<12)|(5<<4)|(0<<0); rSRCPND |= 1<<19; rINTPND |= 1<<19; rINTMSK &= "(1<<19); rGPFCON = 0xd57f; rGPFUP = 0x87; pISR_DMA2 = (U32)DMA2_ISR; PlayMusic(music, sizeof(music)); while(1){ Led(); //占用CPU } return 0; } 作者:李萬(wàn)鵬 |
你好,這個(gè)程序現(xiàn)在還沒(méi)有調(diào)試出來(lái),急啊。。。。可以把你的工程發(fā)一份到 long361800@163.com 嗎??多謝了啊。。。。。 |