本帖最后由 oxygenzz 于 2019-4-17 17:52 编辑
在 PIC18芯片家族中,K42和K83等系列芯片配备有DMA外设。这使得存储器与外设之间的数据传输可以不经过CPU干预来进行,能显著的提高数据传输的吞吐率。
MCC配置界面:
DMA功能框图如下,图中画出了两个DMA通道。
传输方向/源地址/目的地址
DMA数据传输方向是固定的,即从源地址到目的地址。具体的说,DMA能将数据从源地址读出,然后写入目的地址。
源地址(读操作):flash,EEPROM,GPR(SRAM), SFR(外设寄存器)
目的地址(写操作):GPR (SRAM),SFR(外设寄存器)
源地址起始地址寄存器,为24位,DMAxSSAU-DMAxSSAH-DMAxSSAL
目的地址起始地址寄存器,为16位, DMAxDSAH-DMAxSSAL
传输数据长度
传输数据长度由源端数据长度和目的端数据长度决定。这两个数据长度可以设置不同。当设置不同时,每次传输的长度由较小的一端决定。
典型的传输形式举例:
N:1 - 将N字节长度数据通过串口/SPI口传输出去
N:N – 将数据块在存储器不同地址间搬移
1:N – 将ADC采集到数据依次写入到一块预定的存储器空间
1:1 – 两个通信口桥接
DMA 启动/停止控制
DMA数据搬移启动可以由软件操作,也可以由其他外设进行触发。
同样的,停止操作也是可以由软件操作或硬件触发。
DMA与CPU资源使用仲裁
可以设为DMA高优先级或CPU高优先级。
当DMA高优先级时,DMA操作时,CPU执行暂停;当CPU高优先级时,DMA利用
CPU空闲时间进行DMA传输。
MCC生成代码
初始化函数。注意函数中嵌入了一段汇编代码。
void DMA1_Initialize(void)
{
DMA1SSA = 0x000000; //set source start address
DMA1DSA = 0x1000; //set destination start address
DMA1CON1 = 0x00; //set control register1
DMA1SSZ = 0x0000; //set source size
DMA1DSZ = 0x0000; //set destination size
DMA1SIRQ = 0x01; //set DMA Transfer Trigger Source
DMA1AIRQ = 0x01; //set DMA Transfer abort Source
PIR2bits.DMA1DCNTIF =0; // clear Destination Count Interrupt Flag bit
PIR2bits.DMA1SCNTIF =0; // clear Source Count Interrupt Flag bit
PIR2bits.DMA1AIF =0; // clear abort Interrupt Flag bit
PIR2bits.DMA1ORIF =0; // clear overrun Interrupt Flag bit
PIE2bits.DMA1DCNTIE =1; // enable Destination Count 0 Interrupt
PIE2bits.DMA1SCNTIE =1; // enable Source Count Interrupt
PIE2bits.DMA1AIE =1; // enable abort Interrupt
PIE2bits.DMA1ORIE =1; // enable overrun Interrupt
//给与外设访问存储器的权限
asm("BCF INTCON0,7");
asm ("BANKSEL PRLOCK");
asm ("MOVLW 0x55");
asm ("MOVWF PRLOCK");
asm ("MOVLW 0xAA");
asm ("MOVWF PRLOCK");
asm ("BSF PRLOCK, 0");
asm("BSF INTCON0,7");
DMA1CON0 = 0x00; //set control register0
}
源端传输完成中断
void DMA1_DMASCNT_ISR(void)
{
PIR2bits.DMA1SCNTIF=0;// clear Source Count Interrupt Flag
// add your DMA channel 1 source count 0 interrupt custom code
}
目的端传输完成中断
void DMA1_DMADCNT_ISR(void)
{
PIR2bits.DMA1DCNTIF=0; // clear Destination Count Interrupt Flag
// add your DMA channel 1 destination count 0 interrupt custom code
}
中止产生中断
void DMA1_DMAA_ISR(void)
{
PIR2bits.DMA1AIF=0;// clear abort Interrupt Flag
// add your DMA channel 1 abort interrupt custom code
}
过载产生中断
void DMA1_DMAOR_ISR(void)
{
PIR2bits.DMA1ORIF=0;// clear overrun Interrupt Flag
// add your DMA channel 1 overrun interrupt custom code
}
|
可以提高数据传输的吞吐率