RS485多机通讯问题

jiangyouzhi 2012-07-24 11:06:23
请教各位关与485多机通讯问题,小弟用PIC单片机进行RS485多机通讯,1主机4从机,单独一对一通讯都是正常的,但是一起一对四通讯从机可以收到数据,但是主机手表到从机返回的数据,我是采用轮询的方式通讯,先对1号机通讯,1号机收到主机发来的数据后判断是否是本机地址,是本机地址后再返回一个数据,这样对1号机的查询结束后,再对2号进行查询,一直到4号。但是主机却收不到从机发来的数据,每个从机都分配步同的地址,不知是什么问题,折腾好几天了,还望各位大侠帮忙解决下,是什么问题引起的,谢谢!
...全文
620 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
ceee_hero 2012-08-01
  • 打赏
  • 举报
回复
实际的硬件结构图请给出 最好是PCB图
WeiLu_V 2012-08-01
  • 打赏
  • 举报
回复
建议外挂一个232转485的通信模块,使用通用的串口调试助手查看总线上的数据。主机接收不到数据,首先确认分机是否将数据发送出来。一对一能正常收发,多点不能接收,估计主要是发送数据的时序问题。由于485是半双工,在发送完毕后和切换收发时需要做适当的延时,以保证数据的正常接收。在实验室基本可以不考虑线材材质和长度的影响,在现场就需要增加延时或降低波特率来处理。
a250871207 2012-07-27
  • 打赏
  • 举报
回复
网络拓朴结构?
jiangyouzhi 2012-07-25
  • 打赏
  • 举报
回复
主机程序:
#include<pic.h>
#include"My_Hfile.h"
__CONFIG(0X0864);
__CONFIG(0X18ff);

volatile UCHAR Addr; //从机地址
volatile UCHAR Recv_Data[5]; //接收数据缓存
UCHAR Recv_idx; //接受数据缓存索引
UINT CRC; //CRC校验数据
//----LCD封面显示
UCHAR table1[]={"SL1 DATA:"};
UCHAR table2[]={"SL2 DATA:"};
UCHAR table3[]={"SL3 DATA:"};
UCHAR table4[]={"SL3 DATA:"};
//-------------------------------------------------------------------
bit F_T1,Recv_OK; //相关标识位
//-----------------------------------主程序-------------------------------------
void main()
{
UCHAR i;
__delay_ms(100); //等待足够的数据带从机完成初始化
port_init(); //端口初始化
lcd_init(); //LCD初始化
GOTO_XY(0,0); //显示位置设置,及显示内容
write_lcd(table1);
GOTO_XY(0,1);
write_lcd(table2);
GOTO_XY(0,2);
write_lcd(table3);
GOTO_XY(0,3);
write_lcd(table4);
Per_init(); //外设初始化
while(1)
{
//循环访问从机
for(Addr=0x01;Addr<=0X04;Addr++)
{
LED_send=0;
EN_485=1; //允许485发送(禁止接受)
__delay_ms(1);
Send_Byte(Addr); //发送从机地址
Send_Byte(COMMAND); //发送操作命令码
CRC=0XFFFF; //CRC校验复位
CRC16(Addr); //校验从机地址
CRC16(COMMAND); //校验操作命令码
Send_Byte(CRC); //发送CRC低8位
Send_Byte(CRC>>8); //发送CRC高8位
__delay_ms(1);
SET_TIMER1(15000); //设置帧间隔时间
F_T1=0;
Recv_OK=0; //接受成功标志先设0
EN_485=0; //允许485接受(禁止发送)
TMR0=5; //定时器0设定超时时间
TMR0IF=0;
// while(!Recv_OK);
while((!Recv_OK)&&(!F_T1)) ; //如果主机未接收到从机数据且为超时则等待

//------------------------------------------------------
//如果主机接受从机数据成功,则继续下面的处理
if(Recv_OK)
{
GIE=0; //关中断
Recv_OK=0; //接收成功标志设为0
CRC=0XFFFF; //CRC校验复位
for(i=0;i<5;i++) //对当前接收的数据校验
{
CRC16(Recv_Data[i]);
}
//校验成功时显示返回的数据
if(CRC==0X0000)
{
LED_recv=~LED_recv;
switch(Addr)
{
case 0x01:
{
GOTO_XY(9,0);
hex_asc(Recv_Data[2]);
break;
}
case 0x02:
{
GOTO_XY(9,1);
hex_asc(Recv_Data[2]);
break;
}
case 0x03:
{
GOTO_XY(9,2);
hex_asc(Recv_Data[2]);
break;
}
case 0x04:
{
GOTO_XY(9,3);
hex_asc(Recv_Data[2]);
break;
}
default:{
GOTO_XY(9,0);
write_data('E');
write_data('R');
write_data('R');
write_data('O');
write_data('R');
GOTO_XY(9,1);
write_data('E');
write_data('R');
write_data('R');
write_data('O');
write_data('R');
GOTO_XY(9,2);
write_data('E');
write_data('R');
write_data('R');
write_data('O');
write_data('R');
GOTO_XY(9,3);
write_data('E');
write_data('R');
write_data('R');
write_data('O');
write_data('R');
break;
}
}
}

}

//__delay_ms(10); //每完成一个从机数据处理后延时10ms
GIE=1; //再开中断

}
//__delay_ms(15); //每完成一轮扫描后等待10MS
}
}
//定时器中断及485接收中断程序
void interrupt ISR()
{
UCHAR temp;
//-----------------定时器1溢出中断--------------------------------------
if(TMR1IF)
{
TMR1IF=0;
F_T1=1;
}
//-----------------串口接收中断-------------------------------------------------
if(RCIF)
{
TEST1=~TEST1;
Recv_OK=0;
temp=RCREG;
if(Recv_idx==0)
{

if(temp==Addr)
{
Recv_Data[Recv_idx++]=temp; TEST2=~TEST2;
}
else
{
Recv_idx=0;
}
}
else if(Recv_idx==5)
{
Recv_idx=0;
Recv_OK=1;
}
else
{
Recv_Data[Recv_idx++]=temp;
}

}

}

从机主程序:
#include<pic.h>
#include"My_Hfile.h"
__CONFIG(0X0864);
__CONFIG(0X18ff);

volatile UCHAR Recv_Data[4]; //??????
volatile UCHAR Recv_idx; //????????
UCHAR Addr; //?????
UINT CRC; //CRC???
UCHAR return_data; //????????
bit F_T1,Recv_OK; //?????
//LCD????
UCHAR table1[]={"RECV BYTE1:"};
UCHAR table2[]={"RECV BYTE2:"};
UCHAR table3[]={"RECV BYTE3:"};
UCHAR table4[]={"RECV BYTE4:"};

//----------------------------???--------------------------------------------
void main()
{
UCHAR i,j;
Recv_OK=0; //????????0
port_init(); //?????
lcd_init(); //LCD???
//LCD???????????
GOTO_XY(0,0);
write_lcd(table1);
GOTO_XY(0,1);
write_lcd(table2);
GOTO_XY(0,2);
write_lcd(table3);
GOTO_XY(0,3);
write_lcd(table4);

Per_init();//?????
LED_recv=0;

while(1)
{
//???????????4???
if(Recv_OK)
{

Recv_OK=0;
GIE=0; //???
// __delay_ms(10);
//?????????0
CRC=0XFFFF; //CRC?????
for(i=0;i<4;i++) //CRC????????
{
CRC16(Recv_Data[i]);
}
//?????????????????5???????????????????2??CRC?
if(CRC==0X0000)
{
LED_recv=1;
EN_485=1; //485??????????
__delay_ms(1); //?????????????
GOTO_XY(11,0);
hex_asc(Recv_Data[0]);
GOTO_XY(11,1);
hex_asc(Recv_Data[1]);
GOTO_XY(11,2);
hex_asc(Recv_Data[2]);
GOTO_XY(11,3);
hex_asc(Recv_Data[3]);
RB5=~RB5;
if(Recv_Data[0]==Addr)
{
return_data=Addr|(0XF0|(j++));//???????
Send_Byte(Addr); //??????
Send_Byte(COMMAND); //?????
Send_Byte(return_data); //???????

CRC=0xFFFF; //CRC????
CRC16(Addr); //????
CRC16(COMMAND); //?????
CRC16(return_data); //???????
Send_Byte(CRC); //??CRC?8?
Send_Byte(CRC>>8); //??CRC?8?
__delay_ms(1);
EN_485=0; //????????485??
LED_recv=0;
}
}
GIE=1; //???
}
}
}






void interrupt ISR()
{
UCHAR temp;
//-----------------定时器1溢出中断--------------------------------------
if(TMR1IF)
{
TMR1IF=0;
F_T1=1;
}
//-----------------串口接收中断-------------------------------------------------
if(RCIF)
{
TEST1=~TEST1;
Recv_OK=0;
temp=RCREG;

if(Recv_idx==0)
{

if(temp==Addr)
{
Recv_Data[Recv_idx++]=temp; TEST2=~TEST2;
}
else
{
Recv_idx=0;
}
}
else if(Recv_idx==4)
{
Recv_idx=0;
Recv_OK=1;
}
else
{
Recv_Data[Recv_idx++]=temp;
}

}

}

上面是主机和从机的主程序,我都是按地址轮流通讯的,不知道是什么问题?
q2005133218 2012-07-25
  • 打赏
  • 举报
回复
应该是总线冲突问题,建议思路:
1、检查从机和主机发送之后是否回到接收;
2、检查各机做发送是否时间错开!
Barry-当下 2012-07-24
  • 打赏
  • 举报
回复
逐步定位,先定位主机是否发数据,从机是否收到数据,再定位从机是否应答。
常态,所有的主机和从机都是处于接收状态的。
只有在需要发送数据的时候才置为发送。
jiangyouzhi 2012-07-24
  • 打赏
  • 举报
回复
主机发送数据是正常的,因为四个从机都收到了数据,主机没收到从机返回的数据
lbing7 2012-07-24
  • 打赏
  • 举报
回复
最直接的办法是把PC也挂到总线上

然后,光接收,就知道有什么数据出来。

再分析是什么情况下协议冲突了

27,374

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧