485多机通信 通信不正常,请帮助查问题。。。
现在连接 模式是 PC->无源232转485模块--->从机1---->从机2从机上用485芯片。
现在问题是 只接一个从机通信非常稳定,接上第二个从机通信就不正常了,现象是上电只有一个从机能通信上,断电再上电可能变成另一只从机通信上了,断电再上电还可能会变。反正就是只有一个从机可以通信的上。用的modbus协议。
不知道从何查起?
硬件?软件? 本帖最后由 281229961 于 2012-12-6 23:29 编辑
代码如下void USART1_IRQHandler(void) //串口1中断服务程序
{
u8 Res;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)//接收中断
{
Res =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据
if(Res==addr&USART_RX_STA==0) //接收到起始信号
{
USART_RX_BUF=Res;
USART_RX_STA=1;
}
else if (USART_RX_STA!=0)
{
USART_RX_BUF=Res;
USART_RX_STA++;
}
}
if ( USART_RX_STA>7)
checkComm0Modbus();
}
voidreadRegisters(void)
{
unsigned int regaddr,byteCount,i;
unsigned int num;
unsigned int Data;
regaddr=USART_RX_BUF+(USART_RX_BUF<<8);//要读取的寄存器起始地址
num=USART_RX_BUF+(USART_RX_BUF<<8);//要读取的寄存器数量
USART_TX_BUF=addr;
USART_TX_BUF=0x03;
USART_TX_BUF=2*num; //字节数=寄存器数量*2
for(i=0;i<num;i++)
{
USART_TX_BUF=buf>>8;
USART_TX_BUF=buf;
//addr+1+i: 解释如下
//由于上位机读写没有0号地址 上位机读写的起始地址为 读写4WB0001对应于下位机的0号地址
//为了便于上下位机读写地址对应, 所以下位机地址在收发的时候加 1
// 比如上位机读写4WB0001->00 16位读写
// 则下位机 反馈 buf 16位数组
// 这样的话 读写4WB0001->buf 读写4WB0002->buf。。。。。
// (buf就再也用不到了)
//否则不加 1 的 话 读写4WB0001->buf 读写4WB0002->buf。。。。。
//纯属个人习惯!!!
}
byteCount=3+2*num;//CRC校验的字节数
Data = CRCC16(USART_TX_BUF,byteCount);
USART_TX_BUF=Data>>8;
USART_TX_BUF=Data&0xff;
Uart_send_n(USART_TX_BUF,byteCount+2);
//IOWR_ALTERA_AVALON_UART_CONTROL(UART_0_BASE, 0x80);//接收中断使能
}
void presetMultipleRegisters(void)//多寄存器设置
{
unsigned int regaddr,num,i;
unsigned int crcData;
//unsigned int tempData;
regaddr=USART_RX_BUF+(USART_RX_BUF<<8);
num=USART_RX_BUF+(USART_RX_BUF<<8);
for(i=0;i<num;i++)
{
buf=USART_RX_BUF+(USART_RX_BUF<<8);
//addr+1+i: 解释如下
//由于上位机读写没有0号地址 上位机读写的起始地址为 读写4WB0001对应于下位机的0号地址
//为了便于上下位机读写地址对应, 所以下位机地址在收发的时候加 1
// 比如上位机读写4WB0001->00 16位读写
// 则下位机 反馈 buf 16位数组
// 这样的话 读写4WB0001->buf 读写4WB0002->buf。。。。。
// (buf就再也用不到了)
//否则不加 1 的 话 读写4WB0001->buf 读写4WB0002->buf。。。。。
//纯属个人习惯!!!
}
USART_TX_BUF=addr;
USART_TX_BUF=0x10;
USART_TX_BUF=USART_RX_BUF;
USART_TX_BUF=USART_RX_BUF;
USART_TX_BUF=USART_RX_BUF;
USART_TX_BUF=USART_RX_BUF;
crcData = CRCC16(USART_RX_BUF,6);
USART_TX_BUF=crcData>>8;
USART_TX_BUF=crcData;
Uart_send_n(USART_TX_BUF,8);
// Recover();
// IOWR_ALTERA_AVALON_UART_CONTROL(UART_0_BASE, 0x80);//接收中断使能
}
void checkComm0Modbus(void)
{
unsigned int crcData;
unsigned int tempData;//数据个数
if(USART_RX_STA > 4)
{switch(USART_RX_BUF)
{
case 3://读取保持寄存器(一个或多个)
if(USART_RX_STA >= 8)
{//接收完成一组数据
//应该关闭接收中断
//IOWR_ALTERA_AVALON_UART_CONTROL(UART_0_BASE, 0x0);//关闭接收中断
if(USART_RX_BUF==addr) // && checkoutError==0)
{
crcData = CRCC16(USART_RX_BUF,6);
if(crcData == USART_RX_BUF+(USART_RX_BUF<<8))
{//校验正确
if(USART_RX_BUF == 3)
{//读取保持寄存器(一个或多个)
readRegisters();
}
}
}
USART_RX_STA = 0;
// checkoutError = 0;
} break;
case 16://设置多个寄存器
tempData = (USART_RX_BUF<<8) + USART_RX_BUF;
tempData = tempData * 2; //数据个数计算=寄存器数*2+9
tempData += 9; //数据个数
if(USART_RX_STA >= tempData)
{// IOWR_ALTERA_AVALON_UART_CONTROL(UART_0_BASE, 0x0);//关闭接收中断
if(USART_RX_BUF==addr)
{
crcData = CRCC16(USART_RX_BUF,tempData-2);
if(crcData == (USART_RX_BUF<<8)+ USART_RX_BUF)
{
presetMultipleRegisters();
}
}
USART_RX_STA = 0;
}
break;
default:
break;
}
}
} 从机的modbus地址设置成不一样了吗?
485通讯线上有加匹配电阻吗?
zml 发表于 2012-12-6 23:22 static/image/common/back.gif
从机的modbus地址设置成不一样了吗?
485通讯线上有加匹配电阻吗?
地址设置成不一样的了
通信线只有2m长 没有加匹配电阻 从现象上看,像是软件问题。这么长的程序,不一定有人帮你找bug,自己仔细检查一下吧
硬件方面,所有端点,包括所有主机从机的地线连起来试一下 用串口监视 (模式是 PC->无源232转485模块) 接到AB端 看收发资料就可确定
你那485程式 应该没错 跟我使用的一样 我用再PIC上 有个软件,叫modbus poll,可以用来测试。要先分开是软件问题还是硬件问题。 zml 发表于 2012-12-7 18:51 static/image/common/back.gif
有个软件,叫modbus poll,可以用来测试。要先分开是软件问题还是硬件问题。 ...
谢谢 周一再测试了 收发控制脚在作怪,话说没有看到是如何控制这个管脚的 gaolf_2012 发表于 2012-12-7 20:40 static/image/common/back.gif
收发控制脚在作怪,话说没有看到是如何控制这个管脚的
在Uart_send_n 这个函数里面的
一对一通信完全正常 测试一整天 都很好 一对一帧间隔是多少?丢帧不?如果从机程序的控制脚处于发送状态太长,并且超过帧间隔的话会影响总线。另外你的Uart_send_n 函数我真的没找到啊
说的有道理 注意帧间距离
页:
[1]