通訊規則:
1:時鐘7.3728MHz/波特率9600/9個數據位/奇校驗/1個停止位/硬件多機通訊功能/
2:通訊連接采用硬件MAX485,雙向單工
3:每個上行/下行的數據包的字節個數都是一樣的(通訊數據量)
?
4:每個上行/下行的數據包都采用CRC8校驗
5:數據接收采用中斷+查詢的方式
6:總是由主機向從機發送一個數據包,從機收到數據包后向主機回復一個數據包
7:不管是主機還是從機,如果收到的數據包有任何錯誤,都將丟棄該數據包,等效于沒有接收
8:從機之間不能相互通訊,必須通過主機才能交換數據
9:無效地址是0,主機地址是1,從機地址是2.3.4.。。.。。廣播地址是255
*/
#include
#include
#include
#include//CRC校驗函數就在這個文件里面
#defineamount10//設定通訊數據量(包括1個地址幀,n個數據幀,1個校驗幀)
unsignedcharsend[amount];//發件箱
unsignedcharinbox[amount];//收件箱
unsignedcharn=0;//記憶中斷次數
//--------------------------------------------------------------------
interrupt[12]Rxd_isr(void)//接收中斷
{
unsignedcharERROR=0;
if(UCSRA&4||UCSRA&16)ERROR=1;//奇偶效驗錯誤或者幀錯誤就記錄下來
inbox[n]=UDR;//保存到收件箱
n++;//記憶中斷次數
if(ERROR)inbox[0]=0;//如果通訊有錯,收件箱的地址幀就標記成無效地址0
}
//---------------------------------------------------------------------
voidmain(void)
{
usart_init();//串口初始化
UCSRA=0;//主機關閉地址篩選功能(多機通訊功能)
#asm(“sei”)//打開全局中斷
while(1)
{
//-------------與從機2對話,與其他從機對話與下面的程序類似-------------------
n=0;//中斷次數清0
inbox[0]=0;//收件箱地址清0
//請更新準備發送的數據
//send[1]=?
//。。.。。.
//send[n]=?
send[0]=2;//改變這個地址就可以實現與某個從機對話
send[amount-1]=crc8(send,amount-1);//計算發件箱的crc8校驗碼
usart_out(send,amount);//將發件箱的數據send[]發送出去;
//等待,從機接收到數據后會回復數據的,如果是10個字節數據量,不能少于13ms?。?!
//這個時間由人工計算,要考慮從機由于各種中斷延長回復時間的可能
delay_ms(15);
//if(n《3)如果接收到的數據還不到3個,那么就是通訊線路故障
//如果收件箱已經收到amount個數據,并且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
#defineamount10//設定通訊數據量(包括1個地址幀,n個數據幀,1個校驗幀)
#defineaddress2//請在這里設定本機地址
unsignedcharsend[amount];//發件箱
unsignedcharinbox[amount];//收件箱
unsignedcharn=0;//記憶中斷次數
interrupt[12]Rxd_isr(void)//接收中斷
{
unsignedcharERROR=0;
if(UCSRA&4||UCSRA&16)ERROR=1;//記錄奇偶效驗錯誤或者幀錯誤
inbox[n]=UDR;//把接收到的數據保存到收件箱
n++;//記憶接收的次數
if(ERROR)//如果通訊有錯。。.。
{
n=0;//接收計數清0
inbox[0]=0;//把地址改為無效地址0
UCSRA|=0x01;//重新打開接收器的地址幀篩選功能
}
//如果地址匹配本機或者是廣播地址就關閉地址篩選(多機通訊)功能
if(inbox[0]==address||inbox[0]==255)UCSRA&=254;
if(n==amount)//接收到amount個數據以后。。.
{
n=0;//接收計數清0
UCSRA|=0x01;//重新打開接收器的地址幀篩選功能
if(inbox[amount-1]==crc8(inbox,amount-1))//如果crc8校驗正確就。。.
{
if(inbox[0]==address)//如果地址匹配本機就回復數據
{
send[0]=1;//發件箱地址指向主機
send[amount-1]=crc8(send,amount-1);//產生發件箱的crc8校驗碼
usart_out(send,amount);//發送發件箱的數據包send[]
//請在這里備份你的收件箱信息
}
if(inbox[0]==255)//如果是廣播地址就。。.
{
//請在這里添加你的代碼
//收到廣播數據請不要回復
}
}
}
}
voidmain(void)
{
usart_init();
#asm(“sei”)
while(1)
{
//send[1]=?
//。。.。。.
//send[n]=?
};
}
---------------------------------------------------------------------------------
usart.h文件
---------------------------------------------------------------------------------
//波特率9600/9個數據位/1個停止位/奇校驗/收發開啟/接收中斷
voidusart_init(void)
{
UCSRA=0x01;
UCSRB=0x9C;
UCSRC=http://www.pICavr.com/0xB6;
UBRRH=0x00;
UBRRL=47;
PORTD.4=0;//MAX485平時工作在接收狀態
DDRD.4=1;
}
//-----------------------------------------------------------
//從數組datas[]的首地址開始發送amount個數據,其中第0個數據是地址幀,其他是數據幀
voidusart_out(unsignedchar*datas,unsignedcharn)
{
unsignedchari=0;
PORTD.4=1;//使MAX485處于發送狀態
while(i{
if(i==0)UCSRB|=1;elseUCSRB&=254;
UDR=*(datas+i);//裝載數據開始發送
while((UCSRA&64)==0);//等待發送結束
UCSRA|=64;//清除發送結束標志
i++;//發送次數統計
}
PORTD.4=0;//使MAX485處于接收狀態
}
---------------------------------------------------------------------------------
crc8校驗程序
---------------------------------------------------------------------------------
unsignedcharcrc8(unsignedchar*ptr,unsignedcharlen)
{
unsignedchari;
unsignedcharcrc=0;
while(len--!=0)
{
for(i=1;i!=0;i*=2)
{
if((crc&1)!=0){crc/=2;crc^=0x8C;}
elsecrc/=2;
if((*ptr&i)!=0)crc^=0x8C;
}
ptr++;
}
return(crc);
}
評論
查看更多