<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          s3c2440的DMA應(yīng)用

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

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

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


          …………
          //一段純音頻數(shù)據(jù)數(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)
          {
          //用于計(jì)算音頻數(shù)據(jù)的長(zhǎng)度是否超過(guò)DMA所能傳輸?shù)淖止?jié)數(shù)范圍
          //這里音頻數(shù)據(jù)的通道位數(shù)為16位,因此需要length除以2
          remainder = (length>>1) & 0xfffff;//余數(shù)
          result = (length>>1) / 0x100000;//商

          play_state = 1;//置播放標(biāo)志

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

          //配置1341,詳細(xì)講解請(qǐng)看上一篇文章
          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的源基址為音頻數(shù)據(jù)數(shù)組的首地址
          rDISRCC2 = (0<<1)|(0<<0);//AHB,源地址遞增
          rDIDST2 = (U32)IISFIFO;//DMA的目的基址為IIS的FIFO
          rDIDSTC2 = (0<<2)| (1<<1)|(1<<0);//當(dāng)傳輸計(jì)數(shù)值為0時(shí)中斷,APB,目的地址不變
          if (result == 0)//所傳輸?shù)淖止?jié)數(shù)沒(méi)有超出DMA的最大傳輸范圍
          {
          flag = 0;//清標(biāo)志,表示沒(méi)有超出范圍,進(jìn)入DMA中斷后結(jié)束DMA操作
          //握手模式,PCLK同步,傳輸計(jì)數(shù)中斷,單元傳輸,單步服務(wù)模式,IISSDO,
          //硬件請(qǐng)求模式,非自動(dòng)重載,半字,
          rDCON2 = (1<<31) | (0<<30) | (1<<29) | (0<<28) | (0<<27) | (0<<24) | (1<<23) | (1<<22) | (1<<20) | (remainder);

          }
          else//所傳輸?shù)淖止?jié)數(shù)超出了DMA的最大傳輸范圍
          {
          flag = 1;//置標(biāo)志,表示超出范圍
          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;//清播放標(biāo)志
          }
          else//DMA沒(méi)有傳輸完畢,繼續(xù)傳輸
          {
          result --;//商遞減
          rDISRC2 += 0x200000;//DMA源基址遞增。因?yàn)閭鬏數(shù)臄?shù)據(jù)是半字,所以這里遞增0x200000
          if (result == 0 )//只剩下余數(shù)部分需要傳輸
          {
          rDCON2=(rDCON2&(~0xfffff))|(remainder);//需要重新設(shè)置傳輸計(jì)數(shù)值
          flag=0;//清標(biāo)志
          }
          rDMASKTRIG2=(0<<2)|(1<<1)|0;//需要重新設(shè)置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應(yīng)

          評(píng)論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();