/** 功能: 实现根据发送的数据自动添加CRC校验码,接收数据直接连校验值一起送入CRC进行校验。
** 相关文件:
** 修改日志
**相关说明: 1。由于被校验证数据和它校验数值一起校验数值为0,
2。实现这样的校验必须保证发送方是每两个字节组装成一个字进行发送,如果要发送的数据为奇数个字节,那么被校验最后一个字节移动到最高8位,最低8位为0
3。接收方根据发送数据情况进行相应处理,组装成字,如果发送为奇数个数据,则在接收到校验数据前一个字节后将移动到高8位,低8位为0。
4。本程序接收和发送数据协议 包长 + 发送数据 + CRC校验 其中包长是发送字节总数 ,包括包长本身一个字节,还有发送数据字节数,CRC两个字节
*************************************************************/
#include"msp430x54x.h"
//*************************************************************
unsigned int CCITT(unsigned int temp);
// 整型数据位颠倒函数
unsigned int CCITT_Stting(unsigned char transt_flag ,unsigned char *temp,unsigned int len);
// CRC计算
//transt_flag 1 发送数据校验,计算校验值;0 接受数据校验
//temp 指向需要校验的数组起始地址
//len 需要校验字节数
unsigned char utxbuffer[] = {0x04,0x01,0x10,0x20,0x10,0x21,0x00,0x00,0x02,0x20} ;
//发送缓冲器
unsigned char urxbuffer[] = {0x04,0x01,0xDC,0xE5,0x10,0x21,0x00,0x00,0x02,0x20} ;
//接收缓冲器
unsigned int CRC_Value = 0;
//CRC数值
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; //关看狗
unsigned char *transt_buffer_point,*receive_buffer_point;
transt_buffer_point = utxbuffer;
receive_buffer_point = urxbuffer;
CRCINIRES = 0X0000;//初始化CRC
CRC_Value = CCITT_Stting(1,transt_buffer_point,transt_buffer_point[0] - 2);
//调用CRC计算函数
utxbuffer[ utxbuffer[0]-2] = (unsigned char)(CRC_Value >>8);
utxbuffer[ utxbuffer[0]-1] = (unsigned char)(CRC_Value);
//保存CRC数值添加到被校验数组后面
CRCINIRES = 0X0000;
//由于以前用过CRC,再使用需初始化
CRC_Value = CCITT_Stting(0,receive_buffer_point,receive_buffer_point[0] );
//接收校验函数
while(1);
}
/*************************************************
函数(模块)名称:unsigned int CCITT(unsigned int temp)
功能:位颠倒函数
本函数(模块)调用的函数(模块)清单:
调用本函数(模块)的函数(模块)清单:
输入参数: temp
输出参数: unsigned int 输出为输入位颠倒数值,例如 输入为0000000000000001 ,输出为100000000000000
函数返回值说明 :
使用的资源
其它说明: 1。由于F5XX单片机内部CRC模块是CRCDI输入的数据是从高位向低位移动,最低位首先进入校验寄存器最低位,在
校验寄存器中是从最低位向最高位移动,当校验寄存器中最高位移出为1 ,就和生成多项式进行异或。
2。通常标准的CRC-CCITT ,正向方式是,被校验数值从低向高位移动,最高位移出如果是1,那么校验寄存器就会与生成多项式子
异或,校验寄存器内部是从低向高位移动,当移出最高位为1就和生成多项式进行异或。
3。由于F5XX单片机并没有完成符合CCITT标准。被校验数值移动方向相反,比如要求0X0001的校验数值,需要CRCDI输入0X8000,才可以计算出
与欧洲标准一致的数值。 为了是输入方便并且与欧洲标准一致,因此我将输入的数据求颠倒, 比如要求0X0001的校验数值,那么就
直接调用CCITT(OXOOO1)就可以,求出与标准一致的CRC校验值。
*************************************************/
unsigned int CCITT(unsigned int temp)
{
unsigned int mm = 0;
unsigned int i = 0x00;
for( i = 0x8000;i!=0;i >>=1) //从最高开始判断
{
if(temp & i) //如果最高位为1
{
mm >>= 1; //右移1位
mm |= 0x8000; //将最高位置1
}
else //如果最高位为0
{
mm >>= 1 ; //右移动一位
}
}
return mm; //返回颠倒后最后数值
}
/*************************************************
函数(模块)名称:
unsigned int CCITT_Stting(unsigned char transt_flag ,unsigned char *temp,unsigned int len)
功能: CRC计算
本函数(模块)调用的函数(模块)清单:
调用本函数(模块)的函数(模块)清单:
输入参数: transt_flag 1,发送数据校验, 计算校验数值,添加到被校验数据后面;0,接收数据校验
temp 指向需要校验数组起始地址
len 需要校验字节数
输出参数: unsigned int CRC校验数值。当transt_flag 为1,产生包长+ 待发送数据 的CRC数值。当transt_flag 为0 ,
则返回接收所有数据校验数值,如果正确,结果为0;
函数返回值说明 :
使用的资源
其它说明:
*************************************************/
unsigned int CCITT_Stting(unsigned char transt_flag ,unsigned char *temp,unsigned int len)
{
unsigned int t = 0;
if(transt_flag == 1) //如果是发送状态
{
for(unsigned int i = 0;i
{
t <<= 8; //组装数据,将低8位移动到高8位
t |= (unsigned int)( *temp++); //高8位数据不变,下一个字节添加到8位
if((len % 2)&&(i == len-1)) //如果需要校验数据为奇数个字节,现在又处于最后一个字节状态
t <<= 8; //将最后一个字节移动到最高8位
if((i%2) ||(i == len-1)) //如果当i为奇数,或者最后一个字节,那么就计算一次校验数值
{
CRCDI = CCITT(t);
t = 0;
}
}
}
else
{
for(unsigned int i = 0;i
{
t <<= 8; //低8位移动到高8位
t |= (unsigned int)( *temp++);
if((len % 2)&&(i == len-3)) //当接收到的数据除校验数后还有奇数个,那么在接收到校验数值前一个字节后就移动到高8位,低8位为0
t <<= 8;
//如果在接收到被校验数据前遇到i 为奇数,或者当接收字节数为奇数,接收到校验数值前一个字节,或者
//接收到最后一个字节,就计算一次CRC数值
if(((i%2)&&(i <= len-3))||(i == len-1)||((len % 2)&&(i == len-3)))
{
CRCDI = CCITT(t); //调用位颠倒函数,产生CRC校验值
t = 0;
}
}
}
return CRCINIRES;
}
写的不错,不过没检验
生活就是油盐酱醋再加一点糖,快活就是一天到晚乐呵呵的忙
===================================
做一个简单的人,踏实而务实,不沉溺幻想,不庸人自扰
关于上面的程序,我想问问牛人们!几个小问题!transt_buffer_point[0] - 2代表几个字节,怎么计算?还有utxbuffer[ utxbuffer[0]-2] = (unsigned char)(CRC_Value >>8); utxbuffer[ utxbuffer[0]-1] = (unsigned char)(CRC_Value); 这两句怎么理解?没看明白,可以分析一下吗?谢谢!!
你的软件基础需要提高啊,这个是很简单的问题.几乎算是最基础的了。
1. transt_buffer_point[0]-2不是确定的代表几个字节,传输数据包的第一个字节表示整个包长,transt_buffer_point[0]-2就是只整个包长-2.
2. 传输包的最后两个字节用来保存计算出来的CRC值。倒数一位是低8位,倒数第二位是高8位.
utxbuffer[ utxbuffer[0]-2] = (unsigned char)(CRC_Value >>8);
utxbuffer[ utxbuffer[0]-1] = (unsigned char)(CRC_Value);
这两句话就是完成把计算好的CRC值放入传输数组里面。
先谢谢拉!软件基础指的什么呢?我已经学了一个月的430了吧!也不知道怎么学,就自己闷在那里看手册,看程序。教教我呗!大哥!!
传输数据包的第一个字节表示整个包长这句话什么意思啊!能说具体点吗??谢谢!!
倒数一位是低8位,倒数第二位是高8位.这又是什么意思咧?到底是一位还是八位啊??大哥!你能说具体点吗??只在这个程序中谈论,就行!!延伸的太远,我不明白啊!!谢谢!!
当transt_flag 为0 ,则返回接收所有数据校验数值,如果正确,结果为0;
是不是说每个发送数据包的数都会有一个数据校验值,改校验值被传输到接受数据包??如果正确结果为0,谁为0??是CRCINIRES吗??
请您耐心帮忙解释一下,谢谢!!
看教程看手册肯定没错,多看多做多犯错对学习帮助很大,特别是单片机这样应用为主的设备。lz要时刻清楚写出来的代码是什么用途,尽可能的去弄明白
[b]传输数据包的第一个字节表示整个包长;transt_buffer_point[0]=4,需要校验的字节数为2;那就是只对0X04、0X01进行校验,对不?CRC的值如何计算??添加到被校验数组的CRC数值,是不是含有两部分:校验字段和信息字段?CRC数值还是16位吗??
你要看代码啊,不能光提问题,提问题能解决你的问题么?
1. 在程序头的注释上已经很清楚的说明了传输和接收包的格式:
4。本程序接收和发送数据协议 包长 + 发送数据 + CRC校验 其中包长是发送字节总数 ,包括包长本身一个字节,还有发送数据字节数,CRC两个字节
transt_buffer_point[0]=4,表示传输的整个包长是4,第二个直接表示传输数据长度,CRC还要占2个字节,所以一个数据包只能是{4,0,XX,XX},其中XX,XX是CRC的校验值。
只有当第一个包头数据大于4才会有传输数据。
2. CRC校验是通过调用CCITT_Stting函数实现的.