广州公司网站提供,如何推广新品,软件发布流程,wordpress主题首页怎么修改本章重点介绍串口多机通讯使用CRC8校验。
数据格式:$123xxxx*crc8\r\n;
如:$1234567890ABCDEF*06\r\n
如:$1231234567890*31\r\n
crc8是CRC校验值,为十六进制的ASCII码,不包含$和校验值前面的那个* #include REG51.h //包含…本章重点介绍串口多机通讯使用CRC8校验。
数据格式:$123xxxx*crc8\r\n;
如:$1234567890ABCDEF*06\r\n
如:$1231234567890*31\r\n
crc8是CRC校验值,为十六进制的ASCII码,不包含$和校验值前面的那个* #include REG51.h //包含头文件REG51.h,使能51内部寄存器;
#include intrins.h //包含头文件intrins.h,要放在stdio.h的头文件之前;
//使能函数: _nop_(); 相当于汇编的NOP指令;
//使能函数: bit _testbit_( bit bit_value ); 对bit_value进行测试,若bit_value1,返回1,否则返回0;
//使能函数: _cror_( unsigned char x, unsigned char n ); 将字节型变量x的值,向右循环移动n位,然后将其
//值返回;
//相当于汇编的RR A命令;
//使能函数: _iror_( unsigned int x, unsigned char n ); 将双字节型变量x的值,向右循环移动n位,然后将
//其值返回;
//使能函数: _lror_( unsigned long x, unsigned char n ); 将4字节型变量x的值,向右循环移动n位,然后将
//其值返回;
//使能函数: _crol_( unsigned char x, unsigned char n ); 将字节型变量x的值,向左循环移动n位,然后将其
//值返回;
//使能函数: _irol_( unsigned int x, unsigned char n ); 将双字节型变量x的值,向左循环移动n位,然后将
//其值返回;
//使能函数: _lrol_( unsigned long x, unsigned char n ); 将4字节型变量x的值,向左循环移动n位,然后将
//其值返回;
//以上的循环左移和循环右移,同C语言的左移和右移是不同的使用时要小心;
#include string.h
#define OSC_FREQ 11059200L //#define BAUD_115200 256 - (OSC_FREQ/192L)/115200L //
//#define BAUD_38400 256 - (OSC_FREQ/192L)/38400L //
#define BAUD_Time 1
#if(BAUD_Time1)
//若波特率加倍,则使用下面参数;
#define BAUD_57600 256 - (OSC_FREQ/192L)/57600L //255
#define BAUD_28800 256 - (OSC_FREQ/192L)/28800L //254
#define BAUD_19200 256 - (OSC_FREQ/192L)/19200L //253
#define BAUD_14400 256 - (OSC_FREQ/192L)/14400L //252
#define BAUD_9600 256 - (OSC_FREQ/192L)/9600L //250
#define BAUD_4800 256 - (OSC_FREQ/192L)/4800L //244
#define BAUD_2400 256 - (OSC_FREQ/192L)/2400L //232
#define BAUD_1200 256 - (OSC_FREQ/192L)/1200L //208
#else
//若波特率不加倍,则使用下面参数;
#define BAUD_9600 256 - (OSC_FREQ/384L)/9600L
#define BAUD_4800 256 - (OSC_FREQ/384L)/4800L
#define BAUD_1200 256 - (OSC_FREQ/384L)/1200L
#endif
#define receive_buffer_size 30
unsigned char receive_buffer[receive_buffer_size];
bit Start_Flag,Receive_End_Flag;
unsigned char next_in;
//unsigned char crc8;
//函数功能:将y的第i_bit位,设置为1;
unsigned char bit_set( unsigned char y,unsigned char i_bit)
{ unsigned char temp; temp1i_bit; ytemp|y; return(y);
}
//函数功能:将y的第i_bit位,设置为0;
unsigned char bit_clear(char y,char i_bit)
{ char temp; temp1i_bit; temp~temp; ytemp; return(y);
}
//函数功能:若test_data的第test_bit位为1,则返回1,否则返回0;
bit bit_test(char test_data,char test_bit)
{ char temp; bit bit_value; temptest_data; temptemptest_bit; if( (temp0x01)0x01 ) bit_value1; else bit_value0; return(bit_value);
}
//函数功能:产生8位的CRC校验值;
unsigned char generate_8bit_crc(unsigned char* ptr, unsigned int length, unsigned char pattern)
{ unsigned char *current_data; unsigned char crc_byte; unsigned int byte_counter; unsigned char bit_counter; current_data ptr; crc_byte *current_data; for(byte_counter0; byte_counter (length-1); byte_counter) { for(bit_counter0; bit_counter 8; bit_counter) { if( !bit_test(crc_byte,7) ) { crc_bytecrc_byte1; bit_test( *current_data, 7 - bit_counter ) ? crc_bytebit_set(crc_byte,0) : bit_clear(crc_byte,0); continue; } crc_byte 1; bit_test(*current_data, 7 - bit_counter) ? crc_bytebit_set(crc_byte,0) : bit_clear(crc_byte,0); crc_byte ^ pattern; } current_data; } for(bit_counter0; bit_counter 8; bit_counter) { if(!bit_test(crc_byte,7)) { crc_byte 1; continue; } crc_byte 1; crc_byte ^ pattern; } return(crc_byte);
}
//函数功能:将0~9,A~F的ASCII码转换为十六进制(0x00~0x09,0x0a~0x0f)输出;
unsigned char ASCII_To_HEX(unsigned char ASCII )
{ unsigned char temp; if(ASCII9) tempASCII-0; else tempASCII-0x37; return(temp);
}
//函数功能:从串口读入一个字符;
char getc()
{ char c; while (!RI); c SBUF; RI 0; return (c);
}
//函数功能:从串口输出一个字符;
void putc(char c)
{ SBUFc; while (!TI); TI 0;
}
//函数功能:接收和发送中断服务函数;
//数据格式:$123xxxx*crc8\r\n;
//如:$1234567890ABCDEF*06\r\n
//如:$1231234567890*31\r\n
//crc8是CRC校验值,为十六进制的ASCII码,不包含$和校验值前面的那个*
void isr_UART(void) interrupt 4 using 0
{ unsigned char temp,crc8,crc_data; if( RI(!Receive_End_Flag) ) //处理接收数据; { tempgetc(); //从串口接收一个字节; receive_buffer[next_in]temp; putc(temp);//调试时,使用; tempnext_in; //保存下标值; next_in; //修改下标值; if(temp3) //比对从机地址是否为$123 { if( Start_Flag ) { if( (temp0)(receive_buffer[0]!1) ) next_in0; if( (temp1)(receive_buffer[1]!2) ) next_in0; if( (temp2)(receive_buffer[2]!3) ) next_in0;
} else { if(receive_buffer[0]$) Start_Flag1; next_in0;
} } else { if( (receive_buffer[temp-1]\r)(receive_buffer[temp]\n) ) //接收到\r\n { crc8generate_8bit_crc( receive_buffer,temp-4,1); //计算接收到数据的CRC8校验值; crc_dataASCII_To_HEX(receive_buffer[temp-3]); crc_data(crc_data4)0xf0; //获取CRC校验值的高4位值; tempASCII_To_HEX(receive_buffer[temp-2]); //获取CRC校验值的低4位值; crc_datacrc_datatemp; //获取接收到的CRC校验值; if(crc8crc_data) //若CRC校验值正确,则执行下面语句; { Receive_End_Flag1;
} next_in0; //接收完成; Start_Flag0; //为下次接收起始标志做备;
}
} if(next_inreceive_buffer_size) { next_in0; //接收数据太长,取消接收; Start_Flag0; //为下次接收起始标志做备;
}
}
}
//函数功能:若接收到的数据有效,则打印出来;
void Print_Receive_data()
{ unsigned char i; i0; if(Receive_End_Flag) { while(receive_buffer[i]!\n) { putc(receive_buffer[i]); i;
} putc(receive_buffer[i]); //打印\n; Receive_End_Flag0; }
}
//函数功能:初始化串口,设置波特率为9600bps11.0592MHz,使能接收,使用8位UART;
void Serial_Port_Initialization()
{ PCON 0x80; SCON0x50; //串行控制寄存器: SM0,SM1,SM2,REN,TB8,RB8,TI,RI //SM1:SM001,选择方式1,SM20,表示非多机通讯,8-bit UART; //REN1,使能接收; TMOD0x0f; TMOD| 0x20;
//定时器方式控制寄存器:GATE1,C/T1,M11,M10,GATE0,C/T0,M01,M00 //GATE0,TR置1便可以启动Timer;GATE1,TR置1,且INT脚输入高电平,才可以启动Timer; //M11:M1010,选择方式2,8位自动重装载; TH1BAUD_9600; //TH1: reload value for 9600 baud 11.0592MHz; TL1TH1; TR11; //启动Timer1; TI0; //为下次发送做准备; RI0; next_in0; Start_Flag0; Receive_End_Flag0; //将接收完成标志设置为0; ES1; //使能串口接收和发送中断; EA1; //开总中断
} //函数功能: Delay 50us
void delay_50us(unsigned char _50us)
{ while(_50us--)
{ _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); }
} void main(void)
{ Serial_Port_Initialization(); //初始化串口,设置波特率9600bps11.0592MHz,使能接收,使用8位UART; for(;;) { Print_Receive_data(); //若接收到的数据有效,则打印出来; delay_50us(20); //延时1ms; }
}
/*
//函数功能:将hex8的低4位(0~9,a~f)转换为0~9,A~F输出;
unsigned char HEX_To_ASCII(unsigned char hex8 )
{unsigned char temp; temphex8; temp(unsigned char)(temp0x0f); //求低4位值; if(temp0x0a) temp0x30; //将低4位值(在0~9中)转换为ASCII码; else temp0x37; //将低4位值(在a~f中)转换为大写字母的ASCII码; return(temp);
}
//函数功能:将0~9,A~F的ASCII码转换为十六进制(0x00~0x09,0x0a~0x0f)输出;
unsigned char ASCII_To_HEX(unsigned char ASCII )
{ unsigned char temp; if(ASCII9) tempASCII-0; else tempASCII-0x37; return(temp);
}
//函数功能:将y的第i_bit位,设置为1;
unsigned char bit_set( unsigned char y,unsigned char i_bit)
{ unsigned char temp; temp1i_bit; ytemp|y; return(y);
}
//函数功能:将y的第i_bit位,设置为0;
unsigned char bit_clear(char y,char i_bit)
{ char temp; temp1i_bit; temp~temp; ytemp; return(y);
}
//函数功能:若test_data的第test_bit位为1,则返回1,否则返回0;
bit bit_test(char test_data,char test_bit)
{ char temp; bit bit_value; temptest_data; temptemptest_bit; if( (temp0x01)0x01 ) bit_value1; else bit_value0; return(bit_value);
}
//函数功能:产生8位的CRC校验值;
unsigned char generate_8bit_crc(unsigned char* ptr, unsigned int length, unsigned char pattern)
{ unsigned char *current_data; unsigned char crc_byte; unsigned int byte_counter; unsigned char bit_counter; current_data ptr; crc_byte *current_data; for(byte_counter0; byte_counter (length-1); byte_counter) { for(bit_counter0; bit_counter 8; bit_counter) { if( !bit_test(crc_byte,7) ) { crc_bytecrc_byte1; bit_test( *current_data, 7 - bit_counter ) ? crc_bytebit_set(crc_byte,0) : bit_clear(crc_byte,0); continue; } crc_byte 1; bit_test(*current_data, 7 - bit_counter) ? crc_bytebit_set(crc_byte,0) : bit_clear(crc_byte,0); crc_byte ^ pattern; } current_data; } for(bit_counter0; bit_counter 8; bit_counter) { if(!bit_test(crc_byte,7)) { crc_byte 1; continue; } crc_byte 1; crc_byte ^ pattern; } return(crc_byte);
}
//函数功能:将y的第i_bit位,设置为1;调用方式: sbit_set(x,i);
void bit_set( unsigned char *y,unsigned char i_bit)
{ unsigned char temp; temp1i_bit; y[0]temp|y[0];
}
//函数功能:将y的第i_bit位,设置为0;调用方式: sbit_clear(x,i);
void bit_clear(char *y,char i_bit)
{ char temp; temp1i_bit; temp~temp; y[0]temp;
}
//函数功能:若test_data的第test_bit位为1,则返回1,否则返回0;
void bit_test(char test_data,char test_bit,unsigned char *return_value)
{ char temp; //bit bit_value; temptest_data; temptemptest_bit; if( (temp0x01)0x01 ) return_value[0]1; else return_value[0]0; //return(bit_value);
}
//函数功能:产生8位的CRC校验值;
void generate_8bit_crc(unsigned char* ptr, unsigned int length, unsigned char *return_value )
{ unsigned char tenp_value; unsigned char *current_data; unsigned char crc_byte; unsigned int byte_counter; unsigned char bit_counter; unsigned char pattern0x01; current_data ptr; crc_byte *current_data; for(byte_counter0; byte_counter (length-1); byte_counter) { for(bit_counter0; bit_counter 8; bit_counter) { bit_test( crc_byte,7,tenp_value ); //if( !bit_test(crc_byte,7) ) if(tenp_value0) { crc_bytecrc_byte1; bit_test( *current_data, 7 - bit_counter,tenp_value ); //bit_test( *current_data, 7 - bit_counter ) ? bit_set(crc_byte,0) : bit_clear(crc_byte,0); if(tenp_value1) bit_set(crc_byte,0); else bit_clear(crc_byte,0); continue; } crc_byte 1; bit_test( *current_data, 7 - bit_counter,tenp_value ); //bit_test(*current_data, 7 - bit_counter) ? crc_bytebit_set(crc_byte,0) : bit_clear(crc_byte,0); if(tenp_value1) bit_set(crc_byte,0); else bit_clear(crc_byte,0); crc_byte ^ pattern; } current_data; } for(bit_counter0; bit_counter 8; bit_counter) { bit_test( crc_byte,7,tenp_value ); //if(!bit_test(crc_byte,7)) if(tenp_value0) { crc_byte 1; continue; } crc_byte 1; crc_byte ^ pattern; } return_value[0]crc_byte; //return(crc_byte);
}
*/