arduino自定义通信协议-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2970|回复: 1

arduino自定义通信协议

[复制链接]
发表于 2020-11-5 21:14 | 显示全部楼层 |阅读模式
本帖最后由 z01228 于 2021-1-12 01:46 编辑

     这个是我自己写的串口的自定义通信协议(字符串形式),目前就只对命令长度以及数据的取模校验来保证数据的稳定性。也算是对之前的帖子总结下。
  程序分编码发送和接收解码两个部分。具体的应用需要自己对程序进行修改


发送编码:
  1. /**自定义串口通信协议**
  2. 通信协议-写(txxy-tx)
  3.    示例程序使用背景:一个arduino开发板不能完成项目的任务时,就需要两个或者多个模块进行配合使用。
  4. 期间就需要通过串口(软,硬串口)传达参数,为了传达参数的准确性就需要我们设计通信协议。
  5.    这个示例是命令字符串编码 发送部分并且只有一个参数(因为取模校验的原因这个参数只能是整数型),
  6. 有需要更多参数可以自己添加。数据是明文发送没有加密
  7.   
  8.   命令格式“A数据值-L长度值-C校验值#”--
  9.   命令字符串comdata示例:A**L**C*#(A2111L11C5#)
  10.   长度是完整的命令字符串的长度(字符)
  11.   校验是校验数据的准确性,与check(本示例是9)取模的结果

  12. 试验结果:

  13. 完整字符串命令:A2111L11C5#
  14. 完整命令字符串长度 L:11
  15. 取模数 check:9  校验值 C:5

  16. */
  17. //数据部分
  18. String comdata = "";     //串口命令字符串
  19. String A="A";   //  数据开始位
  20. int id1=2111;     //数据1
  21. //数据核验部分
  22. String L="L";     //数据长度开始位
  23. int leng=0;     //数据长度
  24. String C="C";     //检验开始位置
  25. int check = 9;    //取模数
  26. int Ch=0;     //取模的结果
  27. String io="#";     //结束符3

  28. void setup() {
  29.   Serial.begin(9600);     //硬串口
  30.   Ch=id1%check;//计算数据的取模数
  31.   int leng=0;//数据长度置0
  32.   comdata += A;
  33.   comdata += id1;
  34.   comdata += L;
  35.   leng=comdata.length();//原始命令字符串的长度获取
  36.   leng=leng+3;  //提前补充个"L--校验位--#"的长度
  37.   
  38.   //下面的这个if函数是保证命令字符串在10位是正常的 不能删除  --命令字符串长度在99以内是有效的。
  39.   if(leng>=9){leng=leng+2;//如果原始数据没有加长度命令的时候是大于等于9,长度就只需要+2 多出来的是一个数据位一个长度位
  40.   } else{
  41.     leng=leng+1; //如果原始数据没有加长度命令的时候是小于9,长度就只需要+1
  42.   }
  43.   comdata += leng;
  44.   comdata += C;
  45.   comdata += Ch;//**在命令字符串里加入计算完毕的长度
  46.   comdata += io;//**在命令字符串里加入"#"
  47.   leng=comdata.length();
  48.   
  49.   Serial.print("完整字符串命令:");     //换行
  50.   Serial.println(comdata);     //打印完整命令字符串
  51.   
  52.   Serial.print("完整命令字符串长度 L:");     //换行
  53.   Serial.println(leng);     //打印完整命令字符串长度

  54.   Serial.print("取模数 check:");     //换行
  55.   Serial.print(check);     //打印完整命令字符串长度
  56.   Serial.print("  校验值 C:");     //换行
  57.   Serial.println(Ch);     //打印完整命令字符串长度
  58.   Serial.println("");     //换行
  59.   
  60.   
  61. }

  62. void loop() {
  63.   // put your main code here, to run repeatedly:

  64. }
复制代码

接收解码:
  1. /**自定义串口通信协议**
  2. 通信协议-读(txxy-rx)
  3.   示例程序使用背景:一个arduino开发板不能完成项目的任务时,就需要两个或者多个模块进行配合使用。
  4. 期间就需要通过串口(软,硬串口)传达参数,为了传达参数的准确性就需要我们设计通信协议。
  5.   这个示例是对字符串命令解码 接收部分目前只有一个参数(因为取模校验的原因这个参数只能是整数型),
  6. 有需要更多参数可以自己添加。
  7.   对接收命令的长度以及数据值对取模数(这里取9)的取模进行比较,判断数据的正确性。

  8. 命令字符串格式“A数据值-L长度值-C校验值#”
  9. 命令字符串示例:A**L**C*#(A2111L11C5#)
  10. 长度是完整的命令字符串的长度(字符)
  11. 校验是校验数据的准确性,与check(本示例是9)取模的结果

  12. 试验:
  13. 串口调试助手输入:A2111L11C5#(正确的) 与A211L11C5#(错误的)试验结果

  14. 完整命令:A2111L11C5#
  15. 命令正确--输出
  16. 数据:2111 长度:11 校验值:5
  17. 分析的长度:11 分析的校验值:5

  18. 完整命令:A211L11C5#
  19. 命令错误--不输出
  20. 数据:211 长度:11 校验值:5
  21. 分析的长度:10 分析的校验值:4

  22. */
  23. int a_sj = 0; //要接收的数据
  24. int l_cd = 0; //要接收的数据长度
  25. int c_xy = 0; //要接收的数据取模结果
  26. int check = 9;    //取模数
  27. String Str1 = "A2111L11C5#";//数据是2111 的命令字符串  A2111L11C5#
  28. void setup() {
  29.   Serial.begin(9600);     //硬串口

  30. }

  31. void loop() {
  32. while(Serial.read()>= 0){}//清除串口已经有的数据
  33. delay(1000);
  34. Serial.println(Str1); //发送命令
  35. delay(10);   
  36. sjfx();
  37. delay(1000);  
  38. }

  39. void sjfx() {
  40.   if (Serial.available() > 0) {
  41.     delay(12);
  42.     String comdata = "";//存放接收到的原始字符串
  43.     String buf1 = ""; //存放解析出的数据
  44.     String buf2 = ""; //存放解析出的长度
  45.     int leng = 0; //接收的命令长度(用于对有数据进行比较)
  46.     String buf3 = ""; //存放解析出的校验值
  47.     int cm = 0; //对数据结果取模的值(用于对有数据进行比较)

  48.     while (Serial.available() > 0)
  49.     {
  50.       comdata += char(Serial.read());
  51.       delay(2);//一个一个接收数据,每次停顿2毫秒
  52.     }
  53.     if (comdata.length() > 0)//如果有数据收到
  54.     {
  55.       leng = comdata.length();
  56.       int ja, jl, jc, io; //存放收到的字符串中标志字母的下标

  57.       for (int i = 0; i < comdata.length(); i++) {

  58.         if (comdata[i] == 'A') {
  59.           ja = i;
  60.         }
  61.         if (comdata[i] == 'L') {
  62.           jl = i;
  63.         }
  64.         if (comdata[i] == 'C') {
  65.           jc = i;
  66.         }
  67.         if (comdata[i] == '#') {
  68.           io = i;
  69.         }
  70.       }//找到约定标志字母的下标
  71.       for (int k = ja + 1; k < jl; k++) {
  72.         buf1 += char(comdata[k]);
  73.       }
  74.       for (int k = jl + 1; k < jc; k++) {
  75.         buf2 += char(comdata[k]);
  76.       }
  77.       for (int k = jc + 1; k < io; k++) {
  78.         buf3 += char(comdata[k]);
  79.       }//根据约定字母所在的位置依次解析出各个数据
  80.       
  81.       a_sj = buf1.toInt(); //将解析得到的字符串转换为int类型
  82.       l_cd = buf2.toInt();
  83.       c_xy = buf3.toInt();
  84.      leng=comdata.length()-2;//获取命令字符串长度--开发板对开发板时使用Serial.print(Str1);发送命令时不需要减,使用Serial.println(Str1);发送命令时需要减2(如同这个示例)//如果是使用串口助手发送命令就需要减1
  85.      cm=a_sj%check;

  86.    //打印结果
  87.    Serial.print("完整命令:");     //换行
  88.    Serial.print(comdata);     //打印完整命令字符串
  89. if(leng==l_cd && c_xy==cm){
  90.    Serial.println("命令正确--输出");     //换行
  91.    Serial.print("数据:");     //换行
  92.    Serial.print(a_sj);     //打印完整命令字符串
  93.    Serial.print(" 长度:");     //换行
  94.    Serial.print(l_cd);     //打印完整命令字符串
  95.    Serial.print(" 校验值:");     //换行
  96.    Serial.println(c_xy);     //打印完整命令字符串
  97.    
  98.    Serial.print("分析的长度:");     //换行
  99.    Serial.print(leng);     //打印完整命令字符串
  100.    Serial.print(" 分析的校验值:");     //换行
  101.    Serial.println(cm);     //打印完整命令字符串
  102.    Serial.println("");     //换行
  103.    }else{
  104.    Serial.println("命令错误--不输出");     //换行
  105.    Serial.print("数据:");     //换行
  106.    Serial.print(a_sj);     //打印完整命令字符串
  107.    Serial.print(" 长度:");     //换行
  108.    Serial.print(l_cd);     //打印完整命令字符串
  109.    Serial.print(" 校验值:");     //换行
  110.    Serial.println(c_xy);     //打印完整命令字符串
  111.    
  112.    Serial.print("分析的长度:");     //换行
  113.    Serial.print(leng);     //打印完整命令字符串
  114.    Serial.print(" 分析的校验值:");     //换行
  115.    Serial.println(cm);     //打印完整命令字符串
  116.    Serial.println("");     //换行
  117.    }
  118.       
  119.     }
  120.   }
  121. }
复制代码




发表于 2022-3-10 23:14 | 显示全部楼层
学习学习再学习,谢谢谢谢再谢谢!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-11-28 09:35 , Processed in 0.179217 second(s), 15 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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