《单片机原理与应用》课程
课程实验报告
实验四 单片机串口通信实验
- 实验目的
1.学习单片机串行口的使用方法;
2.熟悉基于串行口的双机通信方案的设计与实现方法;
3.熟悉基于串行口的多机通信方案的设计与实现方法。
- 实验内容与步骤
- 基于串口的方式1,以仿真方式实现单片机的双机通信实验
- 实验目标:
- 单片机甲、乙双机串行通信,双机RXD和TXD相互交叉相连,甲机P1口接8个开关,乙机P1口接8个发光二极管;双方晶振均采用11.0592MHz。
- 甲机设置为只能发送不能接收的单工方式。
- 要求甲机读入P1口的8个开关的状态后,通过串行口发送到乙机,乙机将接收到的甲机的8个开关的状态数据送入P1口,由P1口的8个发光二极管来显示8个开关的状态。双方晶振均采用11.0592MHz。
2.主要实验内容:
1) 画双机连接仿真图。
2) 编程实现1端8个开关对另一端8个灯的一对一控制。
- 基于串口方式3的双机通信实验
1.实验目标:
- 甲、乙两单片机进行方式3串行通信。甲机把控制8个流水灯点亮的数据发送给乙机并点亮其P1口的8个LED。
- 要进行校验:乙机接收到的8位二进制数据有可能出错,需进行奇偶校验,其方法是将乙机的RB8和PSW的奇偶校验位P进行比较,如果相同,接收数据;否则拒绝接收。
3)观察:虚拟终端来观察甲机串口发出的数据。
2.主要实验内容:
1)画双机连接仿真图。
2)编程实现1端程序输出数据实现对另一端8个灯的循环亮灯控制。
(三)基于仿真的方式实现单片机的多机通信实验(扩展,选)
1)画双机连接仿真图。
2)编程实现其基于按键的选择控制功能。
三、实验步骤:
(一)基于方式1的双机通信实验
1.画仿真原理图,连接参考图如下。
画图过程的注意事项:
- 在进行总线画法的连线时,要注意支线与总线的连接不要是垂直连接,可采用45度连接,连接总线的支线都要加标号,并要将有连接关系的支线加上相同的标号。
- 通信双方不同单片机连接不同外部电路的支线,其标号不能相同。
- 串口连接关系一定要是交叉连接,即收连发、发连收。
调试过程注意事项:
1)甲方、乙方的程序不同,要分别生成其各自的HEX文件,可放在相同目录中。
2)生成方法有二:一种是在同一工程中分别加入程序,生成各自的HEX文件,这时需要在选项的output对话框中改文件名。第二种是建立两个不同的工程,分别生成甲方、乙方的HEX文件。
(现场验收点1:基于Proteus仿真及工作方式1实现双机通信。)
(二)基于串口方式3的双机通信实验
1.画仿真原理图,连接参考图如下。
2. 编程、调试实现功能。
四、扩展实验:多机通信
三、 实验环境
PC机一台、keil 4/5、 proteus 7/8。
- 实验系统的总体设计
(1)双机串口通信(单工通信)
(2)双机串口通信(双工校验通信)
- 实验系统的详细设计与实验过程
1. 仿真部分:
(1)基于串口的方式1,以仿真方式实现单片机的双机通信实验
(2)基于串口方式3的双机通信实验
(3)基于仿真的方式实现单片机的多机通信实验
- 程序代码
(1)
/*主机
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
void main()
{
uchar temp=0 ;
TMOD=0x20;
TH1=0xfd;
TL1=0xfd;
SCON=0x40;
PCON=0x00 ;
TR1=1;
P1=0xff;
while(1){
temp=P1;
SBUF=temp;
while(TI==0);
TI=0;
}
}
*/
乙机
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
void main( )
{
uchar temp=0;
TMOD=0x20;
TH1=0xfd;
TL1=0xfd;
SCON=0x50;
PCON=0x00;
TR1=1 ;
while(1)
{
while (RI==0);
RI=0;
temp=SBUF;
P1=temp;
}
}
(2)
/甲机
//#include <reg51.h>
//unsigned char Tab[8]= {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f};
//void Send(unsigned char dat)
//{
// TB8=PSW^0;
// SBUF=dat;
// while(TI==0);
// ;
// TI=0;
//}
//void Delay (void)
//{ unsigned char m,n;
// for(m=0;m<250;m++)
// for(n=0;n<250;n++);
//}
//void main(void)
//{ unsigned char i;
// TMOD=0x20;
// SCON=0xc0;
// PCON=0x00;
// TH1=0xfd;
// TL1=0xfd;
// TR1=1;
// while(1)
// { for(i=0;i<8;i++)
// {
// Send(Tab[i]);
// Delay( );
// }
// }
//}
//乙机
#include <reg51.h>
sbit p=0xd0;
unsigned char Receive(void)
{
unsigned char dat;
while(RI==0);
;
RI=0;
ACC=SBUF;
if(RB8==P)
{ dat=ACC;
return dat;
}
return 0;
}
void main(void)
{
TMOD=0x20;
SCON=0xd0;
PCON=0x00;
TH1=0xfd;
TL1=0xfd;
TR1=1;
REN=1;
while(1)
{ P1= Receive( );
}
}
(3)
/*主机
#include <reg51.h>
#include <math.h>
sbit switch1=P0^0;
sbit switch2=P0^1;
sbit switch3=P0^2;
void delay_ms(unsigned int i)
{
unsigned char j;
for(;i>0;i--);
for(j=0;j<125;j++)
;
}
void main()
{
EA=1;
TMOD=0x20;
TL1=0xfd;
TH1=0xfd;
PCON=0x00;
SCON=0xd0;
TR1=1;
ES=1;
SBUF=0xff;
while(TI==0);
TI=0;
while(1)
{
delay_ms(100);
if(switch1==0)
{
TB8=1;
SBUF=0x01;
while(TI==0);
TI=0;
TB8=0;
SBUF=0x00;
while(TI==0);
TI=0;
}
if(switch2==0)
{
TB8=1;
SBUF=0x02;
while(TI==0);
TI=0;
TB8=0;
SBUF=0x00;
while(TI==0);
TI=0;
}
if(switch3==0)
{
TB8=1;
SBUF=0x03;
while(TI==0);
TI=0;
TB8=0;
SBUF=0x00;
while(TI==0);
TI=0;
}
}
}
*/
/*机1
#include <reg51.h>
#include <math.h>
sbit led=P2^0;
bit rrdy=0;
bit trdy=0;
bit err=0;
void delay_ms(unsigned int i)
{
unsigned char j;
for(;i>0;i--);
for(j=0;j<125;j++)
;
}
void main()
{
EA=1;
TMOD=0x20;
TL1=0xfd;
TH1=0xfd;
PCON=0x00;
SCON=0xd0;
TR1=1;
P1=0xff;
ES=1;
while(RI==0);
if(SBUF==0xff) err=0;
else err=1;
RI=0;
SM2=1;
while(1);
}
void int1() interrupt 4
{
if(RI)
{
if(RB8)
{
RB8=0;
if(SBUF==0x01)
{
SM2=0;
led=0;
}
}
else
{
rrdy=1;
P1=SBUF;
SM2=1;
led=1;
}
RI=0;
}
delay_ms(50);
P1=0xff;
}
*/
/*机2
#include <reg51.h>
#include <math.h>
sbit led=P2^0;
bit rrdy=0;
bit trdy=0;
bit err=0;
void delay_ms(unsigned int i)
{
unsigned char j;
for(;i>0;i--);
for(j=0;j<125;j++)
;
}
void main()
{
EA=1;
TMOD=0x20;
TL1=0xfd;
TH1=0xfd;
PCON=0x00;
SCON=0xf0;
TR1=1;
P1=0xff;
ES=1;
while(RI==0);
if(SBUF==0xff) err=0;
else err=1;
RI=0;
SM2=1;
while(1);
}
void int1() interrupt 4
{
if(RI)
{
if(RB8)
{
RB8=0;
if(SBUF==0x02)
{
SM2=0;
led=0;
}
}
else
{
rrdy=1;
P1=SBUF;
SM2=1;
led=1;
}
RI=0;
}
delay_ms(50);
P1=0xff;
}
*/
//机3
#include <reg51.h>
#include <math.h>
sbit led=P2^0;
bit rrdy=0;
bit trdy=0;
bit err=0;
void delay_ms(unsigned int i)
{
unsigned char j;
for(;i>0;i--);
for(j=0;j<125;j++)
;
}
void main()
{
EA=1;
TMOD=0x20;
TL1=0xfd;
TH1=0xfd;
PCON=0x00;
SCON=0xf0;
TR1=1;
P1=0xff;
ES=1;
while(RI==0);
if(SBUF==0xff) err=0;
else err=1;
RI=0;
SM2=1;
while(1);
}
void int1() interrupt 4
{
if(RI)
{
if(RB8)
{
RB8=0;
if(SBUF==0x03)
{
SM2=0;
led=0;
}
}
else
{
rrdy=1;
P1=SBUF;
SM2=1;
led=1;
}
RI=0;
}
delay_ms(50);
P1=0xff;
}
- 实验结果
(1)1端8个开关对另一端8个灯的一对一控制。
(2)1端程序输出数据实现对另一端8个灯的循环亮灯控制,并在虚拟端出现发送数据。
(3)K1控制机1亮灯;K2控制机2亮灯;K3控制机3亮灯;3个开关控制的亮灯效果不同
- 实验分析与总结
- 实验1中刚开始开关只能控制开始的串口数据,然后停止不动,重写代码,重新生成HEX文件得以解决。
- 实验2中,Led灯不亮,数据闪烁,经过检查发现是电源的原因,其中检验函数是成功的关键。
- 实验3中,刚开始K1控制分机,HEX文件导入错误,经过改正,K2控制不了机2,经过检查,线路接口引脚标错,改正后重新导入HEX文件,可以成功控制。
总结:实验中,代码正确,步骤正确,可能也会出现错误,只有不断地检查,完善,改正才是实验的最终目的。
如有不完善,评论指出。