一、介绍
DMA传输是一种不需要占用 CPU的传输方式,当把数据装进去并启动DMA发送后,CPU可以去执行其它主线程任务,而不用等待。使用DMA传输可以给CPU减负,提高程序的执行效率。
二、使用
发送函数如下:
void uart1_dma_tx(uint8_t *buf, uint8_t len)
{
if (len == 0)
{
return;
}
while (!U1STAbits.TRMT); //检测发送缓冲区是否为空
DMA0STAL = (uint16_t)buf;
DMA0CNT = len - 1;
DMA0STAH = 0x0000;
DMA0CONbits.CHEN = 1; // Re-enable DMA0 Channel
DMA0REQbits.FORCE = 1; // Manual mode: Kick-start the first transfer
}
三、常见问题
DMA发送缓冲区覆盖:
调用DMA时,是让DMA0STAL 指向要发送的buf,也就是说如果在DMA执行到一半时,该缓冲区给修改了就会造成发出来的数据出现紊乱的现象。一般解决方法是申请2个或以上缓冲区,采用乒乓形式,当其中一个缓冲区正在发送时,这时候过来数据就用另一个缓冲区去接收,保证不会出现给覆盖现象。当生产数据较快,来不及发送时,可以适当扩大缓冲区,或者采用链表形式将数据保存下来,再取出来一个一个发送(这种消费较大,一般是数据相对重要时才会采用)。
首字节丢失:
博主前面使用while(DMA0CONbits.CHEN == 1);代替while (!U1STAbits.TRMT);时,出现发送出来的首字节会丢失的现象。主要的原因是DMA0CONbits.CHEN并不是在所有数据都发送完之后,硬件自动置0,造成了没有卡住,重复调用DMA发送。当上一帧8bit数据还没发完时,下一帧进来,这时候接着发送直到停止位结束,这时候发的数据格式不是8bit数据位1bit停止位,出现异常造成首字节丢失。