利用串行接口传输各种数值数据

利用串行接口传输各种数值数据

天津滨海职业学院机电系  刘景文 胥宝萍 300451

摘  要:介绍了一种无应答数值发送、接收的协议,如何利用MCS-51单片机进行各种数值发送、在VC下借助 MSComm通信控件进行数值接收 ,并且给出了发送和接收处理程序的源代码及详细注释。解决了串行通信仅能发送字符型数据的难题,提出利用串行通信接口直接传输各种数值数据的方案,运行效果良好。

关键词:串行通信;MSComm;联合体

一、引言

随着计算机技术的发展 ,串口通信在诸多领域得到了广泛的应用 ,迫切需要通过串口来发送诸如浮点型等各种数值数据 ,然后利用计算机进行接收后,再编制程序对接收数据进行进一步分析处理。

本文采用MCS-51单片机进行数据采集和简单处理,将处理后的各种数值数据通过单片机扩展的RS-232串行接口传输出去,计算机端进行数据加工处理。本系统采用周期性的数值数据发送方法,为保证能可靠接收设计了独特的数据包格式,形成一种简单的无应答数值发送、接收协议。计算机根据此协议进行数据接收,还原出各种数值后,进行进一步分析处理。

二、MCS-51单片机端设计

1、通信协议

为做演示说明我们仅发送3个数据顺序依次为:字符型数据、整型数据、浮点型数据,字符型数据、整型数据、浮点型数据在MCS-51单片机的C语言中分别占用1、2、4个字节。由于是采用周期性的数值数据发送方法,为使PC机端能准确接收所发送数据设计数据包如下:

l  所有数据按发送顺序及占用字节数顺序排列,等待发送。

l  数据包以两个字节的数据0XFF表示数据包结尾。

l  当等待发送数据为0XFF时,插入转义字符0X27,避免发送数据中出现连续的两个0XFF,造成虚假的数据包结尾。

l  插入的转义字符在接收时自动删除,为避免发送数据为0X27时被自动删除,在其后也插入转义字符0X27。

2、单片机程序设计

由于发送、接收双方距离较近,故波特率设置为9600bps、数据位数为8 位、没有奇偶校验位、1位停止位。系统的定时器/记数器T0、T1已另作它用,故选择T2做为波特率发生器。使用T2做为波特率发生器时不会产生通讯中断。

单片机发送程序由两个子程序组成:串口初始化、数据发送。代码如下:

void init232(void) //串口初始化子程序
{
    SCON=0x50;
    PCON=0x80;
    T2CON=0x34;
    RCAP2L= 0xb2;
    RCAP2H= 0xff;
    TL2= 0xb2;
    TH2= 0xff;
    TR2=1;
}
void senddata()//数据发送子程序
{
    uchardata * data pd;
    uchari;
    pd=&char_data;  //send char data
    SBUF=*pd;
    while(TI==0);TI=0;
    if(((*pd)==0xff)|| ((*pd)==0x27))
    {
        SBUF=0x27;
        while(TI==0); TI=0;
    }
    pd=&int_data;  //send int data
    for(i=0;i<2;i++)
    {
        SBUF=*pd;
        while(TI==0); TI=0;
        if(((*pd)==0xff) || ((*pd)==0x27))
        {
            SBUF=0x27;
            while(TI==0); TI=0;
        }
        pd++;
    }
    pd=&float_data; &nbsp;//send float data &nbsp; &nbsp; &nbsp; &nbsp;
    for(i=0;i<4;i++)
    {
        SBUF=*pd;
        while(TI==0); TI=0;
        if(((*pd)==0xff) || ((*pd)==0x27))
        {
            SBUF=0x27;
            while(TI==0); TI=0;
        }
        pd++;
    }
    SBUF=0xff;//sendend flag
    while(TI==0); &nbsp;TI=0;
    SBUF=0xff;
    while(TI==0); &nbsp;TI=0;
}

数据发送子程序利用指针指向要发送数据,然后根据数据占用字节数,确定循环次数,在循环体内发送。由于我们定义的指针是字符型,在其指向整型数据、浮点型数据在内存的首地址时,编译器会给出WARNING性提示: “pointer to different objects”,它并不会影响程序的执行效果,可不予理会。要避免出现WARNING性提示,可采用计算机端的方法定义联合体型数据来解决,但代码会很长;另外编译器一般会按定义的次序顺序为变量分配内存,所以指针只要指向要发送的第一个数据,再根据全部数据占用字节数进行循环,可极大减少代码长度。

三、计算机端设计

Visual C++6.0是 Windows环境下的一种简单、高效的可视化编程语言开发系统 ,以其可视化界面设计风格和面向对象的程序设计等特点在工程实践中得到了广泛的应用 ,其简洁性和实用性已经受到了众多计算机用户和程序员的欢迎 ,尤其是其 6. 0版本 ,功能强大且易于掌握。它不但提供了良好的界面开发环境 ,而且具有功能强大的通信控件MicrosoftCommunications Control (MSComm)实用性强、功能完善 ,是实现计算机与外部设备数据交换的强有力工具 ,提供了很强的串口通信能力。计算机端设计过程如下:

1、在程序中嵌入通讯控件

启动VisualC++6.0,利用MFC的AppWizard新建一个项目文件,并命名为CommTe。在Appwizard第一步选择基于对话框的应用程序类型(Dialog based)。在第二步将ActiveX Controls 复选框选中,表示本程序支持ActiveX Controls控件。其他均接收缺省设置,AppWizard将自动生成一个以对话框为主窗口的应用程序。

单击Progect菜单,从菜单中选Add to Project,再单击Commponents and Control,从弹出对话框中单击Registered ActiveXControls,在列表框中选MicrosoftCommunications Control,单击OK。这时会询问你是否加入CMSComm类,单击OK,返回后看到控件工具条上添加了一个通讯控件(在图中用标有“电话”的方框表示),将其拖放到对话框中此时项目中增加一个类MSComm。

2、设置通讯控件的属性值

通过设置MSComm控件的属性对串口实例进行初始化,在OnInitDialog()中填入如下代码:

m_comm.SetCommPort(1);//指定串口号
m_comm.SetSettings("9600,n,8,1");//通信参数设置
m_comm.SetInBufferSize(256);//指定接收缓冲区大小
m_comm.InputMode( 1 );//设置数据获取方式
m_comm.SetInputLen(1 );//每次读操作从缓冲区中取1个字符
m_comm.SetRThreshold(1); //每接收1个字符就触发1次接收事件
m_comm.SetSThreshold(0); //不触发发送事件
m_comm.SetInBufferCount(0);//清空接收缓冲区
m_comm.SetPortOpen(TRUE);//打开串口

3、接收端数值的识别

       接收端数值的识别是方案实施的关键,接收端数值的识别分三种情况:字符型、整型数据、浮点型数据的识别。字符型数值的识别直接将接收的数据赋给字符型变量既可完成识别任务。

浮点型数值的识别采取联合体进行数据转换,以使用普遍的keil C为例,其规定浮点型数据占四个字节,保存顺序是低位在前、高位在后;keil C的浮点型数据和Visualc++6.0基本一致。我们可以定义联合体,利用联合体全部成员占用同一个存储空间的性质完成数据转换,定义的联合体形式如下:

union
{float m_ok_f;//最终转换的浮点数</span>
    struct{
        unsignedchar m_m1;//接收的浮点数据
        unsignedchar m_m2;
        unsignedchar m_m3;
        unsignedchar m_m4;
    }m_m;
}m_ok;

将接收到的四个字节的浮点型数据依次赋给m_ok .m_m .m_m4~1,后通过提取联合体数据成员m_ok.m_ok_f的数值完成浮点型数值转换。

整型数值的识别有多种方法,其识别依据是整型数值在单片机内的表示形式。整型数值以使用普遍的keil C为例,其规定整型数值占两个字节,以16位补码形式保存,低位在前、高位在后;keil C的整型数据和Visualc++6.0不一致,Visualc++6.0的整型数据占四个字节。现介绍两个识别方法:

方法1:在联合体中增加整型数据成员intm_ok_i,将接收到的两个字节的整型数据依次赋给m_ok .m_m .m_m4~3,判断m_ok.m_m .m_m4的值,如果大于0x80,则m_ok.m_m .m_m1~2赋值为0xFF,否则赋值0x00,后通过提取联合体的数据成员m_ok.m_ok_i的数值完成整型数值转换。

方法2:接收到的两个字节的整型数据,如果第一个字节大于0x80说明是负数,否则说明是正数;对正数第一个字节乘256再加第二个字节即可;对负数第一个字节乘256加第二个字节再减0X10000即可。

       需要提起注意,不同编译器存放数据的方式不同,有采用高位在前、低位在后的;也有采用低位在前、高位在后的;在进行接收端数值识别时一定要搞清存储方式再进行。

4、接收程序编制

当有通讯事件发生时(如接收数据),就会触发OnComm事件,在该事件的处理函数中调用Get CommEvent()函数,通过返回值确定是哪类事件,再做出相应的处理。为显示接收数值和进行协议处理,需填加变量和控件,不在缀述。

利用ClassWizard为MSCOMM控件填加消息响应的函数OnComm (),在该函数中添加代码,实现对串口事件的处理,函数GenInput()返回VARIANT型变量,经过COleSafeArray型变量转换为unsigned char型变量,后依次保存在unsigned char型数组buf(接收缓冲区)中,在保存过程中删除转义字符,同时判断是否出现数据包结尾字符,出现结尾标记时进行显示处理并清除接收缓冲区。代码如下:

VARIANTvariant_inp;
COleSafeArraysafearray_inp;
BYTErxdata[256];
longk,len;
if(m_comm.GetCommEvent()==2)
{
	variant_inp= m_comm.GetInput();
	safearray_inp= variant_inp;
	len= safearray_inp.GetOneDimSize();
	for(k= 0;k < len; k++ )
	safearray_inp.GetElement(&k,rxdata+k);
	buf[m_no]=rxdata[0];m_no++;m_st=0;
	if(m_no>9)
	m_no=0;
	if(m_no>1)
	{
		if(((buf[m_no-2]==0xff)&&(buf[m_no-1]==0x27))|| ((buf[m_no-2]==0x27)&&(buf[m_no-1]==0x27)))
		{
			m_no--;  m_st=1;goto lp;
		}
	}
	if((buf[m_no-2]==0xff)&&(buf[m_no-1]==0xff)&&(m_st==0))
	{
		if(m_no==9)//
		{
			m_f1.Format("%d",buf[0]);// 转换字符型数据
			if( buf[1]>=0x80) //转换整型数据
			m_f2.Format("%d", buf[1]*256+ buf[2]-0x10000);
			else
			m_f2.Format("%d", buf[1]*256+ buf[2]);
			m_ok.m_m.m_m1=buf[6];//转换浮点型数据
			m_ok.m_m.m_m2=buf[5];
			m_ok.m_m.m_m3=buf[4];
			m_ok.m_m.m_m4=buf[3];
			m_f3.Format("%f",m_ok.m_ok_f);
		}
		m_no=0;
		UpdateData(FALSE);
		m_comm.SetPortOpen(false);//关串口
		m_comm.SetPortOpen(true);//开串口
	}
lp:;
}

 需要额外说明,接收程序在使用过程中,碰到仅接收显示第一数据包数值的情况,接收到的其后各包值等于第一包;重新执行接收程序后,可正确接收第一数据包值,其后各包值仍等于重新执行接收程序后第一包。在接收完每一数据包后,关、开串口方解决此情况。如果没有出现此情况,可去掉关、开串口两语句。

四、结束语

本文提出了一种利用MCS-51单片机C语言程序和Visual C++实现单片机与计算机串口通讯的程序设计思路, 在此基础上设计的通讯协议可以传送各种类型数值信息,解决串行通信仅能发送、接收字符型数据的难题,运行效果良好。以上方法, 只要稍加改动便可实现计算机与计算机、单片机与单片机间的直接数值传输。该方案简单实用、可靠性高 ,在实际应用中取得了满意的效果。

参考文献:

1、马忠梅等. 单片机的C语言应用程序设计,北京航空航天大学出版社,2003

2、刘景文. 用delphi开发多媒体教室系统[J]. 天津成人高等学校联合学报 , 2005,(02)

作者简介:刘景文 (1968 - ,)男,天津市人,天津滨海职业学院电子信息工程技术教研室主任,副教授,主要研究计算机技术、电子技术的系统应用。胥宝萍(1970 - ,)女,天津市人,天津滨海职业学院电气自动化教研室主任,副教授,主要研究电子技术应用。

Transmit various type value with SerialCommunication interface

LIU Jing-wen   Xu bao-ping(Tianjin Binhai Professional Institute; Tianjin 300451 China)

[Abstract] The sended-received value protocol of non-response isintroduced in this paper, and how to  sendedvarious type value base on msc-51 mcu, and how to received various type valueusing Communication-controller of MSComm depended on VC, the software design ofsending-receiving data  was  described。the problem of Serial Communication only can sended- received char typevalue was Resolved, provides the design of transmitted various type value with Serial Communication interface,,theresult shows that the presented method is effective.

[ Key words]  serialcommunication   MSComm  union

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值