/* ********************************************************************************************************* * * 模块名称 : MODSBUS通信程序 (主机) * 文件名称 : modbus_host.c * 版 本 : V1.0 * 说 明 : 无线通信程序。通信协议基于MODBUS * 修改记录 : * 版本号 日期 作者 说明 * V1.0 2015-04-18 修改协议 * * Copyright (C), 2015-2016, 安富莱电子 www.armfly.com * ********************************************************************************************************* */ #include "bsp.h" #include "param.h" #include "main.h" #include "main_run.h" #include "tcp_modbus_host.h" #include "tcp_echoclient.h" /* 保存每个从机的计数器值 */ MODH_T g_tModH; uint8_t g_modh_timeout = 0; //static void MODH_RxTimeOut(void); static void MODH_AnalyzeApp(void); static void MODH_Read_01H(void); static void MODH_Read_02H(void); static void MODH_Read_03H(void); static void MODH_Read_04H(void); static void MODH_Read_05H(void); static void MODH_Read_06H(void); static void MODH_Read_10H(void); //static void MODH_Read_30H(void); #if 0 /* ********************************************************************************************************* * 函 数 名: MODH_SendPacket * 功能说明: 发送数据包 COM1口 * 形 参: _buf : 数据缓冲区 * _len : 数据长度 * 返 回 值: 无 ********************************************************************************************************* */ void MODH_SendPacket(uint8_t *_buf, uint16_t _len) { RS485_SendBuf1(_buf, _len); } #endif /* ********************************************************************************************************* * 函 数 名: MODH_SendAckWithCRC * 功能说明: 发送应答,自动加CRC. * 形 参: 无。发送数据在 g_tModH.TxBuf[], [g_tModH.TxCount * 返 回 值: 无 ********************************************************************************************************* */ static void MODH_SendAckWithCRC(void) { uint16_t crc; crc = CRC16_Modbus(g_tModH.TxBuf, g_tModH.TxCount); g_tModH.TxBuf[g_tModH.TxCount++] = crc >> 8; g_tModH.TxBuf[g_tModH.TxCount++] = crc; memcpy(g_tClient.TxData, g_tModH.TxBuf, g_tModH.TxCount); /* 要发送的数据放入TCP客户端发送缓冲区 */ g_tClient.TxCount = g_tModH.TxCount; /* TCP将要发送的数据长度 */ //MODH_SendPacket(g_tModH.TxBuf, g_tModH.TxCount); tcp_client_usersent(echoclient_pcb); /* 用户发送g_tClient.TxData中的数据 */ } /* ********************************************************************************************************* * 函 数 名: MODH_AnalyzeApp * 功能说明: 分析应用层协议。处理应答。 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ static void MODH_AnalyzeApp(void) { switch (g_tModH.RxBuf[1]) /* 第2个字节 功能码 */ { case 0x01: /* 读取线圈状态(对应远程开关D01/D02/D03) */ MODH_Read_01H(); break; case 0x02: /* 读取输入状态(对应X0~X7) */ MODH_Read_02H(); break; case 0x03: /* 读取保持寄存器 在一个或多个保持寄存器中取得当前的二进制值 */ MODH_Read_03H(); break; case 0x04: /* 读取输入寄存器(对应A01/A02) ) */ MODH_Read_04H(); break; case 0x05: /* 强制单线圈(对应Y1/Y2) */ MODH_Read_05H(); break; case 0x06: /* 写单个寄存器 */ MODH_Read_06H(); break; case 0x10: /* 写多个寄存器 */ MODH_Read_10H(); break; default: break; } } /* ********************************************************************************************************* * 函 数 名: MODH_Send10H * 功能说明: 发送10H指令,连续写多个保持寄存器. 最多一次支持23个寄存器。 * 形 参: _addr : 从站地址 * _reg : 寄存器编号 * _num : 寄存器个数n (每个寄存器2个字节) 值域 * _buf : n个寄存器的数据。长度 = 2 * n * 返 回 值: 无 ********************************************************************************************************* */ void MODH_Send10H(uint8_t _addr, uint16_t _reg, uint8_t _num, uint8_t *_buf) { uint16_t i; g_tModH.TxCount = 0; g_tModH.TxBuf[g_tModH.TxCount++] = _addr; /* 从站地址 */ g_tModH.TxBuf[g_tModH.TxCount++] = 0x10; /* 从站地址 */ g_tModH.TxBuf[g_tModH.TxCount++] = _reg >> 8; /* 寄存器编号 高字节 */ g_tModH.TxBuf[g_tModH.TxCount++] = _reg; /* 寄存器编号 低字节 */ g_tModH.TxBuf[g_tModH.TxCount++] = _num >> 8; /* 寄存器个数 高字节 */ g_tModH.TxBuf[g_tModH.TxCount++] = _num; /* 寄存器个数 低字节 */ g_tModH.TxBuf[g_tModH.TxCount++] = 2 * _num; /* 数据字节数 */ for (i = 0; i < 2 * _num; i++) { if (g_tModH.TxCount > H_RX_BUF_SIZE - 3) { return; /* 数据超过缓冲区超度,直接丢弃不发送 */ } g_tModH.TxBuf[g_tModH.TxCount++] = _buf[i]; /* 后面的数据长度 */ } MODH_SendAckWithCRC(); /* 发送数据,自动加CRC */ } /* ********************************************************************************************************* * 函 数 名: MODH_Send05H * 功能说明: 发送05H指令,写强置单线圈 * 形 参: _addr : 从站地址 * _reg : 寄存器编号 * _value : 寄存器值,2字节 * 返 回 值: 无 ********************************************************************************************************* */ void MODH_Send05H(uint8_t _addr, uint16_t _reg, uint16_t _value) { g_tModH.TxCount = 0; g_tModH.TxBuf[g_tModH.TxCount++] = _addr; /* 从站地址 */ g_tModH.TxBuf[g_tModH.TxCount++] = 0x05; /* 功能码 */ g_tModH.TxBuf[g_tModH.TxCount++] = _reg >> 8; /* 寄存器编号 高字节 */ g_tModH.TxBuf[g_tModH.TxCount++] = _reg; /* 寄存器编号 低字节 */ g_tModH.TxBuf[g_tModH.TxCount++] = _value >> 8; /* 寄存器值 高字节 */ g_tModH.TxBuf[g_tModH.TxCount++] = _value; /* 寄存器值 低字节 */ MODH_SendAckWithCRC(); /* 发送数据,自动加CRC */ g_tModH.fAck05H = 0; /* 如果收到从机的应答,则这个标志会设为1 */ } /* ********************************************************************************************************* * 函 数 名: MODH_Send06H * 功能说明: 发送06H指令,写1个保持寄存器 * 形 参: _addr : 从站地址 * _reg : 寄存器编号 * _value : 寄存器值,2字节 * 返 回 值: 无 ********************************************************************************************************* */ void MODH_Send06H(uint8_t _addr, uint16_t _reg, uint16_t _value) { g_tModH.TxCount = 0; g_tModH.TxBuf[g_tModH.TxCount++] = _addr; /* 从站地址 */ g_tModH.TxBuf[g_tModH.TxCount++] = 0x06; /* 功能码 */ g_tModH.TxBuf[g_tModH.TxCount++] = _reg >> 8; /* 寄存器编号 高字节 */ g_tModH.TxBuf[g_tModH.TxCount++] = _reg; /* 寄存器编号 低字节 */ g_tModH.TxBuf[g_tModH.TxCount++] = _value >> 8; /* 寄存器值 高字节 */ g_tModH.TxBuf[g_tModH.TxCount++] = _value; /* 寄存器值 低字节 */ MODH_SendAckWithCRC(); /* 发送数据,自动加CRC */ g_tModH.fAck06H = 0; /* 如果收到从机的应答,则这个标志会设为1 */ } /* ********************************************************************************************************* * 函 数 名: MODH_Send03H * 功能说明: 发送03H指令,查询1个或多个保持寄存器 * 形 参: _addr : 从站地址 * _reg : 寄存器编号 * _num : 寄存器个数 * 返 回 值: 无 ********************************************************************************************************* */ void MODH_Send03H(uint8_t _addr, uint16_t _reg, uint16_t _num) { g_tModH.TxCount = 0; g_tModH.TxBuf[g_tModH.TxCount++] = _addr; /* 从站地址 */ g_tModH.TxBuf[g_tModH.TxCount++] = 0x03; /* 功能码 */ g_tModH.TxBuf[g_tModH.TxCount++] = _reg >> 8; /* 寄存器编号 高字节 */ g_tModH.TxBuf[g_tModH.TxCount++] = _reg; /* 寄存器编号 低字节 */ g_tModH.TxBuf[g_tModH.TxCount++] = _num >> 8; /* 寄存器个数 高字节 */ g_tModH.TxBuf[g_tModH.TxCount++] = _num; /* 寄存器个数 低字节 */ MODH_SendAckWithCRC(); /* 发送数据,自动加CRC */ g_tModH.fAck03H = 0; /* 清接收标志 */ g_tModH.RegNum = _num; /* 寄存器个数 */ g_tModH.Reg03H = _reg; /* 保存03H指令中的寄存器地址,方便对应答数据进行分类 */ } #if 0 /* ********************************************************************************************************* * 函 数 名: MODH_ReciveNew * 功能说明: 串口接收中断服务程序会调用本函数。当收到一个字节时,执行一次本函数。 * 形 参: * 返 回 值: 1 表示有数据 ********************************************************************************************************* */ void MODH_ReciveNew(uint8_t _data) { /* 3.5个字符的时间间隔,只是用在RTU模式下面,因为RTU模式没有开始符和结束符, 两个数据包之间只能靠时间间隔来区分,Modbus定义在不同的波特率下,间隔时间是不一样的, 所以就是3.5个字符的时间,波特率高,这个时间间隔就小,波特率低,这个时间间隔相应就大 4800 = 7.297ms 9600 = 3.646ms 19200 = 1.771ms 38400 = 0.885ms */ uint32_t timeout; g_modh_timeout = 0; timeout = 48000000 / g_tParam.HBaud485; /* 计算超时时间,单位us 35000000*/ //timeout = 35000000 / g_tParam.Baud485; /* 计算超时时间,单位us 35000000*/ /* 硬件定时中断,定时精度us 硬件定时器2用于MODBUS从机, 定时器3用于MODBUS从机主机*/ bsp_StartHardTimer(3, timeout, (void *)MODH_RxTimeOut); if (g_tModH.RxCount < H_RX_BUF_SIZE) { g_tModH.RxBuf[g_tModH.RxCount++] = _data; } } /* ********************************************************************************************************* * 函 数 名: MODH_RxTimeOut * 功能说明: 超过3.5个字符时间后执行本函数。 设置全局变量 g_rtu_timeout = 1; 通知主程序开始解码。 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ static void MODH_RxTimeOut(void) { g_modh_timeout = 1; } #endif /* ********************************************************************************************************* * 函 数 名: MODH_Poll * 功能说明: 接收控制器指令. 1ms 响应时间。 * 形 参: 无 * 返 回 值: 0 表示无数据 1表示收到正确命令 ********************************************************************************************************* */ void MODH_Poll(void) { uint16_t crc1; if (g_modh_timeout == 0) { /* 没有超时,继续接收。不要清零 g_tModH.RxCount */ return; } /* 收到命令 05 06 00 88 04 57 3B70 (8 字节) 05 : 数码管屏的号站, 06 : 指令 00 88 : 数码管屏的显示寄存器 04 57 : 数据,,,转换成 10 进制是 1111.高位在前, 3B70 : 二个字节 CRC 码 从05到 57的校验 */ g_modh_timeout = 0; if (g_tModH.RxCount < 4) { goto err_ret; } /* 计算CRC校验和 */ crc1 = CRC16_Modbus(g_tModH.RxBuf, g_tModH.RxCount); if (crc1 != 0) { goto err_ret; } /* 分析应用层协议 */ MODH_AnalyzeApp(); err_ret: g_tModH.RxCount = 0; /* 必须清零计数器,方便下次帧同步 */ } static void MODH_Read_01H(void) { ; } static void MODH_Read_02H(void) { ; } static void MODH_Read_04H(void) { ; } static void MODH_Read_05H(void) { if (g_tModH.RxCount > 0) { if (g_tModH.RxBuf[0] == SlaveAddr) //g_tParam.HAddr485 { g_tModH.fAck05H = 1; /* 接收到应答 */ } }; } /* ********************************************************************************************************* * 函 数 名: MODH_Read_06H * 功能说明: 分析06H指令的应答数据 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ static void MODH_Read_06H(void) { if (g_tModH.RxCount > 0) { if (g_tModH.RxBuf[0] == SlaveAddr) //g_tParam.HAddr485 { g_tModH.fAck06H = 1; /* 接收到应答 */ } } } /* ********************************************************************************************************* * 函 数 名: MODH_Read_03H * 功能说明: 分析03H指令的应答数据 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ void MODH_Read_03H(void) { #if 0 uint8_t bytes; uint8_t *p; if (g_tModH.RxCount > 0) { //BEEP_KeyTone(); bytes = g_tModH.RxBuf[2]; /* 数据长度 字节数 */ switch (g_tModH.Reg03H) { case REG_P01: if (bytes == 32) { p = &g_tModH.RxBuf[3]; g_tVar.P01 = BEBufToUint16(p); p += 2; /* 寄存器 */ g_tVar.P02 = BEBufToUint16(p); p += 2; /* 寄存器 */ g_tVar.P03 = BEBufToUint16(p); p += 2; g_tVar.P04 = BEBufToUint16(p); p += 2; g_tVar.P05 = BEBufToUint16(p); p += 2; g_tVar.P06 = BEBufToUint16(p); p += 2; g_tVar.P07 = BEBufToUint16(p); p += 2; g_tVar.P08 = BEBufToUint16(p); p += 2; g_tVar.P09 = BEBufToUint16(p); p += 2; g_tVar.P10 = BEBufToUint16(p); p += 2; g_tVar.P11 = BEBufToUint16(p); p += 2; g_tVar.P12 = BEBufToUint16(p); p += 2; g_tVar.P13 = BEBufToUint16(p); p += 2; g_tVar.P14 = BEBufToUint16(p); p += 2; g_tVar.P15 = BEBufToUint16(p); p += 2; g_tVar.P16 = BEBufToUint16(p); p += 2; // bsp_PutMsg(MSG_READ_FINISH, 0); /* 开机时读取一次数据,发送消息表示读取完毕 */ g_tModH.fAck03H = 1; } break; case REG_P01 + 16: if (bytes == 32) { p = &g_tModH.RxBuf[3]; g_tVar.P17 = BEBufToUint16(p); p += 2; g_tVar.P18 = BEBufToUint16(p); p += 2; g_tVar.P19 = BEBufToUint16(p); p += 2; g_tVar.P20 = BEBufToUint16(p); p += 2; g_tVar.P21 = BEBufToUint16(p); p += 2; g_tVar.P22 = BEBufToUint16(p); p += 2; g_tVar.P23 = BEBufToUint16(p); p += 2; g_tVar.P24 = BEBufToUint16(p); p += 2; g_tVar.P25 = BEBufToUint16(p); p += 2; g_tVar.P26 = BEBufToUint16(p); p += 2; g_tVar.P27 = BEBufToUint16(p); p += 2; g_tVar.P28 = BEBufToUint16(p); p += 2; g_tVar.P29 = BEBufToUint16(p); p += 2; g_tVar.P30 = BEBufToUint16(p); p += 2; g_tVar.P31 = BEBufToUint16(p); p += 2; g_tVar.P32 = BEBufToUint16(p); p += 2; g_tModH.fAck03H = 2; } break; case REG_P01 + 32: if (bytes == 32) { p = &g_tModH.RxBuf[3]; g_tVar.P33 = BEBufToUint16(p); p += 2; g_tVar.P34 = BEBufToUint16(p); p += 2; g_tVar.P35 = BEBufToUint16(p); p += 2; g_tVar.P36 = BEBufToUint16(p); p += 2; g_tVar.P37 = BEBufToUint16(p); p += 2; g_tVar.P38 = BEBufToUint16(p); p += 2; g_tVar.P39 = BEBufToUint16(p); p += 2; g_tVar.P40 = BEBufToUint16(p); p += 2; g_tVar.P41 = BEBufToUint16(p); p += 2; g_tVar.P42 = BEBufToUint16(p); p += 2; g_tVar.P43 = BEBufToUint16(p); p += 2; g_tVar.P44 = BEBufToUint16(p); p += 2; g_tVar.P45 = BEBufToUint16(p); p += 2; g_tVar.P46 = BEBufToUint16(p); p += 2; g_tVar.P47 = BEBufToUint16(p); p += 2; g_tVar.P48 = BEBufToUint16(p); p += 2; g_tModH.fAck03H = 3; } break; case REG_P01 + 48: if (bytes == 32) { p = &g_tModH.RxBuf[3]; g_tVar.P49 = BEBufToUint16(p); p += 2; g_tVar.P50 = BEBufToUint16(p); p += 2; g_tVar.P51 = BEBufToUint16(p); p += 2; g_tVar.P52 = BEBufToUint16(p); p += 2; g_tVar.P53 = BEBufToUint16(p); p += 2; g_tVar.P54 = BEBufToUint16(p); p += 2; g_tVar.P55 = BEBufToUint16(p); p += 2; g_tVar.P56 = BEBufToUint16(p); p += 2; g_tVar.P57 = BEBufToUint16(p); p += 2; g_tVar.P58 = BEBufToUint16(p); p += 2; g_tVar.P59 = BEBufToUint16(p); p += 2; g_tVar.P60 = BEBufToUint16(p); p += 2; g_tVar.P61 = BEBufToUint16(p); p += 2; g_tVar.P62 = BEBufToUint16(p); p += 2; g_tVar.P63 = BEBufToUint16(p); p += 2; g_tVar.P64 = BEBufToUint16(p); p += 2; g_tModH.fAck03H = 4; } break; case REG_H40: /* 总运行次数 */ if (bytes == 28) /* 扫描读 */ { p = &g_tModH.RxBuf[3]; g_tVar.H40 = BEBufToUint32(p); p += 4; g_tVar.H42 = BEBufToUint32(p); p += 4; g_tVar.H44 = BEBufToUint16(p); p += 2; g_tVar.H45 = BEBufToUint16(p); p += 2; g_tVar.H46 = BEBufToUint16(p); p += 2; g_tVar.H47 = BEBufToUint16(p); p += 2; g_tVar.H48 = BEBufToUint16(p); p += 2; g_tVar.H49 = BEBufToUint16(p); p += 2; g_tVar.H4A = BEBufToUint16(p); p += 2; g_tVar.H4B = BEBufToUint16(p); p += 2; g_tVar.H4C = BEBufToUint16(p); p += 2; g_tVar.H4D = BEBufToUint16(p); p += 2; g_tModH.fAck03H = 5; } #if 0 if (bytes == 4) { p = &g_tModH.RxBuf[3]; g_tVar.H40 = BEBufToUint32(p); g_tModH.fAck03H = 1; } #endif break; case REG_H44: /* 故障内容,查询到主板上报的故障时,自动测试界面返回主菜单 */ if (bytes == 2) { p = &g_tModH.RxBuf[3]; g_tVar.H44 = BEBufToUint16(p); g_tModH.fAck03H = 1; } break; #if 0 case REG_H4A: /* 输入状态查询 */ if (bytes == 2) { p = &g_tModH.RxBuf[3]; g_tVar.H4A = BEBufToUint16(p); g_tModH.fAck03H = 1; } break; case REG_H42: /* 维护后运行的次数 */ if (bytes == 4) { p = &g_tModH.RxBuf[3]; g_tVar.H42 = BEBufToUint32(p); } break; case REG_H47: /* 系统查询1 */ break; case REG_H49: /* 系统查询2 */ break; case REG_H48: /* 系统查询3 */ break; case REG_H4D: /* 系统查询4 */ break; case REG_H4C: /* 系统查询5 */ break; case REG_P16: /* 系统查询6 */ break; case REG_P18: /* 系统查询7 */ break; case REG_H4B: /* 系统查询8 */ break; case REG_P63: /* 系统版本 */ if (bytes == 4) { p = &g_tModH.RxBuf[3]; g_tVar.P63 = BEBufToUint16(p); p += 2; g_tVar.P64 = BEBufToUint16(p); } #endif } } #endif } /* ********************************************************************************************************* * 函 数 名: MODH_Read_10H * 功能说明: 分析10H指令的应答数据 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ void MODH_Read_10H(void) { /* 10H指令的应答: 从机地址 11 功能码 10 寄存器起始地址高字节 00 寄存器起始地址低字节 01 寄存器数量高字节 00 寄存器数量低字节 02 CRC校验高字节 12 CRC校验低字节 98 */ //uint8_t addr; //uint8_t bytes; //uint8_t reg; if (g_tModH.RxCount > 0) { // BEEP_KeyTone(); /* 发送消息. 消息体是寄存器地址和数量 */ #if 0 { uint8_t buf[4]; buf[0] = g_tModH.RxBuf[0]; /* 从机地址 */ buf[1] = g_tModH.RxBuf[5]; /* 寄存器长度 */ buf[2] = g_tModH.RxBuf[2]; /* 寄存器地址高16位 */ buf[3] = g_tModH.RxBuf[3]; /* 寄存器地址低16位 */ bsp_PutMsg(MSG_RX_10H, (uint32_t)buf); } #endif } } /* ********************************************************************************************************* * 函 数 名: MODH_WriteParam * 功能说明: 单个参数. 通过发送06H指令实现,发送之后,等待从机应答。循环10次写命令 * 形 参: 无 * 返 回 值: 1 表示成功。0 表示失败(通信超时或被拒绝) ********************************************************************************************************* */ extern uint8_t g_fTcpState; uint8_t MODH_WriteParam(uint16_t _reg, uint16_t _value) { int32_t time1; uint8_t i; for (i = 0; i < 3; i++) { MODH_Send06H(SLAVE_ADDR, _reg, _value); /* 将TCP状态标志设置为非接收到数据状态 */ g_tClient.TcpState = g_fTcpState; /* 2016-10-17 add by xd */ time1 = bsp_GetRunTime(); /* 记录命令发送的时刻 */ while (1) { bsp_Idle(); /* 超时大于 150ms ,则认为异常, 100ms有时会超时,数据没有接收到,PC软件应答时间间隔几十到一百多浮动 */ if (bsp_CheckRunTime(time1) > 200) //100 { break; } if (g_tClient.TcpState == 2) { break; } } if (g_tClient.TcpState == 2) { break; } } if (g_tClient.TcpState == 2) /* 接收到数据 */ { return 1; } else { return 0; /* 通信超时了 */ } } #if 0 /* ********************************************************************************************************* * 函 数 名: MODH_Read_30H * 功能说明: 分析30H指令的应答数据 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ void MODH_Read_30H(void) { uint8_t addr; uint8_t bytes; if (g_tModH.RxCount > 0) { //BEEP_KeyTone(); addr = g_tModH.RxBuf[0]; bytes = g_tModH.RxBuf[2]; #if 0 if (g_tModH.Reg30H == SREG_STATUS) /* 主机查询状态字 - 实时产量 - 当班员工工号 */ { if ((addr < DEV_NUM_MAX) && (addr > 0) && (addr != ADDR_FF) && (bytes >= 10)) { addr--; g_tVar.Dev[addr].CommErr = 0; /* 通信错误清零 */ g_tVar.Dev[addr].Status = BEBufToUint16(&g_tModH.RxBuf[3]); if (bytes >= 4) { g_tVar.Dev[addr].CountNow = BEBufToUint16(&g_tModH.RxBuf[5]); } if (bytes >= 6) { g_tVar.Dev[addr].GH[0] = BEBufToUint16(&g_tModH.RxBuf[7]); } if (bytes >= 8) { g_tVar.Dev[addr].GH[1] = BEBufToUint16(&g_tModH.RxBuf[9]); } if (bytes >= 10) { g_tVar.Dev[addr].GH[2] = BEBufToUint16(&g_tModH.RxBuf[11]); } bsp_PutMsg(MSG_433M_OK, addr + 1); /* 433M 通信OK, 通知监控界面刷新图标 */ } } #endif } } /* ********************************************************************************************************* * 函 数 名: MODH_WriteParam_05H * 功能说明: 单个参数. 通过发送05H指令实现,发送之后,等待从机应答。 * 形 参: 无 * 返 回 值: 1 表示成功。0 表示失败(通信超时或被拒绝) ********************************************************************************************************* */ uint8_t MODH_WriteParam_05H(uint16_t _reg, uint16_t _value) { int32_t time1; uint8_t i; for (i = 0; i < 10; i++) { MODH_Send05H (SlaveAddr, _reg, _value); time1 = bsp_GetRunTime(); /* 记录命令发送的时刻 */ g_LastTime = bsp_GetRunTime(); /* 300ms */ while (1) { bsp_Idle(); /* 超时大于 150ms ,则认为异常 */ if (bsp_CheckRunTime(time1) > 150) //100 { g_LastTime = bsp_GetRunTime(); break; /* 通信超时了 */ } if (g_tModH.fAck05H > 0) { break; } } if (g_tModH.fAck05H > 0) { break; } } if (g_tModH.fAck05H == 0) { return 0; } else { return 1; } } /* 读一个寄存器 */ uint8_t MODH_ReadParam_03H(uint16_t _reg, uint16_t _num) { int32_t time1; uint8_t i; for (i = 0; i < 10; i++) { MODH_Send03H (SlaveAddr, _reg, _num); time1 = bsp_GetRunTime(); /* 记录命令发送的时刻 */ g_LastTime = bsp_GetRunTime(); /* 300ms */ while (1) { bsp_Idle(); /* 超时大于 150ms ,则认为异常 */ if (bsp_CheckRunTime(time1) > 150) //100 { g_LastTime = bsp_GetRunTime(); break; /* 通信超时了 */ } if (g_tModH.fAck03H > 0) { break; } } if (g_tModH.fAck03H > 0) { break; } } if (g_tModH.fAck03H == 0) { return 0; } else { return 1; /* 写入03H参数成功 */ } } /* 读64个寄存器的参数,读10次 */ uint8_t MODH_ReadParam_03H_16(uint16_t _reg, uint16_t _num) { int32_t time1; uint8_t i; uint8_t State = 0; while (1) { for (i = 0; i < 10; i++) { /* 主板的地址就定0x55,最多连续读16个参数(32字节)*/ MODH_Send03H (SlaveAddr, _reg + State * _num, _num); /* 发送查询命令 */ time1 = bsp_GetRunTime(); /* 记录命令发送的时刻 */ g_LastTime = bsp_GetRunTime(); /* 300ms */ while (1) { bsp_Idle(); /* 超时大于 200ms ,则认为异常 */ if (bsp_CheckRunTime(time1) > 200) //200 { g_LastTime = bsp_GetRunTime(); break; /* 通信超时了 */ } if (g_tModH.fAck03H > 0) { State++; break; } } if (g_tModH.fAck03H > 0) { break; } } if (g_tModH.fAck03H == 0) { return 0; } if (State == 4) { return 1; } } } /* 轮询读14个参数 */ uint8_t MODH_CycleRead_03H(uint16_t _reg) { int32_t time1; /* 主板的地址就定0x55,最多连续读16个参数(32字节)*/ MODH_Send03H (SlaveAddr, _reg, 14); /* 发送查询命令 */ time1 = bsp_GetRunTime(); /* 记录命令发送的时刻 */ g_LastTime = bsp_GetRunTime(); /* 300ms */ while (1) { bsp_Idle(); /* 超时大于 200ms ,则认为异常 */ if (bsp_CheckRunTime(time1) > 200) { g_LastTime = bsp_GetRunTime(); return 0; /* 通信超时了 */ } if (g_tModH.fAck03H > 0) { break; } } return 1; } /* ********************************************************************************************************* * 函 数 名: MODH_AllowRun_05H * 功能说明: 允许禁止运行专用05指令,不调用bsp_Idle(); 调用解析命令函数 * 形 参: 无 * 返 回 值: 1 表示成功。0 表示失败(通信超时或被拒绝) ********************************************************************************************************* */ uint8_t MODH_AllowRun_05H(uint16_t _reg, uint16_t _value) { int32_t time1; uint8_t i; for (i = 0; i < 10; i++) { MODH_Send05H (SlaveAddr, _reg, _value); time1 = bsp_GetRunTime(); /* 记录命令发送的时刻 */ g_LastTime = bsp_GetRunTime(); while (1) { //bsp_Idle(); MODH_Poll(); MODS_Poll(); /* 超时大于 150ms ,则认为异常 */ if (bsp_CheckRunTime(time1) > 150) //100 { g_LastTime = bsp_GetRunTime(); break; /* 通信超时了 */ } if (g_tModH.fAck05H > 0) { break; } } if (g_tModH.fAck05H > 0) { break; } } if (g_tModH.fAck05H == 0) { return 0; } else { return 1; } } #endif /***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/