#include"My_Config.h"
#include"ModBus.h"
#include "CRC_IBM_Table.h"
ModbusReg_Typ ModbusReg; //Modbus 自定义变量结构体
unsigned char MBCommBuf[MBCommBuf_MAX]; //Modbus Comm Buffer
//***********************************Modbus RAM*****************************************************//
// ModbusCoil 输出线圈 读写 功能码:01、05、15
// ModbusInput 输入离散量 只读 功能码:02
// ModbusHoldReg 保持寄存器 读写 功能码:03、06、16
// ModbusInputReg 输入寄存器 只读 功能码:04
//******************************************************************************************************//
unsigned char ModbusCoil[MBCoil_MAX] = {0};
unsigned char ModbusInput[MBInput_MAX] = {0};
unsigned char ModbusHoldReg[MBHoldReg_MAX] = {0};
unsigned char ModbusInputReg[MBInputReg_MAX] = {0};
//*****************************************************************************************
//Modbus 通信先送Hi再送Lo
void Modbus_ReadDat()
{
ModbusInputReg[0] = 0x07;
ModbusInputReg[1] = 0xaa;
ModbusInputReg[2] = 0x00;
ModbusInputReg[3] = 0xff;
ModbusInputReg[14] = 0x14;
ModbusInputReg[15] = 0x15;
}
//*****************************************************************************************
//CRC_IBM
unsigned int CRC_IBM(unsigned char *puchMsg, unsigned short usDataLen)
{
unsigned char uchCRCHi = 0xFF;
unsigned char uchCRCLo = 0xFF;
unsigned char uIndex;
while(usDataLen--)
{
uIndex = uchCRCHi ^ *puchMsg++ ;
uchCRCHi = uchCRCLo ^ AuchCRCHi[uIndex] ;
uchCRCLo = AuchCRCLo[uIndex] ;
}
return (uchCRCHi << 8 | uchCRCLo);
}
/*--------------------------从机响应主机询问函数 function code: 03/04 读多个保持寄存器/输入寄存器值-------------------------------------*/
//接收和发送共用CommBuf
//询问数据包格式:CommBuf[0] MBCommBuf[1] MBCommBuf[2] MBCommBuf[3] MBCommBuf[4] MBCommBuf[5] MBCommBuf[6] MBCommBuf[7]
// MBCommBuf[]={从机地址,功能码,高起始地址,低起始地址,寄存器数高位,寄存器数低位,校验码低位,校验码高位}
//响应数据包格式:CommBuf[0] MBCommBuf[1] MBCommBuf[2] MBCommBuf[3] MBCommBuf[4] MBCommBuf[5]…… MBCommBuf[n]
// MBCommBuf[]={从机地址,功能码,字节数,数据1,数据2……数据i,校验码低位,校验码高位}
/*----------------------------------------------------------------------------------------------------------------------------------------------------*/
void Modbus_ReadRegisters(void)
{
int16u_Typ CRC_Checksum;
if(ModbusReg.ReciveIndex != 8)
ModbusReg.State = MODBUS_STATE_START; //非法指令 放弃帧
else if((MBCommBuf[1] == Read_Input_Registers) &&
(ModbusReg.DataAddress + ModbusReg.DataLength > MBInputReg_MAX))
ModbusReg.State = MODBUS_STATE_START; //读取数据或地址非法 放弃帧
else if((MBCommBuf[1] == Read_Holding_Registers) &&
(ModbusReg.DataAddress + ModbusReg.DataLength > MBHoldReg_MAX))
ModbusReg.State = MODBUS_STATE_START; //读取数据或地址非法 放弃帧
else
{
Modbus_ReadDat();
if(MBCommBuf[1] == Read_Holding_Registers) //03
{
for (unsigned char i = 0; i < ModbusReg.DataLength; i++)
MBCommBuf[3 + i] = ModbusHoldReg[ModbusReg.DataAddress + i];
}
else //04
{
for (unsigned char i = 0; i < ModbusReg.DataLength; i++)
MBCommBuf[3 + i] = ModbusInputReg[ModbusReg.DataAddress + i];
}
CRC_Checksum.int16u = CRC_IBM(MBCommBuf,ModbusReg.DataLength + 3); //数据及其前面3个字节需要做CRC运算
MBCommBuf[ModbusReg.DataLength + 3] = CRC_Checksum.int8u[1];
MBCommBuf[ModbusReg.DataLength + 4] = CRC_Checksum.int8u[0];
ModbusReg.SendIndex = ModbusReg.DataLength + 5;
ModbusReg.State = MODBUS_STATE_SEND; //跳转发送态
}
}
//*****************************************************************************************
//
//
//*****************************************************************************************
void Modbus_PresetMultipleRegisters(void)
{
int16u_Typ CRC_Checksum;
if(ModbusReg.ReciveIndex == 13) //0x10命令必须是13字节数据
{
MBCommBuf[0] = ModbusReg.LocalAddress;
CRC_Checksum.int16u = CRC_IBM(MBCommBuf,ModbusReg.DataLength + 3); //数据及其前面3个字节需要做CRC运算
MBCommBuf[ModbusReg.DataLength + 3] = CRC_Checksum.int8u[1];
MBCommBuf[ModbusReg.DataLength + 4] = CRC_Checksum.int8u[0];
MBCommBuf[0] = ModbusReg.LocalAddress;
ModbusReg.DataLength = 4;
ModbusReg.SendIndex = ModbusReg.DataLength + 5;
}
else
ModbusReg.State = MODBUS_STATE_START; //非法指令 放弃帧
}
//*****************************************************************************************
//ModBus数据解析
//
//*****************************************************************************************
void ModBus_Analysis(void)
{
if(CRC_IBM(MBCommBuf,ModbusReg.ReciveIndex) != 0) //CRC校验错误 放弃帧 跳转起始态
ModbusReg.State = MODBUS_STATE_START;
else
{
ModbusReg.DataAddress = (MBCommBuf[2] << 8) | MBCommBuf[3];
ModbusReg.DataLength = (MBCommBuf[4] << 8) | MBCommBuf[5];
switch(MBCommBuf[1])
{
case Read_Coil_Status:
break;
case Read_Input_Status:
break;
case Read_Holding_Registers:
case Read_Input_Registers:
ModbusReg.DataAddress *= 2;
ModbusReg.DataLength *= 2;
MBCommBuf[2] = ModbusReg.DataLength;
Modbus_ReadRegisters();
break;
case Preset_Multiple_Registers:
ModbusReg.DataAddress *= 2;
ModbusReg.DataLength *= 2;
MBCommBuf[2] = ModbusReg.DataLength;
Modbus_PresetMultipleRegisters();
break;
default:
ModbusReg.State = MODBUS_STATE_START; //非法指令 放弃帧
break;
}
}
}
//*****************************************************************************************
//ModBus数据发送
//
//*****************************************************************************************
void ModBus_Send()
{
TRSEL = 1;
for(unsigned int i = 1000;i > 0;i--);
for(unsigned char i = 0;i < ModbusReg.SendIndex;i++)
{
// Parity_Check(MBCommBuf[i],1);
UART_TransmitByte(MBCommBuf[i]);
}
for(unsigned int i = 1000;i > 0;i--);
TRSEL = 0;
ModbusReg.TimeCounter = 0;
ModbusReg.State = MODBUS_STATE_FINISH; //发送完毕跳转 终止态
}
//*****************************************************************************************
//ModBus处理
//
//*****************************************************************************************
void ModBus_Process(void)
{
if (ModbusReg.State == MODBUS_STATE_PROCESS) //处理态
ModBus_Analysis();
if (ModbusReg.State == MODBUS_STATE_SEND) //发送态
ModBus_Send();
}
//*****************************************************************************************
//Modbus 初始化
//
//*****************************************************************************************
void ModBus_Init(void)
{
ModbusReg.BaudRate = 9600;
ModbusReg.ParityMode = Parity
评论2
最新资源