?? modbus.txt
字號:
//---------------------------------------------------------------------------
// 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 + -