一个主机,三个从机,拨码开关前三个是选择想要通信的从机,矩阵键盘是 将0-F 16个字符输入到主机,在发送到从机,数码管显示
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
主机代码
#include <reg51.h>
#include <string.h>
#define uchar unsigned char
#define uint unsigned int
#define SUCC 0x2A // 接收成功
#define ERR 0xF0 // 接收错误
#define MAXLEN 64 // 缓冲区最大长度
#define KEY P2
uchar buf;
uchar addr;
uchar code duanma[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,};
void delay(uint t) // 延时t毫秒
{
uint i,j;
for (i=0;i<t;i++)
for (j=0;j<125;j++);
}
void senddata(uchar buf) //发送数据函数
{
TI = 0;
TB8 = 0; // 发送数据帧
SBUF =buf;
while(!TI);
TI = 0;
}
void init_serial() // 串口初始化函数
{
TMOD = 0x20;
{
};
// 定时器T1使用工作方式2
TH1 = 250;
TL1 = 250;
TR1 = 1; // 开始计时
PCON = 0x80; // SMOD = 1
SCON = 0xd0; // 工作方式3,9位数据位,波特率9600kbit/s,允许接收SM2=0
}
uchar keyscan() //键盘处理函数
{
uchar a,b,c;
KEY=0x0f; //键盘口置00001111
if(KEY!=0x0f) //查询键口值是否变化
{
delay(20); //去抖
if(KEY!=0x0f) // 有键按下
{
a=KEY; //键值放在寄存器a中
}
KEY=0xf0; //将键盘口置11110000
c=KEY; //将第二次取得值放入寄存器c中
a=a|c; //将两个数据融合
switch(a) //对比数据值
{
case 0xee : b=0;break;
case 0xde : b=1;break;
case 0xbe : b=2;break;
case 0x7e : b=3;break;
case 0xed : b=4;break;
case 0xdd : b=5;break;
case 0xbd : b=6;break;
case 0x7d : b=7;break;
case 0xeb : b=8;break;
case 0xdb : b=9;break;
case 0xbb : b=10;break;
case 0x7b : b=11;break;
case 0xe7 : b=12;break;
case 0xd7 : b=13;break;
case 0xb7 : b=14;break;
case 0x77 : b=15;break;
default:break; //键值错误处理
}
}
return(b); //将b作为返回值
}
void main()
{
while(1)
{
buf=keyscan();
P1=duanma[keyscan()];
/* 通过P0口读要访问的从机地址 */
P0 = 0xff;
addr = P0&0x0f;
init_serial(); // 串口初始化
EA = 1; // 打开所有中断
TI = 0;
TB8 = 1; // 发送地址帧
SBUF = addr;
while(!TI);
TI = 0;
senddata(buf); // 发送数据
}
}
从机代码
#include <reg51.h>
#include <string.h>
#define uchar unsigned char
#define uint unsigned int
#define SUCC 0x2A // 接收成功
#define ERR 0xF0 // 接收错误
#define MAXLEN 64 // 缓冲区最大长度
uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
uchar buf; //数据寄存
uchar addr; //地址寄存
sbit led= P3^4; // 此引脚控制发光管
/* 延时t毫秒 */
void delay(uint t)
{
uint i,j;
for (i=0;i<t;i++)
for (j=0;j<125;j++);
}
/* 接受数据函数 */
uchar recvdata()
{
/* 接收数据 */
while(!RI);
if (RB8==1)
return 0xee; // 若接收的为地址帧,则返回0xee
buf = SBUF;
RI = 0;
return 0; // 返回0
}
/* 串口初始化函数 */
void init_serial()
{
TMOD = 0x20; // 定时器T1使用工作方式2
TH1 = 250;
TL1 = 250;
TR1 = 1; // 开始计时
PCON = 0x80; // SMOD = 1
SCON = 0xd0; // 工作方式,9位数据位,波特率9600kbit/s,允许接收
}
/* 主程序 */
void main()
{
uchar i = 0;
uchar tmp = 0xff;
P1= 0xff;
addr = P1&0x0f; // 获取本机地址
led = 1; // 发光管不亮
init_serial(); // 串口初始化
EA = 1; // 打开所有中断
while(1) //进入从机应答
{
SM2 = 1; // 只接收地址帧
while (tmp!=addr) // 如果接收到的地址帧不是本机地址,则继续等待
{
P0=0XFF; //如果不是本机,就关掉数码管
RI = 0;
while(!RI)
tmp = SBUF;
RI = 0;
}
SM2 = 0; // 允许接收数据
tmp = recvdata(); // 数据接收
if (tmp==0x00)
{
P0=table[buf];
led = 0;
delay(30);
led = 1;
}
// 如果接收数据时发现地址帧,则重新开始整个接收过程
}
}
如果打开运行出错,请重新添加下hex文件,就可以了的。
全部资料51hei下载地址:
多机通信.zip
(98.09 KB, 下载次数: 94)
|