51串口通信协议(新型篇)
51串口协议的完整实现

unsignedchar dat[INBUF_LEN];
}cmdbuf,*pcmdbuf;
extern void init_serialcomm();
extern void send_char_com(unsigned charch);
extern void send_string_com(unsigned char*str,unsigned char strlen);
#endif
51单片机串口通信协议完整实现
51单片机编程经常使用到串口通信。在网上找了很久一直找不到完整的协议实现源码,分享一个我整理的51串口通信协议,方便以后能找到,也分享给有同样需要的人。
手机玩佳经营手机贴膜、手机保护套、手机移动电源、太阳能手机移动电源、手机配件,全店特价销售。
IE |= 0x90; //Enable Serial Interrupt
TR1 = 1; // timer 1 run
}
//向串口发送一个字符
void send_char_com(unsigned char ch)
#define BAUD38400 6
#define BAUD57600 7
#define BAUD115200 8
typedef struct CMD_BUF
{
unsignedchar sync;
unsignedchar cmd;
{
unsignedchar ch;
staticunsigned char count3 = 0; //接收字节计数
if(RI)
{
Байду номын сангаас RI= 0; //RI清零
51单片机串口通信

51单片机串口通信51单片机串口通信(转载)2009-03-03 18:22一、串口通信原理串口通讯对单片机而言意义重大,不但可以实现将单片机的数据传输到计算机端,而且也能实现计算机对单片机的控制。
由于其所需电缆线少,接线简单,所以在较远距离传输中,得到了广泛的运用。
串口通信的工作原理请同学们参看教科书。
以下对串口通信中一些需要同学们注意的地方作一点说明:1、波特率选择波特率(Boud Rate)就是在串口通信中每秒能够发送的位数(bits/second)。
MSC- 51串行端口在四种工作模式下有不同的波特率计算方法。
其中,模式0和模式2波特率计算很简单,请同学们参看教科书;模式1和模式3的波特率选择相同,故在此仅以工作模式1为例来说明串口通信波特率的选择。
在串行端口工作于模式1,其波特率将由计时/计数器1来产生,通常设置定时器工作于模式2(自动再加模式)。
在此模式下波特率计算公式为:波特率=(1+SMOD)*晶振频率/(384*(256-TH1))其中,SMOD——寄存器PCON的第7位,称为波特率倍增位;TH1——定时器的重载值。
在选择波特率的时候需要考虑两点:首先,系统需要的通信速率。
这要根据系统的运作特点,确定通信的频率范围。
然后考虑通信时钟误差。
使用同一晶振频率在选择不同的通信速率时通信时钟误差会有很大差别。
为了通信的稳定,我们应该尽量选择时钟误差最小的频率进行通信。
下面举例说明波特率选择过程:假设系统要求的通信频率在20000bit/s以下,晶振频率为12MHz,设置SMOD=1(即波特率倍增)。
则TH1=256-62500/波特率根据波特率取值表,我们知道可以选取的波特率有:1200,2400,4800,9600,19200。
列计数器重载值,通信误差如下表:因此,在通信中,最好选用波特率为1200,2400,4800中的一个。
2、通信协议的使用通信协议是通信设备在通信前的约定。
单片机、计算机有了协议这种约定,通信双方才能明白对方的意图,以进行下一步动作。
51单片机串口通信(相关例程)

51单片机串口通信(相关例程) 51单片机串口通信(相关例程)一、简介51单片机是一种常用的微控制器,它具有体积小、功耗低、易于编程等特点,被广泛应用于各种电子设备和嵌入式系统中。
串口通信是51单片机的常见应用之一,通过串口通信,可以使单片机与其他外部设备进行数据交互和通信。
本文将介绍51单片机串口通信的相关例程,并提供一些实用的编程代码。
二、串口通信基础知识1. 串口通信原理串口通信是通过串行数据传输的方式,在数据传输过程中,将信息分为一个个字节进行传输。
在51单片机中,常用的串口通信标准包括RS232、RS485等。
其中,RS232是一种常用的串口标准,具有常见的DB-9或DB-25连接器。
2. 串口通信参数在进行串口通信时,需要设置一些参数,如波特率、数据位、停止位和校验位等。
波特率表示在单位时间内传输的比特数,常见的波特率有9600、115200等。
数据位表示每个数据字节中的位数,一般为8位。
停止位表示停止数据传输的时间,常用的停止位有1位和2位。
校验位用于数据传输的错误检测和纠正。
三、串口通信例程介绍下面是几个常见的51单片机串口通信的例程,提供给读者参考和学习:1. 串口发送数据```C#include <reg51.h>void UART_Init(){TMOD = 0x20; // 设置计数器1为工作方式2(8位自动重装) TH1 = 0xFD; // 设置波特率为9600SCON = 0x50; // 设置串口工作方式1,允许串行接收TR1 = 1; // 启动计数器1}void UART_SendChar(unsigned char dat){SBUF = dat; // 发送数据while (!TI); // 等待发送完成TI = 0; // 清除发送完成标志}void main(){UART_Init(); // 初始化串口while (1){UART_SendChar('A'); // 发送字母A}}```2. 串口接收数据```C#include <reg51.h>void UART_Init(){TMOD = 0x20; // 设置计数器1为工作方式2(8位自动重装) TH1 = 0xFD; // 设置波特率为9600SCON = 0x50; // 设置串口工作方式1,允许串行接收TR1 = 1; // 启动计数器1}void UART_Recv(){unsigned char dat;if (RI) // 检测是否接收到数据{dat = SBUF; // 读取接收到的数据 RI = 0; // 清除接收中断标志// 处理接收到的数据}}void main(){UART_Init(); // 初始化串口EA = 1; // 允许中断ES = 1; // 允许串口中断while (1)// 主循环处理其他任务}}```3. 串口发送字符串```C#include <reg51.h>void UART_Init(){TMOD = 0x20; // 设置计数器1为工作方式2(8位自动重装) TH1 = 0xFD; // 设置波特率为9600SCON = 0x50; // 设置串口工作方式1,允许串行接收TR1 = 1; // 启动计数器1}void UART_SendString(unsigned char *str){while (*str != '\0')SBUF = *str; // 逐个发送字符while (!TI); // 等待发送完成TI = 0; // 清除发送完成标志str++; // 指针指向下一个字符}}void main(){UART_Init(); // 初始化串口while (1){UART_SendString("Hello, World!"); // 发送字符串}}```四、总结本文介绍了51单片机串口通信的基础知识和相关编程例程,包括串口发送数据、串口接收数据和串口发送字符串。
fc51通讯协议数据位

fc51通讯协议数据位FC51通讯协议数据位FC51通讯协议是一种常用于工业自动化领域的通信协议,用于实现PLC(可编程逻辑控制器)与外部设备之间的数据交互。
在FC51通讯协议中,数据位是其中一个重要的概念。
数据位是指在通信数据中用来传输信息的最小单位。
在FC51通讯协议中,数据位通常是一个二进制数,用来表示某种特定的状态或值。
根据数据位的不同,可以实现对设备的控制、监测和数据传输等功能。
在FC51通讯协议中,数据位的取值范围通常为0或1,分别表示不同的状态。
例如,当数据位为0时,可以表示设备关闭或停止;当数据位为1时,可以表示设备打开或运行。
通过对不同数据位的组合与解读,可以实现复杂的控制和监测功能。
在使用FC51通讯协议进行数据传输时,需要注意以下几点:1. 数据位的顺序:在通讯协议中,数据位的顺序一般按照从低位到高位的顺序排列。
这样可以确保数据的传输和解读的准确性。
2. 数据位的编码:在FC51通讯协议中,数据位的编码方式有多种,可以根据具体的需求选择合适的编码方式。
常用的编码方式有二进制编码、BCD编码等。
3. 数据位的检验:为了确保数据传输的准确性,通常会在数据位中添加校验位。
校验位可以通过特定的算法计算得出,用于检测数据是否传输错误。
常用的校验算法有奇偶校验、循环冗余校验等。
4. 数据位的长度:在FC51通讯协议中,数据位的长度通常是固定的,根据具体的应用需求确定。
长度过长或过短都可能导致数据传输的错误或不完整。
FC51通讯协议中的数据位在工业自动化领域起到了至关重要的作用。
通过对数据位的灵活应用,可以实现对设备的精确控制和监测。
例如,可以通过数据位的组合来实现对温度、湿度、压力等参数的实时监测和报警;可以通过数据位的状态来控制设备的开关、速度和方向等。
在使用FC51通讯协议进行数据传输时,需要确保数据位的准确性和稳定性。
可以通过合理的设计和配置,选择合适的数据位长度、编码方式和校验算法,来确保数据的可靠传输和解读。
串口通讯协议书范本

串口通讯协议书范本甲方(提供方):_________________________乙方(使用方):_________________________鉴于甲方拥有串口通讯技术,乙方有使用该技术的需求,双方本着平等互利的原则,经协商一致,就串口通讯技术的使用达成如下协议:第一条定义1.1 串口通讯:指通过串行接口进行数据传输的一种通讯方式。
1.2 数据格式:指在串口通讯中,数据的组织和编码方式。
1.3 通讯速率:指串口通讯中数据传输的速度。
1.4 通讯协议:指双方约定的串口通讯规则和标准。
第二条协议内容2.1 甲方同意向乙方提供符合本协议规定的串口通讯技术。
2.2 乙方同意按照本协议的规定使用甲方提供的串口通讯技术。
第三条通讯参数3.1 数据格式:采用_________标准。
3.2 通讯速率:_________ Baud。
3.3 校验方式:_________。
3.4 停止位:_________。
3.5 通讯协议:_________。
第四条权利与义务4.1 甲方应保证提供的串口通讯技术符合本协议规定的标准。
4.2 乙方应按照本协议规定的参数进行通讯,并保证通讯的合法性和安全性。
4.3 双方应共同维护通讯的稳定性和安全性,不得擅自更改通讯参数。
第五条保密条款5.1 双方应对在本协议履行过程中获知的对方的商业秘密和技术秘密负有保密义务。
5.2 保密期限为协议终止后_________年。
第六条违约责任6.1 如一方违反本协议规定,应承担违约责任,并赔偿对方因此遭受的损失。
第七条协议的变更和解除7.1 本协议的任何变更和补充均需双方书面同意。
7.2 如一方要求解除本协议,应提前_________天书面通知对方。
第八条争议解决8.1 双方因履行本协议所发生的任何争议,应通过友好协商解决。
8.2 如协商不成,任何一方均可向甲方所在地人民法院提起诉讼。
第九条其他9.1 本协议自双方签字盖章之日起生效。
9.2 本协议一式两份,甲乙双方各执一份,具有同等法律效力。
51单片机--串口通信

51单⽚机--串⼝通信基本介绍串⼝是⼀种应⽤⼗分⼴泛的通讯接⼝,串⼝成本低、容易使⽤、通信线路简单,可实现两个设备的互相通信。
单⽚机的串⼝可以使单⽚机与单⽚机、单⽚机与电脑、单⽚机与各式各样的模块互相通信,极⼤的扩展了单⽚机的应⽤范围,增强了单⽚机系统的硬件实⼒。
51单⽚机内部⾃带UART(Universal Asynchronous Receiver Transmitter,通⽤异步收发器),可实现单⽚机的串⼝通信。
基本接线简单双向串⼝通信有两根通信线(发送端TXD和接收端RXD)TXD与RXD要交叉连接当只需单向的数据传输时,可以直接⼀根通信线当电平标准不⼀致时,需要加电平转换芯⽚电平标准电平标准是数据1和数据0的表达⽅式,是传输线缆中⼈为规定的电压与数据的对应关系,串⼝常⽤的电平标准有如下三种:TTL电平:+5V表⽰1,0V表⽰0RS232电平:-3-15V表⽰1,+3+15V表⽰0RS485电平:两线压差+2+6V表⽰1,-2-6V表⽰0(差分信号)常见通信接⼝⽐较名称引脚定义通信⽅式特点UART TXD、RXD全双⼯、异步点对点通信I²C SCL、SDA半双⼯、同步可挂载多个设备SPI SCLK、MOSI、MISO、CS全双⼯、同步可挂载多个设备1-Wire DQ半双⼯、异步可挂载多个设备51单⽚机的UARTSTC89C52有1个UARTSTC89C52的UART有四种⼯作模式:模式0:同步移位寄存器模式1:8位UART,波特率可变(常⽤)模式2:9位UART,波特率固定模式3:9位UART,波特率可变串⼝模式图SBUF:串⼝数据缓存寄存器,物理上是两个独⽴的寄存器,但占⽤相同的地址。
写操作时,写⼊的是发送寄存器,读操作时,读出的是接收寄存器串⼝和中断系统串⼝相关寄存器SCON配置SCON:串⾏控制寄存器,可位寻址,⽤于选择串⾏通信的⼯作⽅式和某些控制功能。
SM0,SM1按下列组合确定串⾏⼝的⼯作⽅式:我们⼀般选择⽅式1,所以SM0=0,SM1=1.REN:1则启动串⾏接收器RXD,开始接收信息,0为禁⽌接收,我们先设置为1。
51单片机串口通信原理

51单片机串口通信原理详解1. 引言串口(Serial Port)是一种常用于计算机与外部设备之间进行数据传输的接口,它是一种逐位传输的方式。
51单片机是一种非常常用的单片机,串口通信是其重要的通信方式之一。
本文将详细解释51单片机串口通信的基本原理,包括串口通信的定义、硬件连接示意图、通信协议、数据传输过程以及数据接收处理等方面的内容。
2. 串口通信定义串口通信是一种通过串行通路进行数据传输的通信方式。
它是一种点对点的通信协议,即通信的两端通过共享数据线进行数据交换。
3. 硬件连接示意图完成串口通信,需要将单片机与外部设备进行连接。
下图是一个常见的串口通信连接示意图:___| |TXD <-|---|---> RXD| |RXD <-|---|---> TXD|___|单片机外部设备通常,单片机的TXD引脚连接到外部设备的RXD引脚,而单片机的RXD引脚连接到外部设备的TXD引脚。
4. 串口通信协议串口通信需要明确一种通信协议,以规定数据的传输格式和相关参数。
在51单片机中,常用的串口通信协议有UART(Universal Asynchronous ReceiverTransmitter)和USART(Universal Synchronous Asynchronous Receiver Transmitter)。
UART是指不使用时钟信号而直接利用起始位、数据位和停止位来传输数据的协议,属于异步通信。
USART是指同步和异步传输都能实现的通信协议。
5. 数据传输过程串口通信的数据传输过程可以分为发送和接收两个部分。
5.1 发送数据发送数据的步骤如下:1.配置串口通信参数,包括波特率、数据位、停止位和校验位等。
2.将要发送的数据存放在发送缓冲区中。
3.设置发送开始标志位。
4.如果发送缓冲区为空,则等待直到缓冲区不为空。
5.将发送缓冲区中的数据通过串口发送出去。
6.等待发送完成。
51单片机串口通信(相关例程)

51单片机串口通信1./*打开串口调试程序,将波特率设置为9600,无奇偶校验晶振11.0592MHz,发送和接收使用的格式相同,如都使用字符型格式,在发送框输入hello,I Love MCU ,在接收框中同样可以看到相同字符,说明设置和通信正确*/#include <REG52.H>/*主程序*/void main (void){SCON = 0x50; /* SCON: 模式1, 8-bit UART, 使能接收*/TMOD |= 0x20; /* TMOD: timer 1, mode 2,8-bit reload*/TH1 = 0xFD; /* TH1: **********************************/ TR1 = 1; /* TR1: timer 1 run */EA = 1; /*打开总中断*/ES = 1; /*打开串口中断*/while (1) /*主循环不做任何动作*/{}}void UART_SER (void) interrupt 4 //串行中断服务程序{unsigned char Temp; //定义临时变量if(RI) //判断是接收中断产生{RI=0; //标志位清零Temp=SBUF; //读入缓冲区的值P1=Temp; //把值输出到P1口,用于观察SBUF=Temp; //把接收到的值再发回电脑端}if(TI) //如果是发送标志位,清零TI=0;}2.51单片机与电脑串口通信的C程序,最好是中断方式的#include <reg51.h>#include <string.h>unsigned char ch;bit read_flag= 0 ;void init_serialcom( void ) //串口通信初始设定{SCON = 0x50 ; //UART为模式1,8位数据,允许接收TMOD |= 0x20 ; //定时器1为模式2,8位自动重装PCON |= 0x80 ; //SMOD=1;TH1 = 0xFD ; //Baud:19200 fosc="11".0592MHzIE |= 0x90 ; //Enable Serial InterruptTR1 = 1 ; // timer 1 run}//向串口发送一个字符void send_char_com( unsigned char ch){SBUF=ch;while (TI== 0);TI= 0 ;}void serial () interrupt 4 using 3 //串口接收中断函数{if (RI){RI = 0 ;ch=SBUF;read_flag= 1 ; //就置位取数标志}}main(){init_serialcom(); //初始化串口while ( 1 ){if (read_flag) //如果取数标志已置位,就将读到的数从串口发出{read_flag= 0 ; //取数标志清0send_char_com(ch);}}}3.// 单片机串行口发送/接收程序,每接收到字节即发送出去// 和微机相接后键入的字符回显示在屏幕上// 可用此程序测试#include <reg51.h>#define XTAL 11059200 // CUP 晶振频率#define baudrate 9600 // 通信波特率void main(void){unsigned char c;TMOD = 0x20; // 定时器1工作于8位自动重载模式, 用于产生波特率TH1=(unsigned char)(256 - (XTAL / (32L * 12L * baudrate)));TL1=(unsigned char)(256 - (XTAL / (32L * 12L * baudrate))); // 定时器0赋初值SCON = 0x50;PCON = 0x00;TR1 = 1;IE = 0x00; // 禁止任何中断{while(RI == 0);RI = 0;c = SBUF; // 从缓冲区中把接收的字符放入c中SBUF = c; // 要发送的字符放入缓冲区while(TI == 0);TI = 0;}}4.//////////////// ///////////////////////////////////////////////////////////E51Pro.c//Easy 51Pro编程器主程序,负责通讯,管理编程操作/////////////////////////////////////////////////////////////////////////#include <E51Pro.h>BYTE ComBuf[18];//串口通讯数据缓存,发送和接收都使用UINT nAddress;//ROM中地址计数UINT nTimeOut;//超时计数ProWork pw;//编程器一般操作void Delay_us(BYTE nUs)//微秒级延时<255us{TH0=0;TL0=0;TR0=1;while(TL0<nUs)//利用T0做定时计数器,循环采样,直到达到定时值{}TR0=0;}void Delay_ms(UINT nMs)//豪秒级的延时<65535ms{UINT n=0;TR0=1;while(n<nMs)////利用T0做定时计数器,循环采样,直到达到定时值{TH0=0;TL0=20;while(TH0<4){}n++;}TR0=0;}BOOL WaitComm()//等待上位机的命令,18字节{RI=0;while(!RI){}//等待第一个字节ComBuf[n]=SBUF;RI=0;n++;for(n;n<=17;n++){nTimeOut=0;while(!RI){nTimeOut++;if(nTimeOut>10000)//后17个字节都有超时限制return 0;}ComBuf[n]=SBUF;RI=0;}return 1;}BOOL WaitResp()//等待上位机回应,1字节,有超时限制{nTimeOut=0;RI=0;while(!RI){nTimeOut++;if(nTimeOut>50000){return 0;}}RI=0;ComBuf[0]=SBUF;return 1;}BOOL WaitData()//写器件时等待上位机数据,18字节,有超时限制{BYTE n;RI=0;for(n=0;n<=17;n++){nTimeOut=0;while(!RI){nTimeOut++;if(nTimeOut>10000){return 0;}}RI=0;ComBuf[n]=SBUF;}return 1;}void SendData()//发送数据或回应操作完成,18字节{BYTE n=0;for(n;n<=17;n++){TI=0;SBUF=ComBuf[n];while(!TI){}TI=0;}}void SendResp()//回应上位机1个字节,在写器件函数中使用{TI=0;SBUF=ComBuf[0];while(!TI){}TI=0;}void SetVpp5V()//设置Vpp为5v{P3_4=0;P3_3=0;}void SetVpp0V()//设置Vpp为0v{P3_3=0;P3_4=1;}void SetVpp12V()//设置Vpp为12v{P3_4=0;P3_3=1;}void RstPro()//编程器复位{pw.fpProOver();//直接编程结束SendData();//通知上位机,表示编程器就绪,可以直接用此函数因为协议号(ComBuf[0])还没被修改,下同}void ReadSign()//读特征字{pw.fpReadSign();SendData();//通知上位机,送出读出器件特征字}void Erase()//擦除器件{pw.fpErase();SendData();//通知上位机,擦除了器件}void Write()//写器件{BYTE n;pw.fpInitPro();//编程前的准备工作SendData();//回应上位机表示进入写器件状态,可以发来数据while(1){if(WaitData())//如果等待数据成功{if(ComBuf[0]==0x07)//判断是否继续写{for(n=2;n<=17;n++)//ComBuf[2~17]为待写入数据块{if(!pw.fpWrite(ComBuf[n]))//<<< <<<<<<调用写该器件一个单元的函数{pw.fpProOver();//出错了就结束编程ComBuf[0]=0xff;SendResp();//回应上位机一个字节,表示写数据出错了WaitData();//等待上位机的回应后就结束return;}nAddress++;//下一个单元}ComBuf[0]=1;//回应上位机一个字节,表示数据块顺利完成,请求继续SendResp();}else if(ComBuf[0]==0x00)//写器件结束break;else//可能是通讯出错了{pw.fpProOver();return;}}else//等待数据失败{pw.fpProOver();return;}}pw.fpProOver();//编程结束后的工作Delay_ms(50);//延时等待上位机写线程结束ComBuf[0]=0;//通知上位机编程器进入就绪状态SendData();}void Read()//读器件{BYTE n;pw.fpInitPro();//先设置成编程状态SendData();//回应上位机表示进入读状态while(1){if(WaitResp())//等待上位机回应1个字节{if(ComBuf[0]==0)//ComBuf[0]==0表示读结束{break;}else if(ComBuf[0]==0xff)//0xff表示重发{nAddress=nAddress-0x0010;}for(n=2;n<=17;n++)//ComBuf[2~17]保存读出的数据块{ComBuf[n]=pw.fpRead();//<<<<<<<<<<调用写该器件一个单元的函数nAddress++;//下一个单元}ComBuf[0]=6;//向上位机发送读出的数据块SendData();}elsebreak;//等待回应失败}pw.fpProOver();//操作结束设置为运行状态ComBuf[0]=0;//通知上位机编程器进入就绪状态SendData();}void Lock()//写锁定位{pw.fpLock();SendData();}///////////////////////////////////////////////////////////////////////////////////所支持的FID,请在这里继续添加/////////////////////////////////////////////////////////////////////////////extern void PreparePro00();//FID=00:AT89C51编程器extern void PreparePro01();//FID=01:AT89C2051编程器extern void PreparePro02();//FID=02:AT89S51编程器void main(){SP=0x60;SetVpp5V();//先初始化Vpp为5vSCON=0x00;TCON=0x00;//PCON=0x00;//波特率*2IE=0x00;//TMOD: GATE|C/!T|M1|M0|GATE|C/!T|M1|M0// 0 0 1 0 0 0 0 1TMOD=0x21;//T0用于延时程序TH1=0xff;TL1=0xff;//波特率28800*2,注意PCON//SCON: SM0|SM1|SM2|REN|TB8|RB8|TI|RI// 0 1 0 1 0 0 0 0SCON=0x50;TR1=1;Delay_ms(1000);//延时1秒后编程器自举ComBuf[0]=0;SendData();while(1)//串口通讯采用查询方式{if(!WaitComm())//如果超时,通讯出错{Delay_ms(500);ComBuf[0]=0;//让编程器复位,使编程器就绪}switch(ComBuf[1])//根据FID设置(ProWork)pw中的函数指针{case 0: //at89c51编程器PreparePro00(); break;case 1: //at89c2051编程器PreparePro01(); break;case 2: //at89s51编程器PreparePro02(); break;//case 3:支持新器件时,请继续向下添加// break;//case 4:// break;default: ComBuf[0]=0xff;ComBuf[1]=0xff; //表示无效的操作break;}switch(ComBuf[0])//根据操作ID跳到不同的操作函数{case 0x00:RstPro();break; / /编程器复位case 0x01:ReadSign();break; //读特征字case 0x02:Erase();break;//擦除器件case 0x03:Write();break;//写器件case 0x04:Read();break;//读器件case 0x05:Lock();break;//写锁定位default: SendData();break;}}}5.v oid InitSerial(void){TMOD = 0x20; // T1 方式2PCON=0x00; // PCON=00H,SMOD=0 PD = PCON.2 = 1 进入掉电模式TH1 = TL1 = BAUD_9600; // BAUD: 9600SCON = 0x50; // 串行通信方式1 REN=1 允许接收ET1 = 0; // 不允许中断TR1 = 1; // 开启定时器1IE = 0; // 关闭所有中断允许位memset(&SerialBuf, 0x00, SERIAL_BUF_LEN); // 初始化SerialBuf[SERIAL_BUF_LEN] }/**********************************************************名称:SendByte()**功能:串口发送一个字节**输入:ucData**返回:无**说明:无********************************************************/void SendByte(unsigned char ucData){SBUF = ucData;while(!TI){_CLRWDT_;}TI = 0;}RS232串口通信程序#include <AT89X52.H>unsigned char code dispcode1[]={" welcome! "}; unsigned char code dispcode2[]={""}; unsigned char i,j,k,l,DData;sbit RS = P3^5;sbit RW = P3^6;sbit E = P3^7;unsigned char m=0;void delay(){for(l=0;l<=100;l++){}}void enable() //write order{RS=0;RW=0;E=0;delay();E=1;}void enable2() //write data{RS=1;RW=0;E=0;delay();E=1;}void initializtion() //lcd initializtion{for(i=0;i<=100;i++)P0=0x01;enable();P0=0x38;enable();P0=0x0f;enable();P0=0x06;enable();}void Display(m,DData) // display data{P0=0xC0+m; //write addressenable();P0=DData; //write dataenable2();}void Esisr() interrupt 4 //串口接收中断服务程序{unsigned char temp;ES=0;if(RI == 1){RI = 0;temp = SBUF; //接收数据SBUF=temp; //将接收到的数据发送至PC机Display(m,temp); //将接收到的数据送LCD显示while(!TI); //等待数据发送完成TI=0;m++;if(m>16)m=0;}ES=1;}void system_initial(void) //system initializtion{TMOD=0x21;// 定时器1工作方式2,定时器0工作方式1PCON=0x00;//数据传输率选择。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
51串口通信协议(新型篇)C51编程:这是网友牛毅编的一个C51串口通讯程序!//PC读MCU指令结构:(中断方式,ASCII码表示)//帧:帧头标志|帧类型|器件地址|启始地址|长度n|效验和|帧尾标志//值: 'n' 'y'| 'r' | 0x01 | x | x | x |0x13 0x10//字节数: 2 | 1 | 1 | 1 | 1 | 1 | 2//求和:///////////////////////////////////////////////////////////////////////公司名称:***//模块名:protocol.c//创建者:牛毅//修改者://功能描述:中断方式:本程序为mcu的串口通讯提供(贞结构)函数接口,包括具体协议部分//其他说明:只提供对A T89c51具体硬件的可靠访问接口//版本:1.0//信息:QQ 75011221/////////////////////////////////////////////////////////////////////#include <reg51.h>#include <config.h>//预定义//帧#define F_ST1 0x6e //帧头标志n#define F_ST2 0x79 //帧头标志y#define F_R 0x72 //帧类型读r#define F_W 0x77 //帧类型写w#define F_D 0x64 //帧类型数据帧d#define F_B 0x62 //帧类型写回应帧b#define F_C 0x63 //帧类型重发命令帧c#define F_Q 0x71 //帧类型放弃帧q#define F_ADDR 0x31 //器件地址0-9#define F_END 0x7a //帧尾标志z#define F_SPACE 0x30 //空标志0#define F_ERR1 0x31 //错误标志1,flagerr 1#define F_ERR2 0x32 //错误标志2 2//常数#define S_MAXBUF 16 //接收/发送数据的最大缓存量#define FIELD_MAXBUF 48 //最小场缓存,可以大于48字节,因为协议是以20字节为#define communicationing P1_7 //正在通讯(1)标志#define ERRFRAME_MAX 5 //连续NOFRAME_CNT次帧不正确#define ERR_NOCNTMAX_RESEND if(++errframe_cnt<=ERRFRAME_MAX)resend_frame(); else errframe_cnt=communicationing=0;//若超过ERRFRAME_MAX 次则令通讯停止ERR_NOCNTMAX_RESEND//public 变量unsigned char databuf[FIELD_MAXBUF],errframe_cnt;//函数///////////////////////////////////////////////////////////////////////函数名:send()//功能描述:向串口发送一个字符//函数说明://调用函数://全局变量://输入:ch-要发送的ASCII字符//返回:无//设计者:牛毅//修改者://版本://///////////////////////////////////////////////////////////////////void send(unsigned char ch){SBUF=ch;while(TI==0);TI=0;}///////////////////////////////////////////////////////////////////////函数名:receive()//功能描述:从串口接收一个字符//函数说明://调用函数://全局变量://输入:无//返回:一个ASCII字符//设计者:牛毅//修改者://版本://///////////////////////////////////////////////////////////////////unsigned char receive(void){RI=0;return SBUF;}///////////////////////////////////////////////////////////////////////函数名:CharToHex()//功能描述:把ASCII字符转换为16进制//函数说明://调用函数://全局变量://输入:ASCII字符//返回:16进制//设计者:牛毅//修改者://版本:///////////////////////////////////////////////////////////////////// unsigned char CharToHex(unsigned char bChar) {if((bChar>=0x30)&&(bChar<=0x39))bChar -= 0x30;else if((bChar>=0x41)&&(bChar<=0x46))//大写字母bChar -= 0x37;else if((bChar>=0x61)&&(bChar<=0x66))//小写字母bChar -= 0x57;else bChar = 0xff;return bChar;}///////////////////////////////////////////////////////////////////////函数名:HexToChar()//功能描述:把16进制转换为ASCII字符//函数说明://调用函数://全局变量://输入:16进制//返回:ASCII字符//设计者:牛毅//修改者://版本:///////////////////////////////////////////////////////////////////// unsigned char HexToChar(unsigned char bHex) {if((bHex>=0)&&(bHex<=9))bHex += 0x30;else if((bHex>=10)&&(bHex<=15))//大写字母bHex += 0x37;else bHex = 0xff;return bHex;}///////////////////////////////////////////////////////////////////////函数名:com_int()//功能描述:初始化串口//函数说明:默认其他参数为[baud_rate],n,8,1//调用函数://全局变量://输入:baud_rate 波特率//返回:无//设计者:牛毅//修改者://版本://///////////////////////////////////////////////////////////////////void com_init(unsigned int baud_rate){EA=1;ES=1;//ET1=1;SCON = 0x50; /* 0x52;//SCON */TMOD = 0x20; /*0x20;// TMOD */TCON = 0x60; /*0x60;// TCON */PCON=PCON&0x7f;switch(baud_rate){ //波特率设置case 1200:TL1=0xe8;TH1=0Xe8;break; //1200case 2400:TL1=0xf4;TH1=0Xf4;break; //2400case 4800:TL1=0xfa;TH1=0Xfa;break; //4800case 9600:TL1=0xfd;TH1=0Xfd;break; //9600case 19200:PCON=PCON|0x80;TL1=0xfd;TH1=0Xfd;break; //19200 case 38400:PCON=PCON|0x80;TL1=0xfe;TH1=0Xfe;break; //38400 default:TL1=0xfd;TH1=0Xfd;break;//9600}}//函数名:resend_frame()//功能描述:发送重发帧//函数说明:通知PC重发//调用函数://全局变量://输入:无//返回:无//设计者:牛毅//修改者://版本:///////////////////////////////////////////////////////////////////// void resend_frame(void){send(F_ST1);send(F_ST2);send(F_C);send(F_SPACE);send(F_SPACE);//发送效验和send(F_END);}///////////////////////////////////////////////////////////////////// //函数名:quit_frame()//功能描述:发送放弃帧//函数说明:通知PC放弃通讯//调用函数://全局变量://输入:无//返回:无//设计者:牛毅//修改者://版本:///////////////////////////////////////////////////////////////////// void quit_frame(void){send(F_ST1);send(F_ST2);send(F_Q);send(F_ERR1);send(F_ERR1);//发送效验和send(F_END);}//函数名:com_int()//功能描述:串口中断//函数说明://调用函数://全局变量://输入:无//返回:无//设计者:牛毅//修改者://版本://///////////////////////////////////////////////////////////////////void com_int()interrupt 4{unsigned char i,csaddr,clen,csum,tempbuf[S_MAXBUF]; csum=0;if(receive()==F_ST1){//是侦if(receive()==F_ST2){//头判断完communicationing=1;//设置通讯状态为正常即启动通讯switch(receive()){case F_R://是读指令帧rif(receive()==F_ADDR){P1_2=!P1_2;//地址正确csaddr=CharToHex(receive())<<4;csaddr+=CharToHex(receive());clen=CharToHex(receive())<<4;clen+=CharToHex(receive()); csum=csaddr+clen;i=CharToHex(receive())<<4;i+=CharToHex(receive());if(i==csum){//效验和正确if(receive()==F_END){//结束标志正确//开始发送数据帧csum=0;send(F_ST1);send(F_ST2);send(F_D);send(HexToChar((clen&0xf0)>>4));send(HexToChar(clen&0x0f));csum+=clen;for(i=0;i<clen;i++)send(HexToChar((databuf[i+csaddr]&0xf0)>>4)); send(HexToChar(databuf[i+csaddr]&0x0f));csum+=databuf[i+csaddr];}//if(csum>127)csum-=128;send(HexToChar((csum&0xf0)>>4));send(HexToChar(csum&0x0f));send(F_END);//发送数据帧完毕P1_0=!P1_0;}else{ERR_NOCNTMAX_RESEND break;}//结束标志错误}else{ERR_NOCNTMAX_RESENDbreak;}//效验和错误}//地址不正确break;case F_W://是PC写指令帧wif(receive()==F_ADDR){//地址正确csaddr=CharToHex(receive())<<4;csaddr+=CharToHex(receive());clen=CharToHex(receive())<<4;clen+=CharToHex(receive());csum=csaddr+clen;for(i=0;i<clen;i++){tempbuf[i+csaddr]=CharToHex(receive())<<4; tempbuf[i+csaddr]+=CharToHex(receive());csum+=tempbuf[i+csaddr];}i=CharToHex(receive())<<4;i+=CharToHex(receive()); if(csum!=i){ERR_NOCNTMAX_RESEND break;}//效验和错误if(F_END!=receive())ERR_NOCNTMAX_RESENDbreak;}//结束标志错误for(i=csaddr;i<clen+csaddr;i++)databuf[i-csaddr]=tempbuf[i-csaddr];//正确则保存数据}//从PC获得数据写完毕//开始发送写回应帧send(F_ST1);send(F_ST2);send(F_B);send(F_SPACE);send(F_SPACE);//发送效验和send(F_END);//写回应帧发送完毕P1_1=!P1_1;break;case F_Q://检测接收放弃帧csaddr=receive();csum+=csaddr;//csaddr兼做放弃帧码标志if(csaddr!=F_ERR1 && csaddr!=F_ERR2){ERR_NOCNTMAX_RESEND break;}if(csum!=receive()){ERR_NOCNTMAX_RESENDbreak;}if(F_END!=receive()){ERR_NOCNTMAX_RESENDbreak;}communicationing=0;//出错退出通讯break;default:resend_frame();//要求从发}}//忽略}//忽略if(!communicationing)quit_frame();//调用放弃帧,通知PC 放弃通讯}///////////////////////////////////////////////////////////////////主函数/////////////////////////////////////////////////////////////////void main(void){unsigned char i;for (i=0;i<FIELD_MAXBUF;i++) databuf=i+0x30;com_init(38400);while(1){/*可以处理非串口任务*/}。