⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 modbus.txt

📁 MODBUS代码
💻 TXT
📖 第 1 页 / 共 2 页
字号:
//---------------------------------------------------------------------------
// 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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -