项目进度:
完成基本参数和运行模式页面的代码,可获取基本参数字典,还没有获取运行模式字典模块。
目录
问题1
问题描述
十进制数-10000,转十六进制是0xFFFFD8F0,再转十进制时,数据变成4294957296,再转十六进制没问题,还是0xFFFFD8F0。
原因分析
十进制与十六进制转换函数中,未明确负数转换机制。
python 是将输入的数分割成符号和数值两部分,那就是如电脑计算器算出来的一样:
不会判断符号位,就导致直接转换十六进制数的现象。
解决方案
使用 binascii 和 struct 包进行转换, 参考:http://t.csdn.cn/zvRHN
主要参考的是这块指导,但链接原文说的不太对:
2.十六进制还原为负数
先提取为十六进制的字符串,并逆置
neghex_s = hex(neghex)[2:-1] = 'ffff0520'
neghex_s=neghex_s[::-1] = '0250ffff'
使用binascii.unhexlify进行去十六进制化
neghex_pack=binascii.unhexlify(neghex_s)='\x02P\xff\xff'
再利用struct.unpack进行解析
neg=struct.unpack('i', neghex_pack)=(-45054,)
那么neg[0]就是neghex还原的负数
应该是把字符串 'ffff0520' 改为 '2005ffff',再按程序进行去十六进制化和解析,得到的才是我想要的负数。
更正后代码如下:
def value_translate(value, num):
if value[0:2] == '0x': # value是十六进制
if num == 'dec': # 十进制显示
value = value[2:]
if len(value) < 5: # 如果数据是0x1,则在前面补0,成为0x00000001
while len(value) < 8:
value = '0' + value
else:
pass
value = value[6:8] + value[4:6] + value[2:4] + value[0:2]
value_pack = binascii.unhexlify(value)
trans_value = struct.unpack('i', value_pack)
value = trans_value[0]
print('当前为十六进制,换算后重新显示', value)
......
问题2
问题描述
源地址表中有区分子地址的参数,查找通讯字典对应的地址不正确。举例:
参数:目标位置1,CAN地址:0x3547,子地址:0x01
参数:目标位置2,CAN地址:0x3547,子地址:0x02
查询Modbus通讯地址应为:目标位置1:0x69,目标位置2:0x6B
实际为:目标位置1:0xF0D6,目标位置2:0xF0D8
原因分析
查询通讯字典表时未加入对子地址的数据筛选。
实际是筛选子地址前,会先定位地址,然后应该是以定位地址得到的数据中再次筛选子地址,而当前是以原地址表所有数据筛选子地址了。
解决方案
# 查询Index对应的其他信息
def search(self, index, subindex):
search_dic = {}
i = self.mdic.loc[self.mdic['Od_Index'].isin([index])]
print('ModbusDict')
print(i)
# 判断找地址表,找到则返回字典,没找到则返回0
if i.size > 0:
if len(i) > 1: # 有子地址区分
print('len(i) > 1')
# 错误语句:i = self.mdic.loc[self.mdic['Od_Subindex_hex'].isin([subindex])]
# 更正:
i = i.loc[self.mdic['Od_Subindex_hex'].isin([subindex])]
print(i)
else:
pass
问题3
问题描述
Modbus通讯地址不需转换长度,CANOpen地址和子地址不需转换十进制。
原因分析
进制转换中没对通讯做区分。
解决方案
修改后代码:
if self.B_type.currentIndex() == 0: # Modbus通讯,地址由十进制变十六进制
trans_index = modbus_index(index, num)
print('地址显示:', trans_index)
self.para_index.setItem(1, column - 3, QtWidgets.QTableWidgetItem(trans_index))
else: # Modbus通讯地址不需转换长度,CANOpen地址和子地址不需转换十进制
pass
问题4
问题描述
多段参数表中的运行模式下拉框没有显示对应行列的索引地址。
原因分析
该部分还未完成。
解决方案
2022-6-23 已完成
问题5
问题描述
多段参数表中如有空白的参数,点击时程序退出,无法显示对应的地址。
原因分析
我获取当前点击的单元格用的是QTableWidget.currentItem(),而QTableWidget只有输入数值,才会产生item,因此空白单元格的currentItem()返回是None,而我显示是直接用的currentItem().text(),就会报错None没有text属性。
解决方案
更改为QTableWidget.currentIndex(),无论是否有输入数值,都可以用currentIndex().data()获取空白的内容或输入的数值。
问题6
问题描述
连续点击多段参数表中的参数,显示的地址表中最后一列的标题不对。
原因分析
从列0往列1,列2...删除,要注意每删除一次,原列表的非0索引值会自动递减 1,因此每次都少一删除一列。
# 复原地址表
if self.para_index.columnCount() > 3:
for j in range(0, self.para_index.columnCount() - 2): # 只保留3列
self.para_index.removeColumn(j)
else:
pass
解决方案
更改为从后面往前面删除:
# 复原地址表
if self.para_index.columnCount() > 3:
for j in range(self.para_index.columnCount() - 4, -1, -1): # 只保留3列
self.para_index.removeColumn(j)
else:
pass
问题7
问题描述
多段参数表的运行参数1和2的当前取值,需要转换速度单位。
原因分析
该部分还未完成。
解决方案
2022-6-23已完成
问题8
问题描述
由多段参数表查询地址后,切换回其他模式,地址表的列数显示不对。
原因分析
和问题6相同
解决方案
参考问题6
全部解决时间:2022-6-23