代码如下,从env_dev串口数据,读到数据之后,通过dtu_dev发送出去。之前这样写是没问题的,采用DMA发送方式,dtu_buf是全局变量
if (DTU_flag == 1)
{
//关闭平时通信时的定时器
rt_device_control(hw_dev, HWTIMER_CTRL_STOP, RT_NULL);
rt_event_send(&feed_dog_event, EVENT_FLAG3);
while( cnt2 = rt_device_read(env_dev, -1, dtu_buf, 4096) )
{
rt_device_write(dtu_dev, 0, dtu_buf, cnt2);
}
通过串口助手查看,数据正常
但是阿里云接收到的数据就是断开的,之前偶尔有问题,是json文件的大括号断开了,现在一个完整的数据被分成好几块了。
有个小疑问:
代码如下,从env_dev串口数据,读到数据之后,通过dtu_dev发送出去。之前这样写是没问题的,采用DMA发送方式,dtu_buf是全局变量
究竟是贴图这样写有问题,还是使用DMA方式发送有问题?看完整个帖子,有点没搞明白,究竟哪样是有问题的,然后出现的关键问题点是什么,有何影响?可能需要楼主补充描述下。
汗,把我的 serialX 系列文章通读一遍你就不会有这个疑问了。流设备,没给你保证必须连续完整,被拆包或者粘包都在预料之中。
拆包了需要你自己去做整合处理。
超时判断的方法
dtu_timeout_s.usec = 200000;
dtu_timeout_s.sec = 0;
if (DTU_flag == 1)
{
//关闭平时通信时的定时器
rt_device_control(hw_dev, HWTIMER_CTRL_STOP, RT_NULL);
rt_event_send(&feed_dog_event, EVENT_FLAG3);
if (dtu_timeout == 1 && old_dtu_recv_cnt != 0 && cnt2 == 0)
{
//透传时,关闭dtu使用的定时器
rt_device_control(hw_dtu_timer, HWTIMER_CTRL_STOP, RT_NULL);
dtu_timeout = 0;
rt_uint16_t len = (rt_uint16_t)rt_strlen(dtu_buf);
// LOG_I("total bytes1 %d\n bytes2 %d",len,dtu_recv_cnt);
//串口6用作控制台的话,就不向外输出了
#ifndef UART6_IS_FINSH
rt_device_write(dtu_dev, 0, dtu_buf, len);
rt_thread_mdelay(20);
// LOG_I("\n");
// for(rt_uint16_t i = 0; i < len; i++)
// {
// LOG_I("%2x", dtu_buf[i]);
// }
// LOG_I("\n");
// ulog_hex("dtu data", 16, dtu_buf, len);
// LOG_HEX("dtu data", 16, dtu_buf, len);
#endif
dtu_tmp_ptr = dtu_buf;
rt_memset(dtu_buf, 0, sizeof(dtu_buf));
dtu_recv_cnt = 0;
old_dtu_recv_cnt = 0;
}
else
{
// rt_device_control(hw_dev, HWTIMER_CTRL_STOP, RT_NULL);
while( cnt2 = rt_device_read(env_dev, -1, dtu_tmp_ptr, 4096) )
{
// rt_base_t level;
// level = rt_hw_interrupt_disable();
rt_device_write(hw_dtu_timer, 0, &dtu_timeout_s, sizeof(dtu_timeout_s)) ;
dtu_recv_cnt += cnt2;
dtu_tmp_ptr += cnt2;
old_dtu_recv_cnt = cnt2;
// LOG_I("recv %d bytes, total %d\n", cnt2,dtu_recv_cnt);
// #ifndef UART6_IS_FINSH
// rt_device_write(dtu_dev, 0, dtu_buf, cnt2);
// #endif
// rt_hw_interrupt_enable(level);
}
}
}
else
{
rt_event_send(&feed_dog_event, EVENT_FLAG3);
while (recv_cnt = rt_device_read(env_dev, -1, tmp_ptr, 4096) )
{
// LOG_I("recv_cnt = %d", recv_cnt);
rt_device_write(hw_dev, 0, &timeout_s, sizeof(timeout_s)) ;
cnt += recv_cnt;
tmp_ptr += recv_cnt;
old_recv_cnt = recv_cnt;
}
}
其实有个问题,看描述是发到了dtu设备?
dtu设备也是打包发送到服务器的,拆包/粘包情况理论上也是存在的🤪
为什么你设置的延时会出现发送一部分数据的问题,原因是延时的时间是固定的,数据短的时候可能能发送完整,数据大的时候就会只发送了一部分就被第2次的发送覆盖了。
解决方法有2种。
第一种:
在DMA的发送完成中断中发送一个信号量(或者设置1个发送完成标志),外部等待这个发送完成的信号量或者标志出现后(即上一次的数据DMA已经发送完成)再发送下一帧的数据。
第2种:还是采用你上面用的延时策略,但是要把固定的延时时间改成变动的延时时间,延时时间的大小和发送的数据长度成正比(另外和串口的波特率也有关系,波特率越快,单个字节数据发送的时间可以设置的短一点),比如说发送1个字节的数据延时1ms,那么先计算此次要发送的数据长度为N,则延时N*1ms。
贴图这样写有问题,贴图就是DMA发送的情况。
看到这个帖子 串口发送数据,接收方收到的数据分了几包 似乎跟你的问题有点类似?
@recan
他那个是接受,我这个是发送。我用定时器超时判断,有新的问题,我再试试
@recan](https://oss-club.rt-thread.org/uploads/20221206/da39a3ee5e6b4b0d3255bfef95601890afd80709.png
dma发送语句后加了延时,一整条数据只发一半,然后就转发下一条了
超时判断的代码