51單片機(jī)串口多機(jī)通信的實(shí)現(xiàn)和編程
一、51單片機(jī)的主從模式,首先要設(shè)定工作方式3:(主從模式+波特率可變)
SCON串口功能寄存器:SM0=1;SM1=1(工作方式3)
注:主機(jī)和從機(jī)都要為工作方式3。
【工作方式2 (SM0 SM1 :1 0):串行口為11位異步通信接口。發(fā)送或接收一幀信息包括1位起始位“0”、8位數(shù)據(jù)位、1位可編程位、1位停止位“1”。發(fā)送數(shù)據(jù):發(fā)送前,先根據(jù)通信協(xié)議由軟件設(shè)置TB8為“奇偶校驗(yàn)位”或“數(shù)據(jù)標(biāo)識(shí)位”,然后將要發(fā)送的數(shù)據(jù)寫(xiě)入SBUF,即能啟動(dòng)發(fā)送器。發(fā)送過(guò)程是由執(zhí)行任何一條以SBUF為目的寄存器的指令而啟動(dòng)的,把8位數(shù)據(jù)裝入SBUF,同時(shí)還把TB8裝到發(fā)送移位寄存器的第9位上,然后從TXD(P3.1)端口輸出一幀數(shù)據(jù)。接收數(shù)據(jù):先置REN=1,使串行口為允許接收狀態(tài),同時(shí)還要將RI清“0”。然后再根據(jù)SM2的狀態(tài)和所接收到的RB8的狀態(tài)決定此串行口在信息到來(lái)后是否置R1=1,并申請(qǐng)中斷,通知CPU接收數(shù)據(jù)。當(dāng)SM2=0時(shí),不管RB8為“0”還是為“1”,都置RI=1,此串行口將接收發(fā)送來(lái)的信息。當(dāng)SM2=1時(shí),且RB8=1,表示在多機(jī)通信情況下,接收的信息為“地址幀”, 此時(shí)置RI=1,串行口將接收發(fā)來(lái)的地址。當(dāng)SM2=1時(shí),且RB8=0,表示在多機(jī)通信情況下,接收的信息為“數(shù)據(jù)幀”, 但不是發(fā)給本從機(jī)的,此時(shí)RI不置為“1”,因而SBUF中接收的數(shù)據(jù)幀將丟失。
工作方式3 (SM0 SM1 :1 1):為波特率可變的11位異步通信方式,除了波特率有所區(qū)別之外,其余方式都與方式2相同。】【以上內(nèi)容摘自網(wǎng)絡(luò)】
二、主機(jī)的配置發(fā)送“地址”時(shí),把TB8設(shè)定為1,發(fā)送數(shù)據(jù)時(shí)TB8設(shè)定為0
(類(lèi)似于:主機(jī) TB8=1發(fā)送的是地址,TB8=0發(fā)送的是數(shù)據(jù))
發(fā)送幀結(jié)構(gòu):
假設(shè)主機(jī)將發(fā)送“1234”給地址為1的從機(jī):調(diào)用函數(shù):TXdata(1,"1234$");
void TXdata(uchar addr,uchar *str)
{
TB8 = 1; //發(fā)送地址
SBUF = addr; //把地址發(fā)送出去
while(!TI); //判斷是否發(fā)送成功(發(fā)送成功后TI會(huì)置1,需手動(dòng)清0)
TI = 0;
TB8 = 0; //發(fā)送數(shù)據(jù)
while(*str != '\0') //發(fā)送數(shù)組
{
SBUF = (*str);
while(!TI);
TI = 0;
str++;
}
}
三、從機(jī)配置
1. 從機(jī)接收時(shí),首先串口初始化時(shí),使SM2=1(接收地址模式,即只能接收到TB8=1的數(shù)據(jù),才觸發(fā)中斷),主機(jī)發(fā)送TB=0的數(shù)據(jù),被認(rèn)為是總線上的主機(jī)發(fā)送給別機(jī)的通信數(shù)據(jù),本機(jī)丟棄,不產(chǎn)生中斷。
2. 接收的地址與本機(jī)地址相符后,使SM2=0(接收數(shù)據(jù)模式,接收數(shù)據(jù)正常觸發(fā)中斷)
(類(lèi)似于:從機(jī) SM2=1只接收地址,SM2=0只接收數(shù)據(jù))
void chuan() interrupt 4 //串口中斷服務(wù)函數(shù)
{
ES = 0; //關(guān)閉串口中斷
if(RI) //再次判斷,是否接收到數(shù)據(jù)(接收到數(shù)據(jù)后,RI會(huì)置1,需手動(dòng)清0)
{
RXData = SBUF;
if(RXstart) //判斷是否接收到過(guò)本地址
{
if(RXData != '$') //判斷是否接收到 數(shù)據(jù)結(jié)束 標(biāo)志 $
{
temp[j] = RXData; //沒(méi)有接收到結(jié)束標(biāo)志,正常保存數(shù)據(jù)至數(shù)組
j++;
}
else //接收到 結(jié)束標(biāo)志 $
{
RXstart= 0; //本次接收結(jié)束
SM2 = 1; //重新 配置為:只接收地址 模式,下次發(fā)送TB8=1才中斷
j = 0;
}
}
if(RXData == 1) //判斷是否呼叫本機(jī),地址范圍:000 – 254(00 - FE)
{
RXstart = 1; //開(kāi)始接收數(shù)據(jù)
SM2 = 0; //配置為:接收數(shù)據(jù) 模式
}
}
RI = 0; //清除接收標(biāo)志位
ES = 1; //重新開(kāi)啟串口中斷
}
四、串口初始化配置
89S51、52、STC12Cxxx + 11.0592M晶振,9600bps
void UART_init()
{
TMOD = 0x20; //定時(shí)器1,工作方式2:8位、自動(dòng)重裝
TH1 = 0xfd; //fd: 9600bps @ 11.0592M
TL1 = 0xfd; //e8: 1200bps @ 11.0592M
//f4: 2400bps @ 11.0592M
REN = 1; //允許串口接收
SM0 = 1;
SM1 = 1; //SM0和SM1:串口工作模式3,主從模式 + 波特率可變
SM2 = 1; //只接收地址(從機(jī)如此配置,主機(jī)不需要)
ES = 1; //開(kāi)串口中斷
TR1 = 1; //啟動(dòng)定時(shí)器1
EA = 1; //中斷 總開(kāi)關(guān)
}
五、接線圖和注意事項(xiàng)
1、從機(jī)和從機(jī)之間通信,只能通過(guò)主機(jī)中轉(zhuǎn)。
2、各從機(jī)的TXD輸出不能設(shè)置為推挽輸出,要設(shè)置為開(kāi)漏輸出。
3、通信總線不能過(guò)長(zhǎng),最好不超過(guò)2米。
編輯:admin 最后修改時(shí)間:2018-05-19