本帖最后由 hi我歌月徘徊 于 2016-11-18 14:56 编辑
使用了串口接收DMA,DMA初始化
[mw_shl_code=c,true]重新贴一下代码
[mw_shl_code=applescript,true]DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
if((u32)DMA_Streamx>(u32)DMA2)
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);
}else
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);
}
DMA_DeInit(DMA_Streamx);
while (DMA_GetCmdStatus(DMA_Streamx) != DISABLE){}
DMA_InitStructure.DMA_Channel = chx;
DMA_InitStructure.DMA_PeripheralBaseAddr = par;
DMA_InitStructure.DMA_Memory0BaseAddr = mar; //(1)
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;//串口接收--内存
DMA_InitStructure.DMA_BufferSize = ndtr;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//内存自增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//使能双缓冲模式,将会自动设置为循环模式,参考手册9.3.8提到了
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA_Streamx, &DMA_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;
NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
DMA_DoubleBufferModeConfig(DMA2_Stream5,(uint32_t)RxBuff2, DMA_Memory_0); //(2)设置第二缓冲区地址和选定当前缓冲区
DMA_DoubleBufferModeCmd(DMA2_Stream5,ENABLE); // (3) 使能
DMA_ITConfig(DMA2_Stream5,DMA_IT_TC,ENABLE);//发送完成中断 当DMA_BufferSize =0才算发送完成
DMA_Cmd(DMA2_Stream5,ENABLE);[/mw_shl_code]
不好意思
[/mw_shl_code]
双缓冲模式只需要增加代码中的(2)(3),即可。
两个缓冲区,buff1和buff2,当dma完成以后,自动切换buff2当中继续存储
比如 buff1【1000】,buff2【1000】,DMA_BufferSize =100;发送100个字节到到了buff1,dma就自动将目标地址设为buff2,那么你在发送100字节就到了buff2当中了,如此循环。
但是假如我换一种方式,每当串口来一次数据,我就换一次缓冲区,
比如第一次数据,dma到了buf1;第二次数据,dma到了buf2,第三次数据,又到了buf1,但是buf1当中第一次的数据就会被覆盖。怎么样才能不被覆盖呢?
打开了串口空闲中断,每当串口空闲中断的时候,都会将当前buff切换,比如初始化dma时,当前buff为buff1,那么空闲中断中将当前buff设为buff2第一次串口助手发送:0 1 2 3
接收:
buff1:0 1 2 3
buff2:0 0 0 0
空闲中断,设置当前buff为 buff2
第二次串口助手发送:0 1 2 3
buff1:0 1 2 3 (第一次发送的值)
buff1 : 0 1 2 3
空闲中断,设置当前buff为buff1
第三次串口助手发送:0 1 2 3
buff1:0 1 2 3 此时buff1中收到的值被更新覆盖,其实我想达到的效果为 buff1:0 1 2 3 0 1 2 3 数组指针后移,本来设置的就是内存地址自增(同一个缓冲区内存是自增的),但是一切换缓冲区,内存地址都会从0开始的!!!
buff1 : 0 1 2 3 (第二次发送的值)
怎么解决这个问题呢?? 总不能每次中断都把数据取出来吧?这样也太浪费时间了。还有一种方法,就是在指定缓冲区的时候,把内存基地址在指定一下(buf1地址+上一次收到的数据个数),简单试了一下:
DMA_Cmd(DMA2_Stream5, DISABLE);
rx_num=SEND_BUF_SIZE-DMA_GetCurrDataCounter(DMA2_Stream5);//获得接收数据项数
DMA2_Stream5->CR |= (uint32_t)(DMA_SxCR_CT); /* Set Memory 1 as current memory address */
DMA2_Stream5->M0AR=(uint32_t)&RxBuff2+rx_num; 当前buff存储位置=buff2基地址+上一次接收数据个数
DMA_Cmd(DMA2_Stream5, ENABLE);
这样也可实现,但是数据如果多了 感觉很麻烦了。。。。
请问大神有没有什么好的办法呢? 感激不尽
一周热门 更多>