<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > avr單片機串口多機通訊及實(shí)例

avr單片機串口多機通訊及實(shí)例

作者: 時(shí)間:2016-12-03 來(lái)源:網(wǎng)絡(luò ) 收藏
在多機通信過(guò)程中,所有設備的 RS232接口是并在通信線(xiàn)上的,其中只能有一個(gè)設備為主機,其他為從機,通信由主機發(fā)起。數據幀一般采用1位起始位、9位數據位,其中第9位(RXB8)被用作為表征該幀是地址幀還是數據幀。當幀類(lèi)型表征位為“1”時(shí),表示該幀數據為一個(gè)地址幀;當幀類(lèi)型表征位為“0”時(shí),表示這個(gè)幀為一個(gè)數據幀。

  在A(yíng)VR中,通過(guò)設置從機的UCSRA寄存器中標志位MPCM,可以使能USART接收器對接收的數據幀進(jìn)行過(guò)濾的功能。如果使能了過(guò)濾功能,從機接收器對接收到的那些不是地址信息幀的數據幀將進(jìn)行過(guò)濾,不將其放入接收緩沖器中,這在多機通信中有效的方便了從機MCU處理數據幀程序的編寫(xiě)(同標準51 結構相比)。而發(fā)送器則不受MPCM位設置的影響。
  多機通信模式允許多個(gè)從機并在通信線(xiàn)路上,接收一個(gè)主機發(fā)出的數據。通過(guò)對接收到的地址幀中的地址進(jìn)行解碼,確定哪個(gè)從機被主機尋址。如果某個(gè)從機被主機尋址,它將接收接下來(lái)主機發(fā)出的數據幀,而其它的從機將忽略數據幀,直到再次接收到一個(gè)地址幀。(從機地址是由各個(gè)從機自己的軟件決定的)。
  對于在多機通信系統中的主機MCU,可以設置使用9位數據幀結構(UCSZ=7)。當發(fā)送地址幀時(shí),置第9位為“1”;發(fā)送數據幀時(shí),置第9位為 “0”。在這種情況下,從機也必須設置成接收9位數據幀結構。
  多機通信方式的數據交換過(guò)程如下:
1)設置所有從機工作在多機通信模式(MPCM=1)。
2) 通信開(kāi)始是由主機先發(fā)送一個(gè)地址幀,如8位數據為0X01(1號從機地址),第9位=“1”,呼叫1號從機。
3)所有從機都接收和讀取該主機發(fā)出的地址幀。在所有從機的MCU中,RXC標志位被置位,表示接收到地址幀。
4)每一個(gè)從機MCU讀UDR寄存器,并判斷自己是否被主機尋址。如果被尋址,清UCSAR寄存器中的MPCM位,等待接收數據;否則保持MPCM為 “1”,等待下一個(gè)地址幀的接收(該步應由用戶(hù)軟件處理實(shí)現):
A)作為1號從機的MCU處理過(guò)程為:收到地址幀后,判定讀取UDR數據0X01為自己的地址,將MPCM位置“0”,接收之后所有主機下發(fā)的數據幀,直到下一個(gè)地址幀為止。
B)其它從機MCU的處理過(guò)程:收到地址幀后,判定讀取UDR數據0X01不是自己的地址,將MPCM位置“1”,這樣他們將忽略主機隨后發(fā)送的數據幀,直到主機再次發(fā)送地址幀。
5)當被尋址的從機MCU接收完最后一個(gè)數據幀后,將MPCM位置位,等待下一個(gè)地址幀的出現(該步也應由用戶(hù)軟件處理實(shí)現),然后從步驟2開(kāi)始重復。

本文引用地址:http://dyxdggzs.com/article/201612/325089.htm

[轉]例子;

通訊規則:
1:時(shí)鐘7.3728 MHz/波特率9600/9個(gè)數據位/奇 校驗/1個(gè)停止位/硬件多機通訊功能/
2:通訊連接采用硬件MAX485,雙向單工
3:每個(gè)上行/下行的數據包的字節個(gè)數都是一樣的(通訊數據量)
4:每個(gè)上行/下行的數據包都采用CRC8校驗
5:數據接收采用中斷+查詢(xún)的方式
6:總是由主機向從機發(fā)送一個(gè)數據包,從機收到數據包后向主機回復一個(gè)數據包
7:不管是主機還是從機,如果收到的數據包有任何錯誤,都將丟棄該數據包,等 效于沒(méi)有接收
8:從機之間不能相互通訊,必須通過(guò)主機才能交換數據
9:無(wú)效地址是0,主機地址是1,從機地址是2.3.4......廣 播地址是255
*/
#include
#include
#include
#include //CRC校驗函數就在這個(gè)文件里面

#define amount 10 //設定通訊數據量(包括1個(gè) 地址幀,n個(gè)數據幀,1個(gè)校驗幀)

unsigned char send[amount]; //發(fā)件箱
unsigned char inbox[amount]; //收件箱
unsigned char n=0; //記憶中斷次數

//--------------------------------------------------------------------
interrupt[12] Rxd_isr(void) //接收中斷
{
unsigned char ERROR=0;
if( UCSRA&4 || UCSRA&16 ) ERROR=1; //奇偶效驗錯誤或者幀錯誤就記錄下來(lái)
inbox[n]=UDR; //保存到收件箱
n++; //記憶中斷次數
if(ERROR) inbox[0]=0; //如果通訊有錯,收 件箱的地址幀就標記成無(wú)效地址0
}

//---------------------------------------------------------------------
void main(void)
{
usart_init(); //串口初始化
UCSRA=0; //主機關(guān)閉地址篩選功能(多 機通訊功能)
#asm("sei") //打開(kāi)全局中斷
while(1)
{
//-------------與從機2對話(huà),與其他從機對話(huà)與下面的 程序類(lèi)似-------------------
n=0; //中斷次數清0
inbox[0]=0; //收件箱地址清0
//請更新準備發(fā)送的數據
//send[1]=?
//......
//send[n]=?
send[0]=2; //改變這個(gè)地址就可以實(shí)現與某個(gè)從機對話(huà)
send[amount-1]=crc8(send,amount-1); //計算發(fā)件箱的crc8校 驗碼
usart_out(send,amount); //將發(fā)件箱的數據send[]發(fā) 送出去;

//等待,從機接收到數據后會(huì )回復數據的,如果是10個(gè) 字節數據量,不能少于13ms!!!
//這個(gè)時(shí)間由人工計算,要考慮從機由于各種中斷延長(cháng)回復時(shí)間的可能

delay_ms(15);

//if(n<3)如果接收到的數據還不到3個(gè),那么就是通訊線(xiàn)路故障

//如果收件箱已經(jīng)收到amount個(gè)數據,并且crc8校 驗成功就...
if(n==amount && inbox[amount-1]==crc8(inbox,amount-1))
{
if(inbox[0]==1) //如果收件箱地址幀屬于本機就運行下面的測試 代碼
{
DDRD.3=1;
PORTD.3=1; delay_ms(10);
PORTD.3=0; delay_ms(990);
}

if(inbox[0]==255)
{
//請在這里添加收到廣播數據的處理程序
}
}
}
} //end

---------------------------------------------------------------------------------
從機
---------------------------------------------------------------------------------
#include
#include
#include

#define amount 10 //設定通訊數據量(包括1個(gè) 地址幀,n個(gè)數據幀,1個(gè)校驗幀)
#define address 2 //請在這里設定本機地址

unsigned char send[amount]; //發(fā)件箱
unsigned char inbox[amount]; //收件箱
unsigned char n=0; //記憶中斷次數

interrupt[12] Rxd_isr(void) //接收中斷
{
unsigned char ERROR=0;
if( UCSRA&4 || UCSRA&16 ) ERROR=1; //記錄 奇偶效驗錯誤或者幀錯誤
inbox[n]=UDR; //把接收到的數據保存到 收件箱
n++; //記憶接收的次數
if(ERROR) //如果通訊有錯....
{
n=0; //接收計數清0
inbox[0]=0; //把地址改為無(wú)效地址0
UCSRA|=0x01; //重新打開(kāi)接收器的地址 幀篩選功能
}

//如果地址匹配本機或者是廣播地址就關(guān)閉地址篩選(多機通訊)功能
if(inbox[0]==address ||inbox[0]==255) UCSRA&=254;

if(n==amount) //接收到amount個(gè) 數據以后...
{
n=0; //接收計數清0
UCSRA|=0x01; //重新打開(kāi)接收器的地址 幀篩選功能
if(inbox[amount-1]==crc8(inbox,amount-1)) //如果crc8校 驗正確就...
{
if(inbox[0]==address) //如果地址匹配本機就回 復數據
{
send[0]=1; //發(fā)件箱地址指向主機
send[amount-1]=crc8(send,amount-1);//產(chǎn)生發(fā)件箱的crc8校 驗碼
usart_out(send,amount); //發(fā)送發(fā)件箱的數據包send[]
//請在這里備份你的收件箱信息
}
if(inbox[0]==255) //如果是廣播地址就...
{
//請在這里添加你的代碼
//收到廣播數據請不要回復
}
}
}
}

void main(void)
{
usart_init();
#asm("sei")

while (1)
{
//send[1]=?
//......
//send[n]=?
};
}


---------------------------------------------------------------------------------
usart.h文件
---------------------------------------------------------------------------------
//波特率9600/9個(gè)數據位/1個(gè)停止位/奇校驗/收 發(fā)開(kāi)啟/接收中斷
void usart_init(void)
{
UCSRA=0x01;
UCSRB=0x9C;
UCSRC=0xB6;
UBRRH=0x00;
UBRRL=47;

PORTD.4=0; //MAX485平時(shí)工作在接收狀態(tài)
DDRD.4=1;
}

//-----------------------------------------------------------
//從數組datas[]的首地址開(kāi)始發(fā)送amount個(gè)數據,其 中第0個(gè)數據是地址幀,其他是數據幀
void usart_out(unsigned char *datas,unsigned char n)
{
unsigned char i=0;
PORTD.4=1; //使MAX485處 于發(fā)送狀態(tài)
while(i {
if(i==0) UCSRB|=1; else UCSRB&=254;
UDR=*(datas+i); //裝載數據開(kāi)始發(fā)送
while((UCSRA&64)==0); //等待發(fā)送結束
UCSRA|=64; //清除發(fā)送結束標志
i++; //發(fā)送次數統計
}
PORTD.4=0; //使MAX485處 于接收狀態(tài)
}

---------------------------------------------------------------------------------
crc8校驗程序
---------------------------------------------------------------------------------
unsigned char crc8(unsigned char *ptr, unsigned char len)
{
unsigned char i;
unsigned char crc=0;
while(len--!=0)
{
for(i=1; i!=0; i*=2)
{
if((crc&1)!=0) {crc/=2; crc^=0x8C;}
else crc/=2;
if((*ptr&i)!=0) crc^=0x8C;
}
ptr++;
}
return(crc);
}



關(guān)鍵詞: avr單片機串口多機通

評論


技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>