單個遙測顯示命令6位(21)
D7 09 21 地址 04 XX XX XX XX CS
D7 D6 D5 D4 D3 D2 D1 D0 D7 D6 D5 D4 D3 D2 D1 D0
A,B表示符號 小數點位置 0~9表示顯示0~9
A:+ B:— C:“L”
地址爲遙測表的地址,每個遙測表最多可顯示6位數據。數據位向高位靠,不足補0。
CS表示異或校驗
例如:
1):D7 09 21 01 04 00 12 34 50 8C (顯示數據123450.)
2):D7 09 21 01 04 01 12 34 50 8D (顯示數據12345.0)
3):D7 09 21 01 04 02 12 34 50 8E (顯示數據1234.50)
4):D7 09 21 01 04 0312 34 50 8F (顯示數據123.450)
5):D7 09 21 01 04 04 12 34 50 88 (顯示數據12.3450)
6):D7 09 21 01 04 05 12 34 50 89 (顯示數據1.23450)
7):D7 09 21 01 04 06 12 34 50 8A (顯示數據0.12345)
以下是數據解析:
findDecimal()函數找到小數點在第幾位,比如例子中紅色標記了小數點的位置。找到的位置就是int decimal,要用到BCD編碼函數裏。
int FindDecimal(char *str,int nlen)
{
int len = 0, i;
for(i = 0; i < nlen; i ++)
{
if(str[i] != '.')
{
len ++;
}
else
{
break;
}
}
return nlen - len;
}
以下是BCD編碼
/*-------------------------------------------------------------------------------------------
函數名 : FloattoBCD
函數功能 : BCD編碼
返回類型 : void
函數參數 : int width : 目標寬度, int decimal: 目標小數位數(從0開始)
創建者 : 創建日期 : 2012.3.6
修改 :
-------------------------------------------------------------------------------------------*/
void CMAND2000::FloattoBCD(float value, int width, int &decimal)
{
memset(m_tempbuf,0,sizeof(m_tempbuf));
int i = 0;
int j = 0;
int k = 0;
int m = 0;
int n = 0;
int p = 0;
int q = 0;
int r = 0;
int s = 0;
//判斷傳參數是否有誤
if ((float)value >= pow(10.0, width-decimal))
{
memset(m_tempbuf, 0, width);
return;
}
//折半處理
for (i=0; i<(width-decimal)/2; i++)
{
p = (int)(value/pow(10.0, width-decimal-i*2-1));
q = (int)(value/pow(10.0, width-decimal-i*2-1)+0.5);
r = (int)(value/pow(10.0, width-decimal-i*2-2)+0.5);
s = (int)(value/pow(10.0, width-decimal-i*2-2));
//如果等於最後一個字節時,需要四捨五入處理,否則不處理
if (i == (width/2-1))
{
//當等於最後一個字節,並且有向大於1位目標小數位數進位時
if (q*10 == r)
{
//當向最高位進位時,反之是向次高位進位時,
if (r == 1000000)
{
m_tempbuf[i-2] = 0x10;
m_tempbuf[i-1] = 0;
m_tempbuf[i] = 0;
decimal--;
}
else
{
m_tempbuf[i-2] = q/10000%10*16 + r/10000%10;
m_tempbuf[i-1] = q/100%10*16 + r/100%10;
m_tempbuf[i] = q%10*16 + r%10;
}
}
else
{
m_tempbuf[i] = p%10*16 + r%10;
}
}
else
{
m_tempbuf[i] = p%10*16 + s%10;
}
}
for (i=(width-decimal)/2; i<width/2; i++)
{
j = (int)(value*pow(10, i*2+decimal-width+1));
k = (int)(value*pow(10, i*2+decimal-width+1)+0.5);
m = (int)(value*pow(10, i*2+decimal-width+2)+0.5);
n = (int)(value*pow(10, i*2+decimal-width+2));
//如果等於最後一個字節時,需要四捨五入處理,否則不處理
if (i == (width/2-1))
{
//當等於最後一個字節,並且有向大於1位目標小數位數進位時
if (k*10 == m)
{
//當向最高位進位時,反之是向次高位進位時,
if (m == 1000000)
{
m_tempbuf[i-2] = 0x10;
m_tempbuf[i-1] = 0;
m_tempbuf[i] = 0;
decimal--;
}
else
{
m_tempbuf[i-2] = k/10000%10*16 + m/10000%10;
m_tempbuf[i-1] = k/100%10*16 + m/100%10;
m_tempbuf[i] = k%10*16 + m%10;
}
}
else
{
m_tempbuf[i] = j%10*16 + m%10;
}
}
else
{
m_tempbuf[i] = j%10*16 + n%10;
}
}
}
BCD編碼是網上找的,但是在使用過程中發現有點小問題,已經進行了修改,增加了小數四捨五入得判定,
對應代碼用紅色表示,int i=int(float+0.5)表達式
小工程以外的提外問題:
BCD解碼
long int BCDToInt(char *buf, int len)
{
unsigned char reg = 0, reg2 = 0, ucTemp = 0;
long int tem = 0, i = 0,lValue =0;
for(i=0; i<len; i++)
{
reg = buf[i];
reg2 = reg>>4;
ucTemp = reg&0x0F;
lValue =reg2*10 +ucTemp;
tem = tem*100 + lValue ;
}
return tem;
}
以下是一段調試代碼
#include <STDIO.H>
#include <MATH.H>
#include <STRING.H>
//以下是我用過的函數,希望對你有些幫助
/*----------------------------------------------------------------------
* BCD編碼與解碼
* char* buff : 目標緩衝區
* float value : 值
* int width : 目標寬度
* int decimal: 目標小數位數
*--------------------------------------------------------------------*/
void PackBCD(char* buff, float value, int width, int decimal)
{
int i;
if ((float)value >= pow(10.0, width-decimal))
{
memset(buff, 0, width);
return;
}
for (i=0; i<(width-decimal)/2; i++)
{
buff[i] = (int)(value/pow(10.0, width-decimal-i*2-1)) % 10*16
+ (int)(value/pow(10.0, width-decimal-i*2-2)) % 10;
}
for (i=(width-decimal)/2; i<width/2; i++)
{
buff[i] = (int)(value*pow(10, i*2+decimal-width+1)) % 10 *16
+ (int)(value*pow(10, i*2+decimal-width+2)) % 10;
}
}
float UnPackBCD(char* buff, int width, int decimal)
{
float value = 0;
int i;
for (i=0; i<(width-decimal)/2; i++)
{
value+=(buff[i]/16 * pow(10, width-decimal-i*2-1)
+ buff[i]%16 * pow(10, width-decimal-i*2-2));
}
for (i=(width-decimal)/2; i<width/2; i++)
{
value+=(buff[i]/16 / pow(10, i*2+decimal-width+1)
+ buff[i]%16 / pow(10, i*2+decimal-width+2));
}
return value;
}
int FindDecimal(char *str)
{
int len = 0, i;
for(i = 0; i < strlen(str); i ++)
{
if(str[i]!='.')
{
len ++;
}
else
{
break;
}
}
return strlen(str) - len - 1;
}
int main()
{
unsigned tempbuf[1000];
char str[10];
float fValue=123.45;
memset(tempbuf,0,sizeof(tempbuf));
memset(str,0,sizeof(str));
sprintf(str,"%06f",fValue);
int num=FindDecimal(str);
PackBCD((char *)tempbuf,0.5,6,2);
return 0;
}
網上找的代碼其實有很多小問題的,