• 162.83 KB
  • 29页

微机原理项目报告-双机串行通信

  • 29页
  • 当前文档由用户上传发布,收益归属用户
  1. 1、本文档共5页,可阅读全部内容。
  2. 2、本文档内容版权归属内容提供方,所产生的收益全部归内容提供方所有。如果您对本文有版权争议,可选择认领,认领后既往收益都归您。
  3. 3、本文档由用户上传,本站不保证质量和数量令人满意,可能有诸多瑕疵,付费之前,请仔细先通过免费阅读内容等途径辨别内容交易风险。如存在严重挂羊头卖狗肉之情形,可联系本站下载客服投诉处理。
  4. 文档侵权举报电话:19940600175。
'《微机原理》课程项目实施报告题目(三):双机串行通信组号:第19组任课教师:方针组长:11123128吴慧泽21%成员:11123227丰硕19%成员:11123201温英杰19%成员:11123168范特21%成员:11123260崔向阳20%联系方式:18817393058二零一三年五月十八日 课程项目名单统计表课程项目名单统计表表一:课程项目名单统计表组号:19任课教师(√)方针沈明华王向阳学生学号学生姓名吴慧泽11123128是温英杰11123201是范特11123168是丰硕11123227是崔向阳11123260是 一、课程项目实施方案(题目要求,说明设计思想、指标及实现方法,所需器件清单等)题目要求:实现单片机和PC机之间的双机双工串行通信。(1)设计上位机(汇编语言设计)、下位机通信程序(C语言、汇编不限),通信波特率9600bps,8位数据、1个停止位、无校验。(2)全双工通信。(3)分别在PC机屏幕和实验板LCD上显示接收到的内容(4)其它扩展功能。实验材料:(1)单片机实验板(2)通信接口电缆(3)电阻、电容、三极管等若干单片机选型:通过组内讨论,考虑到实验室发的51系列的单片机相对于学院给我们配发的MSP430单片机的学习资源更丰富,并且项目制作中所需硬件(部分元器件)和软件资源都要相对于MSP430单片机更易获得,所以我们组决定采用51单片机来设计和完成本课程项目。设计思想:硬件方面:实验室所发的单片机实验板上配有许多小部件,可以根据要实现的功能,将STC89C52RC单片机与小部件配合连接使用。由于STC89C52RC单片机有一个全双工UART串行通信接口,通过实验板上的MAX232电平转换芯片和RS-232C非标准(即DB9)串口与PC机连接,从而可实现单片机与PC机之间的全双工串行通信,即同时接收和发送数据。软件方面:上位机和下位机通信程序均用汇编语言编写设计,STC单片机采用中断方式接收PC发送的数据并回送,串行口的工作方式为工作方式1,使用11.0592MHz晶振,并以定时器T1的方式2为波特率发生器,波特率在汇编程序中设置为9600,PC采用查询方式收、发数据。我们采用KeiluVision2软件工具来进行通信程序的编写、编译与调试,采用STC单片机PC端ISP下载控制软件STC-ISP-V4.83将编译调试好的程序烧写到单片机内。指标实现预期:基本指标:满足全双工通信要求,能在PC机屏幕和实验板LCD上显示接收到的内容。扩展功能:随后续项目的进展逐步在原要求功能基础上加以扩展。 一、项目的制作过程领到单片机后,我们组迅速开展了项目资料的查找与学习。大致了解了所用开发板的基本组成和结构,知道了用何种软件将程序烧写到单片机内,以及51单片机程序编译软件,还了解到与单片机串口有关的调试工具——串口调试助手。至此,我们将工作重心放在学习有关的编程语言:C语言和汇编语言,计划开始编写上位机和下位机通信程序。小组成员学习任务都很重,而且组员各自都有自己额外的奋斗目标,比如电子竞赛,考托福,所以开始的时候我们的项目进展缓慢。在获得老师提供的开发板资料后,我们就利用其中配套程序里面的mini80E功能测试程序对单片机的基本功能进行了测试,当时除了串口通信功能外,其余功能均正常。而进行串口通信功能测试时,我们用串口调试助手向单片机发送字符,在接收区看到的字符与发送的字符不一样,不是多一个字符就是乱码。然而我们检查相关的设置,波特率、数据位和停止位都设置无误。后来了解到,是开发板上所带的晶振的问题。开发板上的晶振是12Mhz,我们查资料了解到,在12Mhz晶振下,设置出来的9600波特率与实际有很大的误差,这个误差在串口调试助手接受范围之外,所以出现了乱码。我们就改用我们自己买的单片机上带的11.0592Mhz的晶振,结果收发数据之间没有出现偏差。这使我们终于松了一口气。然而,这仅仅是用现有的配套程序进行功能测试。真正实现单片机与PC机之间的串行通信还有相当多的工作要做。随着微机原理课程的学习和项目的进行,我们小组主要遇到了以下的几个问题:1)用C语言编写还是用汇编语言编写?虽然题目未要求下位机程序用什么语言编程,但根据老师的说法,建议使用汇编语言。由于汇编语言是与CPU紧密相关的,要想学习后达到能编一个程序的水平,就必须要求对CPU的内部结构有一定深度的了解,和与CPU对应的指令系统有很深的了解。说实话,从身边有些同学反映汇编语言学起来很生硬很吃力,以及我们小组成员学习汇编的感受,都感觉汇编不如C形象生动、容易上手,而且我们之前学过C,大家都有一定的底子,所以编程难度降低了不少,加上单片机方面各个部件的参考程序例如液晶显示,矩阵按键程序等等都以C语言居多,所以我们不用花很多时间去研究各种汇编指令,这会使我们项目成功实现所需的时间大大缩短。所以我们一致认同用C编写下位机通信程序。而对于上位机,我们使用的是汇编语言。我们觉得这样既能紧密结合课程所学,亦能节约时间,尽快完成任务。当我们参照C语言样例程序编写了一个能液晶显示、能接收数据的简单通信程序时,这时我们还只是停留在用串口助手进行下位机程序的调试,因为我们还不清楚编写好的上位机通信程序是怎样通过串口线与单片机进行通信。当我们用用串口调试助手向单片机发送字符,当发送十个以下字符时,能从液晶的第一行开始显示,但当两行显示满后,跳到第一行继续显示时,却只能最多显示两个字符,其余的均不能显示;还有,当发送超过十个字符时,就会有字符丢失,但在接收子程序中把液晶写字符函数注释掉后,串口助手能够正确接收 ,没有字符丢失。我们刚开始认为是单片机接收数据时由于字符的ASCII码是7位二进制,而我们设定数据格式为8位数据位,这样发送多个字符时,后面的会和前面排列紧密导致乱序。后来项目答疑的时候问王老师,王老师说不是这个问题。2)要不要对开发板上的矩阵键盘编程?项目要求是要实现双机串行通信,那肯定要求双方既能接收又能发送,所以还要嵌入相应按键发送数据程序。但是,从单片机向PC机发送数据是用开发板上的矩阵键盘还是用PS2键盘,这都涉及如何人为手动发送数据的子程序内嵌问题,这就要求对通信主程序、液晶显示程序和按键发送数据程序进行整合。这会使后面的调试更加复杂。最后我们还是决定用矩阵键盘,虽然用PS2键盘可以发送多种字符,但是这样可以减少项目制作的成本。当我们把矩阵键盘程序嵌入之前的程序里面后,每个按键都有用,按键代表的字符都能在液晶上显示,但唯独接收程序不能接收来自串口助手发来的字符,而且不能显示。这令我们颇为困惑,为此我们琢磨究竟问题出在哪,对程序反复修改并调试,发现注释掉发送程序代码后,单片机可以接收并显示,但不能发送,继续调试了很多次后还是不能同时接收和发送。这个问题一直困扰着我们,我们觉得是接收和发送中断不能等条件的进入中断,导致不能实现既可以发也可以收数据。到后来,我们发现下位机程序中,按键扫描程序是一直在运行的,我们看开发板的组成原理图,发现矩阵键盘四条行线和四条列线是与单片机P3口相接的,这就说明作为串口通信的P3.0、P3.1口被用作普通I/O口了,这就造成了不能准确通信。并且我们还就此咨询了王旭智老师,问是不是P3.0、P3.1口既用作通信口又用作普通I/O口造成的问题,老师说是,说P3口不能既作普通I/0口又作串行通信口,这样会有冲突。后来我们又问了方针老师,并证实了我们的问题就是出在这里。方老师建议说,可以进行I/O口扩展,将矩阵键盘连接到扩展的I/O口上,避免与串口发生冲突,但是需要另外的芯片,然而开发板上没有这样的芯片,基于项目制作成本和我们的能力以及时间问题,我们决定不用矩阵键盘作为按键,而转用独立键盘中不与串口冲突的几个按键。所以我们就编了两个按键只能按0和1两个字符,这时我们可以进行双机通信了,单片机和PC按一个发一个。但是我们有组员觉得两个按键太少了太单调了,所以我们后来又扩展到了8个按键,这8个按键不与P3.0、P3.1连接,所以不会产生冲突,增加了可发送字符的个数,并且我们设置了发送键即PC机上面的回车键(ASCII码为0DH),可以发送一连串的多个字符,因为把将要发送的字符先存到数组里面,按回车键启动发送。3)怎样加入扩展功能?基本要求实现后,我们就开始想如何对功能进行扩展。首先下位机程序中能加入也能容易控制的就属LED了,我们就让单片机的串口每次有数据流时LED就闪烁。但我们觉得这个功能太弱太小儿科了。我们有想过利用红外发射和接收来进行数据传送,但这个对于通电学得不好的我们来说简直很难实现。下位机我们没想出扩展什么功能。上位机可以,我们有组员提出现有的程序是启动就开始通信,但在实际中并不是双机都同时准备好通信了,有可能上位机在处理别的事,所以基于这个,我们设计下位机要想与上位机进行通信需要发送可握手密码,这里我们设定为“7”,上位机程序启动时,是一个黑框框,光标在闪烁,若下位机发送的字符中第一个是“7”,上位机就发送“OK!” 给单片机,表示可以通信了,若不是“7”,黑框框就显示“NO!”。但在调试时发现了问题,不能一开始没建立握手前就按电脑键盘,否则下位机按7发送后,黑框框不仅显示“OK!”,也把刚才按的键也显示在屏幕上了,按理说这不合理,不符合规范。所以我们就加了些提示,提示单片机先发送请求连接字符,这样不会出现上面的问题。我们觉得这比较符合工程规范,下位机是从机,要通信前先请求主机。项目分工情况:刚刚开始的时候我们是一起查找资料,并聚在一起讨论可以从哪几个方面入手这个项目,基本确定了设计思想和项目实现的框架。在单片机测试时是由丰硕和崔向阳测试并发现问题的,最后是由范特解决了问题。上位机程序由组长吴慧泽和范特共同完成,下位机程序由范特与温英杰共同完成,最终报告和PPT由崔向阳与吴慧泽共同完成。其中,组长吴慧泽全程都对各个环节进行了安排、检查与督促。最终经过协商,觉得按封面所示比例量化确定贡献。三、项目的结果分析A.开机初始化时开机后,PC机对话框显示“waiting…”,单片机显示“Pleaseenterthepassword...”B.单片机上各按键代表字符测试:由左到右,由上至下依次按下按键,单片机显示‘7654321’。得到各按键对应含义如下表:7654321ENTERC.建立单片机与PC机的握手测试结果(开机的第一次操作)1、首先单片机发送‘7’,PC机dos窗口显示‘OK!’,并返回‘OK!’给单片机,单片机屏幕显示‘OK!’,表示可以进行通话。2、首先单片机发送‘7654321’PC机显示‘OK!’,并返回‘OK!’给单片机。3、单片机发送除‘7’外的字符,PC机显示‘NO!’,并且不返回给单片机。表示不能通话。当再次发送‘7’时,PC机会先显示按‘7’之前PC机键盘输入的字符,再显示‘OK!’,单片机上显示‘OK!’。因为PC机是读取键盘缓冲区的,未建立连接时,PC机不会显示字符,按PC机的键盘不显示字符,但在建立连接之后,PC机会先读取键盘缓冲区,显示其中的字符,而之前键盘按的字符也在里面,所以会显示出来。D.单片机向PC机发送字符测试(在建立握手对话的基础上)设置了八个按键,实际可显示的有7个字符。分别是‘1’,‘2’,‘3’,‘4’,‘5’,‘6’,‘7’。1、发送‘7654321’,PC机显示‘7654321’;2、发送‘ENTER’,PC机显示换行;3、发送‘7’,PC机显示‘7’。E.PC机向单片机发送字符测试(在建立握手对话的基础上)凡是可显示字符均可发送并发送。按‘ENTER’键发送。1、发送‘0’,单片机显示‘0’,并返回给PC机显示‘0’;2、发送‘1203’时,单片机显示‘1203’,并返回PC机‘1203’。 1、发送‘abcd’,单片机显示‘abcd’,并返回给PC机显示‘abcd’;2、发送空格,单片机显示‘’,并返回给PC机显示‘’;3、发送‘?’,单片机显示‘?’,并返回给PC机显示‘?’;4、单片机无显示字符情况下,发送‘123456789123456789123456789123456789123456789’时,单片机在新的一页显示‘6789123456789’;并返回PC机显示‘123456789123456789123456789123456789123456789’;5、直接按‘ENTER’时,单片机无反应。结果分析:符合我们的如下要求:设计要求:1、上位机使用汇编语言设计,下位机通信程序使用C语言程序,通信波特率9600bps,8位数据、1个停止位、无校验。功能要求:1、实现了全双工通信。2、分别在PC机屏幕和实验板LCD上上显示接收到的内容规则要求(我们自己设定的):1、首次命令,必须建立连接,方法:单片机发送字符‘7’。PC机显示并返回单片机显示‘OK!’。否则其他字符,PC机显示‘NO!’无返回。2、单片机有发送标志‘ENTER’;3、单片机向PC机发送字符,PC机不会返回给单片机;4、PC机向单片机发送字符,单片机返回给PC机并显示,便于检错;5、PC机发送除空格、‘ENTER’字符,单片机显示时主动在后面加空格,便于观察区分发送和接收的;6、PC机直接发送‘ENTER’,单片机不予反应。上位机外加拓展:1、增加了初始时PC机状态、单片机输入密码提示,更加人性化,符合工程规范,便于操作;2、输入密码正确与否的判断与显示。附件一:设计流程图:下位机程序流程图: 是否是是否连接否系统初始化开始读入连接密码发送连接密码到PC机显示“Pleaseenterthepassword!”接收PC机指示接收PC机传来的字符串读入单片机键盘输入字符显示空格显示字符串是否为“ENTER”储存到数组显示字符发送数组到PC机返回字符串到PC机结束上机位程序流程图: 否是是是否系统初始化开始读取单片机发送的连接密码是否为‘7’显示‘NO!’显示‘OK!’发送‘OK!’到单片机否读入单片机传来的字符串读入PC机键盘输入字符显示换行显示字符是否为“ENTER”储存到发送字符缓冲区显示字符发送字符串到单片机结束显示“waiting…”储存到接收字符缓冲区读取字符是否为“ENTER” 附件二:下位机程序:8按键扫描,通信时先要建立握手,发请求信号,我们设计7为请求信号,按回车键(我们定义其中一个键为回车键即0DH)发送,且发送和接收数据后先存入数组,然后回送给PC,注意以0DH结尾。#include#include#include#defineucharunsignedchar#defineuintunsignedintsbitRS=P2^4;//定义端口sbitRW=P2^5;sbitEN=P2^6;sbitKeyPort0=P3^2;sbitKeyPort1=P3^3;sbitKeyPort2=P3^4;sbitKeyPort3=P3^5;sbitKeyPort4=P3^6;sbitKeyPort5=P3^7;ucharcodetable[]={"Pleaseenterthepassword..."};//单片机请输入password#defineDataPortP0#defineRS_CLRRS=0#defineRS_SETRS=1#defineRW_CLRRW=0#defineRW_SETRW=1#defineEN_CLREN=0#defineEN_SETEN=1ucharrec_str[32];ucharsend_str[32];ucharm=0,n=0,num=0;uchark=0;temp=0;unsignedchara=0,b=0,i=0,j=0;unsignedcharflag=0,flag1=0;unsignedcharKeyPro(void);unsignedcharKeyScan(void);voidyjxs(ucharData);voidreceive(uchar*s);voidsend(uchar*r);voiddelay(ucharz){ ucharx,y;for(x=z;x>0;x--)for(y=120;y>0;y--);}/*------------------------------------------------判忙函数------------------------------------------------*/bitLCD_Check_Busy(void){DataPort=0xFF;RS_CLR;RW_SET;EN_CLR;_nop_();EN_SET;return(bit)(DataPort&0x80);}/*------------------------------------------------写入命令函数------------------------------------------------*/voidLCD_Write_Com(unsignedcharcom){while(LCD_Check_Busy());//忙则等待RS_CLR;RW_CLR;EN_SET;DataPort=com;_nop_();EN_CLR;}/*------------------------------------------------写入数据函数------------------------------------------------*/voidLCD_Write_Data(unsignedcharData){while(LCD_Check_Busy());//忙则等待RS_SET;RW_CLR;EN_SET;DataPort=Data;_nop_();EN_CLR;yjxs(Data);} /*------------------------------------------------清屏函数------------------------------------------------*/voidLCD_Clear(void){LCD_Write_Com(0x01);delay(5);}/*------------------------------------------------写入字符函数------------------------------------------------*/voidLCD_Write_Char(unsignedcharx,unsignedchary,unsignedcharData){if(y==0){LCD_Write_Com(0x80+x);}else{LCD_Write_Com(0xC0+x);}LCD_Write_Data(Data);}/*------------------------------------------------LCD初始化函数------------------------------------------------*/voidLCD_Init(void){LCD_Write_Com(0x38);/*显示模式设置*/delay(5);LCD_Write_Com(0x38);delay(5);LCD_Write_Com(0x38);delay(5);LCD_Write_Com(0x38);LCD_Write_Com(0x08);/*显示关闭*/LCD_Write_Com(0x01);/*显示清屏*/LCD_Write_Com(0x06);/*显示光标移动设置*/LCD_Write_Com(0x0f);delay(5);//LCD_Write_Com(0x0C);/*显示开及光标设置*/}/*------------------------------------------------ 发送一个字节------------------------------------------------*/voidSendByte(unsignedchardat){SBUF=dat;while(!TI);TI=0;}/*------------------------------------------------发送一个字符串------------------------------------------------*/voidSendStr(unsignedchar*s){while(*s!=0x0d)//回车表示字符串结束标志,通过检测是否字符串末尾{SendByte(*s);s++;}}voidinitial(){LCD_Init();LCD_Clear();//清屏P1=0xff;//关LED灯TMOD=0x20;TH1=0xfd;TL1=0xfd;TR1=1;//启动定时器1ET1=0;//关定时器1中断SM0=0;//串行工作方式SM1=1;REN=1;//允许串行接受位EA=1;//开cpu总中断ES=1;//打开串口中断TI=0;RI=0;PCON=0x00;//波特率不加倍i=j=0;}/*------------------------------------------------串行中断函数 ------------------------------------------------*/voidser()interrupt4{if(RI==1){P1=0XF0;//进入中断后,P1.4--P1.7灯指示if(m==32){m=-1;}rec_str[m]=SBUF;//接受数据存入数组RI=0;if(rec_str[m]==0x0d)//收到结束位,然后进入显示函数{receive(rec_str);m=-1;}m++;}}/*------------------------------------------------进入主函数------------------------------------------------*/voidmain(){initial();for(k=0;k<29;k++)//显示提示输入连接信号{LCD_Write_Char(i,j,table[k]);}while(1){num=KeyScan();//扫描键盘if(num!=0xff){send_str[n]=num;//读取键盘数据存入数组中if(send_str[n]!=0x0d)//收到发送信号然后发送LCD_Write_Char(i,j,num);//显示按键字符if(n==32){n=-1;}if(send_str[n]==0x0d)//收到发送enter信号然后发送{P1=0X0F;//进入发送函数P1.0--P1.3灯指示send(send_str);//进入发送函数LCD_Write_Char(i,j,0x20);//显示空格表示一次通话结束n=-1;} n++;}}}/*------------------------------------------------接受显示函数------------------------------------------------*/voidreceive(uchar*s){SendStr(s);SendByte(0x0d);while(*s!=0x0d){while(*s!=0x0d){LCD_Write_Char(i,j,*s);s++;}LCD_Write_Char(i,j,0x20);}}/*------------------------------------------------发送函数------------------------------------------------*/voidsend(uchar*r){SendStr(r);SendByte(0x0d);}/*------------------------------------------------液晶显示调整函数------------------------------------------------*/voidyjxs(ucharData){i++;if((i==17)&&(j==1)){j=0;i=0;LCD_Write_Com(0x01);//清屏delay(5);LCD_Write_Char(i,j,Data);delay(5);} if((i==16)&&(j==0)){j++;i=0;}}/*------------------------------------------------键盘扫描函数,使用行列逐级扫描法------------------------------------------------*/unsignedcharKeyScan(void){unsignedcharVal;KeyPort0=KeyPort1=0;KeyPort2=KeyPort3=KeyPort4=KeyPort5=1;//高四位置高,低四位拉低if(!((KeyPort0==0)&&(KeyPort1==0)&&(KeyPort2==1)&&(KeyPort3==1)&&(KeyPort4==1)&&(KeyPort5==1)))//表示有按键按下{delay(10);//去抖if(!((KeyPort0==0)&&(KeyPort1==0)&&(KeyPort2==1)&&(KeyPort3==1)&&(KeyPort4==1)&&(KeyPort5==1))){//表示有按键按下KeyPort0=0;KeyPort1=KeyPort2=KeyPort3=KeyPort4=KeyPort5=1;//检测第一行if(!((KeyPort0==0)&&(KeyPort1==1)&&(KeyPort2==1)&&(KeyPort3==1)&&(KeyPort4==1)&&(KeyPort5==1))){if(KeyPort2==0){Val="3";}if(KeyPort3==0){Val="2";}if(KeyPort4==0){Val="1";}if(KeyPort5==0){Val=0x0d;}while(!((KeyPort0==0)&&(KeyPort1==1)&&(KeyPort2==1)&&(KeyPort3==1)&&(KeyPort4==1)&&(KeyPort5==1)));delay(10);//去抖while(!((KeyPort0==0)&&(KeyPort1==1)&&(KeyPort2==1)&&(KeyPort3==1)&&(KeyPort4==1)&&(KeyPort5==1)));returnVal;}KeyPort1=0;KeyPort0=KeyPort2=KeyPort3=KeyPort4=KeyPort5=1;//检测第二行 if(!((KeyPort0==1)&&(KeyPort1==0)&&(KeyPort2==1)&&(KeyPort3==1)&&(KeyPort4==1)&&(KeyPort5==1))){if(KeyPort2==0){Val="7";}if(KeyPort3==0){Val="6";}if(KeyPort4==0){Val="5";}if(KeyPort5==0){Val="4";}while(!((KeyPort0==1)&&(KeyPort1==0)&&(KeyPort2==1)&&(KeyPort3==1)&&(KeyPort4==1)&&(KeyPort5==1)));delay(10);//去抖while(!((KeyPort0==1)&&(KeyPort1==0)&&(KeyPort2==1)&&(KeyPort3==1)&&(KeyPort4==1)&&(KeyPort5==1)));returnVal;}}}return0xff;}上位机程序:我们有三个程序。上位机程序1:若单片机先要第一个发的数据是7就建立连接,可以开始通信,不是就不能通信,若PC机先按键盘,则PC机收到7后会显示出错STACKSEGMENTDB256DUP(0)ZSDB256DUP(0);定义握手开始建立时的暂时数据缓冲区STACKENDSDATASEGMENTSEDDB256DUP(0);定义发送数据缓冲区RECDB256DUP(0);定义接收数据缓冲区DATAENDSCODESEGMENTASSUMECS:CODE,DS:DATA,SS:STACKBEGINPROCFARPUSHDS;保存PSP段地址XORAX,AXPUSHAX;保存返回地址偏移值START:;初始化8250为:8位数据位,1位停止位,无校验,波特率9600MOVAX,DATAMOVDS,AX LEASI,SEDLEADI,RECLEABP,ZSMOVDX,3FBHMOVAL,80HOUTDX,ALMOVDX,3F8HMOVAL,0CHOUTDX,ALMOVDX,3F9HMOVAL,0OUTDX,ALMOVDX,3FBHMOVAL,03HOUTDX,ALMOVDX,3FCHMOVAL,03H;内部输出输入不反接OUTDX,ALMOVDX,3F9HMOVAL,0;禁止中断,采用查询方式进行信息交换OUTDX,ALXORCX,CXXORBX,BXFOREVER:;循环一,用于双机建立握手时查询请求联络信号MOVDX,3FDHINAL,DXTESTAL,1EH;测接收是否出错JNZB9TESTAL,01H;测接收数据是否准备好JNZWS;是就转握手程序,不是就继续查询JMPFOREVERWS:MOVDX,3F8H;握手程序INAL,DXANDAL,7FHMOV[BP],ALINCBPCMPAL,0DH;判断下位机是否发送,是就转处理程序JZB8JMPFOREVERB7:MOVAL,4EH;不是请求联络信号“7”就显示NO!表示未建立连接MOVBL,0MOVAH,14INT10HMOVAL,4FH MOVBL,0MOVAH,14INT10HMOVAL,21HMOVBL,0MOVAH,14INT10HMOVAL,0AHMOVBL,0MOVAH,14INT10HMOVDL,0DHMOVAH,2INT21HJMPFOREVERB9:JMPERROROK:LEABP,ZS;取暂时握手接收数据缓冲区首地址MOVAL,[BP]CMPAL,37H;第一位是否为7,是就发送OK!注意PC是按回车发送JNZB6;不是就转MOVAL,4FHMOVDX,3F8HOUTDX,ALMOVAL,4BHMOVDX,3F8HOUTDX,ALMOVAL,21HMOVDX,3F8HOUTDX,ALMOVAL,0DHMOVDX,3F8HOUTDX,ALFOREVER1:;发送OK!后,就直接进入正常通信程序,查询输入输出MOVDX,3FDHINAL,DXTESTAL,1EHJNZERRORTESTAL,01HJNZRECEIVETESTAL,40H;测发送移位寄存器是否为空,不空继续查询JZFOREVER1TESTAL,20H;测发送保持寄存器是否为空,不空返回查询JZFOREVER1MOVAH,1;空就测键盘缓冲区是否有字符 INT16HJZFOREVER1;无就返回查询MOVAH,0INT16HMOV[SI],AL;有就存入到发送缓冲区,同时CL作为计数寄存器INCSIINCCLCMPAL,0DH;是否为回车发送,是就转发送处理JZB0MOVBL,0;不是就将按键显示MOVAH,14INT10HJMPFOREVER1B8:JMPB5;由于JZ命令转移范围较小,所以中转一下ERROR:;接收出错处理,显示问号并换行MOVAL,"?"MOVBL,0MOVAH,14INT10HMOVDL,0DH;换行MOVAH,2INT21HJMPFOREVER1B0:MOVAL,0AH;按了回车就要换行MOVBL,0MOVAH,14INT10HMOVDL,0DHMOVAH,2INT21HJMPB1;转B1开始发送B5:JMPOKB6:JMPB7RECEIVE:MOVDX,3F8HINAL,DXANDAL,7FHCMPAL,0DH;第一个是否为回车,为回车就转显示,不是就存入接收缓冲区JZXSMOV[DI],ALINCDIINCCH;将接收到的计数JMPFOREVER1XS:LEADI,REC;显示程序开始 B4:MOVAL,[DI]CMPAL,0DH;第一个是否为回车,是,PC端就换行JZB3DECCH;接收数据个数为0,同样PC端就换行JSB3MOVBL,0;不是就显示在屏幕上MOVAH,14INT10HINCDIJMPB4B1:LEASI,SED;取发送缓冲区首地址B2:MOVAL,[SI]INCSIMOVDX,3F8HOUTDX,ALDECCLJNZB2LEASI,SED;发送完重新指向首地址JMPFOREVER1B3:MOVAL,0AH;换行MOVBL,0MOVAH,14INT10HMOVDL,0DHMOVAH,2INT21HMOVCH,0;换行后置计数值为0LEADI,REC;并重新指向初始设定的地址JMPFOREVER1BEGINENDPCODEENDSENDSTART上位机程序2:升级程序,提示下位机先要发送请求字符,然后才可以通信,这样不会出错STACKSEGMENTDB256DUP(0)ZSDB256DUP(0)STACKENDSDATASEGMENTSEDDB256DUP(0)RECDB256DUP(0) DATAENDSCODESEGMENTASSUMECS:CODE,DS:DATA,SS:STACKBEGINPROCFARPUSHDSXORAX,AXPUSHAXSTART:MOVAX,DATAMOVDS,AXLEASI,SEDLEADI,RECLEABP,ZSMOVDX,3FBHMOVAL,80HOUTDX,ALMOVDX,3F8HMOVAL,0CHOUTDX,ALMOVDX,3F9HMOVAL,0OUTDX,ALMOVDX,3FBHMOVAL,03HOUTDX,ALMOVDX,3FCHMOVAL,03HOUTDX,ALMOVDX,3F9HMOVAL,0OUTDX,ALXORCX,CXXORBX,BXMOVAL,77H;未建立连接之前显示waiting。。。MOVBL,0MOVAH,14INT10HMOVAL,61HMOVBL,0MOVAH,14INT10HMOVAL,69HMOVBL,0 MOVAH,14INT10HMOVAL,74HMOVBL,0MOVAH,14INT10HMOVAL,69HMOVBL,0MOVAH,14INT10HMOVAL,6EHMOVBL,0MOVAH,14INT10HMOVAL,67HMOVBL,0MOVAH,14INT10HMOVAL,2EHMOVBL,0MOVAH,14INT10HMOVAL,2EHMOVBL,0MOVAH,14INT10HMOVAL,2EHMOVBL,0MOVAH,14INT10HFOREVER:MOVDX,3FDHINAL,DXTESTAL,1EHJNZB9TESTAL,01HJNZWSJMPFOREVERWS:MOVDX,3F8HINAL,DXANDAL,7FHMOV[BP],ALINCBPCMPAL,0DH JZB8JMPFOREVERB7:MOVAL,4EHMOVBL,0MOVAH,14INT10HMOVAL,4FHMOVBL,0MOVAH,14INT10HMOVAL,21HMOVBL,0MOVAH,14INT10HMOVAL,0AHMOVBL,0MOVAH,14INT10HMOVDL,0DHMOVAH,2INT21HJMPFOREVERB9:JMPERRORB8:JMPB5OK:LEABP,ZSMOVAL,[BP]CMPAL,37HJNZB6MOVAL,4FHMOVDX,3F8HOUTDX,ALMOVAL,4BHMOVDX,3F8HOUTDX,ALMOVAL,21HMOVDX,3F8HOUTDX,ALMOVAL,0DHMOVDX,3F8HOUTDX,ALFOREVER1:MOVDX,3FDHINAL,DXTESTAL,1EH JNZERRORTESTAL,01HJNZRECEIVETESTAL,40HJZFOREVER1TESTAL,20HJZFOREVER1MOVAH,1INT16HJZFOREVER1MOVAH,0INT16HMOV[SI],ALINCSIINCCLCMPAL,0DHJZB0MOVBL,0MOVAH,14INT10HJMPFOREVER1ERROR:MOVAL,"?"MOVBL,0MOVAH,14INT10HMOVDL,0DHMOVAH,2INT21HJMPFOREVER1B0:MOVAL,0AHMOVBL,0MOVAH,14INT10HMOVDL,0DHMOVAH,2INT21HJMPB1B5:JMPOKB6:JMPB7RECEIVE:MOVDX,3F8HINAL,DXANDAL,7FH CMPAL,0DHJZXSMOV[DI],ALINCDIINCCHJMPFOREVER1XS:LEADI,RECB4:MOVAL,[DI]CMPAL,0DHJZB3DECCHJSB3MOVBL,0MOVAH,14INT10HINCDIJMPB4B1:LEASI,SEDB2:MOVAL,[SI]INCSIMOVDX,3F8HOUTDX,ALDECCLJNZB2LEASI,SEDJMPFOREVER1B3:MOVAL,0AHMOVBL,0MOVAH,14INT10HMOVDL,0DHMOVAH,2INT21HMOVCH,0LEADI,RECJMPFOREVER1BEGINENDPCODEENDSENDSTART上位机程序3:不用发请求联络信号,双方可直接通信,按回车发送STACKSEGMENTDB256DUP(0) STACKENDSDATASEGMENTFSDB256DUP(?);定义发送字符缓冲区DATAENDSCODESEGMENTASSUMECS:CODE,DS:DATA,SS:STACKBEGINPROCFARPUSHDS;保存PSP段地址XORAX,AXPUSHAX;保存返回地址偏移值START:;初始化8250为:8位数据位,1位停止位,无校验,波特率9600MOVAX,DATAMOVDS,AXLEASI,FSMOVDX,3FBHMOVAL,80HOUTDX,ALMOVDX,3F8HMOVAL,0CHOUTDX,ALMOVDX,3F9HMOVAL,0OUTDX,ALMOVDX,3FBHMOVAL,03HOUTDX,ALMOVDX,3FCHMOVAL,03H;内部输出输入不反接OUTDX,ALMOVDX,3F9HMOVAL,0;禁止中断,采用查询方式进行信息交换OUTDX,ALXORCX,CXFOREVER:;查询循环程序MOVDX,3FDHINAL,DXTESTAL,1EHJNZERRORTESTAL,01HJNZRECEIVETESTAL,40H;测发送移位寄存器是否为空,不空继续查询JZFOREVERTESTAL,20H;测发送保持寄存器是否为空,不空返回查询JZFOREVER MOVAH,1;空就测键盘缓冲区是否有字符INT16HJZFOREVER;无就返回查询MOVAH,0INT16HMOV[SI],AL;有就存入到发送缓冲区,同时CX作为计数寄存器INCSIINCCXCMPAL,0DH;是否为回车发送,是就转发送处理JZB0MOVBX,0;不是就将按键显示MOVAH,14INT10HJMPFOREVERB1:LEASI,FS;取发送缓冲区首地址,将暂存的发送B2:MOVAL,[SI]INCSIMOVDX,3F8HOUTDX,ALDECCXJNZB2;没发完继续发LEASI,FS;发完使地址指针归位JMPFOREVERB0:MOVAL,0AH;若为回车就先换行MOVBX,0MOVAH,14INT10HMOVDL,0DHMOVAH,2INT21HJMPB1;再转一个个发送RECEIVE:MOVDX,3F8HINAL,DXANDAL,7FH;取接收数据的低七位CMPAL,30H;比较是否为0JZB3;为0就转B3换行MOVBX,0;不是就一个个显示MOVAH,14INT10HJMPFOREVERB3:MOVAL,0AH;换行程序MOVBX,0MOVAH,14 INT10HMOVDL,0DHMOVAH,2INT21HJMPFOREVERERROR:;出错处理程序MOVDX,3F8HINAL,DXMOVAL,"?"MOVBX,0MOVAH,14INT10HJMPFOREVERBEGINENDPCODEENDSENDSTART'