51单片机串口通信(字符串接收和发送)

  1 #include<reg52.h>
  2
  3 //------------------串口通信协议-----------------//
  4 /*
  5     客户端数据包格式解释(长度恒为15):
  6     例如:A01_fmq_01Off___#
  7     A--------数据包的开始标记(可以为A到Z,意味着数据包可以有26种)
  8     01-----设备代号
  9     fmq_01Off___--------指令(长度恒为10),指令的前4个人字符是指令头部,指令的后6个字符是指令尾部
 10     #---------数据包的结束标记
 11
 12     服务器端数据包格式解释(长度恒为15):
 13     例如:A02_SenT010250#
 14     A--------数据包的开始标记(可以为A到Z,意味着数据包可以有26种)
 15     02-----设备代号
 16     SenT010250--------指令(长度恒为10),指令的前4个人字符是指令头部,指令的后6个字符是指令尾部
 17     #---------数据包的结束标记
 18 */
 19 char buf_string[16];  //定义数据包长度为15个字符
 20 #define deviceID_1Bit ‘0‘                //用于串口通信时,定义本地设备ID的第1位
 21 #define deviceID_2Bit ‘2‘                //用于串口通信时,定义本地设备ID的第2位
 22 #define datapackage_headflag ‘A‘        //用于串口通信时,定义数据包头部的验证标记
 23
 24 char DataPackage_DS18B20[16]={datapackage_headflag,deviceID_1Bit,deviceID_2Bit,‘_‘,‘S‘,‘e‘,‘n‘,‘T‘,‘X‘,‘X‘,‘X‘,‘X‘,‘X‘,‘X‘,‘#‘};
 25 char HeartBeat[16]={datapackage_headflag,deviceID_1Bit,deviceID_2Bit,‘_‘,‘B‘,‘e‘,‘a‘,‘t‘,‘X‘,‘X‘,‘X‘,‘X‘,‘X‘,‘X‘,‘#‘};
 26 //----------------------------------------------//
 27 /*******************************
 28             串口通信
 29     MCU:89C52RC        11.0592MHz
 30
 31 //11.0592MHz 0xd0 1200bps
 32 //12MHz 0xcc 1200bps
 33 //11.0592MHz 0xfa 9600bps
 34 //0xf4 11.0592MHz  0xf3 12MHz 4800bps
 35 //均在SMOD=1的情况下(波特率倍增模式)
 36 *******************************/
 37 //串口发送函数
 38 void PutString(unsigned char *TXStr)
 39 {
 40     ES=0;
 41      while(*TXStr!=0)
 42     {
 43         SBUF=*TXStr;
 44         while(TI==0);
 45         TI=0;
 46         TXStr++;
 47     }
 48     ES=1;
 49 }
 50 //串口接收函数
 51 bit ReceiveString()
 52 {
 53     char * RecStr=buf_string;
 54     char num=0;
 55     unsigned char count=0;
 56     loop:
 57     *RecStr=SBUF;
 58     count=0;
 59     RI=0;
 60     if(num<14)  //数据包长度为15个字符,尝试连续接收15个字符
 61     {
 62         num++;
 63         RecStr++;
 64         while(!RI)
 65         {
 66             count++;
 67             if(count>130)return 0;    //接收数据等待延迟,等待时间太久会导致CPU运算闲置,太短会出现"数据包被分割",默认count=130
 68         }
 69         goto loop;
 70     }
 71     return 1;
 72 }
 73 //定时器1用作波特率发生器
 74 void Init_USART()
 75 {
 76     SCON=0x50;  //串口方式1,使能接收
 77     TMOD|=0x20;  //定时器1工作方式2(8位自动重装初值)
 78     TMOD&=~0x10;
 79     TH1=0xfa;   //9600bps
 80     TL1=0xfa;
 81     PCON|=0x80;  //SMOD=1
 82     TR1=1;
 83     TI=0;
 84     RI=0;
 85     //PS=1;   //提高串口中断优先级
 86     ES=1;  //开启串口中断使能
 87 }
 88 //比较指令头部
 89 bit CompareCMD_head(char CMD_head[])
 90 {
 91     unsigned char CharNum;
 92     for(CharNum=0;CharNum<4;CharNum++)  //指令长度为10个字符
 93     {
 94         if(!(buf_string[CharNum+4]==CMD_head[CharNum]))
 95         {
 96             return 0;  //指令头部匹配失败
 97         }
 98     }
 99     return 1;        //指令头部匹配成功
100 }
101 //比较指令尾部(start:从哪里开始比较,quality:比较多少个字符,CMD_tail[]:要比较的字符串)
102 bit CompareCMD_tail(unsigned char start,unsigned char quality,char CMD_tail[])
103 {
104     unsigned char CharNum;
105     for(CharNum=0;CharNum<quality;CharNum++)
106     {
107         if(!(buf_string[start+CharNum]==CMD_tail[CharNum]))
108         {
109             return 0;
110         }
111     }
112     return 1;
113 }
114 bit Deal_UART_RecData()   //处理串口接收数据包函数(成功处理数据包则返回1,否则返回0)
115 {
116     //PutString(buf_string);
117     if(buf_string[0]==datapackage_headflag&&buf_string[14]==‘#‘)  //进行数据包头尾标记验证
118     {
119         switch(buf_string[1])        //识别发送者设备ID的第1位数字
120         {
121             case ‘0‘:
122                 switch(buf_string[2])        //识别发送者设备ID的第2位数字
123                 {
124                     case ‘3‘:
125                         if(CompareCMD_head("Ligt"))    //判断指令头部是否为"Ligt"
126                         {
127                             //下面是指令尾部分析
128                             switch(buf_string[8])
129                             {
130                                 case ‘0‘:
131                                     switch(buf_string[9])
132                                     {
133                                         case ‘0‘:
134
135                                             return 0;
136                                         case ‘1‘:
137                                             if(CompareCMD_tail(10,3,"Off"))   //A03_Ligt01Off_#
138                                             {
139                                                 //要执行的代码140                                                 return 1;
141                                             }
142                                             if(CompareCMD_tail(10,3,"On_"))
143                                             {
144
145                                                 return 1;
146                                             }
147                                             return 0;
148                                         default:
149                                             return 0;
150                                     }
151                                 case ‘1‘:
152
153                                 default:
154                                     return 0;
155                             }
156                         }
157                         if(CompareCMD_head("SenT"))
158                         {
159
160
161                         }
162                         if(CompareCMD_head("jdq_"))
163                         {
164
165
166                         }
167                         if(CompareCMD_head("Try!"))
168                         {
169
170
171                         }
172                         return 0;
173
174                     default:
175                         return 0;
176                 }
177             default:
178                 return 0;
179         }
180     }
181     return 0;
182 }
183 /************************
184         中断函数
185 ************************/
186 //串口中断服务函数-----------
187 void USART() interrupt 4   //标志位TI和RI需要手动复位,TI和RI置位共用一个中断入口
188 {
189     if(ReceiveString())
190     {
191         //数据包长度正确则执行以下代码
192         Deal_UART_RecData();
193     }
194     else
195     {
196         //数据包长度错误则执行以下代码
197         //LED1=~LED1;
198     }
199     RI=0;  //接收并处理一次数据后把接收中断标志清除一下,拒绝响应在中断接收忙的时候发来的请求
200 }
201 /***************************
202         主函数
203 ***************************/
204 void main()
205 {
206     EA=1;
207     Init_USART();
208     while(1)
209     {
210         //PutString(buf_string);//空格20H,回车0DH
211
212     }
213 }       

这个模块代码用于快速实现可扩展的串口通信

尊重作者的劳动,转载请记得注明来源:http://www.cnblogs.com/weifeng727/p/5617924.html

时间: 2024-08-07 18:13:56

51单片机串口通信(字符串接收和发送)的相关文章

51单片机串口通信

一.原理简介 51 单片机内部有一个全双工串行接口.什么叫全双工串口呢?一般来说,只能接受或只能发送的称为单工串行:既可接收又可发送,但不能同时进行的称为半双工:能同时接收和发送的串行口称为全双工串行口.串行通信是指数据一位一位地按顺序传送的通信方式,其突出优点是只需一根传输线,可大大降低硬件成本,适合远距离通信.其缺点是传输速度较低. 与之前一样,首先我们来了解单片机串口相关的寄存器. SBUF 寄存器:它是两个在物理上独立的接收.发送缓冲器,可同时发送.接收数据,可通过指令对SBUF 的读写

深入理解51单片机串口通信

串口通信的基本认识 通信分为并行通信和串行通信,并行通信时的数据各个位同时传送,可以实现字节为单位通信,但通信线多占用资源,成本高.以前用到的的P1=0x55,一次给P1口的8个管脚分别赋值,同时进行信号输出,类似于8个车道可以过去8辆车,这样的形式是并行的,一般称P0,P1,P2,P3为51单片机的4组并行总线. 串行通信,就是一个车道,一个只能通过一辆车,如果一个0x55这样一个字节的数据要传输过去的话,假如低位在前,高位在后的话,那发送方式是:0-1-0-1-0-1-0-1,一位一位的进行

51单片机串口通信时的定时器设置的相关问题

51单片机在串口通信时需要有一个定时器去调节与计算机通信的波特率,而定时器设置时需要中断寄存器(IE), 定时器控制寄存器(TCON) ,还有T/C控制寄存器共同配合作用, 但在启动定时器功能时,这三个寄存器的配置顺序十分重要,因为在数据传输时的高速情况下,一点点的数据误差就会导致传输的数据出现错误.而在51单片机的串口通信时必须将配置TCON放在配置这三个寄存器的最后,因为在TCON中含有启动定时器的TR1和TR0位,若先启动后对工作方式和溢出率进行配置,就会导致启动时定时器根本无法像预先设定

stm32RS485串口通信——中断接收发送数据

功能:通过PC机的串口调试助手发送数据给串口A,串口B接收到串口A发送的数据,再由串口B将接收到的数据返回给PC机的串口调试助手. PC->串口A->串口B->PC. 实验平台:stm32f407 /********************************************************************* 本平台具有六个串口: com1  485 com2 com3  232 需一个管脚控制DTU com4 485 com5  调试串口  TTL com6

串口通信基础,接收,发送数据

通信接口背景知识 设备之间通信的方式 一般情况下,设备之间的通信方式可以分成并行通信和串行通信两种.它们的区别是: 串行通信的分类 1.按照数据传送方向,分为: 单工:数据传输只支持数据在一个方向上传输:    半双工:允许数据在两个方向上传输.但是,在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信:它不需要独立的接收端和发送端,两者可以合并一起使用一个端口.    全双工:允许数据同时在两个方向上传输.因此,全双工通信是两个单工通信方式的结合,需要独立的接收端和发送端.

labview与单片机串口通信

VISA是虚拟仪器软件体系结构的缩写(即Virtual Instruments Software Architecture),实质上是一个I/O口软件库及其规范的总称. VISA是应用于仪器编程的标准I/0应用程序接口,是工业界通用的仪器驱动器标准API(应用程序接口),采用面向对象编程,具有很好的兼容性.扩展性和独立性.用户可用一个API控制包括VXI.GPIB及串口仪器在内的不同种类的仪器.它还支持多平台工作.多接口控制,是一个多类型的函数库. 在LabVIEW中编写的VISA接口程序,当外

关于单片机串口通信的问题

最近在调板子的时候又遇到了单片机MCU检测不到的问题,之前百度了一堆驱动问题,已经可以正常烧写程序,但是昨天又写不了了,连单片机都检测不到,将驱动器的RxD与TxD短接,使用串口助手自己给自己发送数字,是可以接收到的,证明仿真器没有问题,交换驱动器与单片机的RxD与TxD,从顺接改为交叉连接,还是不行.后来在一哥们的指导下解决了该问题.然后发 现一个小小的串口通信其实门道很多,特别是对于对单片机不熟悉的初级选手是个不小的挑战,所以今天跟小伙伴们聊聊我的感受. 我的问题概而论之就是对于CH340驱

单片机串口通信原理及原理图

转:http://bbs.elecfans.com/forum.php?mod=viewthread&tid=206905  串口通信的概念非常简单,串口按位(bit)发送和接收字节.尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据.它很简单并且能够实现远距离通信.比如IEEE488定义并行通行状态时,规定设备线总长不得超过20米,并且任意两个设备间的长度不得超过2米:而对于串口而言,长度可达1200米.典型地,串口用于ASCII码字符的传输.通信使

单片机串口通信中换行的两种方法

方法一: 在发送的字符串时用格式:"原字符串\r\n". 方法二: 在发送完字符或字符串后连续发送字符0x0d和0x0a,即可实现换行.即连续发送字符'\r'和'\n'. 部分代码例程: 方法一: UartSendStr("转换结束!\r\n"); 方法二(1): UartSendStr("转换结束!"); UartSendChar(0x0d); UartSendChar(0x0a); 方法二(2): UartSendStr("转换结束