OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4892|回复: 7

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

[复制链接]

19

主题

334

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1108
金钱
1108
注册时间
2018-11-6
在线时间
240 小时
发表于 2019-12-30 15:05:47 | 显示全部楼层 |阅读模式
5金钱
我的设备的USART1和一个小模块进行通信,但是通信之前需要握手,过程如下:

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

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











最佳答案

查看完整内容[请看2#楼]

经过一段时间的学习,本人亲自在STM32F103VC的主板上测试通过,示意代码如下: 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; //是否收齐U ...
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

19

主题

334

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1108
金钱
1108
注册时间
2018-11-6
在线时间
240 小时
 楼主| 发表于 2019-12-30 15:05:48 | 显示全部楼层
经过一段时间的学习,本人亲自在STM32F103VC的主板上测试通过,示意代码如下:

     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的通信数据

            switch (step)
            {
                   case 0:
                       延时节拍100毫秒;
                       调用子程序,发送发送请求报文A;
                       限时等待串口中断释放的信号量;
                       解析报文
                        if (报文ok)
                            step = 1;

                       break;

                   case 1:
                        延时节拍100毫秒;

                         count++;
                         if (count > 3)   //自动重发超过3次,跳转到step=0
                        {
                             count =0;
                             step=0;
                         }
                         else
                         {
                              调用子程序,发送发送请求报文B;
                              限时等待串口中断释放的信号量;

                              
解析报文

                             if (报文ok)

                                 step = 2;



                         }
                       break;   
                  
                    case 2:           
                       延时节拍100毫秒;      

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

                          if (等到信号量)

                          {

                              解析报文

                              if (报文ok)

                                  time = 0;  //计时归零

                          }

                          else

                          {

                                 time++;

                                 if (time >= 60)

                                 {

                                       time = 0x00;

                                       step = 0;

                                 }

                          }



                       }

              }
回复

使用道具 举报

19

主题

334

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1108
金钱
1108
注册时间
2018-11-6
在线时间
240 小时
 楼主| 发表于 2019-12-30 15:21:34 | 显示全部楼层
我的规划如下,不知道对不对,请大家指教。

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

      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;
              }      
}
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2019-12-31 01:08:40 | 显示全部楼层
帮顶
回复

使用道具 举报

19

主题

334

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1108
金钱
1108
注册时间
2018-11-6
在线时间
240 小时
 楼主| 发表于 2020-1-3 13:50:40 | 显示全部楼层


  通信要求如下:

      步骤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



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


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

              }            


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

             等待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;
            }      
      }
}
回复

使用道具 举报

19

主题

334

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1108
金钱
1108
注册时间
2018-11-6
在线时间
240 小时
 楼主| 发表于 2020-1-3 14:11:47 | 显示全部楼层
还有一个问题:

   在步骤1、步骤2 时 也会先后收到USART2的通信数据和USART3的通信数据, 该怎么处理呀!

     我准备设计一个自定义消息协议

              msg[0]= 1  收到usart2的通信协议
              msg[0]= 2  收到usart3的通信协议
              msg[0]= 3  收到步骤1的应答报文
              msg[0]= 4  收到步骤2的应答报文
             msg[0]= 5  收到步骤3的应答报文

         如果在步骤1收到msg[0]= 1,msg[0]=2, msg[0]= 4, msg[0]= 5就不理睬,程序不处理。
         如果在步骤2收到msg[0]= 1,msg[0]=2, msg[0]= 4, msg[0]= 5就不理睬,程序不处理。
         如果在步骤3收到msg[0]= 1和msg[0]=2 程序才进行处理。
回复

使用道具 举报

19

主题

334

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1108
金钱
1108
注册时间
2018-11-6
在线时间
240 小时
 楼主| 发表于 2020-1-6 09:09:31 | 显示全部楼层
通信要求如下:

      步骤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;
            }      
      }
}
回复

使用道具 举报

19

主题

334

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1108
金钱
1108
注册时间
2018-11-6
在线时间
240 小时
 楼主| 发表于 2020-1-6 15:55:34 | 显示全部楼层
疑问:

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

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-22 21:55

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表