一個主機,三個從機,撥碼開關前三個是選擇想要通信的從機,矩陣鍵盤是 將0-F 16個字符輸入到主機,在發送到從機,數碼管顯示
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
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)
2019-7-24 15:50 上傳
點擊文件名下載附件
keil代碼工程+proteus仿真工程
|