十进制与BCD码转换的算法
在工作中要对接一些下位机,返回的数据中有些是BCD码(Binary-Coded Decimal),用4位二进制数来表示1位十进制中的0~9这10个数码,是一种二进制的数字编码形式。以下是8421类型的BCD码,还有其它格式的BCD码,但是没怎么遇到过,暂时不表。
| 十进制 | 8421-BCD码 |
|---|---|
| (M10) | D C B A |
| 0 | 0 0 0 0 |
| 1 | 0 0 0 1 |
| 2 | 0 0 1 0 |
| 3 | 0 0 1 1 |
| 4 | 0 1 0 0 |
| 5 | 0 1 0 1 |
| 6 | 0 1 1 0 |
| 7 | 0 1 1 1 |
| 8 | 1 0 0 0 |
| 9 | 1 0 0 1 |
在下位机返回的数据中通常以{0x21, 0x69, 0x10, 0x00, 0x00, 0x02}这样的形式来表示字符串216910000002。所以需要将BCD码转成十进制数值然后再转成字符串。
Visual Studio C代码如下
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#pragma warning(disable:4996)
static uint8_t BCD2DEC(uint8_t bcd)
{
return (bcd - (bcd >> 4) * 6);
}
static uint8_t DEC2BCD(uint8_t dec)
{
return (dec + (dec / 10) * 6);
}
int main(void)
{
int tmp_int;
char tmp_str[3];
uint8_t raw_data[] = { 0x21, 0x69, 0x10, 0x01, 0x01, 0x02 };
int raw_len = sizeof(raw_data) / sizeof(uint8_t);
char * last_data = malloc(raw_len*2+1);
for (int i = 0; i < raw_len; i++)
{
tmp_int = BCD2DEC(raw_data[i]);
// 如果是0,直接写入"00"字符
if (tmp_int == 0)
{
strcpy(tmp_str, "00");
memcpy(last_data + (i * 2), tmp_str, 2);
}
// 如果小于10,则在前一位添加"0"字符
else if (tmp_int < 10)
{
sprintf(tmp_str, "%d", tmp_int);
memcpy(last_data + (i * 2), "0", 1);
memcpy(last_data + (i * 2)+1, tmp_str, 1);
}
else
{
sprintf(tmp_str, "%d", tmp_int);
memcpy(last_data + (i * 2), tmp_str, 2);
}
}
last_data[raw_len*2] = '\0';
printf("%s\n", last_data);
free(last_data);
/*char raw_data[] = "216910010102";
int raw_len = strlen(raw_data)/2;
uint8_t * last_data = malloc(raw_len);
char str[3];
unsigned int n;
for (int i = 0; i < raw_len; i++)
{
memcpy(&str, &raw_data[i*2], 2);
sscanf(str, "%x", &n);
memcpy(last_data + i, &n, 1);
printf("0x%02x,",last_data[i]);
}
free(last_data);*/
return 0;
}使用了上一篇文章中number <---> string相互转换的代码
参考资料:
评论已关闭