實驗一:方式一的應用設計
一、實驗內容
單片機甲、乙雙機串行通信,雙機RXD和TXD相互交叉相連,甲機P1口接8個開關,乙機P1口接8個發光二極管。甲機設置為只能發送不能接收的單工方式。要求甲機讀入P1口的8個開關的狀態后,通過串行口發送到乙機,乙機將接收到的甲機的8個開關的狀態數據送入P1口,由P1口的8個發光二極管來顯示8個開關的狀態。雙方晶振均采用11.0592MHz。
二、實驗原理及步驟
三、電路設計及調試
(1)實驗電路
file:///C:/Users/zyt/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg
(2)程序設計及調試
甲機:
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
void main()
{
uchar temp=0;
TMOD=0x20; //設置定時器T1為方式2
TH1=0xfd; //波特率9600
TL1=0xfd;
SCON=0x40; //串口初始化方式1發送,不接收
PCON=0x00; // SMOD=0
TR1=1; //啟動T1
P1=0xff; //設置P1口為輸入
while(1)
{
while(TI==0); //如果TI=0,未發送完,循環等待
TI=0; //已發送完,把TI清0
temp=P1; //讀入P1口開關的狀態數據
SBUF=temp;}} //數據送串行口發送
乙機:
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
void main( )
{
uchar temp=0;
TMOD=0x20; //設置定時器T1為方式2
TH1=0xfd; //波特率9600
TL1=0xfd;
SCON=0x50; //設置串口為方式1接收,REN=1
PCON=0x00; //SMOD=0
TR1=1; //啟動T1
while(1)
{
while(RI==0); // 若RI為0,未接收到數據
RI=0; // 接收到數據,則把RI清0
temp=SBUF; // 讀取數據存入temp中
P1=temp;}} // 接收的數據送P1口控制8個LED的亮與滅
實驗二:多機通信的應用設計
一、實驗內容
實現主單片機分別與3個從單片機串行通信,原理電路見圖。用戶通過分別按下開關k1、k2或k3來選擇主機與對應1#、2#或3#從機串行通信,當黃色LED點亮,表示主機與相應的從機連接成功;該從機的8個綠色LED閃亮,表示主機與從機在進行串行數據通信。如果斷開k1、k2或 k3,則主機與相應從機的串行通信中斷。
二、實驗原理及步驟
1. 實現主、從機串行通信,各從機程序都相同,只是地址不同。
串行通信約定如下。
(1)3臺從機的地址為01H~03H。
(2)主機發出的0xff為控制命令,使所有從機都處于SM2=1的狀態。
(3)其余的控制命令:00H—接收命令,01H—發送命令。這兩條命令是以數據幀的形式發送的。
(4)從機的狀態字如圖所示。
file:///C:/Users/zyt/AppData/Local/Temp/msohtmlclip1/01/clip_image004.jpg
其中:
ERR(D7位)=1,表示收到非法命令。
TRDY(D1位)=1,表示發送準備完畢。
RRDY(D0位)=1,表示接收準備完畢。
串行通信時,主機采用查詢方式,從機采用中斷方式。主機串口設為方式3,允許接收,并置TB8為1。因只有1個主機,所以主機SCON控制寄存器中的SM2不要置1,故控制字為11011000,即0xd8。
三、電路設計及調試
(1)實驗電路
file:///C:/Users/zyt/AppData/Local/Temp/msohtmlclip1/01/clip_image006.jpg
(2)程序設計及調試
//主機程序
#include <reg51.h>
#include <math.h>
sbit switch1=P0^0; //定義k1與P0.0連接
sbit switch2=P0^1; //定義k2與P0.1連接
sbit switch3=P0^2; //定義k3與P0.2連接
void main() //主函數
{
EA=1; //總中斷允許
TMOD=0x20; //設置定時器T1 定時方式2 自動裝載定時常數
TL1=0xfd; //波特率設為9600
TH1=0xfd;
PCON=0x00; //SMOD=0,不倍增
SCON=0xd0; //SM2設為0,TB8設為0
TR1=1; //啟動定時器T1
ES=1; //允許串口中斷
SBUF=0xff; //串口發送0xff
while(TI==0); //判是否發送完畢
TI=0; //發送完畢,TI清0
while(1)
{
delay_ms(100);
if(switch1==0) //判是否k1按下,k1按下往下執行
{
TB8=1; //發送的第9位數據為1,送TB8,準備發地址幀
SBUF=0x01;//串口發1#從機的地址0x01以及TB8=1
while(TI==0); //判是否發送完畢
TI=0; //發送完畢,TI清0
TB8=0; //發送的第9位數據為0,送TB8,準備發數據幀
SBUF=0x00; //串口發送0x00以及TB8=0
while(TI==0); /判是否發送完畢
TI=0; //發送完畢,TI清0
}
if(switch2==0) //判是否k2按下,k2按下往下執行
{
TB8=1; //發送的第9位數據為1,發地址幀
SBUF=0x02; //串口發2#從機的地址0x02
while(TI==0); /判是否發送完畢
TI=0; //發送完畢,TI清0
TB8=0; //準備發數據幀
SBUF=0x00; //發數據幀0x00及TB8=0
while(TI==0); //判是否發送完畢
TI=0; //發送完畢,TI清0
}
if(switch3==0) //判是否k3按下,如按下,則往下執行
{
TB8=1; //準備發地址幀
SBUF=0x03; //發3#從機地址
while(TI==0); //判是否發送完畢
TI=0; //發送完畢,TI清0
TB8=0; //準備發數據幀
SBUF=0x00; //發數據幀0x00及TB8=0
while(TI==0); //判是否發送完畢
TI=0; //發送完畢,TI清0
}
}
}
void delay_ms(unsigned int i) //函數功能:延時
{
unsigned char j;
for(;i>0;i--)
for(j=0;j<125;j++)
;
}
//從機1串行通信程序
#include <reg51.h>
#include <math.h>
sbit led=P2^0; //定義P2.0連接的黃色LED
bit rrdy=0; //接收準備標志位rrdy=0,表示未做好接收準備
bit trdy=0; //發送準備標志位trdy=0,表示未做好發送準備
bit err=0; //err=1,表示接收到的命令為非法命令
void main() //從機1主函數
{
EA=1; //總中斷打開
TMOD=0x20;//定時器1 工作方式2,自動裝載,用于串口設置波特率
TL1=0xfd;
TH1=0xfd; //波特率設為9600
PCON=0x00; // SMOD=0
SCON=0xd0; //SM2設為0,TB8設為0
TR1=1; //啟動定時器T1
P1=0xff; // 向P1寫入全1,8個綠色LED全滅
ES=1; //允許串口中斷
while(RI==0); //接收控制指令0xff
if(SBUF==0xff) err=0; //如果接收到的數據為0xff,err=0,表示正確
else err=1; //err=1,表示接收出錯
RI=0; //接收中斷標志清0
SM2=1; //多機通訊控制位,SM2置1
while(1);}
void int1() interrupt 4, //函數功能:定時器T1中斷函數
{
if(RI) //如果RI=1
{
if(RB8) //如果RB8=1,表示接收的為地址幀
{
RB8=0;
if(SBUF==0x01) //如收的數據為地址幀0x01,是本從機的地址
{
SM2=0; //則SM2清0,準備接收數據幀
led=0; //點亮本從機黃色發光二極管
}
}
led=1; // 熄滅本從機黃色發光二極管
}
RI=0;
}