51单片机串口通信(字符串接收和发送)
转自:http://www.cnblogs.com/weifeng727/category/845655.html
#include<reg52.h> //------------------串口通信协议-----------------// /* 客户端数据包格式解释(长度恒为15): 例如:A01_fmq_01Off___# A--------数据包的开始标记(可以为A到Z,意味着数据包可以有26种) 01-----设备代号 fmq_01Off___--------指令(长度恒为10),指令的前4个人字符是指令头部,指令的后6个字符是指令尾部 #---------数据包的结束标记 服务器端数据包格式解释(长度恒为15): 例如:A02_SenT010250# A--------数据包的开始标记(可以为A到Z,意味着数据包可以有26种) 02-----设备代号 SenT010250--------指令(长度恒为10),指令的前4个人字符是指令头部,指令的后6个字符是指令尾部 #---------数据包的结束标记 */ char buf_string[16]; //定义数据包长度为15个字符 #define deviceID_1Bit '0' //用于串口通信时,定义本地设备ID的第1位 #define deviceID_2Bit '2' //用于串口通信时,定义本地设备ID的第2位 #define datapackage_headflag 'A' //用于串口通信时,定义数据包头部的验证标记 char DataPackage_DS18B20[16]={datapackage_headflag,deviceID_1Bit,deviceID_2Bit,'_','S','e','n','T','X','X','X','X','X','X','#'}; char HeartBeat[16]={datapackage_headflag,deviceID_1Bit,deviceID_2Bit,'_','B','e','a','t','X','X','X','X','X','X','#'}; //----------------------------------------------// /******************************* 串口通信 MCU:89C52RC 11.0592MHz //11.0592MHz 0xd0 1200bps //12MHz 0xcc 1200bps //11.0592MHz 0xfa 9600bps //0xf4 11.0592MHz 0xf3 12MHz 4800bps //均在SMOD=1的情况下(波特率倍增模式) *******************************/ //串口发送函数 void PutString(unsigned char *TXStr) { ES=0; while(*TXStr!=0) { SBUF=*TXStr; while(TI==0); TI=0; TXStr++; } ES=1; } //串口接收函数 bit ReceiveString() { char * RecStr=buf_string; char num=0; unsigned char count=0; loop: *RecStr=SBUF; count=0; RI=0; if(num<14) //数据包长度为15个字符,尝试连续接收15个字符 { num++; RecStr++; while(!RI) { count++; if(count>130)return 0; //接收数据等待延迟,等待时间太久会导致CPU运算闲置,太短会出现"数据包被分割",默认count=130 } goto loop; } return 1; } //定时器1用作波特率发生器 void Init_USART() { SCON=0x50; //串口方式1,使能接收 TMOD|=0x20; //定时器1工作方式2(8位自动重装初值) TMOD&=~0x10; TH1=0xfa; //9600bps TL1=0xfa; PCON|=0x80; //SMOD=1 TR1=1; TI=0; RI=0; //PS=1; //提高串口中断优先级 ES=1; //开启串口中断使能 } //比较指令头部 bit CompareCMD_head(char CMD_head[]) { unsigned char CharNum; for(CharNum=0;CharNum<4;CharNum++) //指令长度为10个字符 { if(!(buf_string[CharNum+4]==CMD_head[CharNum])) { return 0; //指令头部匹配失败 } } return 1; //指令头部匹配成功 } //比较指令尾部(start:从哪里开始比较,quality:比较多少个字符,CMD_tail[]:要比较的字符串) bit CompareCMD_tail(unsigned char start,unsigned char quality,char CMD_tail[]) { unsigned char CharNum; for(CharNum=0;CharNum<quality;CharNum++) { if(!(buf_string[start+CharNum]==CMD_tail[CharNum])) { return 0; } } return 1; } bit Deal_UART_RecData() //处理串口接收数据包函数(成功处理数据包则返回1,否则返回0) { //PutString(buf_string); if(buf_string[0]==datapackage_headflag&&buf_string[14]=='#') //进行数据包头尾标记验证 { switch(buf_string[1]) //识别发送者设备ID的第1位数字 { case '0': switch(buf_string[2]) //识别发送者设备ID的第2位数字 { case '3': if(CompareCMD_head("Ligt")) //判断指令头部是否为"Ligt" { //下面是指令尾部分析 switch(buf_string[8]) { case '0': switch(buf_string[9]) { case '0': return 0; case '1': if(CompareCMD_tail(10,3,"Off")) //A03_Ligt01Off_# { //要执行的代码 return 1; } if(CompareCMD_tail(10,3,"On_")) { return 1; } return 0; default: return 0; } case '1': default: return 0; } } if(CompareCMD_head("SenT")) { } if(CompareCMD_head("jdq_")) { } if(CompareCMD_head("Try!")) { } return 0; default: return 0; } default: return 0; } } return 0; } /************************ 中断函数 ************************/ //串口中断服务函数----------- void USART() interrupt 4 //标志位TI和RI需要手动复位,TI和RI置位共用一个中断入口 { if(ReceiveString()) { //数据包长度正确则执行以下代码 Deal_UART_RecData(); } else { //数据包长度错误则执行以下代码 //LED1=~LED1; } RI=0; //接收并处理一次数据后把接收中断标志清除一下,拒绝响应在中断接收忙的时候发来的请求 } /*************************** 主函数 ***************************/ void main() { EA=1; Init_USART(); while(1) { //PutString(buf_string);//空格20H,回车0DH } }