吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1985|回复: 10
收起左侧

[C&C++ 原创] ModBus数据CRC计算小工具

[复制链接]
caoxiaolin 发表于 2023-12-30 08:40
Snipaste_2023-12-30_08-39-14.png

[C] 纯文本查看 复制代码
/*
	20231230
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <windows.h>

#define INPUT_BUF_SIZE   1024
#define OUTPUT_BUF_SIZE  (1024 + 1)

void input_data(char *input);
void deblank(char *str);
uint8_t string_to_hex(char *str, uint8_t *out, uint16_t output_buf_size, uint16_t *outlen);
uint16_t ModBusCRC16(uint8_t *data, uint16_t len);
uint8_t modbus_data_calc(char *input, uint8_t *output, uint16_t output_buf_size, uint16_t *outlen);
void output_data(uint8_t *output, uint16_t outlen);

int main(void)
{
	char input[INPUT_BUF_SIZE] = { 0 };
    uint8_t output[OUTPUT_BUF_SIZE] = { 0 };
    uint16_t outlen = 0;
	uint8_t ret;
	
	SetConsoleTitle("modbus_data_calc");
	
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
	printf("\t\t\t\tmodbus_data_calc\t\t\t\t\n");
	printf(":02 03 04 00 EA FD C9\n");
	printf("02 03 04 00 EA FD C9 68 01\n\n");
	
	while(1)
	{
		printf(":");
		
		input_data(input);
		ret = modbus_data_calc(input, output, sizeof(output)/sizeof(*output), &outlen);
		if(ret != 0)
		{
			printf("err:%X\n", ret);
			getchar();
			return ret;
		}
		
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 6);
		printf("data length:%u\n", outlen);
		output_data(output, outlen);
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
		
		printf("\n-----------------------\n\n");
	}
	
	return 0;
}

/*
	输入字符串
	input:输入buf指针
*/
void input_data(char *input)
{
	char ch;
	
	while ((ch = getchar()) != '\n')
	{
		*input = ch;
		++input;
	}
	*input = '\0';
}
/*
	输出数据
	output:数组指针
	outlen:数组大小
*/
void output_data(uint8_t *output, uint16_t outlen)
{
	uint16_t i;
	
	for (i = 0; i < outlen; ++i)
	{
		printf("%02X ", output[i]);
	}
}

/*
	modbus_data_calc
	input:输入字符串buf指针
	output:输出uin8_t类型数组buf指针
	output_buf_size:输出uin8_t类型数组buf大小
	outlen:最终结果数据长度
	
	返回: ok(0) err(!0)
*/
uint8_t modbus_data_calc(char *input, uint8_t *output, uint16_t output_buf_size, uint16_t *outlen)
{
    uint16_t crc16;
	uint16_t tmplen;
	uint8_t ret;
	
	if(input == NULL || output == NULL)
	{
		return 0xFF;
	}
	
	memset(output, 0, output_buf_size); //清空输出buf
	
	ret = string_to_hex(input, output, output_buf_size, &tmplen); //输入字符串转数字放入数组
	
	if(ret != 0)
	{
		return ret;
	}
	
	crc16 = ModBusCRC16(output, tmplen); //计算CRC16
	
	output[tmplen] = (uint8_t)crc16; //结果数组添加CRC16校验
	output[tmplen+1] = (uint8_t)(crc16 >> 8);
	
	(*outlen) = tmplen + 2; //加2字节的CRC校验
	
    return 0;
}

/*
    计算CRC16校验
	data:数据buf
	len:数据长度
	
	返回 CRC16校验结果
*/
uint16_t ModBusCRC16(uint8_t *data, uint16_t len)
{
    uint16_t i, j, tmp, CRC16;

    CRC16 = 0xFFFF; // CRC寄存器初始值
    for (i = 0; i < len; i++)
    {
        CRC16 ^= data[i];
        for (j = 0; j < 8; j++)
        {
            tmp = (uint16_t)(CRC16 & 0x0001);
            CRC16 >>= 1;
            if (tmp == 1)
            {
                CRC16 ^= 0xA001; // 异或多项式
            }
        }
    }
    return CRC16;
}

/*
    删除字符串中的空格
	str:字符串
	
	返回:去除所有空格后的字符串
*/
void deblank(char *str)
{
    int i, j = 0;
    for (i = 0; str[i] != '\0'; i++) // 循环条件也可以写为 i<strlen(str)
    {
        if (str[i] != ' ')     // 也可以写为:if(str[i]==' ')
            str[j++] = str[i]; //			continue;
    }                          //		str[j++]=str[i];
    str[j] = '\0';
}

/*
    字符串转16进制数据
	str:输入字符串
	out:输出字符串
	output_buf_size:输出buf大小
	outlen:输出有效长度
	
	返回: ok(0) err(!0)
*/
uint8_t string_to_hex(char *str, uint8_t *out, uint16_t output_buf_size, uint16_t *outlen)
{
    char *p = str;
    char high = 0, low = 0;
    uint16_t tmplen = strlen(p), cnt = 0;

    deblank(str); // 去除字符串中所有的空格

    tmplen = strlen(p);
	if(tmplen > output_buf_size) // 输入字符超过输出buf大小
	{
		return 0xFE;
	}
	
    while (cnt < (tmplen / 2))
    {
        high = ((*p > '9') && ((*p <= 'F') || (*p <= 'f'))) ? *p - 48 - 7 : *p - 48;
        low = (*(++p) > '9' && ((*p <= 'F') || (*p <= 'f'))) ? *(p)-48 - 7 : *(p)-48;
        out[cnt] = ((high & 0x0f) << 4 | (low & 0x0f));
        p++;
        cnt++;
    }
    if (tmplen % 2 != 0)
        out[cnt] = ((*p > '9') && ((*p <= 'F') || (*p <= 'f'))) ? *p - 48 - 7 : *p - 48;

    if (outlen != NULL)
        *outlen = tmplen / 2 + tmplen % 2;
	
    //return tmplen / 2 + tmplen % 2;
	return 0;
}

免费评分

参与人数 4吾爱币 +9 热心值 +3 收起 理由
BestLove52 + 1 我很赞同!
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
爱的太迟 + 1 + 1 谢谢@Thanks!
阿鹏大大 + 1 我很赞同!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

auguston 发表于 2023-12-30 08:55
挺实用的,感谢分享
阿鹏大大 发表于 2023-12-30 09:04
爱的太迟 发表于 2023-12-30 09:06
52soft 发表于 2023-12-30 09:19
这是什么技术?
CQGaxm 发表于 2023-12-30 09:23
感谢分享,单片机通信
ycb510725 发表于 2023-12-30 11:00
感谢分享、介绍很清楚 ,安装也快。
weekendstar 发表于 2023-12-30 11:54
感谢分享!!!
apull 发表于 2023-12-30 12:54
代码很清晰,学习了
Wangyuang 发表于 2023-12-30 18:11
感谢分享
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 18:29

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表