在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] = {"\r\n"};
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 吴宝林
上一篇:stm32 usart在DMA模式下只能发送一次
下一篇:STM32中GPIO的8种模式
推荐阅读最新更新时间:2024-03-16 16:13
设计资源 培训 开发板 精华推荐
- 电感知识大考:遇到这些问题怎么办?|“MPS电感探索季:发现小且不凡的秘密!”第一站
- 有奖问答|ADI应用之旅——工业大机器健康篇
- 不可错过的一次邂逅,TTI携TE传感器样片与你相见!免费样片申请活动开始啦~
- ADI有奖下载活动之20:基于NDIR和PID的ADI气体探测器解决方案和新产品
- 是时候充充电啦!村田宠粉月重磅开启!
- TI 嵌入式处理主题直播月|报名观看直播赢好礼【低功耗WiFi MCU、Sitara AM57X平台、机器学习】
- Murata旗舰店1周年淘宝直播
- 看视频抽好礼:Type-C承载的高速串行标准,功能多样,挑战也不小
- 有奖直播:TI最新C2000实时控制器,在功率变换应用中实现高性能的成本优化型设计
- 围观Vishay新出炉超低ESR T55系列“萌宠们”,有惊喜!