#include "includes.h" unsigned char g_ucModbusRefreshEN = 1;//更新寄存器列表中的数据的使能标志位,1使能,和ModbusRecvProcess配合使用,用于控制收发 unsigned char g_ucModbusRefreshSHUTDOWN = 0;//控制maintask中的更新寄存器列表中的数据的总开关,1关闭,0开启 unsigned short g_ucModbusRefreshTimeOut = 5;//自动读取从机VALUE的等待超时时间,用于收发控制 unsigned short g_ucRegNumCount = 0;//当前正在处理的寄存器地址在列表中的序号。用于控制收发逻辑 SUT_MODBUS_REGPACK sutModbusRegPack = {0}; /********************************************************************************************************** ModbusRecvProcess() 处理接收到的MODBUS数据 :slave(u8)|function(u8)|bytecount(u8)|value1H(u8)|value1L(u8)|value2H(u8)|value2L(u8)|......|valueNL(u8)|CRC(u16) 成功返回1 失败返回0 num:代表寄存器列表里第几个元素 ************************************************************************************************************/ unsigned char ModbusRecvProcess(unsigned char *pMsg,int len,unsigned short num) { unsigned short crc,CRC16; unsigned char i; unsigned short value[MODBUS_REG_NUM_MAX]; if(len < 5) return 0;//长度小于5的不是MODBUS数据,就不处理 CRC16=crc16_calc(0xffff,pMsg,len-2); crc=((unsigned short)pMsg[len-1]&0xff)<<8; crc+=(unsigned short)pMsg[len-2]&0xff; if(crc != CRC16) return 0;//CRC校验不对,不处理 if(pMsg[1] == HOLDINGREG){//功能码=0x03,保存进寄存器列表 for(i = 0;i < pMsg[2]/2;i++){ value[i]=((unsigned short)pMsg[i*2+3]&0xff)<<8; value[i]+=(unsigned short)pMsg[i*2+4]&0xff; } sutModbusRegPack.RegList[num].value = value[i-1]; }else if(pMsg[1] == WRITESINGLEREG){//功能码=0x06,说明配置寄存器参数成功 g_ucSetControlAckResult &= 1; }else{ g_ucSetControlAckResult &= 0; } return 1; } /********************************************************************************************************** ModbusCmdReadOneValue() 发送请求,读MODBUS设备指定一个寄存器地址的参数 num:代表寄存器列表里第几个元素 ************************************************************************************************************/ void ModbusCmdReadOneValue(SUT_MODBUS_REGLIST *pMsg,unsigned short num) { unsigned short crc,CRC16; unsigned char Pack[8],i; Pack[0] = (pMsg+num)->slave; Pack[1] = HOLDINGREG; Pack[2] = (unsigned char)((pMsg+num)->addr >> 8); Pack[3] = (unsigned char)((pMsg+num)->addr & 0xff); Pack[4] = 0; Pack[5] = 1; CRC16=crc16_calc(0xffff,Pack,6); Pack[6] = (unsigned char)(CRC16 & 0xff); Pack[7] = (unsigned char)(CRC16 >> 8); RS485_DIR_HIGH; for(i=0;i<8;i++) { USART_SendData(USART1,Pack[i]); while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); } RS485_DIR_LOW; } /********************************************************************************************************** *更新寄存器列表参数 ************************************************************************************************************/ void ModbusRefreshValue(void) { if(g_ucModbusRefreshEN == 1) { g_ucModbusRefreshEN = 0; g_ucModbusRefreshTimeOut = 0; g_ucRegNumCount++; if((sutModbusRegPack.RegNum - 1) < g_ucRegNumCount) g_ucRegNumCount = 0; ModbusCmdReadOneValue(sutModbusRegPack.RegList,g_ucRegNumCount); } else { if(g_ucModbusRefreshTimeOut > 5)//返回超时,重置g_ucModbusRecv=1 { g_ucModbusRefreshEN = 1; g_ucModbusRefreshTimeOut = 0; } g_ucModbusRefreshTimeOut++; } } /********************************************************************************************************** *向MODBUS设备发送配置参数命令 数据格式 :slave(u8)|function(u8)|AddrH(u8)|AddrL(u8)|valueH(u8)|valueL(u8)|CRC(u16) ************************************************************************************************************/ void ModbusCmdSetValue(SUT_MODBUS_REGLIST *pMsg) { unsigned short crc,CRC16; unsigned char Pack[8],i; Pack[0] = pMsg->slave; Pack[1] = WRITESINGLEREG; Pack[2] = (unsigned char)(pMsg->addr >> 8); Pack[3] = (unsigned char)(pMsg->addr & 0xff); Pack[4] = (unsigned char)(pMsg->value >> 8); Pack[5] = (unsigned char)(pMsg->value & 0xff); CRC16=crc16_calc(0xffff,Pack,6); Pack[6] = (unsigned char)(CRC16 & 0xff); Pack[7] = (unsigned char)(CRC16 >> 8); RS485_DIR_HIGH; for(i=0;i<8;i++) { USART_SendData(USART1,Pack[i]); while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); } RS485_DIR_LOW; }