|
modbus RTU 协议:先后做1,3,15,16四个命令码,有主从站协议解析。
//--------------------------------------------------------------------------- // FILE: ModbusRTU.c // 程序分两部分:串口操作:中断接收和发送,采用缓冲区发送 // 协议处理:分主战和从站两部分,具体的站需要宏定义指定。 //--------------------------------------------------------------------------- // Ver | dd mmm yyyy | Who | Description of changes // =====|=============|======|=============================================== // 1.00| 2 Nov 2007 | WXJ | start version--03,16两命令分别读写内部寄存器 // // // //--------------------------------------------------------------------------- // Load DSP lib #i nclude "DSP281x_Device.h" #i nclude "DSP281x_Examples.h" // Load system lib #i nclude "EBC_Universal.H" //------------MODBUS CMD----------------------- #define READ_N_COIL 01 #define READ_N_DI 02 #define READ_HLD_REG 03 #define READ_AI 04 #define SET_1_COIL 05 #define SET_1_HLD_REG 06 #define SET_N_COIL 15 #define SET_N_HLD_REG 16 //------------UART_MODULE.Status--------------- #define IDLE_WAIT 0x00 // 空闲态,等待起始位 #define RECE_START 0x01 // 收到起始位,等待结束位 #define RECE_END 0x02 // 收到结束位,等待发送 #define SEND_START 0x03 // 发送起始位 #define SEND_END 0x04 // 发送完毕 #define SEND_EXCHANGE 0x05 // 发送内容切换(读/写,站1/站2) //------------主从站协议选择------------------- #ifdef DSP_EXT #define MODBUS_SLAVE #else #define MODBUS_MASTER #endif //--------------------------------------------- //[i][j]:i--(从站号-1);j--对应从站号通讯起始地址的偏移量 Uint16 WRData[2][100]; //从站1(HMI):500-599; 从站2(DSP2):600-699 Uint16 REData[2][100]; //从站1(HMI):700-799; 从站2(DSP2):800-899 Uint16 REDate[2][100]; //从站1(HMI):700-799; 从站2(DSP2):800-899 Uint16 WRBit[2][20]; //从站1(HMI):000-320; 从站2 Uint16 REBit[2][20]; //从站1(HMI):400-720; 从站2 volatile struct MODBUS_MODULE ModbusModule; //--------------------------------------------- void ConfigureModbus(void); Uint16 RTUFrameAnalyse(Uint16 *dest_p); void ConstructFrame_RTUReadHldReg( Uint16 board_adr,Uint16 start_address,Uint16 lenth); void ConstructFrame_RTUReadNCoil( Uint16 board_adr,Uint16 start_address,Uint16 lenth); void ConstructFrame_RTUSetNHldReg( Uint16 board_adr,Uint16 *com_buf,Uint16 start_address,Uint16 lenth); void ConstructFrame_RTUSetNCoil( Uint16 board_adr,Uint16 *com_buf,Uint16 start_address,Uint16 lenth); //--------------------------------------------- // 程序第一部分:串口程序 // 串口初始化 // 串口收发数据 //--------------------------------------------- #pragma CODE_SECTION(ScibRxInt, "ramfuncs"); #pragma CODE_SECTION(ScibTxInt, "ramfuncs"); //--------------------------------------------- //--------------------------------------------- void ConfigureModbus (void) { Uint16 i;
for(i=0;i<100;i++){ WRData[0][i]=0; WRData[1][i]=0; REData[0][i]=0; REData[1][i]=0; REDate[0][i]=0; REDate[1][i]=0; } for(i=0;i<20;i++){ WRBit[0][i]=0; REBit[0][i]=0; WRBit[1][i]=0; REBit[1][i]=0; } for( i = 0;i < 256 ;i++ ) { ModbusModule.Buf[i] = 0; } ModbusModule.TxLen = 0; ModbusModule.RxLen = 0; ModbusModule.Point = 0; ModbusModule.ReTryTime =0; ModbusModule.TimeoutReg =0; ModbusModule.Tbl_SET1 =0; ModbusModule.Tbl_READ1 =0; ModbusModule.Tbl_SET2 =0; ModbusModule.Tbl_READ2 =0; ModbusModule.Tbl_COIL_SET1=0; ModbusModule.Tbl_COIL_READ1=0; #ifdef MODBUS_MASTER ModbusModule.ID = 1; ModbusModule.FunCode= SET_N_COIL; ModbusModule.RegAddr= 400; ModbusModule.RegNum = 320; ModbusModule.Status = IDLE_WAIT; #endif #ifdef MODBUS_SLAVE ModbusModule.ID = 2; ModbusModule.Status = SEND_END; #endif
PieCtrlRegs.PIEIER9.bit.INTx3=1; //SCIRXINTB PieCtrlRegs.PIEIER9.bit.INTx4=1; //SCITXINTB IER |= M_INT9;
} //--------------------------------------------- //--------------------------------------------- interrupt void ScibTxInt (void) // SCI-B { PieCtrlRegs.PIEACK.bit.ACK9 = 1; if( ModbusModule.TxLen > 0 ){ ScibRegs.SCITXBUF= ModbusModule.Buf[ModbusModule.Point++]; ModbusModule.TxLen--; // ModbusModule.Point++; // ModbusModule.Point %= 128; // }else{ //发送完毕 ModbusModule.Status = SEND_END; //状态切换 ModbusModule.Point=0; ModbusModule.TimeoutReg=0; } }
//--------------------------------------------- // ScibRxInt MODBUS RTU // 以两字符时间停顿为3.5个字符时间 // 程序用5ms时间判断 对应9600--5个字符时间 // 程序帧结束数据在主程序里面处理 //--------------------------------------------- interrupt void ScibRxInt (void) // SCI-B { Uint16 temp; PieCtrlRegs.PIEACK.bit.ACK9 = 1; //ACK复位 temp=ScibRegs.SCIRXBUF.all; switch( ModbusModule.Status ){ case SEND_END: //4 ModbusModule.Status = RECE_START; ModbusModule.Point=0; case RECE_START: //1 ModbusModule.Buf[ModbusModule.Point] = temp; ModbusModule.Point++; ModbusModule.RxLen = ModbusModule.Point; break; } ModbusModule.TimeoutReg=0; } //--------------------------------------------- // 程序第二部分:MODBUS 协议解析与构造 // CRC16 // 协议帧构造 // 协议帧解析 //--------------------------------------------- //--------------------------------------------- // CRC16 calculate // <-Modbus Protocol English pdf // ptr calculate start point // len calculate data length //--------------------------------------------- Uint16 GetCRC16 (Uint16 volatile * ptr,Uint16 len) { Uint16 i; Uint16 crc=0xFFFF; if(len==0){ len=1; } while(len--){ crc^=(*ptr); for(i=0; i<8; i++){ if(crc&1){ crc>>=1; crc^=0xA001; }else{ crc>>=1; } } ptr++; } return(crc); } #ifdef MODBUS_MASTER //--------------------------------------------- // RTU Read Hold Register // CMD=03 READ_HLD_REG // Constructe Frame //--------------------------------------------- void ConstructFrame_RTUReadHldReg ( Uint16 board_adr,Uint16 start_address,Uint16 lenth) { Uint16 i=0,j=0; ModbusModule.Buf[i++] = board_adr; ModbusModule.Buf[i++] = READ_HLD_REG; ModbusModule.Buf[i++] = WORD_HI(start_address); ModbusModule.Buf[i++] = WORD_LO(start_address); ModbusModule.Buf[i++] = WORD_HI(lenth); ModbusModule.Buf[i++] = WORD_LO(lenth); j=GetCRC16(ModbusModule.Buf,i); ModbusModule.Buf[i++] = WORD_LO(j); ModbusModule.Buf[i++] = WORD_HI(j); ModbusModule.TxLen = i; ModbusModule.Point = 0; } //--------------------------------------------- // RTU Read Coil Status // CMD=01 READ_COIL_STATUS // Constructe Frame //--------------------------------------------- void ConstructFrame_RTUReadNCoil ( Uint16 board_adr,Uint16 start_address,Uint16 lenth) { Uint16 i=0,j=0; ModbusModule.Buf[i++] = board_adr; ModbusModule.Buf[i++] = READ_N_COIL; ModbusModule.Buf[i++] = WORD_HI(start_address); ModbusModule.Buf[i++] = WORD_LO(start_address); ModbusModule.Buf[i++] = WORD_HI(lenth); ModbusModule.Buf[i++] = WORD_LO(lenth); j=GetCRC16(ModbusModule.Buf,i); ModbusModule.Buf[i++] = WORD_LO(j); ModbusModule.Buf[i++] = WORD_HI(j); ModbusModule.TxLen = i; ModbusModule.Point = 0; } //--------------------------------------------- // RTU Set N Hold Register // CMD=16 SET_N_HLD_REG // Constructe Frame //--------------------------------------------- void ConstructFrame_RTUSetNHldReg ( Uint16 board_adr,Uint16 *com_buf,Uint16 start_address,Uint16 lenth) { Uint16 i=0,j=0; ModbusModule.Buf[i++] = board_adr; ModbusModule.Buf[i++] = SET_N_HLD_REG; ModbusModule.Buf[i++] = WORD_HI(start_address); ModbusModule.Buf[i++] = WORD_LO(start_address); ModbusModule.Buf[i++] = WORD_HI(lenth); ModbusModule.Buf[i++] = WORD_LO(lenth); ModbusModule.Buf[i++] = lenth<<1; for(j=0;j<lenth;j++){ ModbusModule.Buf[i++] = WORD_HI( * (com_buf+j) ); ModbusModule.Buf[i++] = WORD_LO( * (com_buf+j) ); } j=GetCRC16(ModbusModule.Buf,i); ModbusModule.Buf[i++] = WORD_LO(j); ModbusModule.Buf[i++] = WORD_HI(j); ModbusModule.TxLen = i; ModbusModule.Point = 0; } //--------------------------------------------- // RTU Set N Coil Status // CMD=16 SET_N_COIL_STATUS // Constructe Frame //--------------------------------------------- void ConstructFrame_RTUSetNCoil ( Uint16 board_adr,Uint16 *com_buf,Uint16 start_address,Uint16 lenth) { Uint16 i=0,j=0,byte_num=0,word_num=0; ModbusModule.Buf[i++] = board_adr; ModbusModule.Buf[i++] = SET_N_COIL; ModbusModule.Buf[i++] = WORD_HI(start_address); ModbusModule.Buf[i++] = WORD_LO(start_address); ModbusModule.Buf[i++] = WORD_HI(lenth); ModbusModule.Buf[i++] = WORD_LO(lenth); byte_num =(lenth+7)>>3; word_num =byte_num>>1; ModbusModule.Buf[i++] = byte_num; for(j=0;j<word_num;j++){ ModbusModule.Buf[i++] = WORD_LO( * (com_buf+j) ); ModbusModule.Buf[i++] = WORD_HI( * (com_buf+j) ); } if(byte_num&BIT0){ ModbusModule.Buf[i++] = WORD_LO( * (com_buf+j) ); } j=GetCRC16(ModbusModule.Buf,i); ModbusModule.Buf[i++] = WORD_LO(j); ModbusModule.Buf[i++] = WORD_HI(j); ModbusModule.TxLen = i; ModbusModule.Point = 0; }
//--------------------------------------------- // RTU 主站接收分析 // 3 READ_HLD_REG // 16 SET_N_HLD_REG // 返回值: 0 OK // 1 CRC校验错误 // 2 站号不匹配 // 3 功能码不匹配 // 4 16回应地址不匹配 // 5 16回应数据字数不匹配 //--------------------------------------------- Uint16 RTUMasterFrameAnalyse (Uint16 *dest_p) { Uint16 i; Uint16 crc_result, crc_tmp; Uint16 RegAddr,RegNum; Uint16 rx_byte_num;
crc_tmp = ModbusModule.Buf[ModbusModule.RxLen-1]<<8; crc_tmp += ModbusModule.Buf[ModbusModule.RxLen-2]; crc_result=GetCRC16(ModbusModule.Buf,ModbusModule.RxLen-2); if ( crc_tmp != crc_result ) // CRC 校验正确 { return 1; } if ( ModbusModule.ID != ModbusModule.Buf[0] ){ return 2; } if ( ModbusModule.FunCode != ModbusModule.Buf[1] ){ return 3; } switch (ModbusModule.FunCode){ case READ_N_COIL: //1 rx_byte_num=ModbusModule.Buf[2]; for ( i=0; i<rx_byte_num; i+=2){ *(dest_p + i/2) = ( ModbusModule.Buf[i+4]<<8 ) + ModbusModule.Buf[i+3]; } if(rx_byte_num&BIT0){ *(dest_p + i/2) &=0xFF00; *(dest_p + i/2) |=ModbusModule.Buf[i+3]&0xFF; //low 8 bit renew } break; case READ_HLD_REG: //3 // if ( !(SysSta&ComRecept) ){ for ( i=0; i<ModbusModule.Buf[2]; i+=2){ *(dest_p + i/2) = ( ModbusModule.Buf[i+3]<<8 ) + ModbusModule.Buf[i+4]; } // } break; case SET_N_COIL: //15 case SET_N_HLD_REG: //16 // RegAddr= ((ModbusModule.Buf[2] - (uint8)Uart0.Addr) << 8) + ModbusModule.Buf[3]; // 计算 寄存器首地址 RegAddr= (ModbusModule.Buf[2]<<8) + ModbusModule.Buf[3]; RegNum = (ModbusModule.Buf[4]<<8) + ModbusModule.Buf[5]; if ( RegAddr != ModbusModule.RegAddr ){ return 4; } if ( RegNum != ModbusModule.RegNum ){ return 5; } break; }//end switch return 0; } //--------------------------------------------- // ModbusRTUMasterRun // 主战先发起通讯,发送16(写),然后接收完毕,解析后发送3(读)然后接收完毕,解析(对从站1操作) // 对从站2进行类似操作。然后循环。 // //--------------------------------------------- void ModbusRTUMasterRun () { switch (ModbusModule.Status){ case IDLE_WAIT ://0 if (ModbusModule.TimeoutReg>=5){ //重发延时一结束符以上(3.5字符周期) if (!(SysSta&InitSub1) ){ if(ModbusModule.FunCode ==SET_N_COIL){ ModbusModule.ID=1; ModbusModule.FunCode =SET_N_COIL; ModbusModule.RegAddr=400; ModbusModule.RegNum=320; ConstructFrame_RTUSetNCoil(ModbusModule.ID,&REBit[ModbusModule.ID-1][0],ModbusModule.RegAddr,ModbusModule.RegNum); // } }else if (ModbusModule.FunCode ==SET_N_HLD_REG){ ModbusModule.ID=1; ModbusModule.FunCode =SET_N_HLD_REG; ModbusModule.RegAddr=700; ModbusModule.RegNum=100; ConstructFrame_RTUSetNHldReg(ModbusModule.ID,&REDate[ModbusModule.ID-1][0],ModbusModule.RegAddr,ModbusModule.RegNum); } }else if( ModbusModule.FunCode == SET_N_HLD_REG ){ ConstructFrame_RTUSetNHldReg(ModbusModule.ID,&WRData[ModbusModule.ID-1][0],ModbusModule.RegAddr,ModbusModule.RegNum); }else if ( ModbusModule.FunCode == READ_HLD_REG ){ ConstructFrame_RTUReadHldReg(ModbusModule.ID,ModbusModule.RegAddr,ModbusModule.RegNum); }else if( ModbusModule.FunCode == SET_N_COIL ){ ConstructFrame_RTUSetNCoil(ModbusModule.ID,&WRBit[ModbusModule.ID-1][0],ModbusModule.RegAddr,ModbusModule.RegNum); }else if ( ModbusModule.FunCode == READ_N_COIL ){ ConstructFrame_RTUReadNCoil(ModbusModule.ID,ModbusModule.RegAddr,ModbusModule.RegNum); } ScibRegs.SCITXBUF = ModbusModule.Buf[ModbusModule.Point++]; ModbusModule.TxLen--; ModbusModule.Status = SEND_START; } break; case SEND_START ://3 asm(" nop"); break; case SEND_END ://4 if (ModbusModule.TimeoutReg>=10){ //超时500ms(无回应) InitSci_B(); ModbusModule.ReTryTime++; ModbusModule.TimeoutReg=0; ModbusModule.Status = IDLE_WAIT; } break; case RECE_START ://1 if (ModbusModule.TimeoutReg>=5){ //接收帧结束 ModbusModule.Status = RECE_END; } break; case RECE_END ://2 if( (ModbusModule.FunCode== READ_N_COIL) || (ModbusModule.FunCode== SET_N_COIL)){ if ( RTUMasterFrameAnalyse(&REBit[ModbusModule.ID-1][0])==0 ){ //接收帧解码正确,清除故障 if ( (ModbusModule.ID==1) && (ModbusModule.FunCode==SET_N_COIL) ){ ModbusModule.Tbl_COIL_SET1=0; }else if ( (ModbusModule.ID==1) && (ModbusModule.FunCode==READ_N_COIL) ){ ModbusModule.Tbl_COIL_READ1=0; } ModbusModule.ReTryTime=0; //重试次数清0 ModbusModule.Status = SEND_EXCHANGE; }else{ //接收帧解码有误,重试,重试次数加1 ModbusModule.ReTryTime++; ModbusModule.TimeoutReg=0; ModbusModule.Status =IDLE_WAIT; } }else{ if ( RTUMasterFrameAnalyse(&REDate[ModbusModule.ID-1][0])==0 ){ //接收帧解码正确,清除故障 SysSta|=InitSub1; if ( (ModbusModule.ID==1) && (ModbusModule.FunCode==SET_N_HLD_REG) ){ ModbusModule.Tbl_SET1=0; }else if ( (ModbusModule.ID==1) && (ModbusModule.FunCode==READ_HLD_REG) ){ ModbusModule.Tbl_READ1=0; }else if ( (ModbusModule.ID==2) && (ModbusModule.FunCode==SET_N_HLD_REG) ){ ModbusModule.Tbl_SET2=0; }else if ( (ModbusModule.ID==2) && (ModbusModule.FunCode==READ_HLD_REG) ){ ModbusModule.Tbl_READ2=0; } ModbusModule.ReTryTime=0; //重试次数清0 ModbusModule.Status = SEND_EXCHANGE; }else{ //接收帧解码有误,重试,重试次数加1 ModbusModule.ReTryTime++; ModbusModule.TimeoutReg=0; ModbusModule.Status =IDLE_WAIT; } } break; case SEND_EXCHANGE ://5 if ( (ModbusModule.ID==1) && (ModbusModule.FunCode==SET_N_HLD_REG) ){ ModbusModule.ID = 1; ModbusModule.FunCode= READ_HLD_REG; ModbusModule.RegAddr= 700; ModbusModule.RegNum = 100; }else if ( (ModbusModule.ID==1) && (ModbusModule.FunCode==READ_HLD_REG) ){ ModbusModule.ID = 1; ModbusModule.FunCode= SET_N_COIL; ModbusModule.RegAddr= 00; ModbusModule.RegNum = 320; }else if ( (ModbusModule.ID==1) && (ModbusModule.FunCode==SET_N_COIL) ){ if (!(SysSta&InitSub1) ){ ModbusModule.FunCode= SET_N_HLD_REG; }else{ ModbusModule.ID = 1; ModbusModule.FunCode= READ_N_COIL; ModbusModule.RegAddr= 400; ModbusModule.RegNum = 320; } }else if ( (ModbusModule.ID==1) && (ModbusModule.FunCode==READ_N_COIL) ){ ModbusModule.ID = 2; ModbusModule.FunCode= SET_N_HLD_REG; ModbusModule.RegAddr= 600; ModbusModule.RegNum = 100; }else if ( (ModbusModule.ID==2) && (ModbusModule.FunCode==SET_N_HLD_REG) ){ ModbusModule.ID = 2; ModbusModule.FunCode= READ_HLD_REG; ModbusModule.RegAddr= 800; ModbusModule.RegNum = 100; }else if ( (ModbusModule.ID==2) && (ModbusModule.FunCode==READ_HLD_REG) ){ ModbusModule.ID = 1; ModbusModule.FunCode= SET_N_HLD_REG; ModbusModule.RegAddr= 500; ModbusModule.RegNum = 100; } ModbusModule.TimeoutReg=0; //延时一结束帧判断时间 ModbusModule.Status = IDLE_WAIT; break; default : break; } if(ModbusModule.ReTryTime>=5){ //重试次数到达上限,报错,切换发送 if ( (ModbusModule.ID==1) && (ModbusModule.FunCode==SET_N_HLD_REG) ){ ModbusModule.Tbl_SET1=1; }else if ( (ModbusModule.ID==1) && (ModbusModule.FunCode==READ_HLD_REG) ){ ModbusModule.Tbl_READ1=1; }else if ( (ModbusModule.ID==2) && (ModbusModule.FunCode==SET_N_HLD_REG) ){ ModbusModule.Tbl_SET2=1; }else if ( (ModbusModule.ID==2) && (ModbusModule.FunCode==READ_HLD_REG) ){ ModbusModule.Tbl_READ2=1; }else if ( (ModbusModule.ID==1) && (ModbusModule.FunCode==SET_N_COIL) ){ ModbusModule.Tbl_COIL_SET1=1; }else if ( (ModbusModule.ID==1) && (ModbusModule.FunCode==READ_N_COIL) ){ ModbusModule.Tbl_COIL_READ1=1; } if (SysSta&InitSub1){ ModbusModule.Status = SEND_EXCHANGE; } ModbusModule.ReTryTime=0; } } #endif #ifdef MODBUS_SLAVE //--------------------------------------------- // RTU Set N Hold Register // CMD=16 SET_N_HLD_REG // Constructe Answer Frame //--------------------------------------------- void ModbusSlaveSetNHldRegAnswer ( Uint16 board_adr,Uint16 start_address,Uint16 lenth) { Uint16 i=0,j=0; ModbusModule.Buf[i++] = board_adr; ModbusModule.Buf[i++] = SET_N_HLD_REG; ModbusModule.Buf[i++] = WORD_HI(start_address); ModbusModule.Buf[i++] = WORD_LO(start_address); ModbusModule.Buf[i++] = WORD_HI(lenth); ModbusModule.Buf[i++] = WORD_LO(lenth); j=GetCRC16(ModbusModule.Buf,i); ModbusModule.Buf[i++] = WORD_LO(j); ModbusModule.Buf[i++] = WORD_HI(j); ModbusModule.TxLen = i; ModbusModule.Point = 0; } //--------------------------------------------- // RTU Read Hold Register // CMD=03 READ_HLD_REG // Constructe Answer Frame //--------------------------------------------- void ModbusSlaveReadHldRegAnswer ( Uint16 board_adr,Uint16 *com_buf,Uint16 lenth) { Uint16 i=0,j=0; ModbusModule.Buf[i++] = board_adr; ModbusModule.Buf[i++] = READ_HLD_REG; ModbusModule.Buf[i++] = lenth<<1; for(j=0;j<lenth;j++){ ModbusModule.Buf[i++] = WORD_HI( * (com_buf+j) ); ModbusModule.Buf[i++] = WORD_LO( * (com_buf+j) ); } j=GetCRC16(ModbusModule.Buf,i); ModbusModule.Buf[i++] = WORD_LO(j); ModbusModule.Buf[i++] = WORD_HI(j); ModbusModule.TxLen = i; ModbusModule.Point = 0; } //--------------------------------------------- // RTU 从站接收分析 // 3 READ_HLD_REG // 16 SET_N_HLD_REG // 返回值: 0 OK // 1 CRC校验错误 // 2 站号不匹配 // 4 16写地址不匹配 // 5 16写数据字数不匹配 //--------------------------------------------- Uint16 RTUSlaveFrameAnalyse (Uint16 *dest_p) { Uint16 i; Uint16 crc_result, crc_tmp; Uint16 RegAddr,RegNum;
crc_tmp = ModbusModule.Buf[ModbusModule.RxLen-1]<<8; crc_tmp += ModbusModule.Buf[ModbusModule.RxLen-2]; crc_result=GetCRC16(ModbusModule.Buf,ModbusModule.RxLen-2); if ( crc_tmp != crc_result ) // CRC 校验正确 { return 1; } if ( ModbusModule.ID != ModbusModule.Buf[0] ){ return 2; } // if ( ModbusModule.FunCode != ModbusModule.Buf[1] ){ // return 3; // } ModbusModule.FunCode=ModbusModule.Buf[1]; switch (ModbusModule.FunCode){ case READ_HLD_REG: //3 // for ( i=0; i<ModbusModule.Buf[2]; i+=2){ // *(dest_p + i/2) = ( ModbusModule.Buf[i+3]<<8 ) + ModbusModule.Buf[i+4]; // } // RegAddr= (ModbusModule.Buf[2]<<8) + ModbusModule.Buf[3]; // RegNum = (ModbusModule.Buf[4]<<8) + ModbusModule.Buf[5]; ModbusSlaveReadHldRegAnswer(ModbusModule.ID,&WRData[0][0],100); break; case SET_N_HLD_REG: //16 // RegAddr= ((ModbusModule.Buf[2] - (uint8)Uart0.Addr) << 8) + ModbusModule.Buf[3]; // 计算 寄存器首地址 RegAddr= (ModbusModule.Buf[2]<<8) + ModbusModule.Buf[3]; RegNum = (ModbusModule.Buf[4]<<8) + ModbusModule.Buf[5]; if ( (RegNum<<1) != ModbusModule.Buf[6] ){ //字节长度是否匹配 return 4; } if ( RegAddr != 600 ){ //对应从站2固定的起始地址(自定义) return 5; } for ( i=0; i<ModbusModule.Buf[6]; i+=2){ *(dest_p + i/2) = ( ModbusModule.Buf[i+7]<<8 ) + ModbusModule.Buf[i+8]; } ModbusSlaveSetNHldRegAnswer(ModbusModule.ID,RegAddr,RegNum); break; }//end switch return 0; }
//--------------------------------------------- // ModbusRTUSlaveRun // 通讯由主站发起,从站初始化为接收,并相应的做出回应。 // 站号在初始化中有设置,以后不再更改。 //--------------------------------------------- void ModbusRTUSlaveRun (void) {
switch (ModbusModule.Status){ case IDLE_WAIT ://0 ScibRegs.SCITXBUF = ModbusModule.Buf[ModbusModule.Point++]; ModbusModule.TxLen--; ModbusModule.Status = SEND_START; break; case SEND_START ://3 asm(" nop"); break; case SEND_END ://4 if (ModbusModule.TimeoutReg>=10){ //超时10ms ModbusModule.ReTryTime++; ModbusModule.TimeoutReg=0; InitSci_B(); } break; case RECE_START ://1 if (ModbusModule.TimeoutReg>=5){ //接收帧结束 ModbusModule.Status = RECE_END; } break; case RECE_END ://2 if ( RTUSlaveFrameAnalyse(&REDate[0][0])==0 ){//帧解析正确 ModbusModule.Status =IDLE_WAIT; }else{ //帧解析不正确 ModbusModule.Status =SEND_END; } break;
} } #endif //--------------------------------------------------------------------------- // END //---------------------------------------------------------------------------
|