#include "Data_deal.h"

//note: 2021-2-23 新加入BCDtoHEX相互转的几个函数  ---- Daiyf。 
union Tmp
{
    float  value;									//浮点运算联合体
    unsigned char array[4];
};

union Tmp1
{
    signed short  value;							//S16运算联合体   -32768-32767
    unsigned char array[2];
};

union Tmp2
{
    signed long  value;							    //S32运算联合体   -2147483648--2147483647   存放18位AD值 -131072-131071
    unsigned char array[4];
};

union Tmp3
{
    unsigned long  value;							//U32运算联合体   存放18位AD值0x00000-0x3FFFF
    unsigned char array[4];
};


/*
// C prototype : void StrToHex(BYTE *pbDest, BYTE *pbSrc, int nLen)
// parameter(s): [OUT] pbDest - 输出缓冲区
//	[IN] pbSrc - 字符串
//	[IN] nLen - 16进制数的字节数(字符串的长度/2)
// return value: 
// remarks : 字符串转成16进制数
*/
void StrToHex(uint8_t *pbDest, uint8_t *pbSrc, int nLen)
{
	char h1,h2;
	uint8_t s1,s2;
	int i;

	for (i=0; i<nLen; i++)
	{
		h1 = pbSrc[2*i];
		h2 = pbSrc[2*i+1];

		s1 = toupper(h1) - 0x30;
		if (s1 > 9) 
		s1 -= 7;

		s2 = toupper(h2) - 0x30;
		if (s2 > 9) 
		s2 -= 7;

		pbDest[i] = s1*16 + s2;
	}
}

/*
// C prototype : void HexToStr(BYTE *pbDest, BYTE *pbSrc, int nLen)
// parameter(s): [OUT] pbDest - 存放在目标字符串中
//	[IN] pbSrc - 输入16进制的起始地址
//	[IN] nLen - 16进制的字节数
// return value: 
// remarks : 16进制转换成字符串
*/
void HexToStr(uint8_t *pbDest, uint8_t *pbSrc, int nLen)
{
	char	ddl,ddh;
	int i;

	for (i=0; i<nLen; i++)
	{
		ddh = 48 + pbSrc[i] / 16;
		ddl = 48 + pbSrc[i] % 16;
		if (ddh > 57) ddh = ddh + 7;
		if (ddl > 57) ddl = ddl + 7;
		pbDest[i*2] = ddh;
		pbDest[i*2+1] = ddl;
	}

	pbDest[nLen*2] = '\0';
}

/*******************************************************************************
* Function Name  : Switch_U32_To_AD7691BYTE4
* Description    : 将32位无符号整数转成4字节数组存储
* Input          : temp_U32_data--要转换的U32变量   data--转换后的4字节存储
* Output         : None
* Return         : None
*******************************************************************************/
void Switch_U32_To_BYTE4(unsigned long temp_U32_data, unsigned char*data)
{
    union Tmp3 U32Tmp;
    unsigned char i = 0;
    U32Tmp.value = temp_U32_data;
    for(i = 0; i < 4; i++)
    {
        data[i] = U32Tmp.array[i];		//将U32转换成四字节
    }
}

/*******************************************************************************
* Function Name  : Switch_BYTE4_To_U32
* Description    : 将U32的4字节数组转成32位无符号整数
* Input          : data--转换前四字节数组    temp_U32_data--要转换的U32变量
* Output         : None
* Return         : None
*******************************************************************************/
unsigned long Switch_BYTE4_To_U32(unsigned char*data)
{
    union Tmp3 U32Tmp;
    unsigned char i = 0;
    unsigned long temp_U32_data = 0;
    for(i = 0; i < 4; i++)
    {
        U32Tmp.array[i] = *(data + i);		//4字节数据暂存
    }
    temp_U32_data = U32Tmp.value; 	//4字节转换的U32有符号整数
    return(temp_U32_data);

}

/*******************************************************************************
* Function Name  : Switch_S32_to_ASCII
* Description    : 将32位有符号整数转成ASCII字符串显示
* Input          : S32
* Output         : ASCII字符串
* Return         : None
*******************************************************************************/

void Switch_S32_to_ASCII(signed long data, unsigned char*str)
{
    unsigned short i;       //u16
    signed long temp, tempoten; //s32
    unsigned char temp_length, temp_str[12] = {0};


    if(data < 0)
    {
        str[0] = '-';    //1.确定符号位
        data = -data;
    }
    else str[0] = '+';

    temp = data;

    i = 0;
    tempoten = temp / 10;
    while(tempoten != 0)			    //由低到高存储ASCII码
    {
        temp_str[i] = temp - 10 * tempoten + 48; //to ascii code
        temp = tempoten;
        tempoten = temp / 10;
        i++;
    }
    temp_str[i] = temp + 48;
    temp_length = i + 1;

    for(i = 0; i < temp_length; i++)
    {
        str[i + 1] =	temp_str[temp_length - 1 - i]; //由高到低存储ASCII码
    }

}


/*******************************************************************************
* Function Name  : S32_to_u8  
* Description    : 将32位数转换成8位数组
* Input          : data--要转变量   str--转换后的字节数组
* Output         : None
* Return         : None
*******************************************************************************/
void S32_to_u8(signed long data,unsigned char*str)
{
// int i;
	 str[0] = data>>24;
	 str[1] = data>>16;
	 str[2] = data>>8;
	 str[3] = data;
// for(i=3;i>0;i--)
// {
//    str[i]=(data>>(i*8))& 0xFF;
// }
}


/*******************************************************************************
* Function Name  : Switch_Float_To_ASCII  注：小数点有效数字3位
* Description    : 将浮点数转成ASCII字符串
* Input          : temp_float_data--要转换的float变量   str--转换后的字节数组
* Output         : None
* Return         : None
*******************************************************************************/
void Switch_Float_To_ASCII(float temp_float_data, unsigned char*str)
{
    unsigned short  i, j, k;
    signed long temp, tempoten;
    unsigned char intpart[20], data[20];

    if(temp_float_data < 0)
    {
        str[0] = '-';
        temp_float_data = -temp_float_data;
    }
    else str[0] = '+';


    temp = (signed long)temp_float_data;

    i = 0;
    tempoten = temp / 10;
    while(tempoten != 0)
    {
        intpart[i] = temp - 10 * tempoten + 48; //to ASCII code
        temp = tempoten;
        tempoten = temp / 10;
        i++;
    }
    intpart[i] = temp + 48;

    for(k = 1; k <= i + 1; k++) str[k] = intpart[i + 1 - k];


    for(j = 0; j < 20; j++)
    {
        data[j] = 0;
    }

    temp = (temp_float_data * 1000) - ((signed long)(temp_float_data)) * 1000; //取小数
    if(temp)
    {
        Switch_S32_to_ASCII(temp, data);
        str[i + 2] = '.';

        str[i + 3] = data[1]; //第1位肯定不为0

        if(data[2] != '0')
        {
            str[i + 4] = data[2]; //取2位
        }
        else
        {
            str[i + 4] = 0;
        }
        if(data[3] != '0')
        {
            str[i + 5] = data[3]; //取3位
        }
        else
        {
            str[i + 5] = 0;
        }
        str[i + 6] = 0;
    }
    else
    {
        str[i + 3] = 0;
    }

}

/*******************************************************************************
* Function Name  : Switch_S16_To_Byte2
* Description    : 将有符号整数转成2字节数组存储
* Input          : temp_S16_data--要转换的S16变量   data--转换后的2字节数组
* Output         : None
* Return         : None
*******************************************************************************/
void Switch_S16_To_Byte2(signed short temp_S16_data, unsigned char*data)
{
    union Tmp1 S16Tmp;
    unsigned char i = 0;
    S16Tmp.value = temp_S16_data;       //将S16转存
    for(i = 0; i < 2; i++)
    {
        data[i] = S16Tmp.array[i];		//将S16转换成2字节
    }
}

/*******************************************************************************
* Function Name  : Switch_Byte2_To_S16
* Description    : 2字节数组转成有符号整数
* Input          : data--转换前的2字节数组
* Output         : None
* Return         : 转换后的有符号整数
*******************************************************************************/
signed short Switch_Byte2_To_S16(unsigned char*data)
{
    union Tmp1 S16Tmp;
    unsigned char i = 0;
    signed short temp_S16_data = 0;
    for(i = 0; i < 2; i++)
    {
        S16Tmp.array[i] = data[i];		//2字节数据暂存
    }
    temp_S16_data = S16Tmp.value; 	    //2字节转换的S16有符号整数

    return(temp_S16_data);
}

/*******************************************************************************
* Function Name  : Switch_Byte4_To_Float
* Description    : 四字节数组转成浮点数
* Input          : data--转换前的四字节数组
* Output         : None
* Return         : 转换后的浮点数
*******************************************************************************/
float Switch_Byte4_To_Float(unsigned char*data)
{
    union Tmp floatTmp;
    unsigned char i = 0;
    float temp_float_data = 0;
    for(i = 0; i < 4; i++)
    {
        floatTmp.array[i] = data[i];		//四字节数据暂存
    }
    temp_float_data = floatTmp.value; 	//四字节转换的浮点数

    return(temp_float_data);
}



/*******************************************************************************
* Function Name  : Switch_Float_To_Byte4
* Description    : 将浮点数转成四字节数组存储
* Input          : temp_float_data--要转换的float变量   data--转换后的四字节数组
* Output         : None
* Return         : None
*******************************************************************************/
void Switch_Float_To_Byte4(float temp_float_data, unsigned char*data)
{
    union Tmp floatTmp;
    unsigned char i = 0;
    floatTmp.value = temp_float_data;   //将浮点数转存
    for(i = 0; i < 4; i++)
    {
        data[i] = floatTmp.array[i];		//将浮点数转换成四字节
    }
}


/******************************************************************************

//4字节数存放到数组中	数组起始地址存放高字节
//输入：uint16_t *buf数组起始地址, uint32_t data32存放数 
//返回：无
		
******************************************************************************/
void Data32ToBuf(uint16_t *buf, uint32_t data32)
{
	*buf++ = data32>>16;
	*buf   = data32;
}
/******************************************************************************

//2字节数组组成一个32位数	数组起始地址存放高字节
//输入：uint16_t *buf数组起始地址, int32_t data32存放数 
//返回：32位数
		
******************************************************************************/
int32_t BufToData32(uint16_t *buf)
{
	uint8_t i;
	int32_t temp=0;
	int32_t data32=0 ;
	for(i=0;i<2;i++)
	{
		temp = *buf++;
		data32 = (data32<<16) + (temp&0xffff);
	}
	return 	data32;
}


/*******************************************************************************
* Function Name  : Calc_LRC
* Description    : LRC校验
* Input          : data--要校验的数组  data_len--校验的长度
* Output         : None
* Return         : lrc 校验后的值
*******************************************************************************/
uint16_t Calc_LRC(uint8_t* data, int data_len)
{
	int i;
	uint16_t lrc = 0;
	for ( i = 0; i < data_len; i++)
	{
		lrc ^=  data[i];
	}
	return lrc;
}
/*******************************************************************************
* Function Name  : LRC_Check
* Description    : LRC校验
* Input          : data--要校验的数组 
* Output         : None
* Return         : result 校验后的值
*******************************************************************************/
uint16_t LRC_Check(uint8_t *data)
{
	uint8_t i;
	int k;
	uint16_t result;
	uint16_t lrcdata[12];

	for (i = 1;i < 12 + 1;i++)
	{
		if (data[i]>0x40)
			lrcdata[i - 1] = data[i] - 0x41 + 10;
		else
			lrcdata[i - 1] = data[i] - 0x30;
	}
	k = 0;
	for (i = 0;i<12 / 2;i++) 
	{
		k += (lrcdata[2 * i] * 16 + lrcdata[2 * i + 1]);
	}
	k = k % 256;
	k = 256 - k;
	result = k % 256;
	return result;
}

//单字节BCD转为HEX子程序
unsigned char BCDtoHEX(unsigned char bcd_data)  
{
    unsigned char temp; 
    temp=(bcd_data/16*10 + bcd_data%16); 
    return temp; 
} 

//单字节HEX转为BCD子程序
unsigned char HEXtoBCD(unsigned char hex_data)  
{ 
    unsigned char temp; 
    temp=(hex_data/10*16 + hex_data%10); 
    return temp; 
}
/********** BCD to HEX **********/
//双字节数值范围：0~9999
uint16_t BCD2HEX(uint16_t bcd)
{
  uint16_t temp;
  temp = (((bcd>>12) & 0x000f) * 1000)
       + (((bcd>>8) & 0x000f) * 100)
       + (((bcd>>4) & 0x000f) * 10)
       + (bcd& 0x000f);
  return temp;
}

/********** BCD to HEX **********/
//双字节数值范围：0~9999
uint16_t HEX2BCD(uint16_t hex)
{
      uint16_t bcd;
    bcd = ((HEXtoBCD((hex/100))) << 8);
    bcd += HEXtoBCD(hex%100);
    return bcd;
}




/*******************************************************************************
* Function Name  : MODBUS_ASCII_AsciiToFloat
* Description    : 将目标中的8个字节转化为一个浮点数
* Input          : pbDest--要转化的数组
* Output         : None
* Return         : float 转化后的值
*******************************************************************************/
float MODBUS_ASCII_AsciiToFlaot(uint8_t *pbDest)
{

	  union Tmp floatTmp;
	  unsigned char  data[8];
    unsigned char i = 0;
    float temp_float_data = 0;
    for(i = 0; i < 4; i++)
    {   
			  data[i] =  MODBUS_ASCII_AsciiToHex(pbDest+i*2);   //一个字节一个转
        floatTmp.array[3-i] = data[i];		//四字节数据暂存
    }
    temp_float_data = floatTmp.value; 	//四字节转换的浮点数

    return(temp_float_data);
}


/*******************************************************************************
* Function Name  : MODBUS_Float_to_ASCII
* Description    : float数据转换为8个字节的ASCII数据
* Input          : data32--要转换的数据
* Output         : pAsciiBuf  转换后的数组
* Return         : 
*******************************************************************************/
void MODBUS_Float_to_ASCII(float data32 ,uint8_t *pAsciiBuf )
{
	uint8_t i;
	union Tmp2 a32Tmp;
	union Tmp floatTmp;
	floatTmp.value = data32;
	
	for(i=0;i<4;i++)a32Tmp.array[i]=floatTmp.array[i];
	
	for(i=0;i<8;i++)
	{
	
		pAsciiBuf[i] = (a32Tmp.value>>(28-i*4))&0x0F;
		if(pAsciiBuf[i]<=0x09)
			pAsciiBuf[i] = pAsciiBuf[i]+0x30;
		else
		{
			pAsciiBuf[i]=toupper(pAsciiBuf[i])+55;
		}
		
	}
	
}
/*******************************************************************************
* Function Name  : MODBUS_ASCII_AsciiToHex
* Description    : 转化为16进制
* Input          : pbDest--要转化的数组
* Output         : None
* Return         : s1*16 + s2 转化后的值
*******************************************************************************/
uint8_t MODBUS_ASCII_AsciiToHex(uint8_t *pbDest)
{
	
	char h1,h2;
	uint8_t s1,s2;
	
		h1 = pbDest[0];
		h2 = pbDest[1];

		s1 = toupper(h1) - 0x30;
		if (s1 > 9) 
		s1 -= 7;

		s2 = toupper(h2) - 0x30;
		if (s2 > 9) 
		s2 -= 7;

		return (s1*16 + s2);
}

uint8_t MODBUS_GetLrc(uint8_t *pCyAsciiBuf, uint8_t cyLen)
{
	uint8_t i;
	uint8_t cyLrcVal;
	

	//cyLen /= 2;
	cyLrcVal = 0;
	for (i = 0; i < cyLen; i++)
	{
		cyLrcVal +=  *(pCyAsciiBuf + i);
	}
	
	cyLrcVal = ~cyLrcVal;
	cyLrcVal += 1;
	
	return (cyLrcVal);
}

/*******************************************************************************
* Function Name  : MODBUS_ASCII_GetLrc
* Description    : LRC校验
* Input          : pCyAsciiBuf--要校验的数组 cyLen--长度
* Output         : None
* Return         : cyLrcVal 校验后的值
*******************************************************************************/
uint8_t MODBUS_ASCII_GetLrc(uint8_t *pCyAsciiBuf, uint16_t cyLen)
{
	uint16_t i;
	uint8_t cyLrcVal;
	
	if (1 == (cyLen % 2) )
	{
		return 0;
	}
	
	cyLen /= 2;
	cyLrcVal = 0;
	for (i = 0; i < cyLen; i++)
	{
		cyLrcVal +=  MODBUS_ASCII_AsciiToHex(pCyAsciiBuf + i * 2);
	}
	
	cyLrcVal = ~cyLrcVal;
	cyLrcVal += 1;
	
	return (cyLrcVal);
}




/*******************************************************************************
* Function Name  : MODBUS_Hex_GetLrc
* Description    : LRC校验
* Input          : pCyAsciiBuf--要校验的数组 cyLen--长度
* Output         : None
* Return         : cyLrcVal 校验后的值
*******************************************************************************/
uint8_t MODBUS_Hex_GetLrc(uint8_t *pCyAsciiBuf, uint8_t cyLen)
{
	uint8_t i;
	uint8_t cyLrcVal;
	
//	if (1 == (cyLen % 2) )
//	{
//		return 0;
//	}
	
//	cyLen /= 2;
	cyLrcVal = 0;
	for (i = 0; i < cyLen; i++)
	{
		cyLrcVal +=  *(pCyAsciiBuf + i * 1);
	}
	
	cyLrcVal = ~cyLrcVal;
	cyLrcVal += 1;
	
	return (cyLrcVal);
}




/*******************************************************************************
* Function Name  : MODBUS_S32_to_ASCII
* Description    : 32位数据转换为单个8位数据
* Input          : data32--要转换的数据
* Output         : pAsciiBuf  转换后的数组
* Return         : 
*******************************************************************************/
void MODBUS_S32_to_ASCII(int32_t data32 ,uint8_t *pAsciiBuf )
{
	uint8_t i;
	for(i=0;i<8;i++)
	{
		pAsciiBuf[i] = (data32>>(28-i*4))&0x0F;
		if(pAsciiBuf[i]<=0x09)
			pAsciiBuf[i] = pAsciiBuf[i]+0x30;
		else
		{
			pAsciiBuf[i]=toupper(pAsciiBuf[i])+55;
		}
		
	}
	
}

/*******************************************************************************
* Function Name  : MODBUS_S16_to_ASCII
* Description    : 16为数据转换为ASCII数据
* Input          : data16--要转换的数据
* Output         : pAsciiBuf  转换后的数组
* Return         : 
*******************************************************************************/
void MODBUS_S16_to_ASCII(int16_t data16 ,uint8_t *pAsciiBuf )
{
	uint8_t i;
	for(i=0;i<4;i++)
	{
		pAsciiBuf[i] = (data16>>(12-i*4))&0x0F;
		if(pAsciiBuf[i]<=0x09)//if((pAsciiBuf[i]>=0x00)&&(pAsciiBuf[i]<=0x09))
			pAsciiBuf[i] = pAsciiBuf[i]+0x30;
		else
		{
			pAsciiBuf[i]=toupper(pAsciiBuf[i])+55;
		}
		
	}
}

/*******************************************************************************
* Function Name  : MODBUS_S8_to_ASCII
* Description    : 8为数据转换为ASCII数据
* Input          : data8--要转换的数据
* Output         : pAsciiBuf  转换后的数组
* Return         : 
*******************************************************************************/
void MODBUS_S8_to_ASCII(int8_t data8 ,uint8_t *pAsciiBuf )
{
	uint8_t i;
	for(i=0;i<2;i++)
	{
		pAsciiBuf[i] = (data8>>(4-i*4))&0x0F;
		if(pAsciiBuf[i]<=0x09)//if((pAsciiBuf[i]>=0x00)&&(pAsciiBuf[i]<=0x09))
			pAsciiBuf[i] = pAsciiBuf[i]+0x30;
		else
		{
			pAsciiBuf[i]=toupper(pAsciiBuf[i])+55;
		}
	}
}

////将一个8位数高低4位交换 
//static inline unsigned char bswap_8(unsigned char v)
//{	
//	return ((v & 0xff) << 4) | (v >> 4) ;   //将参数(v & 0xff) << 4 相当于放到高位， v >> 4 位相当于放在低位
//}                                               //以下两个代码分析雷同
////将一个16位数高低8位交换 
//static inline unsigned short bswap_16(unsigned short v)
//{
//	return ((v & 0xff) << 8) | (v >> 8);
//}
////将一个32位数高低16位交换 
//static inline unsigned int bswap_32(unsigned int v)
//{
//	return ((v & 0xff) << 24) | ((v & 0xff00) << 8) |
//		((v & 0xff0000) >> 8) | (v >> 24);
//}

/*******************************************************************************
* Function Name  : CRC16
* Description    : CRC16校验
* Input          : pBuf--要校验的数据  nLength--校验的长度
* Output         : ((wReturn & 0xff) << 8) | (wReturn >> 8)  校验后的数组
* Return         : 
*******************************************************************************/ 
uint16_t CRC16(unsigned char *pBuf,int nLength)  
{  
	uint16_t wReturn = 0xFFFF;
	int nDataLen=0;
	int nIndex=0;
	for(nDataLen=0;nDataLen<nLength;nDataLen++)
	{
		wReturn^=(unsigned short)(pBuf[nDataLen]);//(BYTE(pBuf[nDataLen]));
		for(nIndex=0;nIndex<8;nIndex++)
		{
			if(wReturn&0x0001)
			{
				wReturn>>=1;
				wReturn^=0xA001;
			}
			else
			{
				wReturn>>=1;
			}
		}
	}
		return	((wReturn & 0xff) << 8) | (wReturn >> 8);//高低互换
//	 return wReturn;
}



static uint16_t const wCRC16Table[256] = {      
    0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,     
    0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,     
    0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,      
    0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,     
    0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,       
    0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,     
    0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,     
    0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,     
    0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,     
    0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,        
    0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,     
    0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,     
    0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,     
    0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,     
    0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,        
    0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,     
    0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,     
    0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,     
    0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,     
    0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,        
    0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,     
    0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,     
    0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,     
    0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,     
    0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,       
    0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,     
    0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,     
    0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,     
    0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,     
    0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,       
    0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,     
    0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040};


uint16_t Key_CRC16(const unsigned char* pDataIn, const unsigned char iLenIn)     
{     
     uint16_t wResult = 0xFFFF;     
     uint16_t wTableNo = 0;     
     int i = 0;
    for( i = 0; i < iLenIn; i++)     
    {     
        wTableNo = ((wResult & 0xff) ^ (pDataIn[i] & 0xff));     
        wResult = ((wResult >> 8) & 0xff) ^ wCRC16Table[wTableNo];     
    }     
    return wResult;     
} 
// crcValue=CRC16(SendBuf,4);
//    SendBuf[4]=(unsigned char)crcValue;
//    SendBuf[5]=(unsigned char)(crcValue>>8);


void InvertUint8(unsigned char *dBuf, unsigned char *srcBuf)
{
    int i;
    unsigned char tmp[4];
    tmp[0] = 0;
    for(i = 0; i < 8; i++)
    {
        if(srcBuf[0] & (1 << i))
            tmp[0] |= 1 << (7 - i);
    }
    dBuf[0] = tmp[0];
}

void InvertUint16(unsigned short *dBuf, unsigned short *srcBuf)
{
    int i;
    unsigned short tmp[4];
    tmp[0] = 0;
    for (i = 0; i < 16; i++)
    {
        if(srcBuf[0] & (1 << i))
            tmp[0] |= 1 << (15 - i);
    }
    dBuf[0] = tmp[0];
}
unsigned short CRC16_MODBUS(unsigned char *puchMsg, unsigned int usDataLen)
{
    int i;
	  unsigned short temp;
	  unsigned short temp1;
    unsigned short wCRCin = 0xFFFF;
    unsigned short wCPoly = 0x8005;
    unsigned char wChar = 0;
    while(usDataLen--)
    {
        wChar = *(puchMsg++);
        InvertUint8(&wChar, &wChar);
        wCRCin ^= (wChar << 8);
        for(i = 0; i < 8; i++)
        {
            if(wCRCin & 0x8000)
                wCRCin = (wCRCin << 1)^wCPoly;
            else
                wCRCin = wCRCin << 1;
        }
    }
    InvertUint16(&wCRCin, &wCRCin);
		temp1=wCRCin>>8&0x00ff;
		temp=(temp1)+(wCRCin<<8);
    return(temp);
}
