#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;
}
}
//###########################################################################
//
// 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.
//===========================================================================
//###########################################################################
//
// 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.
//===========================================================================