通讯规矩:
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);
}