FreeRTOS编程,类似TCP三次握手、超时检测以及自动重发机制的通信任务该如何设计

ba_wang_mao 2019-12-31 12:16:42
我的设备的USART1和一个小模块进行通信,但是通信之前需要握手,过程如下:

第一步: 我的设备先定时(定时200毫秒时间,时间不需要非常准确)给小模块发送握手请求报文A
设备正常收到小模块的应答报文后,跳转到第二步;否则重复发送请求报文A
第二步: 我的设备先定时(定时200毫秒时间,时间不需要非常准确)给小模块发送握手请求报文B
设备正常收到小模块的应答报文后,跳转到第三步;
否则重复发送请求报文B,如果自动重发次数超过3,则跳转到第一步,重新发送握手请求报文A。
第三步: 我的设备开始定时(定时500毫秒时间,时间不需要非常准确)给小模块发送请求报文C。
请求报文C中包含要发送的数据从USART2通信和USART3通信以及其它任务中读取。
如果长时间(假如1分钟,时间不需要非常准确)没有收到小模块的应答报文(心跳包报文),则跳转到第一步,重新发送握手请求报文A。

请问:我该如何设计和规划通信任务?

...全文
320 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
ba_wang_mao 2020-01-08
  • 打赏
  • 举报
回复
疑问:

1、在上线握手过程中,USART2和USART3的通信数据导致消息队列B满该怎么办呢?(注:USART2和USART3的通信数据本机无法控制)。
2、对系统有影响吗?
3、该如何消除?
4、是增加限制条件吗?(即:握手不成功时,USART2和USART3的通信任务不发送消息)
这种增加限制条件,即条件不满足时不发送消息队列数据,是否太牵强了!
ba_wang_mao 2020-01-06
  • 打赏
  • 举报
回复
通信要求如下:

步骤1:
发送请求报文A,然后等待应答报文;
(1)、如果收到应答报文,跳转到步骤2.
(2)、如果没有收到应答,定时重发发送请求报文A。
步骤2:
发送请求报文B,然后等待应答报文;
(1)、如果收到应答报文,跳转到步骤3.
(2)、如果超时未等到应答报文,重发发送请求报文B,如果连续3次超时,则跳转到步骤1。
步骤3:
(1)、等待接收USART2的通信数据。
(2)、等待接收USART3的通信数据。
(3)、IF (先后收到USART2的通信数据和USART3的通信数据)
{
发送请求报文C
}

(4)、等待应答报文。
(5)、如果连续1分钟没有收到应答报文,则跳转到步骤1



我的任务设计如下,是否可行,请指教!
如果有缺陷,请指出好的方法!


事先创建2个消息队列,以下简称消息队列A和消息队列B
消息队列A用来接收应答报文
消息队列B用来接收USART2和USART3的通信数据


void my_task(void)
{
static int step = 0; // 0=发送请求报文A,1=发送请求报文B,2=发送请求报文C
static int count = 0; //计数器,自动重发超过3次,跳转到step=0,转去发送请求报文A
static int time = 0; //计时,连续1分钟计时
static int OK=0; //是否收齐USART2和USART3的通信数据


//-------------------------定时发送USART1的请求报文部分
switch (step)
{
case 0:
调用子程序,发送发送请求报文A;
break;

case 1:
count++;
if (count > 3) //自动重发超过3次,跳转到step=0
{
count =0;
step=0;
}
else
{
调用子程序,发送发送请求报文B;
}
break;

case 2:

通过消息队列B,等待USART2的消息队列通信数据,如果收到OK|=0x01;
通过消息队列B,等待USART3的消息队列通信数据,如果收到OK|=0x02;
if (k==0x03) //收齐USART2和USART3的通信数据
{
OK=0;
调用子程序,发送发送请求报文C;
}

}



//-------------------------等待USART1的应答报文部分

通过消息队列A,等待usart1的消息队列(最大等待时间=500ms)
switch (step)
{
case 0:
if (消息队列收到消息)
{
解析报文
if (报文ok)
step = 1;
}
break;
case 1:
if (消息队列收到消息)
{
解析报文
if (报文ok)
{
count =0;//自动重发次数清零
step = 2;
}
else
{
count++: //自动重发次数+1
}
break;
case 2:
if (消息队列收到消息)
{
解析报文
time = 0x00;//连续1分钟计时单元清零
}
else
{
time++;//连续1分钟计时单元+1
if (time >= 20) //如果1分钟到时
{
OK=0;
count=0;
time=0;
}
}
break;
}
}
}
ba_wang_mao 2020-01-06
  • 打赏
  • 举报
回复
引用 2 楼 鲸鱼niko 的回复:
我的设计思路,设计3个线程,一个线程专发,一个线程专收,一个线程管超时重发。3个线程通过状态标志进行同步。发送一个报文后,将等待超时的标志置起来;收到回复,将等待超时标志消除,并且跳到下一状态机。


兄弟,单片机内部资源有限,你这样定义3个线程,太浪费资源啦!
ba_wang_mao 2019-12-31
  • 打赏
  • 举报
回复
我的规划如下,不知道对不对,请大家指教。

设计一个任务,定时发送和阻塞接收全部在一个任务中实现。

void my_task(void)
{
static int step = 0; // 0=发送请求报文A,1=发送请求报文B,2=发送请求报文C
static int count = 0; //计数器,自动重发超过3次,跳转到step=0,转去发送请求报文A
static int time = 0; //计时,连续1分钟计时


//-------------------------定时发送部分
switch (step)
{
case 0:
调用子程序,发送发送请求报文A;
break;

case 1:
count++;
if (count > 3) //自动重发超过3次,跳转到step=0
{
count =0;
step=0;
}
else
{
调用子程序,发送发送请求报文B;
}
break;

case 2:

等待USART2,USART3和其它任务通过消息队列发送的数据),最大等待时间=500毫秒
调用子程序,发送发送请求报文C;

}



//-------------------------等待USART1的消息队列部分


等待usart1的消息队列
switch (step)
{
case 0:
解析报文
if (报文ok)
step = 1;
break;
case 1:
解析报文
if (报文ok)
{
count =0;//自动重发次数清零
step = 2;
}
break;
case 2:
解析报文
break;
}
}
狗蛋王-yo 2019-12-31
  • 打赏
  • 举报
回复
我的设计思路,设计3个线程,一个线程专发,一个线程专收,一个线程管超时重发。3个线程通过状态标志进行同步。发送一个报文后,将等待超时的标志置起来;收到回复,将等待超时标志消除,并且跳到下一状态机。

27,375

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧