《微机原理项目报告双机串行通信.doc》由会员分享,可在线阅读,更多相关《微机原理项目报告双机串行通信.doc(29页珍藏版)》请在三一办公上搜索。
1、微机原理课程项目实施报告题 目(三): 双机串行通信 组 号: 第19组 任课教师: 方 针 组 长: 11123128 吴慧泽 21% 成 员: 11123227 丰 硕 19% 成 员: 11123201 温英杰 19% 成 员: 11123168 范 特 21% 成 员: 11123260 崔向阳 20% 联系方式: 18817393058 二零一三 年 五 月 十八 日课程项目名单统计表课程项目名单统计表表一:课程项目名单统计表 组号: 19 任课教师()方针沈明华王向阳学生学号学生姓名吴慧泽11123128是温英杰11123201是范 特11123168是丰 硕11123227是崔向
2、阳11123260是一、 课程项目实施方案(题目要求,说明设计思想、指标及实现方法,所需器件清单等)题目要求:实现单片机和PC机之间的双机双工串行通信。(1) 设计上位机(汇编语言设计)、下位机通信程序(C语言、汇编不限),通信波特率9600bps,8位数据、1个停止位、无校验。(2) 全双工通信。(3) 分别在PC机屏幕和实验板LCD上显示接收到的内容(4) 其它扩展功能。实验材料:(1)单片机实验板(2)通信接口电缆(3)电阻、电容、三极管等若干单片机选型:通过组内讨论,考虑到实验室发的51系列的单片机相对于学院给我们配发的MSP430单片机的学习资源更丰富,并且项目制作中所需硬件(部分元
3、器件)和软件资源都要相对于MSP430单片机更易获得,所以我们组决定采用51单片机来设计和完成本课程项目。设计思想:硬件方面:实验室所发的单片机实验板上配有许多小部件,可以根据要实现的功能,将STC89C52RC单片机与小部件配合连接使用。由于STC89C52RC单片机有一个全双工UART串行通信接口,通过实验板上的MAX232电平转换芯片和RS-232C非标准(即DB9)串口与PC机连接,从而可实现单片机与PC机之间的全双工串行通信,即同时接收和发送数据。软件方面:上位机和下位机通信程序均用汇编语言编写设计,STC单片机采用中断方式接收PC发送的数据并回送,串行口的工作方式为工作方式1,使用
4、11.0592MHz晶振,并以定时器T1的方式2为波特率发生器,波特率在汇编程序中设置为9600,PC采用查询方式收、发数据。我们采用Keil uVision2软件工具来进行通信程序的编写、编译与调试,采用STC单片机PC端ISP下载控制软件STC-ISP-V4.83将编译调试好的程序烧写到单片机内。指标实现预期:基本指标:满足全双工通信要求,能在PC机屏幕和实验板LCD上显示接收到的内容。扩展功能:随后续项目的进展逐步在原要求功能基础上加以扩展。二、 项目的制作过程领到单片机后,我们组迅速开展了项目资料的查找与学习。大致了解了所用开发板的基本组成和结构,知道了用何种软件将程序烧写到单片机内,
5、以及51单片机程序编译软件,还了解到与单片机串口有关的调试工具串口调试助手。至此,我们将工作重心放在学习有关的编程语言:C语言和汇编语言,计划开始编写上位机和下位机通信程序。小组成员学习任务都很重,而且组员各自都有自己额外的奋斗目标,比如电子竞赛,考托福,所以开始的时候我们的项目进展缓慢。在获得老师提供的开发板资料后,我们就利用其中配套程序里面的mini80E功能测试程序对单片机的基本功能进行了测试,当时除了串口通信功能外,其余功能均正常。而进行串口通信功能测试时,我们用串口调试助手向单片机发送字符,在接收区看到的字符与发送的字符不一样,不是多一个字符就是乱码。然而我们检查相关的设置,波特率、
6、数据位和停止位都设置无误。后来了解到,是开发板上所带的晶振的问题。开发板上的晶振是12Mhz,我们查资料了解到,在12Mhz晶振下,设置出来的9600波特率与实际有很大的误差,这个误差在串口调试助手接受范围之外,所以出现了乱码。我们就改用我们自己买的单片机上带的11.0592Mhz的晶振,结果收发数据之间没有出现偏差。这使我们终于松了一口气。然而,这仅仅是用现有的配套程序进行功能测试。真正实现单片机与PC机之间的串行通信还有相当多的工作要做。随着微机原理课程的学习和项目的进行,我们小组主要遇到了以下的几个问题:1)用C语言编写还是用汇编语言编写?虽然题目未要求下位机程序用什么语言编程,但根据老
7、师的说法,建议使用汇编语言。由于汇编语言是与CPU紧密相关的,要想学习后达到能编一个程序的水平,就必须要求对CPU的内部结构有一定深度的了解,和与CPU对应的指令系统有很深的了解。说实话,从身边有些同学反映汇编语言学起来很生硬很吃力,以及我们小组成员学习汇编的感受,都感觉汇编不如C形象生动、容易上手,而且我们之前学过C,大家都有一定的底子,所以编程难度降低了不少,加上单片机方面各个部件的参考程序例如液晶显示,矩阵按键程序等等都以C语言居多,所以我们不用花很多时间去研究各种汇编指令,这会使我们项目成功实现所需的时间大大缩短。所以我们一致认同用C编写下位机通信程序。而对于上位机,我们使用的是汇编语
8、言。我们觉得这样既能紧密结合课程所学,亦能节约时间,尽快完成任务。当我们参照C语言样例程序编写了一个能液晶显示、能接收数据的简单通信程序时,这时我们还只是停留在用串口助手进行下位机程序的调试,因为我们还不清楚编写好的上位机通信程序是怎样通过串口线与单片机进行通信。当我们用用串口调试助手向单片机发送字符,当发送十个以下字符时,能从液晶的第一行开始显示,但当两行显示满后,跳到第一行继续显示时,却只能最多显示两个字符,其余的均不能显示;还有,当发送超过十个字符时,就会有字符丢失,但在接收子程序中把液晶写字符函数注释掉后,串口助手能够正确接收,没有字符丢失。我们刚开始认为是单片机接收数据时由于字符的A
9、SCII码是7位二进制,而我们设定数据格式为8位数据位,这样发送多个字符时,后面的会和前面排列紧密导致乱序。后来项目答疑的时候问王老师,王老师说不是这个问题。2)要不要对开发板上的矩阵键盘编程?项目要求是要实现双机串行通信,那肯定要求双方既能接收又能发送,所以还要嵌入相应按键发送数据程序。但是,从单片机向PC机发送数据是用开发板上的矩阵键盘还是用PS2键盘,这都涉及如何人为手动发送数据的子程序内嵌问题,这就要求对通信主程序、液晶显示程序和按键发送数据程序进行整合。这会使后面的调试更加复杂。最后我们还是决定用矩阵键盘,虽然用PS2键盘可以发送多种字符,但是这样可以减少项目制作的成本。当我们把矩阵
10、键盘程序嵌入之前的程序里面后,每个按键都有用,按键代表的字符都能在液晶上显示,但唯独接收程序不能接收来自串口助手发来的字符,而且不能显示。这令我们颇为困惑,为此我们琢磨究竟问题出在哪,对程序反复修改并调试,发现注释掉发送程序代码后,单片机可以接收并显示,但不能发送,继续调试了很多次后还是不能同时接收和发送。这个问题一直困扰着我们,我们觉得是接收和发送中断不能等条件的进入中断,导致不能实现既可以发也可以收数据。到后来,我们发现下位机程序中,按键扫描程序是一直在运行的,我们看开发板的组成原理图,发现矩阵键盘四条行线和四条列线是与单片机P3口相接的,这就说明作为串口通信的P3.0、P3.1口被用作普
11、通I/O口了,这就造成了不能准确通信。并且我们还就此咨询了王旭智老师,问是不是P3.0、P3.1口既用作通信口又用作普通I/O口造成的问题,老师说是,说P3口不能既作普通I/0口又作串行通信口,这样会有冲突。后来我们又问了方针老师,并证实了我们的问题就是出在这里。方老师建议说,可以进行I/O口扩展,将矩阵键盘连接到扩展的I/O口上,避免与串口发生冲突,但是需要另外的芯片,然而开发板上没有这样的芯片,基于项目制作成本和我们的能力以及时间问题,我们决定不用矩阵键盘作为按键,而转用独立键盘中不与串口冲突的几个按键。所以我们就编了两个按键只能按0和1两个字符,这时我们可以进行双机通信了,单片机和PC按
12、一个发一个。但是我们有组员觉得两个按键太少了太单调了,所以我们后来又扩展到了8个按键,这8个按键不与P3.0、P3.1连接,所以不会产生冲突,增加了可发送字符的个数,并且我们设置了发送键即PC机上面的回车键(ASCII码为0DH),可以发送一连串的多个字符,因为把将要发送的字符先存到数组里面,按回车键启动发送。3) 怎样加入扩展功能?基本要求实现后,我们就开始想如何对功能进行扩展。首先下位机程序中能加入也能容易控制的就属LED了,我们就让单片机的串口每次有数据流时LED就闪烁。但我们觉得这个功能太弱太小儿科了。我们有想过利用红外发射和接收来进行数据传送,但这个对于通电学得不好的我们来说简直很难
13、实现。下位机我们没想出扩展什么功能。上位机可以,我们有组员提出现有的程序是启动就开始通信,但在实际中并不是双机都同时准备好通信了,有可能上位机在处理别的事,所以基于这个,我们设计下位机要想与上位机进行通信需要发送可握手密码,这里我们设定为“7”,上位机程序启动时,是一个黑框框,光标在闪烁,若下位机发送的字符中第一个是“7”,上位机就发送“OK!”给单片机,表示可以通信了,若不是“7”,黑框框就显示“NO!”。但在调试时发现了问题,不能一开始没建立握手前就按电脑键盘,否则下位机按7发送后,黑框框不仅显示“OK!”,也把刚才按的键也显示在屏幕上了,按理说这不合理,不符合规范。所以我们就加了些提示,
14、提示单片机先发送请求连接字符,这样不会出现上面的问题。我们觉得这比较符合工程规范,下位机是从机,要通信前先请求主机。项目分工情况:刚刚开始的时候我们是一起查找资料,并聚在一起讨论可以从哪几个方面入手这个项目,基本确定了设计思想和项目实现的框架。在单片机测试时是由丰硕和崔向阳测试并发现问题的,最后是由范特解决了问题。上位机程序由组长吴慧泽和范特共同完成,下位机程序由范特与温英杰共同完成,最终报告和PPT由崔向阳与吴慧泽共同完成。其中,组长吴慧泽全程都对各个环节进行了安排、检查与督促。最终经过协商,觉得按封面所示比例量化确定贡献。三、项目的结果分析A开机初始化时开机后,PC机对话框显示“waiti
15、ng”,单片机显示“Please enter the password.”B单片机上各按键代表字符测试:由左到右,由上至下依次按下按键,单片机显示7654321。得到各按键对应含义如下表:7654321ENTERC建立单片机与PC机的握手测试结果(开机的第一次操作)1、首先单片机发送7,PC机dos窗口显示OK!,并返回OK!给单片机,单片机屏幕显示OK!,表示可以进行通话。2、首先单片机发送7654321PC机显示OK!,并返回OK!给单片机。3、单片机发送除7外的字符,PC机显示NO!,并且不返回给单片机。表示不能通话。当再次发送7时,PC机会先显示按7之前PC机键盘输入的字符,再显示OK
16、!,单片机上显示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。EPC机向单片机发送字符测试(在建立握手对话的基础上)凡是可显示字符均可发送并发送。按ENTER键发送。1、 发送0,单片机显示0,并返回
17、给PC机显示0;2、 发送1203时,单片机显示1203,并返回PC机1203。3、 发送abcd,单片机显示abcd,并返回给PC机显示abcd;4、 发送空格,单片机显示 ,并返回给PC机显示 ;5、 发送?,单片机显示?,并返回给PC机显示?;6、 单片机无显示字符情况下,发送123456789123456789123456789123456789123456789时,单片机在新的一页显示6789123456789;并返回PC机显示123456789123456789123456789123456789123456789;7、 直接按ENTER时,单片机无反应。结果分析:符合我们的如下要
18、求:设计要求: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字符,单片机显示时主动在后面加空格,便于观察
19、区分发送和接收的;6、 PC机直接发送ENTER,单片机不予反应。上位机外加拓展:1、 增加了初始时PC机状态、单片机输入密码提示,更加人性化,符合工程规范,便于操作;2、 输入密码正确与否的判断与显示。附件一:设计流程图:下位机程序流程图:是否是是否连接否系统初始化开始读入连接密码发送连接密码到PC机显示“Please enter the password!”接收PC机指示接收PC机传来的字符串读入单片机键盘输入字符显示空格显示字符串是否为“ENTER”储存到数组显示字符发送数组到PC机返回字符串到PC机结束上机位程序流程图:否是是是否系统初始化开始读取单片机发送的连接密码是否为7显示NO!
20、显示OK!发送OK!到单片机否读入单片机传来的字符串读入PC机键盘输入字符显示换行显示字符是否为“ENTER”储存到发送字符缓冲区显示字符发送字符串到单片机结束显示“waiting”储存到接收字符缓冲区读取字符是否为“ENTER”附件二:下位机程序:8按键扫描,通信时先要建立握手,发请求信号,我们设计7为请求信号,按回车键(我们定义其中一个键为回车键即0DH)发送,且发送和接收数据后先存入数组,然后回送给PC,注意以0DH结尾。#include #include#include#define uchar unsigned char#define uint unsigned intsbit RS
21、 = P24; /定义端口 sbit RW = P25;sbit EN = P26;sbit KeyPort0=P32;sbit KeyPort1=P33;sbit KeyPort2=P34;sbit KeyPort3=P35;sbit KeyPort4=P36;sbit KeyPort5=P37;uchar code table=Please enter the pass word.; /单片机请输入password#define DataPort P0#define RS_CLR RS=0 #define RS_SET RS=1#define RW_CLR RW=0 #define RW_
22、SET RW=1 #define EN_CLR EN=0#define EN_SET EN=1uchar rec_str32;uchar send_str32;uchar m=0,n=0,num=0;uchar k=0;temp=0;unsigned char a=0,b=0,i=0,j=0;unsigned char flag=0,flag1=0;unsigned char KeyPro(void);unsigned char KeyScan(void);void yjxs(uchar Data);void receive(uchar *s); void send(uchar *r);voi
23、d delay(uchar z)uchar x,y;for(x=z;x0;x-)for(y=120;y0;y-);/*- 判忙函数-*/ bit LCD_Check_Busy(void) DataPort=0xFF; RS_CLR; RW_SET; EN_CLR; _nop_(); EN_SET; return (bit)(DataPort & 0x80); /*- 写入命令函数-*/ void LCD_Write_Com(unsigned char com) while(LCD_Check_Busy(); /忙则等待 RS_CLR; RW_CLR; EN_SET; DataPort= com
24、; _nop_(); EN_CLR; /*- 写入数据函数-*/ void LCD_Write_Data(unsigned char Data) while(LCD_Check_Busy(); /忙则等待 RS_SET; RW_CLR; EN_SET; DataPort= Data; _nop_(); EN_CLR; yjxs(Data); /*- 清屏函数-*/ void LCD_Clear(void) LCD_Write_Com(0x01); delay(5); /*- 写入字符函数-*/ void LCD_Write_Char(unsigned char x,unsigned char
25、y,unsigned char Data) if (y = 0) LCD_Write_Com(0x80 + x); else LCD_Write_Com(0xC0 + x); LCD_Write_Data( Data); /*- LCD初始化函数-*/ void LCD_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); /*显示关闭*
26、/ LCD_Write_Com(0x01); /*显示清屏*/ LCD_Write_Com(0x06); /*显示光标移动设置*/ LCD_Write_Com(0x0f); delay(5); /LCD_Write_Com(0x0C); /*显示开及光标设置*/ /*- 发送一个字节-*/void SendByte(unsigned char dat) SBUF = dat;while(!TI);TI=0;/*- 发送一个字符串-*/void SendStr(unsigned char *s) while(*s!=0x0d)/ 回车表示字符串结束标志,通过检测是否字符串末尾 SendByte(
27、*s); s+; void initial()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;/*- 串行中断函数-*/void ser() interrupt 4 if(RI=1)P1=0XF0;/进入中断后,P1.4-P1.7灯指示if(m=32)m=-
28、1;rec_strm=SBUF;/接受数据存入数组RI=0;if(rec_strm=0x0d)/收到结束位,然后进入显示函数 receive(rec_str);m=-1;m+;/*- 进入主函数-*/void main()initial();for(k=0;k29;k+)/显示提示输入连接信号LCD_Write_Char(i,j,tablek); while(1) num=KeyScan();/扫描键盘if(num!=0xff)send_strn=num;/读取键盘数据存入数组中if(send_strn!=0x0d)/收到发送信号然后发送LCD_Write_Char(i,j,num);/显示按
29、键字符if(n=32)n=-1;if(send_strn=0x0d)/收到发送enter信号然后发送 P1=0X0F;/进入发送函数P1.0-P1.3灯指示send(send_str);/进入发送函数LCD_Write_Char(i,j,0x20);/显示空格表示一次通话结束n=-1;n+; /*- 接受显示函数-*/void receive(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);/*- 发送函数-*/
30、void send(uchar *r)SendStr(r);SendByte(0x0d);/*- 液晶显示调整函数-*/void yjxs(uchar Data) 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;/*- 键盘扫描函数,使用行列逐级扫描法-*/unsigned char KeyScan(void) unsigned char Val; KeyPort0=KeyPort1=0; KeyPort2=KeyPo
31、rt3=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
32、(!(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)
33、&(KeyPort2=1)&(KeyPort3=1)&(KeyPort4=1)&(KeyPort5=1); return Val; 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
34、(!(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); return Val; return 0xff;上位机程序:我们有三个程序。上位机程序1:若单片机先要第一个发的数据是7就建立连接,可以开始通信,不是就不能通信,若PC机先按键盘,则PC机收到7后会显示出错STACK SEGMENT D
35、B 256 DUP(0)ZS DB 256 DUP (0) ;定义握手开始建立时的暂时数据缓冲区STACK ENDSDATA SEGMENTSED DB 256 DUP (0) ;定义发送数据缓冲区REC DB 256 DUP (0) ;定义接收数据缓冲区DATA ENDSCODE SEGMENT ASSUME CS:CODE,DS:DATA,SS:STACKBEGIN PROC FAR PUSH DS ;保存PSP段地址 XOR AX,AX PUSH AX ;保存返回地址偏移值START: ;初始化8250为:8位数据位,1位停止位,无校验,波特率9600 MOV AX,DATA MOV DS,AX LEA SI,SED LEA DI,REC LEA BP,ZS MOV DX,3FBH MOV AL,80H OUT DX,AL MOV DX,3F8H MOV AL,0CH OUT DX,AL MOV DX,3F9H MOV AL,0 OUT DX,AL MOV DX,3FBH MOV AL,03H OUT DX,AL MOV DX,3FCH MOV AL,03H ;内部输出输入不反接 OUT DX,AL MOV DX,3F