MODBUS RTU简例--DSP281x

1,此处为程序正文

 

#include "DSP281x_Device.h"                                  //网上搜索到的头文件,放在后面。
#include "DSP281x_Examples.h"                             //网上搜索到头文件,放在后面。
#include "ModbusRTU.h"                                          //没有找到文件
#include "DSP_CRC.h"


//------------MODBUS FUNCODE-----------------------
#define READ_N_DO 01
#define READ_N_DI 02
#define READ_AO    03
#define READ_AI    04
#define SET_1_DO   05
#define SET_1_AO   06
#define SET_N_DO   15
#define SET_N_AO   16

//定义错误码
#define ERROR_FUNCODE    1    //错误功能码
#define ERROR_ADDR        2    //错误地址
#define ERROR_DATA        3    //错误数据
#define ERROR_FAILURE    4    //从机故障

//------------UART_MODULE.Status---------------
#define IDLE_WAIT        0x00        // 空闲态,等待起始位
#define RECE_START      0x01        // 收到起始位,等待结束位
#define RECE_END        0x02        // 收到结束位,等待发送
#define SEND_START      0x03        // 发送起始位
#define SEND_END        0x04        // 发送完毕

//---------------------------------------------
volatile struct MODBUS_MODULE ModbusModule;
//---------------------------------------------
Uint16 RTUFrameAnalyse(Uint16 *dest_p);
void ModbusDefaultInitSci();
void ConstructFrame_RTUReadReg( Uint16 type,Uint16 start_address,Uint16 lenth);
void ConstructFrame_RTUSetNReg( Uint16 type,Uint16 *com_buf,Uint16 start_address,Uint16 lenth);

void ReadSci(volatile Uint16 * buf ,volatile Uint16 * inx);

//---------------------------------------------
//---------------------------------------------

void ConfigureModbus (Uint16 ID,Uint16 SCI)
{
Uint16 i;

    for( i = 0;i < 256 ;i++ )
    {
        ModbusModule.Buf[i] = 0;
    }
    ModbusModule.TxLen = 0;
    ModbusModule.RxLen = 0;
    ModbusModule.TimeoutReg =0;
//现在开始只作为从站使用
ModbusModule.ID = ID;
ModbusModule.Status = IDLE_WAIT;
ModbusModule.SCI = SCI;
ModbusDefaultInitSci(); 
}
//---------------------------------------------

//复位SCI_A
void ModbusDefaultInitSci()
{
    EALLOW;
    GpioMuxRegs.GPGMUX.all |= 0x0030;
    EDIS;
    
    EALLOW;
    GpioMuxRegs.GPFMUX.all |= 0x0030;
    EDIS;
    if(ModbusModule.SCI==0)
    {
       SciaRegs.SCICCR.all = 0x07;
        
       SciaRegs.SCICTL1.all = 0x03;
       SciaRegs.SCICTL2.all = 0x00;
        
        //初始的时候不启动发送中断
       SciaRegs.SCICTL2.bit.TXINTENA =0;
       SciaRegs.SCICTL2.bit.RXBKINTENA =1;
       
       SciaRegs.SCIHBAUD = 0x01;
       SciaRegs.SCILBAUD = 0xe7;
       SciaRegs.SCICCR.all = 0x07;

       SciaRegs.SCIFFTX.all=0xE040;//0xC028;
       SciaRegs.SCIFFRX.all=0x0028;
       SciaRegs.SCIFFCT.all=0x00;

       SciaRegs.SCICTL1.all =0x0023;     // Relinquish SCI from Reset
       
       SciaRegs.SCIFFTX.bit.TXFIFOXRESET=1;
       SciaRegs.SCIFFRX.bit.RXFIFORESET=1;
   }else
   {
    
   }


}
void ResetSci()
{
if(ModbusModule.SCI==0){
   SciaRegs.SCIFFRX.bit.RXFIFORESET=0;
   SciaRegs.SCIFFRX.bit.RXFIFORESET=1;
}else{
   ScibRegs.SCIFFRX.bit.RXFIFORESET=0;
   ScibRegs.SCIFFRX.bit.RXFIFORESET=1;
}

}
void ReadSci(volatile Uint16 * buf ,volatile Uint16 * inx)
   {
if(ModbusModule.SCI==0){
    if(SciaRegs.SCIFFRX.bit.RXFIFST!=0){
     while(SciaRegs.SCIFFRX.bit.RXFIFST!=0)
        {
        buf[(*inx)++]=SciaRegs.SCIRXBUF.all;
        }
        //读到字符
        ModbusModule.TimeoutReg=0;
    }
    }else{
    if(ScibRegs.SCIFFRX.bit.RXFIFST!=0){
     while(ScibRegs.SCIFFRX.bit.RXFIFST!=0)
        {
        buf[(*inx)++]=ScibRegs.SCIRXBUF.all;
        }
        //读到字符
        ModbusModule.TimeoutReg=0;
    }
    }

   }
   void WriteSci()
   {
    int i;
if(ModbusModule.SCI==0){
     for(i = 0;i     {
        SciaRegs.SCITXBUF=ModbusModule.Buf[i];
         while(SciaRegs.SCIFFTX.bit.TXFFST==0x10){};
    }
}else{
     for(i = 0;i     {
        ScibRegs.SCITXBUF=ModbusModule.Buf[i];
         while(ScibRegs.SCIFFTX.bit.TXFFST==0x10){};
    }
   }

}

//---------------------------------------------
// RTU Set N Hold Register
// CMD=16 SET_N_HLD_REG
// Constructe Answer Frame
//---------------------------------------------

char ModbusSlaveSetNRegAnswer ( Uint16 type,Uint16 start_address,volatile Uint16 * buf,Uint16 lenth) 
{
Uint16 crc=0;

if(ModbusModule.WriteData(type,start_address,lenth,buf)) return ERROR_ADDR;
//多路更改
if(type==SET_N_AO){
    crc=GetCRC16(ModbusModule.Buf,6);
    ModbusModule.Buf[6] = WORD_HI(crc);
    ModbusModule.Buf[7] = WORD_LO(crc);
    ModbusModule.TxLen    = 8;
}else{
     //如果是单个更改,原样返回
     ModbusModule.TxLen    = 8;
}//i+=lenth*2;
return 0;
}
//---------------------------------------------
// RTU Read Hold Register
// CMD=03 READ_HLD_REG
// Constructe Answer Frame
//---------------------------------------------
char ModbusSlaveReadRegAnswer ( Uint16 type,Uint16 addr,Uint16 lenth)
{
Uint16 i=0,j=0;

ModbusModule.Buf[i++] = ModbusModule.ID;
ModbusModule.Buf[i++] = type;
ModbusModule.Buf[i++] = lenth<<1;
if(ModbusModule.ReadData(type,addr,lenth,&ModbusModule.Buf[i])) return ERROR_ADDR;
i+=lenth*2;
j=GetCRC16(ModbusModule.Buf,i);
ModbusModule.Buf[i++] = WORD_HI(j);
ModbusModule.Buf[i++] = WORD_LO(j);
ModbusModule.Buf[i] = 0;
ModbusModule.TxLen    = i;
return 0;
}
//---------------------------------------------
// RTU 从站接收分析 
// 3 READ_HLD_REG
// 16 SET_N_HLD_REG
// 返回值: 0 OK
//    1 CRC校验错误
//    2 站号不匹配 
//    4 16写地址不匹配
//    5 16写数据字数不匹配
//---------------------------------------------
Uint16 RTUSlaveFrameAnalyse ()
{
Uint16 ErrorFlag=0;
Uint16 crc_result, crc_tmp;
Uint16 RegAddr,RegNum;

crc_tmp = ModbusModule.Buf[ModbusModule.RxLen-2]<<8;
crc_tmp += ModbusModule.Buf[ModbusModule.RxLen-1];
crc_result=GetCRC16(ModbusModule.Buf,ModbusModule.RxLen-2);
//校验错误和站号不对不返回
    if ( crc_tmp != crc_result )       // CRC 校验正确
    {
        return 1;
    }

if ( ModbusModule.ID != ModbusModule.Buf[0] ){
return 2;
}

ModbusModule.FunCode=ModbusModule.Buf[1];
RegAddr= (ModbusModule.Buf[2]<<8) + ModbusModule.Buf[3];
switch (ModbusModule.FunCode){      
case READ_AI:
case READ_AO: //3,4读AIAO
       RegNum = (ModbusModule.Buf[4]<<8) + ModbusModule.Buf[5];
       ErrorFlag=ModbusSlaveReadRegAnswer(ModbusModule.FunCode,RegAddr,RegNum);
       //ModbusModule.TxLen=0;
       break;
case SET_1_AO: //0x06 写单个数据
       ErrorFlag=ModbusSlaveSetNRegAnswer(ModbusModule.FunCode,RegAddr,&ModbusModule.Buf[5],1);    
       break;       
case SET_N_AO: //0x10 写数据
         //第六个字节代表长度然后依次跟数据和crc
        RegNum = (ModbusModule.Buf[4]<<8) + ModbusModule.Buf[5];
        if ( (RegNum<<1) != ModbusModule.Buf[6] ){ //字节长度是否匹配
            ErrorFlag= ERROR_DATA; 
        }else{
               ErrorFlag=ModbusSlaveSetNRegAnswer(ModbusModule.FunCode,RegAddr,&ModbusModule.Buf[7],RegNum);    
        }
       break;
    default:
         ErrorFlag=ERROR_FUNCODE;//不支持的命令
   }//end switch
   //这些错误可以返回
   if(ErrorFlag)
   {
      //出现错误,将功能码最高位值1
      ModbusModule.Buf[1] = ModbusModule.Buf[1]|0x80;
    ModbusModule.Buf[2] = ErrorFlag;
    ModbusModule.TxLen=3;
      
   }
return 0;
}

//---------------------------------------------
// ModbusRTUSlaveRun
// 通讯由主站发起,从站初始化为接收,并相应的做出回应。
// 站号在初始化中有设置,以后不再更改。
//---------------------------------------------
void ModbusRTUSlaveRun (void)
{
switch(ModbusModule.Status){
    case IDLE_WAIT: //空闲
    //如果在空闲状态有数据,开始接收
    if(SciaRegs.SCIFFRX.bit.RXFIFST)
        {
        //ResetSci();
          ModbusModule.Status = RECE_START;
        //ModbusModule.TimeoutReg=0;
        }
    break;
    case RECE_START: //正在接收
    //停止时间超过5个毫秒结束
    ReadSci(&ModbusModule.Buf[0],&ModbusModule.RxLen);
    if (ModbusModule.TimeoutReg>=5){ //接收帧结束
         
         ModbusModule.Status = RECE_END;
       }
    break;
    case RECE_END: //接收完毕
       if ( RTUSlaveFrameAnalyse()==0 ){//帧解析正确
            ModbusModule.Status =SEND_START;
        }else{          //帧解析不正确
            ModbusModule.Status =SEND_END;
       }      
       ModbusModule.RxLen = 0;
       break;
    case SEND_START: //开始发送
    WriteSci();
      ModbusModule.Status =SEND_END;
    ModbusModule.TimeoutReg=0;
    break;
    case SEND_END: //发送完毕
       //重置fifo
       ResetSci();
       ModbusModule.Status=IDLE_WAIT;
       
       /*
       if (ModbusModule.TimeoutReg>=10){ //超过10ms
          ModbusModule.TimeoutReg=0;
          //超过10个毫秒重置等待
          ModbusModule.Status=IDLE_WAIT;
       }
       */

    break;

   
}
}



2,此处为DSP281x_Device.h

//###########################################################################

//

// FILE:  DSP281x_Device.h

//

// TITLE: DSP281x Device Definitions.

//

//###########################################################################

//

// Ver | dd mmm yyyy | Who  |Description of changes

//=====|=============|======|===============================================

// 1.00| 11 Sep 2003 | L.H. | Changes since previous version (v.58 Alpha)

//     |             |      | Added symbols created by the linker

//      |             |      |    cmd file for relocating code.

//     |             |      | Added float to the datatype typedefs

//     |             |      | Added #if DSP28_DATA_TYPES wrapperaround the

//     |             |      |    typedefs

//      |             |      | Added DSP28_BIOS and DSP28_NONBIOSswitches

//     |             |      |    to include or not include the default ISR's

//     |             |      | Moved files and info specific to theDSP28 examples

//     |             |     |     toDSP28_common\include\DSP28_Examples.h

//     |             |      | Changed F2812 -> DSP28_F2812

//     |             |      | Changed F2810 -> DSP28_F2810

//###########################################################################

 

#ifndef DSP281x_DEVICE_H

#define DSP281x_DEVICE_H

 

 

#ifdef __cplusplus

extern "C" {

#endif

 

 

#define  TARGET   1

//---------------------------------------------------------------------------

// User To Select Target Device:

 

#define  DSP28_F2812   TARGET

#define  DSP28_F2810   0

 

//---------------------------------------------------------------------------

// Common CPU Definitions:

//

 

extern cregister volatile unsigned int IFR;

extern cregister volatile unsigned int IER;

 

#define EINT   asm(" clrc INTM")

#define DINT   asm(" setc INTM")

#define ERTM   asm(" clrc DBGM")

#define DRTM   asm(" setc DBGM")

#define EALLOW asm(" EALLOW")

#define EDIS   asm(" EDIS")

#define ESTOP0 asm(" ESTOP0")

 

#define M_INT1  0x0001

#define M_INT2  0x0002

#define M_INT3  0x0004

#define M_INT4  0x0008

#define M_INT5  0x0010

#define M_INT6  0x0020

#define M_INT7  0x0040

#define M_INT8  0x0080

#define M_INT9  0x0100

#define M_INT10 0x0200

#define M_INT11 0x0400

#define M_INT12 0x0800

#define M_INT13 0x1000

#define M_INT14 0x2000

#define M_DLOG  0x4000

#define M_RTOS  0x8000

 

#define BIT0    0x0001

#define BIT1    0x0002

#define BIT2    0x0004

#define BIT3    0x0008

#define BIT4    0x0010

#define BIT5    0x0020

#define BIT6    0x0040

#define BIT7    0x0080

#define BIT8    0x0100

#define BIT9    0x0200

#define BIT10   0x0400

#define BIT11   0x0800

#define BIT12   0x1000

#define BIT13   0x2000

#define BIT14   0x4000

#define BIT15   0x8000

 

 

 

//---------------------------------------------------------------------------

// For Portability, User Is Recommended ToUse Following Data Type Size

// Definitions For 16-bit and 32-BitSigned/Unsigned Integers:

//

 

#ifndef DSP28_DATA_TYPES

#define DSP28_DATA_TYPES

typedef int             int16;

typedef long            int32;

typedef unsigned int    Uint16;

typedef unsigned long   Uint32;

typedef float           float32;

typedef long double     float64;

#endif

 

 

//---------------------------------------------------------------------------

// Include All Peripheral Header Files:

//

 

#include "DSP281x_SysCtrl.h"            // System Control/Power Modes

#include "DSP281x_DevEmu.h"             // Device Emulation Registers

#include "DSP281x_Xintf.h"              // External Interface Registers

#include"DSP281x_CpuTimers.h"         // 32-bit CPU Timers

#include "DSP281x_PieCtrl.h"            // PIE Control Registers

#include "DSP281x_PieVect.h"            // PIE Vector Table

#include "DSP281x_Spi.h"                // SPI Registers

#include "DSP281x_Sci.h"                // SCI Registers

#include "DSP281x_Mcbsp.h"              // McBSP Registers

#include "DSP281x_ECan.h"               // Enhanced eCAN Registers

#include "DSP281x_Gpio.h"               // General Purpose I/O Registers

#include "DSP281x_Ev.h"                 // Event Manager Registers

#include "DSP281x_Adc.h"                // ADC Registers

#include"DSP281x_XIntrupt.h"          // External Interrupts

#include"DSP281x_DefaultISR.h"          // DefaultISR

 

#ifdef __cplusplus

}

#endif /* extern "C" */

 

#endif // end of DSP281x_DEVICE_H definition

 

 

//===========================================================================

// No more.

//===========================================================================


3,此处为DSP281x_Examples.h

//###########################################################################

//

// FILE:  DSP281x_Examples.h

//

// TITLE: DSP281x Device Definitions.

//

//###########################################################################

//

// Ver | dd mmm yyyy | Who  |Description of changes

//=====|=============|======|===============================================

// 1.00| 11 Sep 2003 | L.H. | First release.  Seperated example specific headers

//     |             |      |    from the DSP28 peripheral headers.

//     |             |      | Added DSP28_BIOS and DSP28_NONBIOSswitches

//     |             |      |    to include or not include the default ISR's

//###########################################################################

 

#ifndef DSP281x_EXAMPLES_H

#define DSP281x_EXAMPLES_H

 

 

#ifdef __cplusplus

extern "C" {

#endif

 

 

/*-----------------------------------------------------------------------------

     Specify the clock rate of the CPU (SYSCLKOUT) in nS.

 

     Take into account the input clock frequency and the PLL multiplier

     selected in step 1.

 

     Use one of the values provided, or define your own.

     The trailing L is required tells the compiler to treat

     the number as a 64-bit value. 

 

     Only one statement should be uncommented.

 

     Example:  CLKIN is a 30MHzcrystal.

 

                In step 1 the user specifiedPLLCR = 0xA for a

                150Mhz CPU clock (SYSCLKOUT =150MHz). 

 

                In this case, the CPU_RATE willbe 6.667L

               Uncomment the line:  #define CPU_RATE  6.667L  

-----------------------------------------------------------------------------*/

//#define CPU_RATE    6.667L   // fora 150MHz CPU clock speed (SYSCLKOUT)

//#define CPU_RATE    7.143L   // fora 140MHz CPU clock speed (SYSCLKOUT)

//#define CPU_RATE    8.333L   // fora 120MHz CPU clock speed (SYSCLKOUT)

#define CPU_RATE   10.000L   // for a 100MHz CPU clock speed (SYSCLKOUT)

//#define CPU_RATE   13.330L   // fora 75MHz CPU clock speed (SYSCLKOUT)

//#define CPU_RATE   20.000L   // for a 50MHz CPU clock speed  (SYSCLKOUT)

//#define CPU_RATE   33.333L   // fora 30MHz CPU clock speed  (SYSCLKOUT)

//#define CPU_RATE   41.667L   // fora 24MHz CPU clock speed  (SYSCLKOUT)

//#define CPU_RATE   50.000L   // for a 20MHz CPU clock speed  (SYSCLKOUT)

//#define CPU_RATE   66.667L   // fora 15MHz CPU clock speed  (SYSCLKOUT)

//#define CPU_RATE  100.000L   // for a 10MHz CPU clock speed  (SYSCLKOUT)

 

//----------------------------------------------------------------------------

 

 

 

//---------------------------------------------------------------------------

// Include Example Header Files:

//

 

#include"DSP281x_GlobalPrototypes.h"      // Prototypes for global functions within the

                                            // .c files.

 

#include"DSP281x_SWPrioritizedIsrLevels.h" // Used for SoftwarePrioritization of ISR's

 

 

// Include files not used with DSP/BIOS

#ifndef DSP28_BIOS

#include "DSP281x_DefaultISR.h"

#endif

 

 

// DO NOT MODIFY THIS LINE. 

#define DELAY_US(A)  DSP28x_usDelay(((((long double) A * 1000.0L) / (long double)CPU_RATE) - 9.0L) / 5.0L)

 

 

#ifdef __cplusplus

}

#endif /* extern "C" */

 

#endif // end of DSP281x_EXAMPELS_H definition

 

 

//===========================================================================

// No more.

//===========================================================================



你可能感兴趣的:(通信及接口)