19.3.2 从机程序设计

这里在KeilµVision3集成开发环境中,使用Keil C51语言进行设计。建立项目的方法可以参考双机通信一节,这里主要介绍多机通信时从机的程序。

1.主函数

在多机通信从机的主函数中,首先初始化串口,然后进行空循环,监视串口的中断。从机的通信处理部分放在中断服务例程中执行。主函数的源代码示例如下。


include<reg52.h>

define uchar unsigned char

define SLAVE 0x00

define BN 16

uchar idata SendData[16];

uchar idata ReceiveData[16];

void main(void)

{

SCON=0x70;//设置串行口:方式1,8位UART,允许接收

TMOD|=0x20;//设置定时器T1,方式2,8位自动重装

PCON=0x80;//设置SMOD=1

TL1=0xF4;//波特率4800bit/s,初值

TH1=0xF4;

TR1=1;//启动定时器T1

ES=1;

EA=1;//开串行口中断

while(1)//主循环

{

}

}


2.中断服务例程

中断服务例程用于从机处理数据的发送和接收。在程序中,首先判断接收到的是否为本机地址,如果是则继续接收指令。当接收的指令为0x01时,则继续接收主机发送的数据。当接收的指令为0x02时,则向主机发送数据。中断服务例程的流程图如图19.15所示。中断服务例程的程序代码示例如下。

19.3.2 从机程序设计 - 图1

图 19.15 中断服务例程的流程图


void slave(void)interrupt 4 using 1//中断服务例程

{

uchar p,i;

uchar a;

bit SendBit;//准备发送标志

bit ReceiveBit;//准备接收标志

RI=0;//关串行口中断

ES=0;

if(SBUF!=SLAVE)//非本机地址

{

ES=1;

goto Exit;

}

SM2=0;//取消监听状态

SBUF=SLAVE;//发回从机地址

while(TI!=1);

TI=0;

while(RI!=1);

RI=0;

if(RB8==1)//地址不符,从机复位

{

SM2=1;

ES=1;

goto Exit;

}

a=SBUF;//接收命令

if(a==0x01)//从机接收主机的数据

{

if(ReceiveBit==1)

SBUF=0x01;//接收准备好,发回0x01

else

SBUF=0x00;

while(TI!=1);

TI=0;

while(RI!=1);

RI=0;

if(RB8==1)

{

SM2=1;

ES=1;

goto Exit;

}

//开始接收数据

ReceiveBit=0;

while(1)

{

p=0;//初始化校验和为0

for(i=0;i<BN;i++)

{

while(RI!=1);RI=0;

SendData[i]=SBUF;//接收数据

p+=ReceiveData[i];

}

while(RI!=1);

RI=0;

if(SBUF==p)

{

SBUF=0x00;//校验和相同,返回00H

break;

}

else

{

SBUF=0xEE;//返回EEH,重新接收

while(TI!=1);

TI=0;

}

}

SM2=1;

ES=1;

ReceiveBit=1;//准备接收标志

}

else if(a==0x02)//从机向主机发送数据

{

if(SendBit==1)

SBUF=0x02;//发送准备好

else

SBUF=0x00;

while(TI!=1);

TI=0;

while(RI!=1);

RI=0;

if(RB8==1)

{

SM2=1;

ES=1;

goto Exit;

}

//开始发送数据

SendBit=0;

do

{

p=0;//初始校验和为0

for(i=0;i<BN;i++)

{

SBUF=SendData[i];//发送数据

p+=SendData[i];

while(TI!=1);

TI=0;

}

SBUF=p;//发送校验和

while(TI!=1);

TI=0;

while(RI!=1);

RI=0;

}while(SBUF!=0);//主机接收不正确,重新发送

SM2=1;

ES=1;

SendBit=1;//准备发送标志

}

else//非法命令

{

SBUF=0x80;

while(TI!=1);

TI=0;

SM2=1;

ES=1;//恢复监听

}

Exit:;

}