嵌入式软件工程师赶鸭子上架开发PC工具的故事之手撕hex通讯-连载(二)

目录

1 需求确定的重要性

2 提炼必须功能

3 继续干

3.1 校验和帧尾添加

3.2 组包并发送

3.3 串口接收调整

3.4 十六进制发送和接收测试


1 需求确定的重要性

书接上回,由于之前做过一个案子经过是这样的:

Step 1:

客户给我发来一个压缩包,里面十几个文件。

Step 2:

我辛辛苦苦看明白所有文档,这才搞清楚客户的需求到底是啥。

Step 3:

将需求整理为文档,发给客户(不是邮件只相当于口头沟通)。

Step 4:

客户口头回复就按照这个做一个版本。(由于客户当时前忙别的案子,没有一一对需求项)

Step 5:

按照需求一顿抡,并调试完成,交付给客户。

Step 6:
第二天,我以为客户可以打款了。结果客户重新给了一份明确的需求过来,看似和我们做的大差不差,但应用层几乎得重做一遍。我当时就直接爆粗了,然并卵,客户就是上帝,还得按照需求改。

被这样坑过一次后,后续做案子我都必须要求有明确的需求。明确的需求拿到之前可以提前动,但都是一些必须用到的功能可以先做,应用层次的东西则暂缓。

这次的案子也是这样,要得比较急,但是明确的应用功能需求没有明确。

2 提炼必须功能

上回说到这个案子是用串口控制设备,串口收发数据通道已经打通。

而具体内容,就需要通讯协议承载,而设备是现有的这个协议也不会变化。

3 继续干

设备通讯协议如上图所示,先来解决校验和帧尾字段。

3.1 校验和帧尾添加

实现一个简单的数据包封装功能,它计算输入缓冲区的校验和,并在缓冲区末尾添加校验和和结束标志。

代码如下:

type

           SendBuffer = array[1..200] of Byte;

function TForm1.PackCheckAndEnd(InputDa:SendBuffer;InputLen:Integer):SendBuffer;

var

  I:Integer;

  sum:Byte;

begin

  sum := 0;

  for I := 1 to InputLen do

  begin

    sum := sum + InputDa[I];

  end;

  sum := not sum;                     //取反操作

  sum := sum + 1;

  InputDa[InputLen+1] := sum;

  InputDa[InputLen+2] := $7d;       // $7d就是0x7d

  Result := InputDa;

end;

代码解释:

  1. 初始化变量: sum 初始化为 0,用于累加输入缓冲区中的所有字节值。
  2. 计算校验和:使用 for 循环遍历输入缓冲区 InputDa 的有效部分(从索引 1 到 InputLen)。在每次循环中,累加当前字节的值到 sum 中。

(3)取反并加 1

(4)添加校验和和结束标志:

将计算得到的校验和值 sum 写入到 InputDa 的 InputLen+1 位置。

在 InputDa 的 InputLen+2 位置添加一个结束标志 $7D。

(6)返回结果,函数返回修改后的 InputDa 缓冲区。

3.2 组包并发送

实现数据包的构建和发送功能,它首先初始化数据包,并在其中添加起始标志。接着调用 PackCheckAndEnd 函数计算校验和并添加结束标志,最后将数据包发送出去并通过 Memo2 显示发送的数据。

代码如下:

function TForm1.TestSendCmd(test:string):Boolean;

var

  Bytes: SendBuffer;

  MySendStr: string;

  DataLen:Integer;

  I:Integer;

  str:string;

begin

  Result := True;



  Bytes[1] := $7b;

  DataLen := 2;

  {添加组包代码}

  

  Bytes := PackCheckAndEnd(Bytes,DataLen);

  DataLen := DataLen + 2;



  for I := 1 to DataLen do

  begin

    str := str + IntToHex(Bytes[I] , 2) + ' ';

  end;

  Memo2.Lines.Add(chr($d) + chr($a) + '发送数据:' + str);



  // 发送数据

  SetLength(MySendStr,DataLen);

  Move(Bytes,Pchar(MySendStr)^,DataLen);

  Form1.Comm1.WriteCommData(PChar(MySendStr),DataLen);

end;

代码解释:

(1)初始化变量:

•  Result 初始化为 True,表示默认发送成功。

(2)初始化数据包:

•  Bytes[1] := $7B; 在 Bytes 数组的第一个位置添加起始标志 $7B。

•  DataLen := 2; 设置初始数据长度为 2(包括起始标志)。

(3)添加组包代码:

•  这里应该有添加数据到 Bytes 数组的代码,但示例中这部分被注释掉了。

•  你可以在这里添加自己的数据,例如 Bytes[2] := SomeValue;。

(4)计算校验和并添加结束标志:

•  调用 PackCheckAndEnd 函数计算校验和并添加结束标志 $7D。

•  DataLen := DataLen + 2; 更新数据包长度,增加校验和和结束标志所占的空间。

(5)构建十六进制字符串:

•  使用 for 循环遍历 Bytes 数组的有效部分,并使用 IntToHex 函数将每个字节转换为十六进制字符串。

•  将转换后的字符串拼接起来,并添加到 Memo2 控件中。

(6)发送数据:

•  使用 SetLength 函数设置 MySendStr 的长度为 DataLen。

•  使用 Move 函数将 Bytes 数组的内容复制到 MySendStr。

•  调用 Comm1.WriteCommData 方法发送数据。

3.3 串口接收调整

上回做的串口接收,是接收并打印字符串,由于协议是十六进制包,需要调整。

实现串口接收到数据时的处理功能,它首先判断是否处理接收到的数据,然后遍历接收到的数据缓冲区,将每个字节转换为十六进制字符串,并将结果显示在 Memo2 控件中。这样可以监控串口通信过程中的数据传输情况。

代码如下:

procedure TForm1.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;

  BufferLength: Word);

var

  str:string;

  I:  Word;

  ByteValue: Byte;

  P: PByte;

begin

  if s_com then

  begin

    application.ProcessMessages;

    str := '';

    P := PByte(Buffer);

    for I := 0 to BufferLength - 1 do

    begin

      ByteValue := P^;

      str := str + IntToHex(ByteValue , 2) + ' ';

      Inc(P);

    end;

    Memo2.Lines.Add(datetimetostr(now) + chr($0d) + chr($0a) + str);

  end;

end;

代码解释:

(1)处理消息:

•  application.ProcessMessages; 这行代码用于处理窗口的消息队列,确保 GUI 的响应性。

(2)初始化变量:

•  str := ''; 初始化字符串 str 为空字符串。

•  P := PByte(Buffer); 将 Buffer 指针转换为 PByte 指针,方便访问缓冲区中的字节。

(3)构建十六进制字符串:

•  使用 for 循环遍历缓冲区中的每个字节。

•  使用 P^ 获取当前指针位置的字节值,并存储在 ByteValue 变量中。

•  使用 IntToHex 函数将 ByteValue 转换为十六进制字符串,并拼接到 str 字符串中。

•  使用 Inc(P); 增加指针,使其指向下一个字节。

(4)显示接收到的数据:

•  使用 DateTimeToStr(Now) 获取当前时间,并将其与转换后的十六进制字符串一起添加到 Memo2 控件中。

3.4 十六进制发送和接收测试

现阶段由于还没有拿到设备,我将串口线的发送和接收直接短接,可初步测试数据发送和接收效果。效果如下图:

欲知后事如何,请看下回道来。

【创作不易,欢迎转载,转载请注明出处】

如果大家对相关文章感兴趣,可以关注公众号“嵌入式毛哥”,持续分享嵌入式干货,不限于疑难故障分析解决、算法共享、开发设计思想等,志在帮助更多人在嵌入式行业发光发热。

  • 18
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式毛哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值