一种VB和单片机进行串行通信的可靠协议Word格式文档下载.docx
《一种VB和单片机进行串行通信的可靠协议Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《一种VB和单片机进行串行通信的可靠协议Word格式文档下载.docx(13页珍藏版)》请在冰豆网上搜索。
![一种VB和单片机进行串行通信的可靠协议Word格式文档下载.docx](https://file1.bdocx.com/fileroot1/2022-11/16/efd3022f-40a7-4fe3-b6b8-7dffe200175a/efd3022f-40a7-4fe3-b6b8-7dffe200175a1.gif)
如果在给定时间内(100MS)计算机不回,则重发。
如果连发三次都失败,则转向错误处理。
B、数据帧定义:
起始标志
数据长度
数据
校验位
0X55(U)
由函数的参数N决定
每帧不能超过128个字节
数据和校验
说明:
起始标志也可以作为标志位使用。
例如:
如果单片机要求计算机发送数据,则可以以0X56为起始标志,数据长度设为1,数据任填。
C、应答帧:
计算机每收到一个完整而正确的帧,就给单片机连发两个0X63(c)。
单片机收到任意一个即可认为应答成功。
此设计主要是防止应答数据丢失或错误。
D、错误处理:
如果任何一帧接收不成功,则向单片机发0xEE表示接收错误并要求重发。
同时,VB记录错误原因,以便编程者分析。
如果单片机连发三次都不成功,则指出错误原因。
VB的接收错误有:
握手错误、数据帧的起始帧错误、数据帧的校验帧错误。
单片机的发送错误有:
握手失败、数据传输失败。
二、单片机的软件设计
近一两年来单片机的C语言已经成为单片机编程的主要工具。
KeilC软件产生的代码长度以比的上中等程序员用汇编的水平。
而开发速度,软件质量和可从用方面,则远远超过了汇编。
因而软件部分用C51编写。
为了使协议较为清晰,笔者用流程图将计算机和单片机端的流程图画出,而具体的程序实现有兴趣着可参考后附的程序(程序实现以下例子的功能及信息出错的统计)。
(左图为单片机主程序,右图为握手函数)
例程:
单片机发送30H到50H的内存内容给计算机并由计算机统计传输次数、检测出错原因及次数。
A、SMAIN模块是主程序模块,主要进行内存的初始化、握手和数据传送。
传送成功后能显示。
B、SFUNCTION模块是函数模块,包括init_s(串口初始化),voidint_t0(void)interrupt1(定时中断),bitAck()(握手应答),voidSend_Data(chardata*Adrress,unsignedcharn)(任意长度的内存数据发送)
C、OnError(charErrorN)通信错误处理模块,主要功能是指出通信错误类型并强制停机。
(源程序及注解附后)
(此图为应答函数流程)
三、VB的软件设计
使用微软的VisualBasic6.0(简称VB6)来开发串口通信应用软件十分方便,编程工作量相对较小,只需进行主要应用功能的编程和少量界面控制的编程。
其中MSCOMM.OCX即是用于串行通信的控件。
常用的收发数据的方法有ONCOMM事件法、轮询法。
理论上讲,ONCOMM事件较为方便,可任意设置触发事件,字符串长度。
可设置Rthreshold=0使VB在一有数据时就触发ONCOMM事件。
但实际上,由于WINDOWS是多任务系统,很难获得精确的定时,因而也很容易漏掉数据包。
另外,对于变长的帧数据传输,ONCOMM事件也不太合适。
因而笔者采用轮询的方法,借助数据帧的先验知识,一直等待并对接收的数据进行校验。
如果校验错误则要求重发。
模块说明:
A、FunctionWaitRecieveByte()AsByte查询法等待数据模块
B、PrivateSubForm_Load()初始化模块
C、PrivateSubSendBuff(buff()AsByte)查询发发送数据模块
D、PrivateSubCommBegin_Click()整帧接收并校验模块
四、通信的可靠性分析
对于串行通信而言,程序的可靠性是由协议保证的。
通信的可靠性主要体现在所使用通信协议的可靠性上。
本通信协议的可靠性主要有以下考虑:
(1)通信之前先握手。
通过握手的方式可以判断硬件是否正常,计算机是否处于等待状态。
每次握手之间等待一段时间,以确保计算机状态。
并且连发三次,既可以给计算机一点反映时间,又可防止丢包。
(单片机发给计算机的握手信号丢)
(2)数据传输使用帧的方式。
这样整帧数据决不可能全部丢失。
校验字将整帧信号进行和校验则使误收的可能很小。
如果还不放心,则可采用CRC校验,极为可靠。
(3)帧方式通过帧方式判断帧头起始字符来决定一帧的开始这样就避免了部分数据进入到内部数据处理之中,这使数据处理错误的可能性又减少1/256,并可防止其他串行数据和要求数据混淆。
(4)应答采用连发两次0X63,即使丢包一次也不影响程序运行。
当然,如果两个包同时都丢,则单片机可能死机。
但这种情况实在是太少了。
可以采用硬件看门购狗的方式解决。
而且即使是在强干扰环境,对于单片机接收而言,一般也只是数据传输错误,很少丢包。
(5)单片机和VB程序都给出了详细的错误处理程序,很容易定位通信错误原因,并有针对性地修改协议。
结束语:
本文提出了一种单片机和微机串行通信时一种较为可靠的协议,并对此协议的可靠性进行了分析。
正文后所附程序正是为检验此协议的可靠性而设计的。
实践证明,一个好的通信协议会使单片机产品的可靠性大为提高。
参考文献:
史斌星史佳《VisualBasic贯通教程》清华大学出版社
马忠梅等《单片机的C语言应用程序设计》北京航空航天出版社
附1:
单片机程序
A、SMAIN模块
#include<
reg51.h>
stdio.h>
/*---全局变量---*/
charErrorNum=0;
/*ErrorNum出错时错误代码*/
/*-函数原型---*/
externvoidinit_s(void);
externvoidinit_t0(void);
/*内存填充函数*/
externvoidinit_m(chardata*Adress,unsignedcharn);
externbithd2hd();
//握手函数
externvoidSend_Data(chardata*Adrress,unsignedcharn);
//发送数据
externbitAck();
//应答函数
externvoidOnError(charErrorN);
//错误处理
/*--------------------------------------------------*/
voidmain(void)
{
chardata*da_point;
chardata*data_add;
init_s();
/*s串行通信初始化*/
da_point=0x30;
/*从30H开始初始化内存*/
init_m(da_point,35);
/*Memoryformatprogram*/
init_t0();
if(hd2hd()==0)/*握手*/
{
ErrorNum=1;
OnError(ErrorNum);
}
/*将30H开始地内存内容发送出去*/
data_add=0x30;
do
Send_Data(data_add,30);
}while(Ack()==0);
//--------------------------------
TI=1;
printf("
Sendsucess!
\n"
);
TI=0;
}
B、SFUNCTION模块
#include<
intrins.h>
#definetrueunsignedchar1
#definefalseunsignedchar0
#defineCOUNT10/*延时常数10*COUNTms*/
/*----------------------------------------*/
/*全局变量*/
bitflag_t=0;
/*-----------------------------------*/
/*串行通信初始化*/
voidinit_s(void)
TMOD=0X20;
TH1=0XE8;
TL1=0XE8;
PCON=0X00;
/*SMOD=0;
*/
SCON=0X50;
/*方式1且允许接收*/
TR1=1;
/*Memoryformatfunction*/
voidinit_m(chardata*Address,unsignedcharn)
unsignedchari=0;
Address=0x30;
for(i=0;
i<
n;
i++)
*Address=0x55;
Address++;
/*TIMER0初始化*/
voidinit_t0(void)
TMOD=TMOD|0X21;
/*ITISNOTAgerneralline*/
TH0=0xdc;
/*10MSinterruptdelay*/
TL0=0x00;
EA=1;
ET0=0;
/*enableitifwanttowork*!
!
TR0=0;
/*----------------------interruptprogram----------------------*/
voidint_t0(void)interrupt1
staticunsignedcharn=0;
n+=1;
/*notbest*/
if(n==COUNT)
flag_t=1;
n=0;
//---------------------------------------------------------
/*应答*/
bitAck()
unsignedchari,j;
while(RI==0);
RI=0;
i=SBUF;
ET0=1;
//---------------!
TR0=1;
while(RI==0&
&
flag_t==0);
/*wait*/
//-------------------restoreflag
RI=0;
flag_t=0;
j=SBUF;
//--------------------
if((