用 C 解释来自 Modbus ASCII 的数据
Interpret data from Modbus ASCII in C
我收到了来自 MODBUS ASCII 协议设备的回复。
我将回复的 "data" 部分存储到 C:
中的一个数组中
char test_reply[10];
char buffer[255]; //contains all the reply from modbus device following ascii protocol
//store the "data part" of the reply to test_reply to fix endianness
test_reply[0] = buffer[9];
test_reply[1] = buffer[10];
test_reply[2] = buffer[7];
test_reply[3] = buffer[8];
test_reply[4] = buffer[13];
test_reply[5] = buffer[14];
test_reply[6] = buffer[11];
test_reply[7] = buffer[12];
我打印了这个,我得到了:
printf("this is the data reply: %s\n", test_reply)
"this is the data reply: 7B346543"
如果我得到字符串的长度,我得到 8(我认为这是正确的)。
我相信每个字符都可以这样解释:
char(0x37) = 7
char(0x42) = B
字符(0x33) = 3
等等...
现在,我必须从回复中得到值“229.20”。
我所做的是手动将它们输入到变量中并使用 python 中的命令进行计算。
像这样:
>> x = chr(0x7B) + chr(0x34) + chr(0x65) +chr(0x43)
>> y = "".join(x)
>> z = struct.unpack("<f",y)
>> print z
(229.2050,)
我相信你在 C 中的做法与我之前的 post 一样:
想请问有没有办法用C做另外一个
您正在从 ModBus 接收浮点 229,20 的十六进制表示的 ASCII 值。您必须像下面的示例一样手动转换它们。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
uint8_t getDigit ( uint8_t digit)
{
uint8_t retVal = 0;
if ((digit >= '0') && (digit <= '9'))
{
retVal = digit - '0';
}
else if ((digit >= 'A') && (digit <= 'F'))
{
retVal = digit - 'A' + 10;
}
else if ((digit >= 'a') && (digit <= 'f'))
{
retVal = digit - 'a' + 10;
}
else
{
printf("Wrong char\n");
}
return retVal;
}
uint8_t ascii2bin (uint8_t hi, uint8_t lo)
{
uint8_t retVal = (getDigit(hi) << 4) | getDigit(lo);
return retVal;
}
int main()
{
char *ModBus_value = "33336543";
float yourFloatData;
char *special_ptr = (char *)(&yourFloatData);
int i;
int len = strlen(ModBus_value);
if ( len == (sizeof(float)*2) )
{
for (i=0; i<len; i+=2)
{
*special_ptr = ascii2bin(ModBus_value[i], ModBus_value[i+1]);
special_ptr++;
}
printf("yourFloatData_1: %f\n", yourFloatData );
}
else
{
printf("Wrong string\n");
}
return 0;
}
其他实现,getDigit 的较少读取应该是:
uint8_t getDigit ( uint8_t digit)
{
uint8_t retVal = 0;
if ((digit >= '0') && (digit <= '9'))
{
retVal = digit - '0';
}
else if ((digit >= 'A') && (digit <= 'F'))
{
retVal = digit - '7';
}
else if ((digit >= 'a') && (digit <= 'f'))
{
retVal = digit - 'W';
}
else
{
printf("Wrong char\n");
}
return retVal;
}
或者
uint8_t getDigit ( uint8_t digit)
{
uint8_t retVal = 0;
if ((digit >= '0') && (digit <= '9'))
{
retVal = digit - '0';
}
else if ((digit >= 'A') && (digit <= 'F'))
{
retVal = digit - 55;
}
else if ((digit >= 'a') && (digit <= 'f'))
{
retVal = digit - 87;
}
else
{
printf("Wrong char\n");
}
return retVal;
}
或者
uint8_t getDigit ( uint8_t digit)
{
uint8_t retVal = 0;
if ((digit >= '0') && (digit <= '9'))
{
retVal = digit - '0';
}
else if ((digit >= 'A') && (digit <= 'F'))
{
retVal = digit - 55;
}
else if ((digit >= 'a') && (digit <= 'f'))
{
retVal = digit - 87;
}
else
{
printf("Wrong char\n");
}
return retVal;
}
所以你需要的是一种将 { 0x37, 0x42 }
的 2 字节序列 "7B"
转换为单字节 0x7b
.
的方法
sscanf
和 x
格式是您所需要的。假设您知道 test_reply 中只有 8 个有用的字符,并且您已经处理了平台上的字节顺序并希望将它们存储在 32 位浮点数中,您可以这样做:
int i;
float z;
unsigned char *ix = (unsigned char *) &z; // you can always convert any address to a char *
for(i=0; i<4; i++) {
sscanf(test_reply + 2 * i, "%2hhx", &ix[i]); // 2 to process only 2 chars, hh to store only one byte
}
// control:
printf("%f\n", z); // should output 229.205002
我收到了来自 MODBUS ASCII 协议设备的回复。
我将回复的 "data" 部分存储到 C:
中的一个数组中char test_reply[10];
char buffer[255]; //contains all the reply from modbus device following ascii protocol
//store the "data part" of the reply to test_reply to fix endianness
test_reply[0] = buffer[9];
test_reply[1] = buffer[10];
test_reply[2] = buffer[7];
test_reply[3] = buffer[8];
test_reply[4] = buffer[13];
test_reply[5] = buffer[14];
test_reply[6] = buffer[11];
test_reply[7] = buffer[12];
我打印了这个,我得到了:
printf("this is the data reply: %s\n", test_reply)
"this is the data reply: 7B346543"
如果我得到字符串的长度,我得到 8(我认为这是正确的)。
我相信每个字符都可以这样解释:
char(0x37) = 7
char(0x42) = B
字符(0x33) = 3
等等...
现在,我必须从回复中得到值“229.20”。
我所做的是手动将它们输入到变量中并使用 python 中的命令进行计算。
像这样:
>> x = chr(0x7B) + chr(0x34) + chr(0x65) +chr(0x43)
>> y = "".join(x)
>> z = struct.unpack("<f",y)
>> print z
(229.2050,)
我相信你在 C 中的做法与我之前的 post 一样:
想请问有没有办法用C做另外一个
您正在从 ModBus 接收浮点 229,20 的十六进制表示的 ASCII 值。您必须像下面的示例一样手动转换它们。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
uint8_t getDigit ( uint8_t digit)
{
uint8_t retVal = 0;
if ((digit >= '0') && (digit <= '9'))
{
retVal = digit - '0';
}
else if ((digit >= 'A') && (digit <= 'F'))
{
retVal = digit - 'A' + 10;
}
else if ((digit >= 'a') && (digit <= 'f'))
{
retVal = digit - 'a' + 10;
}
else
{
printf("Wrong char\n");
}
return retVal;
}
uint8_t ascii2bin (uint8_t hi, uint8_t lo)
{
uint8_t retVal = (getDigit(hi) << 4) | getDigit(lo);
return retVal;
}
int main()
{
char *ModBus_value = "33336543";
float yourFloatData;
char *special_ptr = (char *)(&yourFloatData);
int i;
int len = strlen(ModBus_value);
if ( len == (sizeof(float)*2) )
{
for (i=0; i<len; i+=2)
{
*special_ptr = ascii2bin(ModBus_value[i], ModBus_value[i+1]);
special_ptr++;
}
printf("yourFloatData_1: %f\n", yourFloatData );
}
else
{
printf("Wrong string\n");
}
return 0;
}
其他实现,getDigit 的较少读取应该是:
uint8_t getDigit ( uint8_t digit)
{
uint8_t retVal = 0;
if ((digit >= '0') && (digit <= '9'))
{
retVal = digit - '0';
}
else if ((digit >= 'A') && (digit <= 'F'))
{
retVal = digit - '7';
}
else if ((digit >= 'a') && (digit <= 'f'))
{
retVal = digit - 'W';
}
else
{
printf("Wrong char\n");
}
return retVal;
}
或者
uint8_t getDigit ( uint8_t digit)
{
uint8_t retVal = 0;
if ((digit >= '0') && (digit <= '9'))
{
retVal = digit - '0';
}
else if ((digit >= 'A') && (digit <= 'F'))
{
retVal = digit - 55;
}
else if ((digit >= 'a') && (digit <= 'f'))
{
retVal = digit - 87;
}
else
{
printf("Wrong char\n");
}
return retVal;
}
或者
uint8_t getDigit ( uint8_t digit)
{
uint8_t retVal = 0;
if ((digit >= '0') && (digit <= '9'))
{
retVal = digit - '0';
}
else if ((digit >= 'A') && (digit <= 'F'))
{
retVal = digit - 55;
}
else if ((digit >= 'a') && (digit <= 'f'))
{
retVal = digit - 87;
}
else
{
printf("Wrong char\n");
}
return retVal;
}
所以你需要的是一种将 { 0x37, 0x42 }
的 2 字节序列 "7B"
转换为单字节 0x7b
.
sscanf
和 x
格式是您所需要的。假设您知道 test_reply 中只有 8 个有用的字符,并且您已经处理了平台上的字节顺序并希望将它们存储在 32 位浮点数中,您可以这样做:
int i;
float z;
unsigned char *ix = (unsigned char *) &z; // you can always convert any address to a char *
for(i=0; i<4; i++) {
sscanf(test_reply + 2 * i, "%2hhx", &ix[i]); // 2 to process only 2 chars, hh to store only one byte
}
// control:
printf("%f\n", z); // should output 229.205002