支持标准Modbus的下位机程序

上位机如触摸屏采用ModbusRTU或ModbusTCP通讯协议与下位机如单片机通过串口或网络通信时,需要解析上位机报文

 

Modbus寄存器读写的单位是字Word,读写Map表元素长度必须为字的整数倍,同时注意使用内存下标对齐时务必注意使用内存按字对齐

支持功能码03/06/10

0x03读保持寄存器            
 设备地址功能码起始地址寄存器数量CRC校验      
请求0x010x03高字节低字节高字节低字节高字节低字节      
注释十六进制 0x0000至0xFFFF1至125(0x7D)        
样例0x01     03       00       6B       00       03       17       74 //请求读寄存器108-110的实例 
 设备地址功能码字节数寄存器值(N*2个字节)CRC校验  
响应0x010x03N*2n=1高字节n=1低字节n=2高字节n=2低字节n=N高字节n=N低字节高字节低字节  
注释十六进制 N=寄存器数量          
样例0x01     03       06       02       2B       00       00       00       64                7A       05  
 设备地址差错码异常码           
错误0x010x8301或02或03或04          
注释十六进制功能码+0x80           
样例0x01     83       01/02/03/04          

 

0x06写单个寄存器            
 设备地址功能码寄存器地址寄存器值CRC校验      
请求0x010x06高字节低字节高字节低字节高字节低字节      
注释十六进制 0x0000至0xFFFF0x0000至0xFFFF        
样例0x01     06       00       01       00       03       0B       98 //请求将十六进制00 03写入寄存器2的实例
 设备地址功能码输出寄存器地址输出寄存器值CRC校验      
响应0x010x06高字节低字节高字节低字节高字节低字节      
注释十六进制 0x0000至0xFFFF0x0000至0xFFFF        
样例0x01     06       00       01       00       03       0B       98      
 设备地址差错码异常码           
错误0x010x8601或02或03或04          
注释十六进制功能码+0x80           
样例0x01     86       01/02/03/04          

 

0x10(16)写多个寄存器                     
 设备地址功能码起始地址寄存器数量字节数寄存器值(N*2个字节)CRC校验       
请求0x010x10高字节低字节高字节低字节N*2n=1高字节n=1低字节n=2高字节n=2低字节n=N高字节n=N低字节高字节低字节       
注释十六进制 0x0000至0xFFFF0x0001至0x0078N=输入寄存器的数量              
样例0x01     10       00       01       00       02       04       00       0A       01       02                                  30       92//请求将十六进制00 0A和01 02 写入以2开始的两个寄存器的实例
 设备地址功能码起始地址寄存器数量CRC校验               
响应0x010x10高字节低字节高字节低字节高字节低字节               
注释十六进制 0x0000至0xFFFF1至123(0x7B)                 
样例0X01     10       00       01       00       02       08       10               
 设备地址差错码异常码                    
错误0x010x1001或02或03或04                   
注释十六进制功能码+0x80                    
样例0x01     10       01/02/03/04                   
#pragma pack(2)
typedef struct tagRGV_MAP
{
    u16 a,
    u32 b,
    float c,
    int d,
}RGV_MAP;
#pragma pack()

RGV_MAP MyRGV_Map;

/**
 * @brief 处理触摸屏消息Modbus协议
 * @param Uart_Ch 数据通道
 * @param uLen 数据长度
 * @param p  接收数据区
 * @param pT 发送数据区
 */
void DealUartMessgae( u8 Uart_Ch, u16 uLen, u8 *p, u8 *pT )
{
	u8  uPlcAdr;
	u8  uCommand;
	u16 uRegAdr,uRegLen;
	u8  uBytes;
	u16 uInx,uInt,i;
	u16 *pAdr;
 	
	uPlcAdr = p[0];
	uCommand = p[1];
	uRegAdr = p[2]<<8 | p[3];
	uRegLen = p[4]<<8 | p[5];
	

	#define MODBUS_R_REG				0x03		// 读寄存器
	#define MODBUS_W_HOLDREG			0x06		// 写寄存器
	#define MODBUS_W_HOLDREG_M			0x10		// 写多个寄存器
	
	switch(uCommand)
	{
	case MODBUS_R_REG://读寄存器
			Refresh_RGV_Map_Read();
			uInx = 0;
			pT[uInx++] = uPlcAdr;
			pT[uInx++] = uCommand;
			pT[uInx++] = 2*uRegLen;
	
			pAdr = (u16*)&MyRGV_Map + uRegAdr;
			uInx = 3;
			for(i=0;i<uRegLen;i++)
			{
				uInt = *pAdr++;
				pT[uInx++] = uInt>>8;
				pT[uInx++] = uInt;
			}
			
			ModBusCRC(pT,uInx,1);
			StartModbusTranst_CH(Uart_Ch,uInx+2);
		break;
	case MODBUS_W_HOLDREG://写寄存器
			uInt = p[4]<<8 | p[5];
			pAdr = (u16*)&MyRGV_Map + uRegAdr;
			*pAdr = uInt;
	
			uInx = 0;
			pT[uInx++] = uPlcAdr;
			pT[uInx++] = uCommand;
			pT[uInx++] = uRegAdr>>8;
			pT[uInx++] = uRegAdr;
			pT[uInx++] = uInt>>8;
			pT[uInx++] = uInt;
			ModBusCRC(pT,uInx,1);
			StartModbusTranst_CH(Uart_Ch,uInx+2);
	
			Deal_HMI_Message();
		break;
	case MODBUS_W_HOLDREG_M:
			uInx = 0;
			pT[uInx++] = uPlcAdr;
			pT[uInx++] = uCommand;
			pT[uInx++] = uRegAdr>>8;
			pT[uInx++] = uRegAdr;
			pT[uInx++] = uRegLen>>8;
			pT[uInx++] = uRegLen;
			ModBusCRC(pT,uInx,1);
			StartModbusTranst_CH(Uart_Ch,uInx+2);
	
			uBytes = p[6];
			if(uBytes!=2*uRegLen){
				break;
			}
			
			pAdr = (u16*)&MyRGV_Map + uRegAdr;

			uInx = 7;
			for(i=0;i<uRegLen;i++)
			{
				uInt = p[uInx]<<8 | p[uInx+1];
				uInx += 2;
				*pAdr++ = uInt;
			}
			
			Deal_HMI_Message();
		break;		
	default:
		break;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值