程序如下,单片机是STC12C5A60S2,目前的程序量是60K,当多个下位机被主机读时,第一个被读到的地址总是一次就能读成功,以后的地址读第二次才能被读到,请教是什么原因?
void Modbus_Comm()
{
if( (Receive_State == Receive_Done) )
{
if( Modbus_Check_CRC() )
{
Modbus_Function();
Modbus_Send_CRC();
SendFlag = 1;
}
if(SendFlag) // max485(半双工通信) RE/DE定义 RE=0为接受状态 DE=1为发送状态(参考MAX485芯片管脚)
{
ES=0;
while( Send_Num > 0 )
{
Send_Num--;
TI=0;
SBUF =Send_Sbuf[Send_Num1] ;
while(TI==0);
Send_Num1++;
}
Send_Num1 = 0;
SendFlag = 0;
RS485E = 0; //接收状态
ES=1;
}
Receive_State = Start_Receive;
}
if(abc_true && (Local_Addr == 0 | Local_Addr == 253) )
{
abc_true = 0 ;
Local_Addr = 253 ; //临时子机地址
Send_Sbuf[0] = 0x01 ; //主机地址
Send_Sbuf[1] = 0x03 ; //读命令
Send_Sbuf[2] = 0x00 ;
Send_Sbuf[3] = 0xfd ; //地址
Send_Sbuf[4] = 0x00 ;
Send_Sbuf[5] = 0x01 ; //数量
Send_Num = 8;
Modbus_Send_CRC();
ES=0;
while( Send_Num > 0 )
{
Send_Num--;
TI=0;
SBUF =Send_Sbuf[Send_Num1] ;
while(TI==0);
Send_Num1++;
}
Send_Num1 = 0;
SendFlag = 0;
RS485E = 0; //接收状态
ES=1;
}
if(abc_true && (Local_Addr != 0 | Local_Addr != 253) )
{
abc_true = 0 ;
Send_Sbuf[0] = 0x01 ; //主机地址
Send_Sbuf[1] = 0x03 ; //读命令
Send_Sbuf[2] = 0x00 ;
Send_Sbuf[3] = 0xfe ; //地址
Send_Sbuf[4] = 0x00 ;
Send_Sbuf[5] = 0x01 ; //数量
Send_Num = 8;
Modbus_Send_CRC();
ES=0;
while( Send_Num > 0 )
{
Send_Num--;
TI=0;
SBUF =Send_Sbuf[Send_Num1] ;
while(TI==0);
Send_Num1++;
}
Send_Num1 = 0;
SendFlag = 0;
RS485E = 0; //接收状态
ES=1;
}
}
void Modbus_Delay(Uchar i)
{
Uchar j;
for(i; i > 0; i--)
for(j = 200; j > 0; j--);
}
Uint Modbus_CRC_Check(Uchar *pack, Uint num)
{
Uchar CRCcode_H = 0XFF; // 高CRC字节初始化
Uchar CRCcode_L = 0XFF; // 低CRC 字节初始化
Uchar index; // 数据索引
while (num--)
{
index = CRCcode_L ^ (*pack++);
CRCcode_L = CRCcode_H ^ CRC_H[index];
CRCcode_H = CRC_L[index];
}
return (CRCcode_L << 8 | CRCcode_H); // MODBUS 规定低位在前
}
void Modbus_Read_Reg(void)
{
Uchar i,dat_H,dat_L;
Uchar j=3;
Send_Sbuf[2] = Receive_Sbuf[5] * 2; // 返回 读取的字节个数
Send_Num = 5 + Send_Sbuf[2]; // 5个固定字节+数据个数 addr1 + fun1 + num1 +【data】+ crc2
for(i=0; i<Receive_Sbuf[5]; i++) //i++为连续读
{
dat_H = 0;
switch(Receive_Sbuf[3] + i) // 地址索引递增 //上位机命令地址加上 字节数
{
case 0: dat_L = Local_Addr; //Local_Addr
break; //通讯地址
case 1: dat_L = 0; //txslnum
break;//70 通讯速率
case 2 :
if(Receive_Sbuf[2]==0xfd )
{
Send_Sbuf[0] = 0xfd ; //子机地址
Send_Sbuf[1] = 0x06 ; //写命令
Send_Sbuf[2] = 0x00;
Send_Sbuf[3] = 0x01;
Send_Sbuf[4] = 0x00 ;
Send_Sbuf[5] = Local_Addr*100+ziji_addr ;
ziji_addr++;
Send_Num = 8;
}
break;
}
if((Receive_Sbuf[3] + i)!=253)
{
Send_Sbuf[j++] = dat_H; // 数据高位
Send_Sbuf[j++] = dat_L; // 数据低位
}
}
}
void Modbus_Force_Reg(void)
{
Send_Sbuf[2] = Receive_Sbuf[2]; //高地址
Send_Sbuf[3] = Receive_Sbuf[3]; //低地址
Send_Sbuf[4] = Receive_Sbuf[4]; //数据个数高位
Send_Sbuf[5] = Receive_Sbuf[5]; //数据个数低位
Send_Num = 0;
// tongxun_xie_flag=1;
switch( Receive_Sbuf[3])// + i) // 地址索引
{
case 0: Local_Addr = Receive_Sbuf[5]; //Local_Addr
break;; //通讯地址
}
}
void Modbus_Send_CRC(void)
{
Uint send_CRC;
send_CRC = Modbus_CRC_Check(&Send_Sbuf, Send_Num-2);
Send_Sbuf[Send_Num -2] = send_CRC >> 8;
Send_Sbuf[Send_Num -1] = send_CRC; // 将校验位加入发送缓冲
RS485E=1;
Modbus_Delay(50);
}
Uchar Modbus_Check_CRC(void)
{
Uint rec_CRC;
rec_CRC = Modbus_CRC_Check(Receive_Sbuf,Receive_Num-2);
if(rec_CRC == (Receive_Sbuf[Receive_Num-2]<<8)+ Receive_Sbuf[Receive_Num-1])
{
return 1;
}
else
{
return 0;
}
}
void Modbus_Function(void)
{
Send_Sbuf[0] = Receive_Sbuf[0];
Send_Sbuf[1] = Receive_Sbuf[1];
switch(Receive_Sbuf[1]) // 功能号
{
case 3: Modbus_Read_Reg();
break;
case 6: Modbus_Force_Reg();
break;
}
}
void Serial() interrupt 4
{
if(RI)
{
RI=0;
Redata = SBUF;
switch(Receive_State) //判断当前接受状态
{
case Start_Receive: Receive_Num = 0;
if(Redata == Local_Addr)//&&(Send_Over = 1))//通讯地址一致
{
Receive_Sbuf[Receive_Num++] = SBUF;//接受缓冲区开始接收数据
Receive_State = Receive_Ing; //接收状态改为正在接收
}
break;
case Receive_Ing: Receive_Sbuf[Receive_Num++] = Redata;
if(Receive_Num==8) //全部接受完以后再发送
{
Receive_State=Receive_Done; //接收完以后改变接收状态
}
break;
}
}
if(TI)
{
TI=0;
}
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
一周热门 更多>