控制器与对靶装置通信协议

一、 控制示意图

控制器发送自定义的协议给对靶系统,对靶系统也返回对应的帧。
在这里插入图片描述

1.1 控制器—>对靶装置

这是控制器发送到对靶装置的协议格式:
在这里插入图片描述

1.2 对靶装置—>控制器

这是对靶装置发给控制器的协议格式:
在这里插入图片描述

二、命令格式具体参数意义

2.1登入命令

2.1.1 控制器作为客户端发送命令

在这里插入图片描述
完整的数据包(16进制):02734C442003
代码如下:

byte[] login ={ 0x02, 0x73, 0x4C, 0x44,0x20,0x03 };  //登录指令

clientStream.Write(loginlidar, 0, loginlidar.Length); //发送登录指令
if (clientStream.CanRead)
{
byte[] loginanswer = new byte[1024]; //开辟缓存区
StringBuilder myCompleteMessage = new StringBuilder(); //接收结果变量
int numberOfBytesRead = 0;
do
{
numberofBytesRead = clientStream.Read(loginanswer, 0, loginanswer.Length);
//读出 TCPIP 通信接收缓存区
myCompleteMessage.AppendFormat("{0}",Encoding.ASCII.GetString(myReadBuffer, 0,
numberOfBytesRead));
//将网口读到的所有信息堆栈写入接收结果变量
}
while (clientStream.DataAvailable); //若数据没到达则循环接收
//可以继续操作 myCompleteMessage 中的接受信息以确定进一步操作, 下面继续简单提取了关键指令信息, 其中可能包含了 ETX, STX, 您需要进一步精细的进行处理
string result = myCompleteMessage.ToString();
string[] split = result.Split(new char[] { ' ' });//用空格将接收字符串分割成 N 个字符串数组 。
loginresult.Text = split[3];//第 3 部分为设备登录结果信息+ETX , 首字节为登录结果信息

2.1.2 对靶装置接收到登入命令的返回值

在这里插入图片描述
完整的数据包(16进制,失败):02734C44203131602003
控制器的代码:

#define PIN 2
volatile long count =0;
volatile int flag = 0;
volatile int mode_flag =0 ;
volatile long maxnum;
byte comdata[8]={0};
char numdata[8]={0,0,0,0};
 
#define A0_Command 0x10  #可用模式选择
#define A1_Command 0x11
#define A2_Command 0x20
#define A3_Command 0x21
 
void receive_data(void);
void test_do_data(void);
 
void setup() {
  Serial.begin(9600);
  Serial3.begin(9600);
  pinMode(PIN,INPUT);
  pinMode(13,OUTPUT);
  pinMode(8,OUTPUT);
  attachInterrupt(0,blinkA,FALLING);
}
 
void loop() {
 
  if(Serial3.available()>0)
  {
      receive_data();
      test_do_data();
    }
 
  delay(100); //自己发出脉冲信号测试
  digitalWrite(8,HIGH);
  digitalWrite(8,LOW); 
}
 
void receive_data() #数据接收
{
    int i;
    for(i=0;i<8;i++)
    {
        comdata[i]= Serial3.read();
        delay(2);
      }
    for(i=0;i<4;i++)
    {
        numdata[i]= char(Serial3.read());
        delay(2);
      }
  }
 
void test_do_data(void)
{
    int x;
    if(comdata[0] == 0x02)  // 帧头
    {   
      Serial.println("head is ok");
      
        if (comdata[1]==0x73 && comdata[2]==0x4c && comdata[3]==0x44) //下位机登入对靶系统
        { 
          Serial.println("LIGIN DEVICE");
          switch(comdata[5]){
            case 0x30:
            Serial.println("Ligin Successful");
            break;
            case 0x31:
            Serial.println("Ligin failed");
            break;
            }
        }
          for(x=0;x<8;x++)
          maxnum=(maxnum*10+long(numdata[x]-'0')); 
   }
 }
      
void blinkA()
{
  count++;
  if(count>=maxnum)
  {
      if(flag==0)
        digitalWrite(13,HIGH);
      else
        digitalWrite(13,LOW);
      flag=~flag;
      count=0;       
    }
}

由于对靶系统的接收和发送程序还没调试好,在此用Arduino的两个串口来测试控制器接收到返回值,对应操作。
通过串口发送hex数据给控制器mage2560,执行结果:
在这里插入图片描述

2.2 设备同步指令

2.2.1 控制器作为客户端发送命令

在这里插入图片描述
代码如下:

byte[] login ={ 0x02, 0x73, 0x54, 0x4D,0x20,0x03 };  //调整指令

clientStream.Write(loginlidar, 0, loginlidar.Length); //发送调整指令
if (clientStream.CanRead)
{
byte[] loginanswer = new byte[1024]; //开辟缓存区
StringBuilder myCompleteMessage = new StringBuilder(); //接收结果变量
int numberOfBytesRead = 0;
do
{
numberofBytesRead = clientStream.Read(loginanswer, 0, loginanswer.Length);
//读出 TCPIP 通信接收缓存区
myCompleteMessage.AppendFormat("{0}",Encoding.ASCII.GetString(myReadBuffer, 0,
numberOfBytesRead));
//将网口读到的所有信息堆栈写入接收结果变量
}
while (clientStream.DataAvailable); //若数据没到达则循环接收
//可以继续操作 myCompleteMessage 中的接受信息以确定进一步操作, 下面继续简单提取了关键指令信息, 其中可能包含了 ETX, STX, 您需要进一步精细的进行处理
string result = myCompleteMessage.ToString();
string[] split = result.Split(new char[] { ' ' });//用空格将接收字符串分割成 N 个字符串数组 。
loginresult.Text = split[3];//第 3 部分为设备登录结果信息+ETX , 首字节为登录结果信息

2.2.2 对靶装置接收到模式设置命令的返回值

在这里插入图片描述
完整数据包(16进制,进入调试模式):0273544D3030203030502003
控制解析返回值代码如下:

#define PIN 2
volatile long count =0;
volatile int flag = 0;
volatile int mode_flag =0 ;
volatile long maxnum;
byte comdata[8]={0};
char numdata[8]={0,0,0,0};
 
#define A0_Command 0x10  #可用模式选择
#define A1_Command 0x11
#define A2_Command 0x20
#define A3_Command 0x21
 
void receive_data(void);
void test_do_data(void);
 
void setup() {
  Serial.begin(9600);
  Serial3.begin(9600);
  pinMode(PIN,INPUT);
  pinMode(13,OUTPUT);
  pinMode(8,OUTPUT);
  attachInterrupt(0,blinkA,FALLING);
}
 
void loop() {
 
  if(Serial3.available()>0)
  {
      receive_data();
      test_do_data();
    }
 
  delay(100); //自己发出脉冲信号测试
  digitalWrite(8,HIGH);
  digitalWrite(8,LOW); 
}
 
void receive_data() #数据接收
{
    int i;
    for(i=0;i<8;i++)
    {
        comdata[i]= Serial3.read();
        delay(2);
      }
    for(i=0;i<4;i++)
    {
        numdata[i]= char(Serial3.read());
        delay(2);
      }
  }
 
void test_do_data(void)
{
    int x;
    if(comdata[0] == 0x02)  // 帧头
    {   
      Serial.println("head is ok");
      
        if(comdata[1]==0x73 && comdata[2]==0x54 && comdata[3]==0x4D){ //模式设置
          Serial.println("Setting mode");
          switch(comdata[5]){
            case 0x31:
            Serial.println("Mode one");
            break;
            case 0x32:
            Serial.println("Mode two");
            break;
            }
        }
          for(x=0;x<8;x++)
          maxnum=(maxnum*10+long(numdata[x]-'0')); 
   }
 }
      
void blinkA()
{
  count++;
  if(count>=maxnum)
  {
      if(flag==0)
        digitalWrite(13,HIGH);
      else
        digitalWrite(13,LOW);
      flag=~flag;
      count=0;       
    }
}

执行结果:
在这里插入图片描述

2.3设备索引指令

2.3.1 控制器发送指令到对靶系统

在这里插入图片描述
代码基本同上。

2.3.2 控制器得到返回值解析

在这里插入图片描述
代码如下:

#define PIN 2
volatile long count =0;
volatile int flag = 0;
volatile int mode_flag =0 ;
volatile long maxnum;
byte comdata[6]={0};
char numdata[4]={0,0,0,0};
 
#define A0_Command 0x10
#define A1_Command 0x11
#define A2_Command 0x20
#define A3_Command 0x21
 
void receive_data(void);
void test_do_data(void);
 
void setup() {
  Serial.begin(9600);
  Serial3.begin(9600);
  pinMode(PIN,INPUT);
  pinMode(13,OUTPUT);
  pinMode(8,OUTPUT);
  attachInterrupt(0,blinkA,FALLING);
}
 
void loop() {
 
  if(Serial3.available()>0)
  {
      receive_data();
      test_do_data();
    }
 
  delay(100); //自己发出脉冲信号测试
  digitalWrite(8,HIGH);
  digitalWrite(8,LOW); 
}
 
void receive_data()
{
    int i;
    for(i=0;i<6;i++)
    {
        comdata[i]= Serial3.read();
        delay(2);
      }
    for(i=0;i<4;i++)
    {
        numdata[i]= char(Serial3.read());
        delay(2);
      }
  }
 
void test_do_data(void)
{
    int x;
    if(comdata[0] == 0x02)  // 头
    {   
      Serial.println("head is ok");
      
        if (comdata[1]==0x73 && comdata[2]==0x4c && comdata[3]==0x44) //模式选择
        { 
          Serial.println("LIGIN DEVICE");
          switch(comdata[5]){
            case 0x30:
            Serial.println("Login Successful");
            break;
            case 0x31:
            Serial.println("Login failed");
            break;
            }
        }
        
        if(comdata[1]==0x73 && comdata[2]==0x54 && comdata[3]==0x4D){
          Serial.println("Setting mode");
          switch(comdata[5]){
            case 0x30:
            Serial.println("Mode one");
            break;
            case 0x31:
            Serial.println("Mode two");
            break;
            }
          }
          
        if (comdata[1]==0x73 && comdata[2]==0x52 && comdata[3]==0x44) //设备索引
        { 
          Serial.println("Device index");
          if(numdata[1]==0x53 &&numdata[1]==0x43&& numdata[1]==x41&& numdata[1]==0x55)
          Serial.println("SCAU");
        } 
         
        if (comdata[1]==0x73 && comdata[2]==0x54 && comdata[3]==0x49) //对靶装置设定
        
          Serial.println("Device index");
        }          
                
          for(x=0;x<4;x++)
          maxnum=(maxnum*10+long(numdata[x]-'0'));
 
   }

      
void blinkA()
{
  count++;
  if(count>=maxnum)
  {
      if(flag==0)
        digitalWrite(13,HIGH);
      else
        digitalWrite(13,LOW);
      flag=~flag;
      count=0;       
    }
}

在这里插入图片描述

2.3 注销命令

2.3.1控制器登出对靶装置

在这里插入图片描述
完整数据包(16进制):02734C4F2003
代码如下:

byte[] logout ={ 0x02, 0x73, 0x4C, 0x4f,0x20,0x03 };  //调整指令

clientStream.Write(loginlidar, 0, loginlidar.Length); //发送调整指令
if (clientStream.CanRead)
{
byte[] loginanswer = new byte[1024]; //开辟缓存区
StringBuilder myCompleteMessage = new StringBuilder(); //接收结果变量
int numberOfBytesRead = 0;
do
{
numberofBytesRead = clientStream.Read(loginanswer, 0, loginanswer.Length);
//读出 TCPIP 通信接收缓存区
myCompleteMessage.AppendFormat("{0}",Encoding.ASCII.GetString(myReadBuffer, 0,
numberOfBytesRead));
//将网口读到的所有信息堆栈写入接收结果变量
}
while (clientStream.DataAvailable); //若数据没到达则循环接收
//可以继续操作 myCompleteMessage 中的接受信息以确定进一步操作, 下面继续简单提取了关键指令信息, 其中可能包含了 ETX, STX, 您需要进一步精细的进行处理
string result = myCompleteMessage.ToString();
string[] split = result.Split(new char[] { ' ' });//用空格将接收字符串分割成 N 个字符串数组 。
loginresult.Text = split[3];//第 3 部分为设备登录结果信息+ETX , 首字节为登录结果信息

2.3.2控制器对对靶装置返回值的处理

在这里插入图片描述
完整数据包(16进制):02734C4F203030502003
代码如下:

#define PIN 2
volatile long count =0;
volatile int flag = 0;
volatile int mode_flag =0 ;
volatile long maxnum;
byte comdata[6]={0};
char numdata[4]={0,0,0,0};
 
#define A0_Command 0x10
#define A1_Command 0x11
#define A2_Command 0x20
#define A3_Command 0x21
 
void receive_data(void);
void test_do_data(void);
 
void setup() {
  Serial.begin(9600);
  Serial3.begin(9600);
  pinMode(PIN,INPUT);
  pinMode(13,OUTPUT);
  pinMode(8,OUTPUT);
  attachInterrupt(0,blinkA,FALLING);
}
 
void loop() {
 
  if(Serial3.available()>0)
  {
      receive_data();
      test_do_data();
    }
 
  delay(100); //自己发出脉冲信号测试
  digitalWrite(8,HIGH);
  digitalWrite(8,LOW); 
}
 
void receive_data()
{
    int i;
    for(i=0;i<6;i++)
    {
        comdata[i]= Serial3.read();
        delay(2);
      }
    for(i=0;i<4;i++)
    {
        numdata[i]= char(Serial3.read());
        delay(2);
      }
  }
 
void test_do_data(void)
{
    int x;
    if(comdata[0] == 0x02)  // 头
    {   
      Serial.println("head is ok");
      
        if (comdata[1]==0x73 && comdata[2]==0x4c && comdata[3]==0x44) //登入解析
        { 
          Serial.println("LIGIN DEVICE");
          switch(comdata[5]){
            case 0x30:
            Serial.println("Login Successful");
            break;
            case 0x31:
            Serial.println("Login failed");
            break;
            }
        }
        
        if(comdata[1]==0x73 && comdata[2]==0x54 && comdata[3]==0x4D){ //模式选择
          Serial.println("Setting mode");
          switch(comdata[5]){
            case 0x30:
            Serial.println("Mode one");
            break;
            case 0x31:
            Serial.println("Mode two");
            break;
            }
          }
          
        if (comdata[1]==0x73 && comdata[2]==0x52 && comdata[3]==0x44) //设备索引
        { 
          Serial.println("Device index");
          if(numdata[1]==0x53 &&numdata[1]==0x43&& numdata[1]==0x41&& numdata[1]==0x55)
          Serial.println("SCAU");
        } 
         
        if (comdata[1]==0x73 && comdata[2]==0x4C && comdata[3]==0x4f) //对靶装置设定
          Serial.println("Logout");
          switch(comdata[5]){
            case 0x30:
            Serial.println("Logout successful");
            break;
            case 0x31:
            Serial.println("Logout failed");
            break;
            }          
        }          
                
          for(x=0;x<4;x++)
          maxnum=(maxnum*10+long(numdata[x]-'0'));
 }

      
void blinkA() //做执行操作
{
  count++;
  if(count>=maxnum)
  {
      if(flag==0)
        digitalWrite(13,HIGH);
      else
        digitalWrite(13,LOW);
      flag=~flag;
      count=0;       
    }
}

执行结果:
在这里插入图片描述

2.4 关闭对靶系统命令

2.4.1 控制器关闭对靶装置

协议的具体形式在这里插入图片描述
代码与上相似

2.4.2 控制器对返回值处理

在这里插入图片描述
代码与上相似。

2.5控制器对对靶装置设置参数

后续补充

2.6 控制请求数据(单次)

后续补充

2.7 控制器请求数据(多次)

后续补充

总结

在这个自定义的协议中,发送给对靶装置的指令数据包是固定长度6个长度,对靶装置的返数据包是不固定,有的没有包括数据包,有的包括数据字段,使其数据包要单独提出来分析。
有几个问题:
(1)在数据接收部分,校验部分代码没有实现,只是接收保存。
(2)在数据解析部分是对指令解析了,但是没有对数据段内容具体解析。
(3)不固定数据长度的怎么接收处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值