numconvert軟體上顯示的十六進位制是大端順序,即數值順序。
modbus協議規定是按大端傳輸(見英文版說明),但是確切的說,它只是借用“大端”這個術語以表示它是由左往右依次位元組傳輸的,因為畢竟大小端只有到了數值層面才有意義。
針對16位傳輸,只存在正序(AB)或反序(BA)兩種方式。
針對雙字32位資料傳輸,存在四種順序方式:
Big-endian :ABCD
Little-endian :DCBA
Big-endian byte swap :BADC
Little-endian byte swap :CDAB
ModbusSlave軟體,它傳輸的順序就是它顯示的十六進位制位元組順序,也即,對於一個暫存器中的數值來說,無論顯示還是傳輸,都是它的大端序。
ModbusSlave軟體,可以設定浮點數格式,如果設定為Little-endian byte swap,也就是先把四個位元組調換為小端DCBA,再把字內部位元組調換回大端,例如浮點數65.253,其數值即大端序為0x42828189,當在ModbusSlave上設定值為65.253後,切換為十六進位制會看到,其兩個暫存器先後是0x8189 0x4282。
ModbusSlave軟體,要把一個浮點數切換為十六進位制顯示,需要按住ctrl鍵,選中它所佔用的兩個暫存器。
使用libmodbus庫時,呼叫它的uint16_t相關接收函式時,它自動對每個字(注意,僅僅是字,即兩位元組,而不是四位元組)在記憶體層面進行了高低位元組轉換,此時資料在記憶體中每個字的兩個位元組跟傳送端順序是對調了的,那麼因此,字的數值順序看上去反而是跟傳送端順序一致的,這個過程可以表示為[以數值4為例,程式以小端序0x0400賦值-->程式會按大端序0x0004傳送-->libmodbus自動又轉回小端序0x0400],在ModbusSlave軟體上把一個暫存器賦值為4,看到十六進位制顯示的是0x0004,是因為它是直接按大端顯示的,實際上相當於“程式以小端序0x0400賦值”,總之一句話,用了libmodbus後,無需再執行ntohs啥的進行轉換,拿到的就是傳送程式的;由於位運算用的是數值順序而不是記憶體順序,因此在做位運算時直接以傳送端順序為參照做即可,這一點尤其注意。
在使用printf(%04x)列印字時,它是把整個字看作一個整體,按大端輸出的,即你看到的順序跟記憶體中的順序是反著的,這一點尤其在做位運算的時候注意迷惑性:
uint16_t d;
printf("[%04x]\n", d); // 輸出的是大端,即跟記憶體中順序相反
如果要按記憶體中的順序列印,則應當使用printf(%02x)逐個位元組列印:
printf("[%02x][%02x]\n", *((unsigned char *)(&d)), *((unsigned char *)(&d) + 1));
大小端轉換可以使用htons和ntohs,並且對於大小端轉換來說,它倆效果是一樣的,用哪個都行。
位運算用的是數值順序而不是記憶體順序,這一點尤其在做位運算的時候需要注意。
————————————————
版權宣告:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處連結和本宣告。
原文連結:https://blog.csdn.net/dyzhen/article/details/135980360