本帖最后由 Ryanhsiung 于 2011-10-15 17:32 编辑
DMA这个功能在高速处理大量数据,非常的重要。所以这个是必须玩的!
声明:
//本文为抄袭Swallow_0322之作 https://bbs.21ic.com/icview-235493-1-1.html,:HOT大叔NUC120助学板第十一贴----SPI(PDMA方式)
这里谢谢Swallow_0322 网友的例程,
盗版之处:
1、简化了一些操作,去掉了DMA1通道只留了DMA0
2、将其变更为UART串口事件驱动
3、DMA操作完成后,返回刚接收到的数据
DMA使用注意:
1 、要注意 使能相应外设 PDMA 功能 (DrvUART_EnablePDMA(UART_PORT0);)
缺点:
1、若是有PING-PONG操作最好,可以不间断的使用DMA
void PDMA0_Configuration (void)
{
STR_PDMA_T sPDMA;
uint32_t UARTPort;
DrvPDMA_Init(); // 初始化PDMA(PDMA 控制器时钟使能控制)
UARTPort = UART0_BASE; //
DrvPDMA_SetCHForAPBDevice(eDRVPDMA_CHANNEL_0, eDRVPDMA_UART0, eDRVPDMA_READ_APB);// APB设备选择 PDMA 通道 SPI选择PDMA通道0 读操作
//DrvPDMA_SetCHForAPBDevice(eDRVPDMA_CHANNEL_1,eDRVPDMA_UART1,eDRVPDMA_WRITE_APB);
sPDMA.sSrcCtrl.u32Addr = UARTPort; // 选择DMA 操作的源地址
sPDMA.sDestCtrl.u32Addr = (uint32_t)DestArray; // 选择DMA 操作目标地址
sPDMA.u8TransWidth = eDRVPDMA_WIDTH_8BITS; // 传输宽度
sPDMA.u8Mode = eDRVPDMA_MODE_APB2MEM; // 操作模式: IP到存储器模式 (APB-to-Memory)
sPDMA.sSrcCtrl.eAddrDirection = eDRVPDMA_DIRECTION_FIXED; // 传输地址固定
sPDMA.sDestCtrl.eAddrDirection = eDRVPDMA_DIRECTION_INCREMENTED; // 传输地址 持续增加
sPDMA.i32ByteCnt = 10; // 字节数
DrvPDMA_Open(eDRVPDMA_CHANNEL_0, &sPDMA); // 配置 并打开PDMA1
DrvPDMA_EnableInt(eDRVPDMA_CHANNEL_0, eDRVPDMA_BLKD); // 使能PDMA通道0中断 中断源为:eDRVPDMA_BLKD(PDMA Transfer Done 中断使能)
DrvPDMA_InstallCallBack(eDRVPDMA_CHANNEL_0, eDRVPDMA_BLKD, (PFN_DRVPDMA_CALLBACK) PDMA0_Callback ); // PDMA 通道0 安装中断回调函数
DrvUART_EnablePDMA(UART_PORT0); // 使能相应外设 PDMA 功能
DrvPDMA_CHEnableTransfer(eDRVPDMA_CHANNEL_0); // 使能PDMA通道0 csr.trig_en位置1 ,传输完成后自动清0
}
DMA接收完成后,返回相应数据,并从新打开DMA
void PDMA0_Callback(void)
{
printf("当次:%x、%x、%x、%x、%x、%x、%x、%x、%x、%x\n",DestArray[0],DestArray[1],DestArray[2]\
,DestArray[3],DestArray[4],DestArray[5],DestArray[6],DestArray[7],DestArray[8],DestArray[9] );
DrvPDMA_CHEnableTransfer(eDRVPDMA_CHANNEL_0); //使能PDMA通道0 从新开始接收
}
|