用C语言解释Modbus ASCII中的数据

时间:2016-02-15 06:48:25

标签: python c ascii modbus

我收到了MODBUS ASCII协议设备的回复。

我存储"数据"在C中回复数组的部分:

name=somefile
path=$(dirname "$name")
filename=$(basename "$name")
extension="${filename##*.}"
filename="${filename%.*}"
if [[ -e $path/$filename.$extension ]] ; then
    i=2
    while [[ -e $path/$filename-$i.$extension ]] ; do
        let i++
    done
    filename=$filename-$i
fi
target=$path/$filename.$extension

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];

如果我得到字符串的长度,我得到8(我认为是正确的)。

我相信每个角色都可以这样解释:

char(0x37)= 7

char(0x42)= B

char(0x33)= 3

依旧......

现在,我必须得到" 229.20"来自回复。

我所做的是手动将它们输入到变量并使用python中的命令进行计算。

像这样:

printf("this is the data reply: %s\n", test_reply)
"this is the data reply: 7B346543"

我相信你在C中这样做的方式就像我以前的帖子一样: Unpacking in C

我想问一下是否有办法在C

中做另一个

2 个答案:

答案 0 :(得分:1)

所以你需要的是一种将"7B"的2字节序列{ 0x37, 0x42 }转换为单字节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

答案 1 :(得分:0)

您正在从浮点数229,20的HEX表示的ModBus 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;
}