|
发表于 2009-4-23 16:30:37
|
显示全部楼层
郁闷死了,老板让我编写Modbus通讯程序,编译通过,就是调试不通,程序是从网上下的;然后改了一些地址映射;麻烦大侠指点一下
/********Modbus.h ********/
#ifndef MODBUS_H
#define MODBUS_H
#ifdef __cplusplus
extern "C" {
#endif
typedef unsigned char boolean; /* Boolean value type. */
typedef unsigned long int uint32; /* Unsigned 32 bit value */
typedef unsigned short uint16; /* Unsigned 16 bit value */
typedef unsigned char uint8; /* Unsigned 8 bit value */
//typedef signed long int int32; /* Signed 32 bit value */
//typedef signed short int16; /* Signed 16 bit value */
typedef signed char int8; /* Signed 8 bit value */
//------------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 // 发送完毕
//------------MODBUS REGS-----------------------
/*ModBus 寄存器缓冲区起始绝对地址,位于L1SARAM
ModBus 寄存器缓冲区0x009F00~0x009FFF,总长度256个字长度,512个字节 */
#define MBRRegAdd 0x009F00
/*只读寄存器
起始地址:0x009F00;
长度 :0x20
*/
#define MBDriveVerB6 *(int *)(MBRRegAdd)/* 传动型号寄存器组 */
#define MBSoftVerBt6 *(int *)(MBRRegAdd+0x03)/* 软件版本寄存器组 */
#define MBSoftVerBt8 *(int *)(MBRRegAdd+0x06)/* 出厂编号寄存器组 */
#define MBStatusReg1_2 *(int *)(MBRRegAdd+0x0A)/* 状态寄存器1 */
#define MBStatusReg2_2 *(int *)(MBRRegAdd+0x0B)/* 状态寄存器2 */
#define MBStatusReg3_2 *(int *)(MBRRegAdd+0x0C)/* 状态寄存器3 */
#define MBStatusReg4_2 *(int *)(MBRRegAdd+0x0D)/* 状态寄存器4 */
#define MBStatusReg5_2 *(int *)(MBRRegAdd+0x0E)/* 状态寄存器5 */
#define MBStatusReg6_2 *(int *)(MBRRegAdd+0x0F)/* 状态寄存器6 */
#define MBFreqOut_4 *(int *)(MBRRegAdd+0x10)/* 实际频率输出寄存器 */
/*可读写寄存器*/
#define MBRWRegAdd 0x009F20
/*读写寄存器
起始地址:0x009F20;
长度 :0x10;
*/
/*EEPROM寄存器*/
/*可读写
起始地址:0x009F30;
长度 :0xCF;
*/
#define MBEEPROMRegAdd 0x009F30
// ------------功能指令----------------------------
#define WORD_LO(xxx) ((char)((int)(xxx) & 255))/* 得到一个字的低位*/
#define WORD_HI(xxx) ((char)((int)(xxx) >> 8)) /* 得到一个字的高位*/
//#define B_PTR(var) ((char *)(void *) &(var)) /*得到一个变量的地址(word宽度)*/
#define W_PTR(var) ((int *)(void *) &(var)) /*得到一个变量的地址(word宽度)*/
//#define MEM_B(x) (*( (char *)(x))) /*得到指定地址上的一个字节*/
#define MEM_W(x) (*( (int *)(x))) /*得到指定地址上的一个字*/
// 定义MODBUS数据结构
struct MODBUSDATA
{
unsigned int ID;
unsigned int FunCode;
unsigned int RegAdd;
unsigned int RegNum;
unsigned int Buf[128];
unsigned int Status;
unsigned int TxLen;
unsigned int RxLen;
unsigned int Point;
unsigned int TimeoutReg;
unsigned int TimeoutCounter;
};
//--------------------供外部调用函数-------------------------------
extern struct MODBUSDATA ModbusModule;
extern void ConfigureModbus(Uint16 brat,Uint16 SwitchRate);
extern void ModbusRTUSlaveRun(void);
#ifdef __cplusplus
}
#endif /* extern "C" */
#endif // end of DSP280x_SCI_H definition
//===========================================================================
// End of file.
//===========================================================================
// SC File $Revision:
// Checkin $Date:
//###########################################################################
//
// FILE: Modbus.c
//
// TITLE:
//
//###########################################################################
// $TI Release:
// $Release Date:
#include "DSP280x_Device.h" // DSP280x Headerfile Include File
#include "DSP280x_Examples.h" // DSP280x Examples Include File
#include "Modbus.h"
const unsigned char auchCRCHi[] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
} ;
/* CRC低位字节值表*/
const unsigned char auchCRCLo[] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
0x43, 0x83, 0x41, 0x81, 0x80, 0x40
} ;
struct MODBUSDATA ModbusModule;
// -------Modbus初始化----------0
void ConfigureModbus (void)
{
Uint16 i;
Uint16 *dest_p;
dest_p=((Uint16*)MBRRegAdd);
for(i=0;i<256;i++)
{
*(dest_p+i)=0x0000;
}
ModbusModule.TxLen = 0;
ModbusModule.RxLen = 0;
ModbusModule.Point = 0;
//ModbusModule.ReTryTime =0;
ModbusModule.ID = 2;
ModbusModule.Status = SEND_END;
}//
/*
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个字符时间
// 程序帧结束数据在主程序里面处理
//3.5字符数计数器公式:
//设波特率为 int BtRate(4800;9600;19200;)
//设开关频率volatile int SwitchRate(1K~20K,单位为KHZ)
//设3.5字符时间为delay3.5 =(int)(3.5*10*1000/BtRate);
//计数器Timeout3.5=delay3.5*SwitchRate;
//---------------------------------------------
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 * puchMsg,Uint16 usDataLen)
{
unsigned char uchCRCHi = 0xFF ; /* 高CRC字节初始化 */
unsigned char uchCRCLo = 0xFF ; /* 低CRC 字节初始化 */
Uint32 uIndex ; /* CRC循环中的索引 */
while (usDataLen--) /* 传输消息缓冲区 */
{
uIndex = uchCRCHi ^ *puchMsg++ ; /* 计算CRC */
uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;
uchCRCLo = auchCRCLo[uIndex] ;
}
return (uchCRCHi << 8 | uchCRCLo) ;
}//uint16 crc16(uint8 *puchMsg, uint16 usDataLen)
//---------------------------------------------
// 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 站号不匹配
// 3 读地址无效
// 4 16写地址不匹配
// 5 16写数据字数不匹配
//---------------------------------------------
Uint16 RTUSlaveFrameAnalyse (void)
{
Uint16 i;
Uint16 *dest_p;
Uint16 crc_result, crc_tmp;
Uint16 RegNum;
int16 RegAddr;
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;
}
ModbusModule.FunCode=ModbusModule.Buf[1];
RegAddr= (ModbusModule.Buf[2]<<8) + ModbusModule.Buf[3]-0x4000;
RegNum = (ModbusModule.Buf[4]<<8) + ModbusModule.Buf[5];
switch (ModbusModule.FunCode)
{
case READ_HLD_REG: //3
if(RegAddr>0xFF||RegAddr<0) return 3;
if((RegAddr+RegNum-1)>0xff) return 3;
dest_p=((Uint16*)(MBRRegAdd+RegAddr+RegNum-1));
ModbusSlaveReadHldRegAnswer(ModbusModule.ID,dest_p,RegNum);
break;
//case SET_1_HLD_REG: //6
case SET_N_HLD_REG: //16
if(RegAddr>0x2F||RegAddr<0x20) return 4;
if((RegAddr+RegNum-1)>0x2f) return 4;
if((RegNum<<1) != ModbusModule.Buf[6])return 4;
dest_p=((Uint16*)(MBRRegAdd+RegAddr+RegNum-1));
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()==0 )
{//帧解析正确
ModbusModule.Status =IDLE_WAIT;
}
else
{ //帧解析不正确
ModbusModule.Status =SEND_END;
}
break;
}
} |
|