一.乒乓缓冲原理
一般情况下,串口数据 DMA 传输到 BUF1(内存上的一片连续的缓冲区)的过程中,是不
建议对 BUF1 进行操作的。但由于串口数据是一个连续传输的过程,比如接收 GPS 数据,不
能等待 BUF1 满了才处理数据,你 CPU 在处理数据的同时,串口源源不断接收数据,此时会
造成串口数据丢失,而乒乓缓冲就完美地解决了这个问题。
具体过程是:当串口 BUF1 满了时,DMA 的目标地址迅速切换到 BUF2,此时可以处理
BUF1 的数据;当串口 BUF2 满了时,DMA 的目标地址迅速切换到 BUF1,此时可以处理 BUF2
的数据。如此一直循环下去,就像打乒乓球一样,你推我挡,故称作乒乓缓冲。二 . DMA就不在这里班门弄斧的讲解了,分享一下程序吧。
DMA配置代码: DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //外设作源头 DMA_InitStructure.DMA_BufferSize = dma_len; //BUF 大小 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器不变 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增 下边是设置数据宽度: DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //数据宽度为 8 位 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //正常缓存模式(非连续传输) 一些基本定义: #define dma_len 100 //定义串口 DMA 传输数据长度(如果串口一次接收数据没有达到 dma_len 个 byte,则不会发生 DMA 中断) extern u8 USART1_DMA_Buf1[dma_len]; //BUF1 extern u8 USART1_DMA_Buf2[dma_len]; //BUF2 typedef enum {BUF_NO1=0,BUF_NO2=1}BUF_NO; extern BUF_NO Free_Buf_Now; extern bool Buf_Ok; 乒乓思想在这里体现: void DMA1_Channel5_IRQHandler(void) { if(DMA_GetITStatus(DMA1_IT_TC5)) { //DataCounter = DMA_GetCurrDataCounter(DMA1_Channel5); //获取剩余长度,一般都为 0,调试用 DMA_ClearITPendingBit(DMA1_IT_GL5); //清除全部中断标志
//转换可操作 BUF if(Free_Buf_Now==BUF_NO1) //如果 BUF1 空闲,将 DMA 接收数据赋值给 BUF1 { DMA_InitStructure.DMA_MemoryBaseAddr = (u32)USART1_DMA_Buf1; DMA_Init(DMA1_Channel5, &DMA_InitStructure); Free_Buf_Now=BUF_NO2; } else //如果 BUF2 空闲,将 DMA 接收数据赋值给 BUF2 { DMA_InitStructure.DMA_MemoryBaseAddr = (u32)USART1_DMA_Buf2; DMA_Init(DMA1_Channel5, &DMA_InitStructure); Free_Buf_Now=BUF_NO1; } Buf_Ok=TRUE; } }
|
DMA双缓冲区(也称乒乓缓冲)
最新推荐文章于 2024-04-23 18:07:11 发布