vb字符串怎么存入byte数组?

程wasd 2018-11-14 07:43:22
新手请教:
命令格式:A1 01 05 D5 M1 M2 M3 X
1、频率值M1M2M3说明:M1M2M3 取值范围:40.0000-70.0000,两位小数。
2、示例: A1 01 05 D5 50 00 00 25; //设置频率为50Hz
A1 01 05 D5 60 00 00 35; //设置频率为60Hz
校验和X等于信息帧中各字节内容(不包括地址代码、信息长度值与校验和本身)按16进制数逐字节累加,丢弃进位值后所得到的单字节16进制数据。

现在问题是 我把命令定义成一个byte数组,假设输入40,根据协议转化后的对应命令字符串是 00 40 00 怎么赋值给我定义的数组呢,还有最后一位校验和怎么计算后怎么赋值给数组
Dim hz(8) As Byte ' 频率命令
hz(0) = &HA1
hz(1) = &H1
hz(2) = &H5
hz(3) = &HD5
...全文
217 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
舉杯邀明月 2018-11-17
  • 打赏
  • 举报
回复
当然,也不排除“电压”有4字节的可能:
  当设置一个“高压”时,共用到了4字节,约为100万伏了。
而“电压值有多少位”,按“数据长度”的值动态计算, 就是“长度 - 3”的字节数。
 这个“3”指的是 指令码(D8)、通道(相)、校验和占用的3个字节。
 按“计算结果”值,从相应的字节处开始,取出对应字节数的值就可以了。

不过: 这只是我的“猜测”。
实际是否是这样,我这儿是不可能验证的;而15楼的“协议”内容,也看不出“明确结果”。
脆皮大雪糕 2018-11-17
  • 打赏
  • 举报
回复
总觉得BCD码提供给LED啥的显示用的,咋想的放在和上位机的通讯协议里。
舉杯邀明月 2018-11-16
  • 打赏
  • 举报
回复
看你贴出来的“协议”内容,大概可以明白,它的那些“数值”是BCD格式的定点小数。
  并且估计“空间长度”都是3字节的,它的“D8”说明中的 M4部分,估计是编写的人失误。

电压、电流,应该是前2字节是“整数部分”(最多可以表示4位10进制数),第3字节是小数部分;
而“频率”很可能就是第1字节是“整数部分”、第2字节是小数部分;第3字节未用,恒为“00”。

舉杯邀明月 2018-11-16
  • 打赏
  • 举报
回复
其实它这个“协议”,举例的数据太过“特殊”了,并不具备代表性。
尤其无法准确反应出“小数”部分的数据如何表示的。
(TMD尽举些“小数部分为0”的数据,不是有病么!!!)

还有那个“电压”的设置,举的例子明显跟它的“协议说明”不相符嘛……
看下图:


再有一个: 它在说明校验和的计算时,特意提到“16进制相加”,纯粹就是放屁!
 这些“指定范围内的字节值”相加,用得着管什么进制么!

比如说数组a( )中,a(5) = &H50 ,   a(6) = &H70
难道 a(5) + a(6) ,只能说它等于 &HC0
不能说它是“80 + 112 = 192”吗!!!
难道16进制的和 &HC0 , 跟10进制的和 192 “不是同一个值”????

程wasd 2018-11-16
  • 打赏
  • 举报
回复
引用 14 楼 Chen8013 的回复:
任何计算机语言,都不存在“计算结果为XX进制”之说吧!
16进制、二进制,或者说“10进制”,并没有区别啊。
关键是“值是多少”!
计算机中的数值,都是二进制,为了“便于给人看”,才有10进制和16进制的。

比如你上面的“例子”中,多处写到的: hz(0) = &HA1
这个“&HA1”自然是“16进制值”,
但我写成: hz(0) = 161  难道它不是相同的效果吗!!!
你用“16进制”来表示,它是A1; 用10进制表示,它就是161; 二进制就是 10100001 了。
但它们都是“相同的值”,有必要去纠结“XX进制”吗?


反正你这儿说了半天,我至今仍然不能“十分肯定”你的那个“频率”的表示方法是否正确。


尤其是你在13楼,冒个“0.55a”(电流 0.55安 ?)表示为 00 05 55
说实在的,我只能说4个字: 莫明其妙 !


我把协议一部分发来您瞧瞧,有可能我理解的不是很对,我是按照协议比葫芦画瓢给写得代码,不过最终结果测试没问题,哈哈

附录:

1.采用异步串行通讯接口进行信息传递。串行数据以字节为基本单元,低位在前,高位在后,有一个起始位和一个停止位,无校验。波特率:9600。
2.通讯时信息以帧为单位传递。帧格式为:地址代码 + 信息长度值(L) + 信息 + 校验和(X).
地址代码:A1 01。
信息长度值:信息长度值L等于信息帧中除"地址代码"和"信息长度值"外所有内容(包括校验和)的字节数。L数值范围为00H-9FH。
校验和:校验和X等于信息帧中各字节内容(不包括地址代码、信息长度值与校验和本身)按16进制数逐字节累加,丢弃进位值后所得到的单字节16进制数据。
示例:发送的一帧数据为:A1 01 05 C0 02 01 01 C4,其中A1 01为地址代码;05为信息长度值,它包括长度字节后边的所有字节数;C0 02 01 01为信息数据;C4为校验和,它等于C0+02+01+01的值。
3.设置
设置电流幅度命令格式:A1 01 06 D9 CH M1 M2 M3 X
举例:
A1 01 06 D9 01 00 05 00 DF;// A相电流幅度设置为5.00A

电压幅值设置命令 D8
命令格式:A1 01 07 D8 CH M1 M2 M3 M4 X
举例:
A1 01 06 D8 01 02 20 00 FB;//A相电压幅度设置为220.00V

频率命令格式:A1 01 05 D5 M1 M2 M3 X
1、频率值M1M2M3说明:M1M2M3 取值范围:40.00-70.00,两位小数。
2、示例: A1 01 05 D5 50 00 00 25; //设置频率为50Hz


我就照着他写的协议比葫芦画瓢给他发送命令


舉杯邀明月 2018-11-16
  • 打赏
  • 举报
回复
任何计算机语言,都不存在“计算结果为XX进制”之说吧!
16进制、二进制,或者说“10进制”,并没有区别啊。
关键是“值是多少”!
计算机中的数值,都是二进制,为了“便于给人看”,才有10进制和16进制的。

比如你上面的“例子”中,多处写到的: hz(0) = &HA1
这个“&HA1”自然是“16进制值”,
但我写成: hz(0) = 161  难道它不是相同的效果吗!!!
你用“16进制”来表示,它是A1; 用10进制表示,它就是161; 二进制就是 10100001 了。
但它们都是“相同的值”,有必要去纠结“XX进制”吗?


反正你这儿说了半天,我至今仍然不能“十分肯定”你的那个“频率”的表示方法是否正确。


尤其是你在13楼,冒个“0.55a”(电流 0.55安 ?)表示为 00 05 55
说实在的,我只能说4个字: 莫明其妙 !
程wasd 2018-11-16
  • 打赏
  • 举报
回复
引用 12 楼 Chen8013 的回复:
你的 sum 声明为String类型,这个不正确嘛……
既然是保存“整数数值”的,就要用Long或者Integer类型啊。
这样后面就避免了一些不必要的“字符串 <---> 数值”之间的类型转换。

strhz = Format(nunhz, "0000")
这个没必要通过Format函数来转换。
你在前面已经检查“值是否合法”了。
对于合法值,在前面“乘以100”之后,必然是“4位数”的结果。
因此 strhz= numhz 就可以正确转换了。

hz(4) = Val("&H" & Left$(strhz, 2))
hz(5) = Val("&H" & Right$(strhz, 2))



感谢老哥解惑,你这么一说我豁然开朗,主要我不做这方面开发,所以很多地方都哪里报错或者运行结果不正确了,再去百度。

【你的 sum 声明为String类型,这个不正确嘛……
既然是保存“整数数值”的,就要用Long或者Integer类型啊。】
感谢,这个地方我理解的是计算结果应该是16进制数,但是百度说没有这种数据类型,我一直不知道应该定义成什么类型,这个地方我定义成了string类型是因为当时溢出这个问题,自己想不明白原因,也没百度出来结果,我就随便定义类型挨个测试的,还好不影响后面的运算结果。
【strhz = Format(nunhz, "0000")
这个没必要通过Format函数来转换。】
频率设置这个地方确实多余的。不过电流跟电压值用户可以设置成小数比如:0.55a 按照协议 对应的命令 00 05 55 所以我就对结果都格式化了一下。
【你的“频率值”不是二进制(或说“16进制”)表示的值,那也只能“绕路”转换一下了。】
这个没有理解错误,我一直想找能直接给传递过去的函数没找到,哈哈,老想着走捷径。如果是二进制的话是否用CopyMemory这个函数呢




另外:关于接受下位机数据,按字节接受有这方面的例子吗,我都是清空下接收缓冲区,给下位机发送读取的命令,然后把接收缓冲取的数据都接受到数组里面,对数据对错也不加判断,就对数据长度判断一下,虽然简单了,但是感觉很不科学。

MSComm1.InBufferCount = 0 '清除接收缓冲区
MSComm1.Output = dq '给下位机发送读取命令
YanShi (500) '延时
MSComm1.InputMode = comInputModeBinary '按2进制接收方式
jieshou = MSComm1.Input '接收数据到数组
upper = UBound(jieshou) '获取接收数组的上标
If upper > 125 Then '当缓存区有数据时
舉杯邀明月 2018-11-16
  • 打赏
  • 举报
回复
你的 sum 声明为String类型,这个不正确嘛……
既然是保存“整数数值”的,就要用Long或者Integer类型啊。
这样后面就避免了一些不必要的“字符串 <---> 数值”之间的类型转换。

strhz = Format(nunhz, "0000")
这个没必要通过Format函数来转换。
你在前面已经检查“值是否合法”了。
对于合法值,在前面“乘以100”之后,必然是“4位数”的结果。
因此 strhz= numhz 就可以正确转换了。

hz(4) = Val("&H" & Left$(strhz, 2))
hz(5) = Val("&H" & Right$(strhz, 2))
舉杯邀明月 2018-11-16
  • 打赏
  • 举报
回复
10输入错误1个字: 字条串处理函数用了 “Variant版”

更正一下:
  字符串处理函数用了 “Variant版”
舉杯邀明月 2018-11-16
  • 打赏
  • 举报
回复
1. 你的“频率值”不是二进制(或说“16进制”)表示的值,那也只能“绕路”转换一下了。
  如果你对“格式”没有理解错,用你目前的方式处理也可以的。
  毕竟就那么两个字节,只要不是“高频调用”的场景下,尽量用“简单”的方式处理就行了。
  以“数值运算”方式转换,也许运行效率会高点,但得多写好几行代码啊。
  并且,这么点儿数据,效率提升也非常有限,没什么必要。

  不过你的代码,有个我认为“不好”的地方是:
  变量没有“明确”类型、字条串处理函数用了 “Variant版”。


2. 几个字节直接相加会“溢出”的问题,这个确实太常见了。
  毕竟Byte类型的值域太小,你的“直接相加”,运算结果也会要求在“Byte类型”的值域内。
  只要“和值”超出,就产生溢出了。
  如果要“求和”的字节数比较多,象我在2楼回复中那样用循环、通过“较大类型”的中间变量求和就可以了。
  象你这个只有3字节相加的,就用你这个写法就行。
  要图省事,就写最左边的一个clng( ) 也可以。比如:
  sum = CLng(hz(3)) + hz(4) + hz(5)
程wasd 2018-11-16
  • 打赏
  • 举报
回复
引用 6 楼 Chen8013 的回复:
[quote=引用 5 楼 qq446804118 的回复:]
@舉杯邀明月 老哥请再帮我看看吧

你的“频率值”转换示例,纯粹是莫明其妙!
10进制/16进制混为一谈……


hz(6) = hz(3) And &HFF 跟hz(6) = hz(3)有本质区别吗!

…………
算了,想让别人帮你,自己就要把问题说清楚。
[/quote]


谢谢啦 总算搞定 你说的地方我确实写错了应该是 hz(6) = sum And &HFF 新手老是忙中出错,不过这个地方是笔误
Dim sum As String '校验位求和
Dim numZHI As Double '用户设置有效值

Dim hz(7) As Byte ' 频率命令
Dim numhz As Long '频率转化整数
Dim strhz As String '频率转换成字符串
numZHI = Val(Text16.Text)
If numZHI < 40 Or numZHI > 70 Then
X = MsgBox("超出范围!", 48, "警告!") '48标示显示警告图标
Else
nunhz = Round(numZHI, 2) * 100
strhz = Format(nunhz, "0000")
hz(0) = &HA1
hz(1) = &H1
hz(2) = &H4
hz(3) = &HD5
hz(4) = Val("&H" & Mid(strhz, 1, 2))
hz(5) = Val("&H" & Mid(strhz, 3, 2))
sum = (CLng(hz(3)) + CLng(hz(4)) + CLng(hz(5)))
hz(6) = sum And &HFF
Debug.Print Hex(hz(6))
MSComm1.OutBufferCount = 0 '清除发送缓冲区
MSComm1.Output = hz '设置频率



老哥帮忙看看有没有可以改进的地方,感谢。


中间主要另个点不懂:
1.比如用户设置为44.55 我怎么把他转化存进命令数组 hz(4)=44 hz(5)=55,
2.校验码为什么直接相加溢出呢 sum = hz(3) + hz(4) + hz(5) hz(6) = sum And &HFF ,

两个问题最用用比较笨的方法解决了,东西也交付客户了,
我是做web开发的,对vb的格式转化一窍不通,感谢老哥的指点,谢谢拉。

最后上个图:
舉杯邀明月 2018-11-15
  • 打赏
  • 举报
回复
你的那个“频率值”,是用的BCD编码来表示的吗?
舉杯邀明月 2018-11-15
  • 打赏
  • 举报
回复
引用 5 楼 qq446804118 的回复:
@舉杯邀明月 老哥请再帮我看看吧

你的“频率值”转换示例,纯粹是莫明其妙!
10进制/16进制混为一谈……


hz(6) = hz(3) And &HFF 跟hz(6) = hz(3)有本质区别吗!

…………
算了,想让别人帮你,自己就要把问题说清楚。
程wasd 2018-11-15
  • 打赏
  • 举报
回复
@舉杯邀明月 老哥请再帮我看看吧
程wasd 2018-11-15
  • 打赏
  • 举报
回复
dim hz(7) as byte
Numzhi = Val(Text16.Text)
nunhz = Round(Numzhi, 2) * 100
strhz = Format(nunhz, "0000")
hz(3) = &HD5
hz(4) = Val("&H" & Mid(strhz, 1, 2))
hz(5) = Val("&H" & Mid(strhz, 3, 2))
sum = &HD5 + hz(4) + hz(5)
hz(6) = hz(3) And &HFF


这是我写的代码,第一个问题算是解决了,但是感觉方法不是很科学,第二个sum计算提示溢出
程wasd 2018-11-15
  • 打赏
  • 举报
回复
昨天给的协议有点问题,我在描述下吧。

校验和:校验和X等于信息帧中各字节内容(不包括地址代码、信息长度值与校验和本身)按16进制数逐字节累加,丢弃进位值后所得到的单字节16进制数据。
示例:发送的一帧数据为:A1 01 05 C0 02 01 01 C4,其中A1 01为地址代码;05为信息长度值,它包括长度字节后边的所有字节数;C0 02 01 01为信息数据;C4为校验和,它等于C0+02+01+01的值。

频率设置命令格式:A1 01 04 D5 M1 M2 X
举例:
A1 01 04 D5 50 00 25; //设置频率为50.00Hz
A1 01 04 D5 60 00 35; //设置频率为60.00Hz
用户设置值是随机的。

我现在有两个问题:
1.比如设置为44.55 我怎么把他转化存进命令数组 hz(4)=44 hz(5)=55
2.校验码为什么直接相加溢出呢 sum = hz(3) + hz(4) + hz(5) hz(6) = sum And &HFF 这些我写的计算校验码的


本人vb新手啊,对数据类型之间的格式转化跟计算搞得不太清楚,用户又催的着急,感谢各位朋友不吝赐教
脆皮大雪糕 2018-11-15
  • 打赏
  • 举报
回复

Dim strTest As String
Dim aryData() As Byte
Dim lngDataSum As Long
Dim btyCheckSum As Byte
Dim i As Long
strTest = "This is a test string 这是一个测试字符串 12345"

aryData = StrConv(strTest, vbFromUnicode)
For i = LBound(aryData) To UBound(aryData)
lngDataSum = lngDataSum + aryData(i)
Next
btyCheckSum = lngDataSum And &HFF

Dim strOutput As String
strOutput = "数据信息:" & vbCrLf
strOutput = strOutput & "字符串包含字符:" & Len(strTest) & vbCrLf
strOutput = strOutput & "字符串字节数:" & UBound(aryData) + 1 & vbCrLf
strOutput = strOutput & "按字节累加和:" & lngDataSum & vbCrLf
strOutput = strOutput & "check sum:" & btyCheckSum & "(0x" & Hex(btyCheckSum) & ")" & vbCrLf
MsgBox strOutput


不管啥BCD码,还是HEX还是啥啥啥的,你只要整理出正确的字符串,上面代码给你算好。
舉杯邀明月 2018-11-14
  • 打赏
  • 举报
回复
感觉你的“格式”,说了半天根本就没说清。

你的“频率值”,究竟如何表示?
说是“整数”呢,你偏又说是“带两位小数”的,
  但也没看出你的“小数”如何表示、放在哪的……
说是“浮点数”呢,你“举例”的数据,明显是整数格式,还“莫明其妙”的……
  整数一般用2字节或4字节吧,你的竟用3字节?


先“照葫芦画瓢”猜一下吧……
你在“最后”说的那段“数据”,算下来数据长度是8字节吧?
定义8字节的数组,是: dim hz(7) as byte  不是(8) 。
要把“40 00 00”放进数组相应的位置:
dim w as long
w = &H40
hz(4) = 255 and w
hz(5) = 255 and (w \ 256)
hz(6) = 255 and (w \ &H10000)

计算“校验和”:

dim i as long
w = 0
for i = 3 to 7
w= w + hz(i)
next
hz(8) = 255 and w

程wasd 2018-11-14
  • 打赏
  • 举报
回复
上面写错了 根据协议转化后的对应命令字符串是 40 00 00怎么赋值给我定义的数组呢,还有最后一位校验和怎么计算后怎么赋值给数组

7,763

社区成员

发帖
与我相关
我的任务
社区描述
VB 基础类
社区管理员
  • VB基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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