×
单片机 > 单片机程序设计 > 详情

串口使用DMA发送数据时的数据覆盖问题

发布时间:2020-05-23 发布时间:
|

在STM32等单片机中,为了提高程序的执行效率,在使用串口时,经常会使用DMA的方式来进行收发数据,这样,CPU只需要把数据放在发送缓存区即可离开。


但是,由于在串口发送中使用的是引用调用,即数据传递时是将要发送的指针进行传递,而非将数据复制了一份。这样的好处是方便快捷,但同时带来的一个后果时,当该数据还未发送完时,下一串数据就不能放入该发送缓冲区,否则,就会发生数据覆盖问题,即后一串数据覆盖前边还未发完的数据。


一般发生这种数据覆盖问题,都是在连续发送两串以上数据的时候,第一次的还没发完,后边的就会将前一次的数据覆盖。


若是在每次发送之前进行判断上次数据是否发完,如果没有发完就等待的话,就会降低CPU的效率;或者,如果在每次使用串口发送函数的前边或后边使用延时的话,就可以解决这样的问题,但是如果这样做,那使用DMA的意义就没有了。


所以为了解决这个问题,笔者自己想到了一种建立双缓冲区的方法,直接贴代码:


void SendData(uint8_t* pData, uint16_t dataLen)

{

    uint8_t ret = 0;

static uint8_t num = 0;

static uint8_t buffer1[256] = {" "};

static uint8_t buffer2[256] = {0};

    //使用DMA发送时,建立双缓冲区交替发送,防止数据的覆盖

if(num == 0)

{

ret = DMA_USART1_Transmit(buffer1, strlen((const char*)buffer1));

if(ret == 0)

{

num++;

memset(buffer2, 0, sizeof(buffer2));

strcat((char*)buffer2, (char*)pData);

}

else

{

strcat((char*)buffer1, (char*)pData);

}

}

else

{

ret = DMA_USART1_Transmit(buffer2, strlen((const char*)buffer2));

if(ret == 0)

{

num--;

memset(buffer1, 0, sizeof(buffer1));

strcat((char*)buffer1, (char*)pData);

}

else

{

strcat((char*)buffer2, (char*)pData);

}

}

    

}


在上段代码中函数SendData()为外部调用,参数为需要发送的字符串以及发送数据的长度。函数DMA_USART1_Transmit()为真正的发送函数,在该函数中,发送成功会返回0,如果当前有数据正在发送则返回1,返回其他为发送错误。


该部分代码的想法就是,在发送时,先发送buffer1中的数据,在发送buffer1的数据时,之后传过来需要发的数据都存放在buffer2中,当buffer1发送完成之后,就发送buffer2的数据,这时传过来的数据全部存放在buffer1中。这样采用交替发送的方式,利用双缓冲区,就可以有效的解决单缓冲区的数据覆盖问题。287320150   13568401331 吴宝林


关键字:串口  DMA  发送数据  数据覆盖 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
51单片机的数码管动态扫描方法