当前位置: 首页 > news >正文

怎样在网站做视频链接凌晨三点看的片韩国

怎样在网站做视频链接,凌晨三点看的片韩国,旅游网站哪个好,商店建筑设计1. modbus协议简介#xff1a; modbus协议基于rs485总线#xff0c;采取一主多从的形式#xff0c;主设备轮询各从设备信息#xff0c;从设备不主动上报。 日常使用都是RTU模式#xff0c;协议帧格式如下所示#xff1a; 地址 功能码 寄存器地址 读取寄存器…1. modbus协议简介 modbus协议基于rs485总线采取一主多从的形式主设备轮询各从设备信息从设备不主动上报。 日常使用都是RTU模式协议帧格式如下所示 地址   功能码     寄存器地址       读取寄存器个数        寄存器数据1   .....       CrcL   CrcH 1 2 3 4 5 6 7 8 9 /* AA      03     00     00        00     0A     DC     16 addr   cmd    regH    regL     lenH  lenL    crcL    crcH     主机发送 AA    03    14 00 00 00 00 00 00 00 00 00 03 00 01 00 00 00 18 00 1C 00 00 81 4B      从机回复 addr  cmd   datelen .... AA      10    00     0a      00 01      02         00 02       主机修改从机寄存器值 addr   cmd   regH   regL    regNum     datalen     data */ 功能码及对应的操作字长 目前比较简单的实现了读多个保持寄存器以及写多个保持寄存器由于不是使用的PLC所以寄存器地址的划分没有严格按照上表具体地址后面解释。 2.Modbus协议编写步骤很多设备厂家都会有自己的modbus协议大多数都不是很标准 1分析板子的具体信息编写不同的设备结构体比如只读的结构体可读写的结构体保存配置信息的结构体当主机发送改变配置信息的消息帧时会改变相应的变量并写入flash 2 modbus寄存器映射定义保持寄存器的指针 2本此编写采用轮询处理485串口接受到的数据每次的间隔肯定大于3.5个字符时间标准的Modbus帧间隔所以不用但心接受不完整的情况。串口接收完成之后 会首先进行处理在串口数据中找出符合要求接收正确的数据帧并记录其功能码输出帧的真实地址就可以得到主机想要操作的从机的寄存器地址。 3根据上一步获取的从机寄存器地址对保持寄存器的指针进行偏移指向即指向不同信息结构体的首地址此过程判断寄存器地址是否溢出。 4根据功能码进行解析操作设备读写操作就是将寄存器地址里的值直接操作指针读取出/写入。 以上过程都会判断是否错误发生错误码如下所示 10x01 功能码错误或者不存在 20x02  寄存器地址超出范围 30x04 CRC校验错误 错误回复帧的格式为地址码   功能码|0x80  错误码  CRCL    CRCH 下面就是本次用到的代码包括将配置信息结构体读写flash 1 /******************************************* Modbus **********************************************/2 3 uint16_t *Modbus_HoldReg NULL;//保持寄存器4 TRtuCommand g_tCurRtuCmd;5 6 /*7 AA 03 00 00 00 0A DC 16 8 addr cmd regH regL lenH lenL crcL crcH 读寄存器值9 10 AA 03 14 00 00 00 00 00 00 00 00 00 03 00 01 00 00 00 18 00 1C 00 00 81 4B 11 addr cmd datelen ....12 13 AA 10 00 0a 00 01 02 00 02 写寄存器值14 addr cmd regH regL regNum datalen data15 */16 17 18 19 /*20 函数名Modbus_RegMap21 功 能根据读取寄存器的起始地址选择映射对象将不同的地址映射到22 不同的结构体数据23 输入参数说明24 输出参数说明:25 返回值说明无26 备 注: 27 */28 void Modbus_RegMap(uint16_t wStartAddr)29 {30 uint16_t woffset 0;31 uint16_t wTemp 0;32 33 if((wStartAddr REG_BASE_INFO_OFFSET) (wStartAddr (REG_BASE_INFO_OFFSET REG_BASE_INFO_NUM)))34 {35 Modbus_HoldReg (uint16_t *)g_tdeviceinfo;36 woffset wStartAddr - REG_BASE_INFO_OFFSET;37 wTemp REG_BASE_INFO_NUM;38 }39 else if(wStartAddr (REG_BASE_INFO_OFFSET REG_BASE_INFO_NUM) (wStartAddr REG_CONFIG_INFO_OFFSET) )40 {41 g_tCurRtuCmd.m_byExceptionCode 0x02; //异常码0x02超出寄存器范围42 }43 else if((wStartAddr REG_CONFIG_INFO_OFFSET) (wStartAddr (REG_CONFIG_INFO_OFFSET REG_CONFIG_INFO_NUM )))44 {45 Modbus_HoldReg (uint16_t *)g_tConfigInfo;46 woffset wStartAddr - REG_CONFIG_INFO_OFFSET;47 wTemp REG_CONFIG_INFO_NUM;48 }49 else if(wStartAddr (REG_CONFIG_INFO_OFFSET REG_CONFIG_INFO_NUM))50 {51 g_tCurRtuCmd.m_byExceptionCode 0x02; //异常码0x02超出寄存器范围52 }53 g_tCurRtuCmd.m_wStartAddr woffset;54 g_tCurRtuCmd.m_wRegOffsetNum wTemp;55 }56 57 58 /*59 函数名DeviceInfoRefresh60 功 能更新设备运行的状态值同时更新modbus寄存器的值61 输入参数说明62 输出参数说明:63 返回值说明无64 备 注: 65 */66 void DeviceInfoRefresh(void)67 {68 69 GetHumiAndTempVlue();70 71 g_tdeviceinfo.m_wlightStripRly HAL_GPIO_ReadPin(DOOR_LED_RELAY_GPIO_Port,DOOR_LED_RELAY_Pin);72 g_tdeviceinfo.m_wFanRly HAL_GPIO_ReadPin(FAN_RELAY_GPIO_Port,FAN_RELAY_Pin);73 g_tdeviceinfo.m_wWarningLed1 HAL_GPIO_ReadPin(WARNING_LED_1_GPIO_Port,WARNING_LED_1_Pin);74 g_tdeviceinfo.m_wWarningLed2 HAL_GPIO_ReadPin(WARNING_LED_2_GPIO_Port,WARNING_LED_2_Pin);75 76 g_tdeviceinfo.m_wGMvalue LightLevelPersenGet(); /* 光照等级 */77 g_tdeviceinfo.m_wDoorLimit HAL_GPIO_ReadPin(LIMIT_SW_DOOR_GPIO_Port,LIMIT_SW_DOOR_Pin);78 g_tdeviceinfo.m_wWaterLimit HAL_GPIO_ReadPin(WATER_MARK_GPIO_Port,WATER_MARK_Pin);79 g_tdeviceinfo.m_Temp (uint16_t)s_tsht2xInfo.m_fTemp;80 g_tdeviceinfo.m_Humi (uint16_t)s_tsht2xInfo.m_fHumi;81 g_tdeviceinfo.m_vibration Mma8452StatusGet();82 }83 84 85 /*86 函数名RtuReceiveHandle87 功 能处理接受到的modbus数据并读取/设置相应寄存器的值88 输入参数说明89 pbydata 串口接收到的数据90 输出参数说明:91 dwLength 输入数据长度92 返回值说明无93 备注:由于modubusRtu函数不支持功能码0x06(写单一寄存器),所以0x06不处理94 */95 void RtuReceiveHandle(uint8_t *pbydata,uint32_t dwLength)96 { 97 uint8_t i;98 uint16_t wCrc 0;99 uint16_t wIndex 0, wRealLength 0, wStartOff 0; 100 uint8_t byAddr (g_tConfigInfo.m_bydeviceAddr) 0xFF; 101 g_tCurRtuCmd.m_byExceptionCode 0; 102 103 if(pbydata NULL || dwLength 0) 104 { 105 TCLX_PLATFORM_DIAG((No data received\n)); 106 return; 107 } 108 109 for(wIndex 0; wIndex dwLength; wIndex) 110 { 111 if(modubusRtu(pbydata wIndex, dwLength - wIndex, byAddr, 1, wRealLength, (g_tCurRtuCmd.m_byFunCode), wStartOff)) 112 { 113 wStartOff wIndex; /* 找到真实的Modbus数据帧 */ 114 115 /* 记录命令在主循环处理 */ 116 g_tCurRtuCmd.m_wStartAddr (pbydata[wStartOff 2] 8) pbydata[wStartOff 3]; 117 118 Modbus_RegMap(g_tCurRtuCmd.m_wStartAddr); 119 120 TCLX_PLATFORM_DIAG((Offset[%d] Len[%d] FunCode[0x%x] StartAddr[0x%x] RegNum[%d]\n, wStartOff, wRealLength,g_tCurRtuCmd.m_byFunCode, g_tCurRtuCmd.m_wStartAddr, g_tCurRtuCmd.m_wRegNum)); 121 122 switch(g_tCurRtuCmd.m_byFunCode) 123 { 124 case 0x03: 125 g_tCurRtuCmd.m_wRegNum (pbydata[wStartOff 4] 8) pbydata[wStartOff 5]; 126 if((g_tCurRtuCmd.m_wRegNum g_tCurRtuCmd.m_wStartAddr) g_tCurRtuCmd.m_wRegOffsetNum) 127 { 128 abySendData[0] g_tConfigInfo.m_bydeviceAddr; 129 abySendData[1] g_tCurRtuCmd.m_byFunCode; 130 abySendData[2] g_tCurRtuCmd.m_wRegNum * 2; 131 for(i 0; i g_tCurRtuCmd.m_wRegNum; i) 132 { 133 abySendData[3i*2] (Modbus_HoldReg[g_tCurRtuCmd.m_wStartAddri]8)0xFF;// /先发送高字节--在发送低字节 134 abySendData[4i*2] (Modbus_HoldReg[g_tCurRtuCmd.m_wStartAddri])0xFF; // 135 } 136 wCrc crc16(abySendData, g_tCurRtuCmd.m_wRegNum*2 3); 137 abySendData[g_tCurRtuCmd.m_wRegNum*2 3] wCrc 0x00FF; 138 abySendData[g_tCurRtuCmd.m_wRegNum*2 4] (wCrc 8) 0x00FF; 139 140 usart_send(USART_485_INDEX, abySendData, g_tCurRtuCmd.m_wRegNum*2 5); 141 } 142 else 143 { 144 g_tCurRtuCmd.m_byExceptionCode 0x02; //异常码,超出寄存范围 145 } 146 break; 147 case 0x06: 148 149 Modbus_HoldReg[g_tCurRtuCmd.m_wStartAddr] pbydata[wStartOff 4]8 | ((uint16_t)pbydata[wStartOff 5]);//高字节在前 150 151 abySendData[0] pbydata[wStartOff]; 152 abySendData[1] pbydata[wStartOff 1]; 153 abySendData[2] pbydata[wStartOff 2]; 154 abySendData[3] pbydata[wStartOff 3]; 155 abySendData[4] pbydata[wStartOff 4]; 156 abySendData[5] pbydata[wStartOff 5]; 157 158 wCrc crc16(abySendData,6); 159 160 abySendData[6](wCrc8)0xFF; 161 abySendData[7](wCrc)0xFF; 162 usart_send(USART_485_INDEX, abySendData,8); 163 break; 164 165 case 0x10: 166 g_tCurRtuCmd.m_wRegNum (pbydata[wStartOff 4] 8) pbydata[wStartOff 5]; 167 if((g_tCurRtuCmd.m_wRegNum g_tCurRtuCmd.m_wStartAddr) g_tCurRtuCmd.m_wRegOffsetNum) 168 { 169 for(i0;ig_tCurRtuCmd.m_wRegNum ;i) 170 { 171 Modbus_HoldReg[g_tCurRtuCmd.m_wStartAddri] pbydata[wStartOff 7i*2] 8 ; //低字节在前 172 Modbus_HoldReg[g_tCurRtuCmd.m_wStartAddri]|((uint16_t)pbydata[wStartOff 8i*2]); //高字节在后 173 } 174 abySendData[0] pbydata[wStartOff]; 175 abySendData[1] pbydata[wStartOff 1]; 176 abySendData[2] pbydata[wStartOff 2]; 177 abySendData[3] pbydata[wStartOff 3]; 178 abySendData[4] pbydata[wStartOff 4]; 179 abySendData[5] pbydata[wStartOff 5]; 180 181 wCrc crc16(abySendData,6); 182 abySendData[6](wCrc8)0xFF; 183 abySendData[7](wCrc)0xFF; 184 185 /* 如果配置信息发生改变就写入flash,不用做比较相等处理写flash函数已经处理 */ 186 writeConfigInfoToFlash(CONFIG_DATA_FLASH_ADDR,g_tConfigInfo); 187 188 189 usart_send(USART_485_INDEX, abySendData,8); 190 } 191 else 192 { 193 g_tCurRtuCmd.m_byExceptionCode 0x02; //异常码,超出寄存范围 194 } 195 break; 196 default: 197 g_tCurRtuCmd.m_byExceptionCode 0x01; //异常码功能码错误或者不存在 198 break; 199 } 200 201 if(g_tCurRtuCmd.m_byExceptionCode ! 0) 202 { 203 TCLX_PLATFORM_DIAG((exception code[%d]\n, g_tCurRtuCmd.m_byExceptionCode)); 204 abySendData[0] g_tConfigInfo.m_bydeviceAddr; 205 abySendData[1] g_tCurRtuCmd.m_byFunCode 0x80; 206 abySendData[2] g_tCurRtuCmd.m_byExceptionCode; 207 wCrc crc16(abySendData, 3); 208 abySendData[3] wCrc 0x00FF; 209 abySendData[4] (wCrc 8) 0x00FF; 210 usart_send(USART_485_INDEX, abySendData, 5); 211 } 212 213 memset(g_tCurRtuCmd, 0, sizeof(TRtuCommand)); 214 215 wIndex (wStartOff wRealLength - 1); 216 }/* switch(g_tCurRtuCmd.m_byFunCode) */ 217 218 }/* if modbusRtu do.... */ 219 usartRcvRestore(USART_485_INDEX); 220 } 221 222 223 /************************************** flash opration *****************************************/ 224 225 226 /* 227 函数名Read_FlashData 228 功 能从flash读取配置信息 229 输入参数说明 230 FlashReadBaseAdd配置信息基地址 231 输出参数说明: 232 DeviceCfg 配置参数 233 返回值说明无 234 备 注: 235 */ 236 void Read_FlashData(uint32_t FlashReadBaseAdd,DeviceConfigInfo_t *DeviceCfg) 237 { 238 if(NULL DeviceCfg) 239 { 240 return; 241 } 242 __IO DeviceConfigInfo_t *ptPos (__IO DeviceConfigInfo_t*)FlashReadBaseAdd; 243 244 memcpy(DeviceCfg,(const char *)ptPos,sizeof(DeviceConfigInfo_t)); 245 } 246 247 /* 248 函数名writeConfigInfoToFlash 249 功 能向flash写配置信息 250 输入参数说明 251 FlashReadBaseAdd配置信息基地址 252 输出参数说明: 253 DeviceCfg 配置参数 254 返回值说明无 255 备 注: 256 */ 257 void writeConfigInfoToFlash(uint32_t FlashWriteBaseAdd,DeviceConfigInfo_t *DeviceCfg) 258 { 259 uint8_t byIndex 0; 260 uint16_t wIndex 0; 261 262 DeviceConfigInfo_t DeviceCfgTemp {0}; 263 264 for(byIndex 0;byIndex 10;byIndex) 265 { 266 Read_FlashData(FlashWriteBaseAdd,DeviceCfgTemp); 267 268 if(0 memcmp(DeviceCfg,DeviceCfgTemp,sizeof(DeviceConfigInfo_t))) 269 { 270 TCLX_PLATFORM_DIAG((write succeed: Data equal\r\n)); 271 return; 272 } 273 else 274 { 275 HAL_Delay(500); 276 DIS_INT; 277 HAL_StatusTypeDef status HAL_OK; 278 if(HAL_OK ! (status HAL_FLASH_Unlock())) 279 { 280 TCLX_PLATFORM_DIAG(( falsh unlock err\r\n)); 281 continue; 282 } 283 FLASH_EraseInitTypeDef f; 284 f.TypeErase FLASH_TYPEERASE_PAGES; 285 f.PageAddress (uint32_t)FlashWriteBaseAdd; 286 f.NbPages 1; 287 uint32_t PageError 0; 288 289 if(HAL_OK ! (status HAL_FLASHEx_Erase(f, PageError))) 290 { 291 if(0 ! PageError) 292 { 293 TCLX_PLATFORM_DIAG((HAL_FLASHEx_Erase:failed(%d-%d)\n,status,PageError)); 294 HAL_FLASH_Lock(); 295 continue; 296 } 297 } 298 for(wIndex 0; wIndex (sizeof(DeviceConfigInfo_t) / sizeof(uint32_t)); wIndex ) 299 { 300 if(HAL_OK ! (status HAL_FLASH_Program(TYPEPROGRAM_WORD,FlashWriteBaseAdd (wIndex * sizeof(uint32_t)) ,((uint32_t *)DeviceCfg)[wIndex]))) 301 { 302 TCLX_PLATFORM_DIAG((HAL_FLASH_Program:CONFIG_DATA_FLASH_ADDR failed(%d)\n,status)); 303 HAL_FLASH_Lock(); 304 continue; 305 } 306 307 } 308 if(HAL_OK ! (status HAL_FLASH_Lock())) 309 { 310 TCLX_PLATFORM_DIAG((HAL_FLASH_Lock:HAL_FLASH_Lock(%d)\n,status)); 311 } 312 EN_INT; 313 return ; 314 } 315 } 316 } 参考下面例程此例程比较详细 1 #include modbus.h2 #include led.h3 #include lcd.h4 #include stm32f10x_tim.h5 6 7 ///8 u32 RS485_Baudrate9600;//通讯波特率9 u8 RS485_Parity0;//0无校验1奇校验2偶校验10 u8 RS485_Addr1;//从机地址11 u16 RS485_Frame_Distance4;//数据帧最小间隔ms),超过此时间则认为是下一帧12 13 u8 RS485_RX_BUFF[2048];//接收缓冲区2048字节14 u16 RS485_RX_CNT0;//接收计数器15 u8 RS485_FrameFlag0;//帧结束标记16 u8 RS485_TX_BUFF[2048];//发送缓冲区17 u16 RS485_TX_CNT0;//发送计数器18 19 20 //Modbus寄存器和单片机寄存器的映射关系21 vu32 *Modbus_InputIO[100];//输入开关量寄存器指针(这里使用的是位带操作)22 vu32 *Modbus_OutputIO[100];//输出开关量寄存器指针(这里使用的是位带操作)23 u16 *Modbus_HoldReg[1000];//保持寄存器指针24 u32 testData11201,testData21002,testData32303,testData48204;25 void Modbus_RegMap(void)26 {27 28 29 //输入开关量寄存器指针指向30 Modbus_InputIO[0](vu32*)PEin(4);//KEY0 //PEin(4)取PE4的地址(vu32*)PEin(4)将PE4地址强制转换为uw32类型的地址Modbus_InputIO[0](vu32*)PEin(4); 将转换好的地址送给地址指针Modbus_InputIO[0]31 Modbus_InputIO[1](vu32*)PEin(3);//KEY1 //*Modbus_InputIO[0] 取出地址中的内容。32 Modbus_InputIO[2](vu32*)PEin(2);//KEY233 Modbus_InputIO[3](vu32*)PAin(0);//KEY334 35 //输出开关量寄存器指针指向36 Modbus_OutputIO[0](vu32*)PBout(5);//LED037 Modbus_OutputIO[1](vu32*)PEout(5);//LED138 39 //保持寄存器指针指向40 Modbus_HoldReg[0](u16*)testData1;//测试数据1 41 Modbus_HoldReg[1](u16*)testData2;//((u16*)testData1)1;//测试数据1 42 Modbus_HoldReg[2](u16*)testData3;//(u16*)testData2;//测试数据243 Modbus_HoldReg[3](u16*)testData4;//((u16*)testData2)1;//测试数据2 44 Modbus_HoldReg[4](u16*)testData1;45 Modbus_HoldReg[5](u16*)testData2;46 Modbus_HoldReg[6](u16*)testData3;47 }48 /49 50 //CRC校验 自己后面添加的51 52 const u8 auchCRCHi[] { 53 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 54 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 55 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 56 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 57 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 58 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 59 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 60 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 61 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 62 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 63 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 64 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 65 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40} ; 66 67 68 const u8 auchCRCLo[] { 69 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 70 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 71 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 72 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 73 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 74 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 75 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 76 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 77 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 78 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 79 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 80 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, 81 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,0x43, 0x83, 0x41, 0x81, 0x80, 0x40} ;82 83 84 u16 CRC_Compute(u8 *puchMsg, u16 usDataLen) 85 { 86 u8 uchCRCHi 0xFF ; 87 u8 uchCRCLo 0xFF ; 88 u32 uIndex ; 89 while (usDataLen--) 90 { 91 uIndex uchCRCHi ^ *puchMsg ; 92 uchCRCHi uchCRCLo ^ auchCRCHi[uIndex] ; 93 uchCRCLo auchCRCLo[uIndex] ; 94 } 95 return ((uchCRCHi 8) | (uchCRCLo)) ; 96 }//uint16 crc16(uint8 *puchMsg, uint16 usDataLen)97 98 99 //初始化USART2 100 void RS485_Init(void) 101 { 102 GPIO_InitTypeDef GPIO_InitStructure; 103 USART_InitTypeDef USART_InitStructure; 104 NVIC_InitTypeDef NVIC_InitStructure; 105 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOD,ENABLE); 106 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE); 107 108 GPIO_InitStructure.GPIO_PinGPIO_Pin_2;//PA2TX复用推挽输出 109 GPIO_InitStructure.GPIO_ModeGPIO_Mode_AF_PP; 110 GPIO_InitStructure.GPIO_SpeedGPIO_Speed_50MHz; 111 GPIO_Init(GPIOA,GPIO_InitStructure); 112 GPIO_SetBits(GPIOA,GPIO_Pin_2);//默认高电平 113 114 GPIO_InitStructure.GPIO_PinGPIO_Pin_3;//PA3RX输入上拉 115 GPIO_InitStructure.GPIO_ModeGPIO_Mode_IN_FLOATING; //修改原GPIO_Mode_IPU输入上拉-GPIO_Mode_IN_FLOATING(浮空输入)/ 116 GPIO_Init(GPIOA,GPIO_InitStructure); 117 118 GPIO_InitStructure.GPIO_PinGPIO_Pin_9;//修改PG9RE/DE通用推挽输出-PD7RE/DE通用推挽输出// 119 GPIO_InitStructure.GPIO_ModeGPIO_Mode_Out_PP; 120 GPIO_Init(GPIOG,GPIO_InitStructure); 121 GPIO_ResetBits(GPIOG,GPIO_Pin_9);//默认接收状态 122 123 USART_DeInit(USART2);//复位串口2 124 USART_InitStructure.USART_BaudRateRS485_Baudrate; 125 USART_InitStructure.USART_HardwareFlowControlUSART_HardwareFlowControl_None; 126 USART_InitStructure.USART_WordLengthUSART_WordLength_8b; 127 USART_InitStructure.USART_StopBitsUSART_StopBits_1; 128 USART_InitStructure.USART_ModeUSART_Mode_Rx|USART_Mode_Tx;//收发模式 129 switch(RS485_Parity) 130 { 131 case 0:USART_InitStructure.USART_ParityUSART_Parity_No;break;//无校验 132 case 1:USART_InitStructure.USART_ParityUSART_Parity_Odd;break;//奇校验 133 case 2:USART_InitStructure.USART_ParityUSART_Parity_Even;break;//偶校验 134 } 135 USART_Init(USART2,USART_InitStructure); 136 137 USART_ClearITPendingBit(USART2,USART_IT_RXNE); 138 USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);//使能串口2接收中断 139 140 NVIC_InitStructure.NVIC_IRQChannelUSART2_IRQn; 141 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority2; 142 NVIC_InitStructure.NVIC_IRQChannelSubPriority2; 143 NVIC_InitStructure.NVIC_IRQChannelCmdENABLE; 144 NVIC_Init(NVIC_InitStructure); 145 146 USART_Cmd(USART2,ENABLE);//使能串口2 147 RS485_TX_EN0;//默认为接收模式 148 149 Timer7_Init();//定时器7初始化用于监视空闲时间 150 Modbus_RegMap();//Modbus寄存器映射 151 } 152 153 //定时器7初始化 154 void Timer7_Init(void) 155 { 156 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 157 NVIC_InitTypeDef NVIC_InitStructure; 158 159 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE); //TIM7时钟使能 160 161 //TIM7初始化设置 162 TIM_TimeBaseStructure.TIM_Period RS485_Frame_Distance*10; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 163 TIM_TimeBaseStructure.TIM_Prescaler 7200; //设置用来作为TIMx时钟频率除数的预分频值 设置计数频率为10kHz 164 TIM_TimeBaseStructure.TIM_ClockDivision 0; //设置时钟分割:TDTS Tck_tim 165 TIM_TimeBaseStructure.TIM_CounterMode TIM_CounterMode_Up; //TIM向上计数模式 166 TIM_TimeBaseInit(TIM7, TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位 167 168 TIM_ITConfig( TIM7, TIM_IT_Update, ENABLE );//TIM7 允许更新中断 169 170 //TIM7中断分组配置 171 NVIC_InitStructure.NVIC_IRQChannel TIM7_IRQn; //TIM7中断 172 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 2; //先占优先级2级 173 NVIC_InitStructure.NVIC_IRQChannelSubPriority 3; //从优先级3级 174 NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE; //IRQ通道被使能 175 NVIC_Init(NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 176 } 177 178 179 180 // 181 //发送n个字节数据 182 //buff:发送区首地址 183 //len发送的字节数 184 void RS485_SendData(u8 *buff,u8 len) 185 { 186 RS485_TX_EN1;//切换为发送模式 187 while(len--) 188 { 189 while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)RESET);//等待发送区为空 190 USART_SendData(USART2,*(buff)); 191 } 192 while(USART_GetFlagStatus(USART2,USART_FLAG_TC)RESET);//等待发送完成 193 } 194 195 196 / 197 void USART2_IRQHandler(void)//串口2中断服务程序 198 { 199 200 u8 res; 201 u8 err; 202 203 if(USART_GetITStatus(USART2,USART_IT_RXNE)!RESET) 204 { 205 if(USART_GetFlagStatus(USART2,USART_FLAG_NE|USART_FLAG_FE|USART_FLAG_PE)) err1;//检测到噪音、帧错误或校验错误 206 else err0; 207 LED00; 208 resUSART_ReceiveData(USART2); //读接收到的字节同时相关标志自动清除 209 210 if((RS485_RX_CNT2047)(err0)) 211 { 212 RS485_RX_BUFF[RS485_RX_CNT]res; 213 RS485_RX_CNT; 214 215 TIM_ClearITPendingBit(TIM7,TIM_IT_Update);//清除定时器溢出中断 216 TIM_SetCounter(TIM7,0);//当接收到一个新的字节将定时器7复位为0重新计时相当于喂狗 217 TIM_Cmd(TIM7,ENABLE);//开始计时 218 } 219 } 220 } 221 222 /// 223 //用定时器7判断接收空闲时间当空闲时间大于指定时间认为一帧结束 224 //定时器7中断服务程序 225 void TIM7_IRQHandler(void) 226 { 227 if(TIM_GetITStatus(TIM7,TIM_IT_Update)!RESET) 228 { 229 TIM_ClearITPendingBit(TIM7,TIM_IT_Update);//清除中断标志 230 TIM_Cmd(TIM7,DISABLE);//停止定时器 231 RS485_TX_EN1;//停止接收切换为发送状态 232 RS485_FrameFlag1;//置位帧结束标记 233 } 234 } 235 236 / 237 //RS485服务程序用于处理接收到的数据(请在主函数中循环调用) 238 u16 startRegAddr; 239 u16 RegNum; 240 u16 calCRC; 241 void RS485_Service(void) 242 { 243 u16 recCRC; 244 if(RS485_FrameFlag1) 245 { 246 if(RS485_RX_BUFF[0]RS485_Addr)//地址正确 247 { 248 if((RS485_RX_BUFF[1]01)||(RS485_RX_BUFF[1]02)||(RS485_RX_BUFF[1]03)||(RS485_RX_BUFF[1]05)||(RS485_RX_BUFF[1]06)||(RS485_RX_BUFF[1]15)||(RS485_RX_BUFF[1]16))//功能码正确 249 { 250 startRegAddr(((u16)RS485_RX_BUFF[2])8)|RS485_RX_BUFF[3];//获取寄存器起始地址 251 if(startRegAddr1000)//寄存器地址在范围内 252 { 253 calCRCCRC_Compute(RS485_RX_BUFF,RS485_RX_CNT-2);//计算所接收数据的CRC 254 recCRCRS485_RX_BUFF[RS485_RX_CNT-1]|(((u16)RS485_RX_BUFF[RS485_RX_CNT-2])8);//接收到的CRC(低字节在前高字节在后) 255 if(calCRCrecCRC)//CRC校验正确 256 { 257 ///显示用 258 259 LCD_ShowxNum(10,230,RS485_RX_BUFF[0],3,16,0X80);//显示数据 260 LCD_ShowxNum(42,230,RS485_RX_BUFF[1],3,16,0X80);//显示数据 261 LCD_ShowxNum(74,230,RS485_RX_BUFF[2],3,16,0X80);//显示数据 262 LCD_ShowxNum(106,230,RS485_RX_BUFF[3],3,16,0X80);//显示数据 263 LCD_ShowxNum(138,230,RS485_RX_BUFF[4],3,16,0X80);//显示数据 264 LCD_ShowxNum(170,230,RS485_RX_BUFF[5],3,16,0X80);//显示数据 265 /// 266 / 267 switch(RS485_RX_BUFF[1])//根据不同的功能码进行处理 268 { 269 case 2://读输入开关量 270 { 271 Modbus_02_Solve(); 272 break; 273 } 274 275 case 1://读输出开关量 276 { 277 Modbus_01_Solve(); 278 break; 279 } 280 281 case 5://写单个输出开关量 282 { 283 Modbus_05_Solve(); 284 break; 285 } 286 287 case 15://写多个输出开关量 288 { 289 Modbus_15_Solve(); 290 break; 291 } 292 293 case 03: //读多个寄存器 294 { 295 Modbus_03_Solve(); 296 break; 297 } 298 299 case 06: //写单个寄存器 300 { 301 Modbus_06_Solve(); 302 break; 303 } 304 305 case 16: //写多个寄存器 306 { 307 Modbus_16_Solve(); 308 break; 309 } 310 311 312 } 313 // 314 } 315 else//CRC校验错误 316 { 317 318 RS485_TX_BUFF[0]RS485_RX_BUFF[0]; 319 RS485_TX_BUFF[1]RS485_RX_BUFF[1]|0x80; 320 RS485_TX_BUFF[2]0x04; //异常码 321 RS485_SendData(RS485_TX_BUFF,3); 322 } 323 } 324 else//寄存器地址超出范围 325 { 326 RS485_TX_BUFF[0]RS485_RX_BUFF[0]; 327 RS485_TX_BUFF[1]RS485_RX_BUFF[1]|0x80; 328 RS485_TX_BUFF[2]0x02; //异常码 329 RS485_SendData(RS485_TX_BUFF,3); 330 } 331 } 332 else//功能码错误 333 { 334 RS485_TX_BUFF[0]RS485_RX_BUFF[0]; 335 RS485_TX_BUFF[1]RS485_RX_BUFF[1]|0x80; 336 RS485_TX_BUFF[2]0x01; //异常码 337 RS485_SendData(RS485_TX_BUFF,3); 338 } 339 } 340 341 RS485_FrameFlag0;//复位帧结束标志 342 RS485_RX_CNT0;//接收计数器清零 343 RS485_TX_EN0;//开启接收模式 344 } 345 } 346 347 //Modbus功能码02处理程序/程序已验证OK -----必须先配置PE4 PE3 PE2 PA0 初始化按键才可以OK KEY_Init(); 348 //读输入开关量 349 void Modbus_02_Solve(void) 350 { 351 u16 ByteNum; 352 u16 i; 353 RegNum (((u16)RS485_RX_BUFF[4])8)|RS485_RX_BUFF[5];//获取寄存器数量 354 if((startRegAddrRegNum)100)//寄存器地址数量在范围内 355 { 356 RS485_TX_BUFF[0]RS485_RX_BUFF[0]; 357 RS485_TX_BUFF[1]RS485_RX_BUFF[1]; 358 ByteNumRegNum/8;//字节数 359 if(RegNum%8) ByteNum1;//如果位数还有余数则字节数1 360 RS485_TX_BUFF[2]ByteNum;//返回要读取的字节数 361 for(i0;iRegNum;i) 362 { 363 if(i%80) RS485_TX_BUFF[3i/8]0x00; 364 RS485_TX_BUFF[3i/8]1;//低位先发送 365 RS485_TX_BUFF[3i/8]|((*Modbus_InputIO[startRegAddri])7)0x80; 366 if(iRegNum-1)//发送到最后一个位了 367 { 368 if(RegNum%8) RS485_TX_BUFF[3i/8]8-(RegNum%8);//如果最后一个字节还有余数则剩余MSB填充0 369 } 370 } 371 calCRCCRC_Compute(RS485_TX_BUFF,ByteNum3); 372 RS485_TX_BUFF[ByteNum3](calCRC8)0xFF; 373 RS485_TX_BUFF[ByteNum4](calCRC)0xFF; 374 RS485_SendData(RS485_TX_BUFF,ByteNum5); 375 } 376 else//寄存器地址数量超出范围 377 { 378 RS485_TX_BUFF[0]RS485_RX_BUFF[0]; 379 RS485_TX_BUFF[1]RS485_RX_BUFF[1]|0x80; 380 RS485_TX_BUFF[2]0x02; //异常码 381 RS485_SendData(RS485_TX_BUFF,3); 382 } 383 } 384 385 //Modbus功能码01处理程序 ///程序已验证OK 386 //读输出开关量 387 void Modbus_01_Solve(void) 388 { 389 u16 ByteNum; 390 u16 i; 391 RegNum (((u16)RS485_RX_BUFF[4])8)|RS485_RX_BUFF[5];//获取寄存器数量 392 if((startRegAddrRegNum)100)//寄存器地址数量在范围内 393 { 394 RS485_TX_BUFF[0]RS485_RX_BUFF[0]; 395 RS485_TX_BUFF[1]RS485_RX_BUFF[1]; 396 ByteNumRegNum/8;//字节数 397 if(RegNum%8) ByteNum1;//如果位数还有余数则字节数1 398 RS485_TX_BUFF[2]ByteNum;//返回要读取的字节数 399 for(i0;iRegNum;i) 400 { 401 if(i%80) RS485_TX_BUFF[3i/8]0x00; 402 RS485_TX_BUFF[3i/8]1;//低位先发送 403 RS485_TX_BUFF[3i/8]|((*Modbus_OutputIO[startRegAddri])7)0x80; 404 if(iRegNum-1)//发送到最后一个位了 405 { 406 if(RegNum%8) RS485_TX_BUFF[3i/8]8-(RegNum%8);//如果最后一个字节还有余数则剩余MSB填充0 407 } 408 } 409 calCRCCRC_Compute(RS485_TX_BUFF,ByteNum3); 410 RS485_TX_BUFF[ByteNum3](calCRC8)0xFF; 411 RS485_TX_BUFF[ByteNum4](calCRC)0xFF; 412 RS485_SendData(RS485_TX_BUFF,ByteNum5); 413 } 414 else//寄存器地址数量超出范围 415 { 416 RS485_TX_BUFF[0]RS485_RX_BUFF[0]; 417 RS485_TX_BUFF[1]RS485_RX_BUFF[1]|0x80; 418 RS485_TX_BUFF[2]0x02; //异常码 419 RS485_SendData(RS485_TX_BUFF,3); 420 } 421 } 422 423 //Modbus功能码05处理程序 ///程序已验证OK 424 //写单个输出开关量 425 void Modbus_05_Solve(void) 426 { 427 if(startRegAddr100)//寄存器地址在范围内 428 { 429 if((RS485_RX_BUFF[4]0xFF)||(RS485_RX_BUFF[5]0xFF)) *Modbus_OutputIO[startRegAddr]0x01; 430 else *Modbus_OutputIO[startRegAddr]0x00; 431 432 RS485_TX_BUFF[0]RS485_RX_BUFF[0]; 433 RS485_TX_BUFF[1]RS485_RX_BUFF[1]; 434 RS485_TX_BUFF[2]RS485_RX_BUFF[2]; 435 RS485_TX_BUFF[3]RS485_RX_BUFF[3]; 436 RS485_TX_BUFF[4]RS485_RX_BUFF[4]; 437 RS485_TX_BUFF[5]RS485_RX_BUFF[5]; 438 439 calCRCCRC_Compute(RS485_TX_BUFF,6); 440 RS485_TX_BUFF[6](calCRC8)0xFF; 441 RS485_TX_BUFF[7](calCRC)0xFF; 442 RS485_SendData(RS485_TX_BUFF,8); 443 } 444 else//寄存器地址超出范围 445 { 446 RS485_TX_BUFF[0]RS485_RX_BUFF[0]; 447 RS485_TX_BUFF[1]RS485_RX_BUFF[1]|0x80; 448 RS485_TX_BUFF[2]0x02; //异常码 449 RS485_SendData(RS485_TX_BUFF,3); 450 } 451 } 452 453 //Modbus功能码15处理程序 //程序已验证OK 454 //写多个输出开关量 455 void Modbus_15_Solve(void) 456 { 457 u16 i; 458 RegNum(((u16)RS485_RX_BUFF[4])8)|RS485_RX_BUFF[5];//获取寄存器数量 459 if((startRegAddrRegNum)100)//寄存器地址数量在范围内 460 { 461 for(i0;iRegNum;i) 462 { 463 if(RS485_RX_BUFF[7i/8]0x01) *Modbus_OutputIO[startRegAddri]0x01; 464 else *Modbus_OutputIO[startRegAddri]0x00; 465 RS485_RX_BUFF[7i/8]1;//从低位开始 466 } 467 468 RS485_TX_BUFF[0]RS485_RX_BUFF[0]; 469 RS485_TX_BUFF[1]RS485_RX_BUFF[1]; 470 RS485_TX_BUFF[2]RS485_RX_BUFF[2]; 471 RS485_TX_BUFF[3]RS485_RX_BUFF[3]; 472 RS485_TX_BUFF[4]RS485_RX_BUFF[4]; 473 RS485_TX_BUFF[5]RS485_RX_BUFF[5]; 474 calCRCCRC_Compute(RS485_TX_BUFF,6); 475 RS485_TX_BUFF[6](calCRC8)0xFF; 476 RS485_TX_BUFF[7](calCRC)0xFF; 477 RS485_SendData(RS485_TX_BUFF,8); 478 } 479 else//寄存器地址数量超出范围 480 { 481 RS485_TX_BUFF[0]RS485_RX_BUFF[0]; 482 RS485_TX_BUFF[1]RS485_RX_BUFF[1]|0x80; 483 RS485_TX_BUFF[2]0x02; //异常码 484 RS485_SendData(RS485_TX_BUFF,3); 485 } 486 } 487 488 //Modbus功能码03处理程序///已验证程序OK 489 //读保持寄存器 490 void Modbus_03_Solve(void) 491 { 492 u8 i; 493 RegNum (((u16)RS485_RX_BUFF[4])8)|RS485_RX_BUFF[5];//获取寄存器数量 494 if((startRegAddrRegNum)1000)//寄存器地址数量在范围内 495 { 496 RS485_TX_BUFF[0]RS485_RX_BUFF[0]; 497 RS485_TX_BUFF[1]RS485_RX_BUFF[1]; 498 RS485_TX_BUFF[2]RegNum*2; 499 for(i0;iRegNum;i) 500 { 501 RS485_TX_BUFF[3i*2](*Modbus_HoldReg[startRegAddri]8)0xFF;// /先发送高字节--在发送低字节 502 RS485_TX_BUFF[4i*2](*Modbus_HoldReg[startRegAddri])0xFF; // 503 } 504 calCRCCRC_Compute(RS485_TX_BUFF,RegNum*23); 505 RS485_TX_BUFF[RegNum*23](calCRC8)0xFF; //CRC高地位不对吗 // 先高后低 506 RS485_TX_BUFF[RegNum*24](calCRC)0xFF; 507 RS485_SendData(RS485_TX_BUFF,RegNum*25); 508 } 509 else//寄存器地址数量超出范围 510 { 511 RS485_TX_BUFF[0]RS485_RX_BUFF[0]; 512 RS485_TX_BUFF[1]RS485_RX_BUFF[1]|0x80; 513 RS485_TX_BUFF[2]0x02; //异常码 514 RS485_SendData(RS485_TX_BUFF,3); 515 } 516 } 517 518 519 //Modbus功能码06处理程序 //已验证程序OK 520 //写单个保持寄存器 521 void Modbus_06_Solve(void) 522 { 523 *Modbus_HoldReg[startRegAddr]RS485_RX_BUFF[4]8;//高字节在前 修改为高字节在前低字节在后 524 *Modbus_HoldReg[startRegAddr]|((u16)RS485_RX_BUFF[5]);//低字节在后 525 526 RS485_TX_BUFF[0]RS485_RX_BUFF[0]; 527 RS485_TX_BUFF[1]RS485_RX_BUFF[1]; 528 RS485_TX_BUFF[2]RS485_RX_BUFF[2]; 529 RS485_TX_BUFF[3]RS485_RX_BUFF[3]; 530 RS485_TX_BUFF[4]RS485_RX_BUFF[4]; 531 RS485_TX_BUFF[5]RS485_RX_BUFF[5]; 532 533 calCRCCRC_Compute(RS485_TX_BUFF,6); 534 RS485_TX_BUFF[6](calCRC8)0xFF; 535 RS485_TX_BUFF[7](calCRC)0xFF; 536 RS485_SendData(RS485_TX_BUFF,8); 537 } 538 539 //Modbus功能码16处理程序 /已验证程序OK 540 //写多个保持寄存器 541 void Modbus_16_Solve(void) 542 { 543 u8 i; 544 RegNum (((u16)RS485_RX_BUFF[4])8)|((RS485_RX_BUFF[5]));//获取寄存器数量 545 if((startRegAddrRegNum)1000)//寄存器地址数量在范围内 546 { 547 for(i0;iRegNum;i) 548 { 549 *Modbus_HoldReg[startRegAddri]RS485_RX_BUFF[7i*2]; //低字节在前 /// 低字节在前高字节在后正常 550 *Modbus_HoldReg[startRegAddri]|((u16)RS485_RX_BUFF[8i*2])8; //高字节在后 551 } 552 553 RS485_TX_BUFF[0]RS485_RX_BUFF[0]; 554 RS485_TX_BUFF[1]RS485_RX_BUFF[1]; 555 RS485_TX_BUFF[2]RS485_RX_BUFF[2]; 556 RS485_TX_BUFF[3]RS485_RX_BUFF[3]; 557 RS485_TX_BUFF[4]RS485_RX_BUFF[4]; 558 RS485_TX_BUFF[5]RS485_RX_BUFF[5]; 559 560 calCRCCRC_Compute(RS485_TX_BUFF,6); 561 RS485_TX_BUFF[6](calCRC8)0xFF; 562 RS485_TX_BUFF[7](calCRC)0xFF; 563 RS485_SendData(RS485_TX_BUFF,8); 564 } 565 else//寄存器地址数量超出范围 566 { 567 RS485_TX_BUFF[0]RS485_RX_BUFF[0]; 568 RS485_TX_BUFF[1]RS485_RX_BUFF[1]|0x80; 569 RS485_TX_BUFF[2]0x02; //异常码 570 RS485_SendData(RS485_TX_BUFF,3); 571 } 572 } 573 574 575 576 stm32编写Modbus步骤 - 纯洁de小学生 - 博客园 (cnblogs.com)
http://www.ho-use.cn/article/10821857.html

相关文章:

  • 常州天狼网站建设wordpress章节添加章节
  • 遵义网上制作网站石家庄网站做网站
  • 做钢管用哪个门户网站建立网上商城应考虑哪些问题
  • 成都龙泉网站建设win2008 wordpress
  • mvc网站开发之美做资源网站需要什么
  • 北京市住房城乡建设行业从业人员考务网站网络公司做网站的合同
  • 网站建设方案设计设计企业网站哪家好
  • 做网站湖州中国制造网外贸平台
  • 专门做超市海报的网站做网站app是什么h行业
  • 做网站后台维护的岗位叫什么阿里指数查询官网入口
  • 网站建设公司做网站要多少费用国内外创意网站欣赏
  • 上海自适应网站制作建立网站需要哪些费用
  • 做号网站吗宁波网站建设公司哪家好
  • 网站建设中的图片网站设计高端网站制作
  • 怎么用阿里云建网站南京营销型网站制作
  • 如何制作一个公司网站网站设计 素材
  • 重庆手机网站推广2020最近的新闻大事10条
  • 小公司网站建设费用网页网站公司如何做备份
  • 网站建设与运营在线考试营销型网站整体优化
  • 建设网站需要什么技术支持卖辅助网站怎么做
  • 中国建设银行网站首页下载建设安全备案登入那个网站
  • 网赌网站怎么做的1 建设网站目的是什么意思
  • 抄袭网站后台会侵权吗网络科技公司取什么名字好
  • 成都营销网站设计赣州营销公司
  • 传动设备 技术支持 东莞网站建设微信电子宣传册制作app
  • 河北燕郊网站制作logo素材网站有哪些
  • 惠州免费建站模板自助网站建设怎么建设
  • 温州seo网站建设国家工商信息公示系统
  • 做网站公司做网站公司网络优化工程师前景
  • 网站推广方案中确定目标是指小吃培训机构排名前十