/* ********************************************************************************************************* * * 模块名称 : MODSBUS通信程序,主机模式【原创】 * 文件名称 : modbus_host.c * 版 本 : V1.4 * 说 明 : MODBUS协议 * * Copyright (C), 2020-2030, 安富莱电子 www.armfly.com * ********************************************************************************************************* */ #include "bsp.h" #include "modbus_host.h" /* ********************************************************************************************************* * 变量 ********************************************************************************************************* */ #define TIMEOUT 1000 /* 接收命令超时时间, 单位ms */ #define NUM 1 /* 循环发送次数 */ /* Baud rate Bit rate Bit time Character time 3.5 character times 2400 2400 bits/s 417 us 4.6 ms 16 ms 4800 4800 bits/s 208 us 2.3 ms 8.0 ms 9600 9600 bits/s 104 us 1.2 ms 4.0 ms 19200 19200 bits/s 52 us 573 us 2.0 ms 38400 38400 bits/s 26 us 286 us 1.75 ms(1.0 ms) 115200 115200 bit/s 8.7 us 95 us 1.75 ms(0.33 ms) 后面固定都为1750us */ typedef struct { uint32_t Bps; uint32_t usTimeOut; }MODBUSBPS_T; const MODBUSBPS_T ModbusBaudRate[] = { {2400, 16000}, /* 波特率2400bps, 3.5字符延迟时间16000us */ {4800, 8000}, {9600, 4000}, {19200, 2000}, {38400, 1750}, {115200, 1750}, {128000, 1750}, {230400, 1750}, }; MODH_T g_tModH = {0}; uint8_t g_modh_timeout = 0; VAR_T g_tVar; /* ********************************************************************************************************* * 函数声明 ********************************************************************************************************* */ 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); /* ********************************************************************************************************* * 函 数 名: MODH_SendPacket * 功能说明: 发送数据包 COM1口 * 形 参: _buf : 数据缓冲区 * _len : 数据长度 * 返 回 值: 无 ********************************************************************************************************* */ void MODH_SendPacket(uint8_t *_buf, uint16_t _len) { RS485_SendBuf(_buf, _len); } /* ********************************************************************************************************* * 函 数 名: MODH_SendAckWithCRC * 功能说明: 发送应答,自动加CRC. * 形 参: 无。 * 返 回 值: 无 ********************************************************************************************************* */ 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; MODH_SendPacket(g_tModH.TxBuf, g_tModH.TxCount); } /* ********************************************************************************************************* * 函 数 名: MODH_AnalyzeApp * 功能说明: 分析应用层协议。处理应答。 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ static void MODH_AnalyzeApp(void) { switch (g_tModH.RxBuf[1]) /* 第2个字节 功能码 */ { case 0x01: /* 读取线圈状态 */ MODH_Read_01H(); break; case 0x02: /* 读取输入状态 */ MODH_Read_02H(); break; case 0x03: /* 读取保持寄存器 在一个或多个保持寄存器中取得当前的二进制值 */ MODH_Read_03H(); break; case 0x04: /* 读取输入寄存器 */ MODH_Read_04H(); break; case 0x05: /* 强制单线圈 */ MODH_Read_05H(); break; case 0x06: /* 写单个寄存器 */ MODH_Read_06H(); break; case 0x10: /* 写多个寄存器 */ MODH_Read_10H(); break; default: break; } } /* ********************************************************************************************************* * 函 数 名: MODH_Send01H * 功能说明: 发送01H指令,查询1个或多个线圈寄存器 * 形 参: _addr : 从站地址 * _reg : 寄存器编号 * _num : 寄存器个数 * 返 回 值: 无 ********************************************************************************************************* */ void MODH_Send01H(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++] = 0x01; /* 功能码 */ 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.fAck01H = 0; /* 清接收标志 */ g_tModH.RegNum = _num; /* 寄存器个数 */ g_tModH.Reg01H = _reg; /* 保存01H指令中的寄存器地址,方便对应答数据进行分类 */ } /* ********************************************************************************************************* * 函 数 名: MODH_Send02H * 功能说明: 发送02H指令,读离散输入寄存器 * 形 参: _addr : 从站地址 * _reg : 寄存器编号 * _num : 寄存器个数 * 返 回 值: 无 ********************************************************************************************************* */ void MODH_Send02H(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++] = 0x02; /* 功能码 */ 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.fAck02H = 0; /* 清接收标志 */ g_tModH.RegNum = _num; /* 寄存器个数 */ g_tModH.Reg02H = _reg; /* 保存02H指令中的寄存器地址,方便对应答数据进行分类 */ } /* ********************************************************************************************************* * 函 数 名: 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指令中的寄存器地址,方便对应答数据进行分类 */ } /* ********************************************************************************************************* * 函 数 名: MODH_Send04H * 功能说明: 发送04H指令,读输入寄存器 * 形 参: _addr : 从站地址 * _reg : 寄存器编号 * _num : 寄存器个数 * 返 回 值: 无 ********************************************************************************************************* */ void MODH_Send04H(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++] = 0x04; /* 功能码 */ 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.fAck04H = 0; /* 清接收标志 */ g_tModH.RegNum = _num; /* 寄存器个数 */ g_tModH.Reg04H = _reg; /* 保存04H指令中的寄存器地址,方便对应答数据进行分类 */ } /* ********************************************************************************************************* * 函 数 名: 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_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_ReciveNew * 功能说明: 串口接收中断服务程序会调用本函数。当收到一个字节时,执行一次本函数。 * 形 参: 接收数据 * 返 回 值: 1 表示有数据 ********************************************************************************************************* */ void MODH_ReciveNew(uint8_t _data) { /* 3.5个字符的时间间隔,只是用在RTU模式下面,因为RTU模式没有开始符和结束符, 两个数据包之间只能靠时间间隔来区分,Modbus定义在不同的波特率下,间隔时间是不一样的, 详情看此C文件开头 */ uint8_t i; /* 根据波特率,获取需要延迟的时间 */ for(i = 0; i < (sizeof(ModbusBaudRate)/sizeof(ModbusBaudRate[0])); i++) { if(HBAUD485 == ModbusBaudRate[i].Bps) { break; } } /* 硬件定时中断,硬件定时器1用于MODBUS从机, 定时器2用于MODBUS主机*/ bsp_StartHardTimer(2, ModbusBaudRate[i].usTimeOut, (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; } /* ********************************************************************************************************* * 函 数 名: MODH_Poll * 功能说明: 接收控制器指令. 1ms 响应时间。 * 形 参: 无 * 返 回 值: 0 表示无数据 1表示收到正确命令 ********************************************************************************************************* */ void MODH_Poll(void) { uint16_t crc1; if (g_modh_timeout == 0) /* 超过3.5个字符时间后执行MODH_RxTimeOut()函数。全局变量 g_rtu_timeout = 1 */ { /* 没有超时,继续接收。不要清零 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; /* 接收到的数据小于4个字节就认为错误,地址(8bit)+指令(8bit)+操作寄存器(16bit) */ if (g_tModH.RxCount < 4) { goto err_ret; } /* 计算CRC校验和,这里是将接收到的数据包含CRC16值一起做CRC16,结果是0,表示正确接收 */ crc1 = CRC16_Modbus(g_tModH.RxBuf, g_tModH.RxCount); if (crc1 != 0) { goto err_ret; } /* 分析应用层协议 */ MODH_AnalyzeApp(); err_ret: g_tModH.RxCount = 0; /* 必须清零计数器,方便下次帧同步 */ } /* ********************************************************************************************************* * 函 数 名: MODH_Read_01H * 功能说明: 分析01H指令的应答数据,读取线圈状态,bit访问 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ static void MODH_Read_01H(void) { uint8_t bytes; uint8_t *p; if (g_tModH.RxCount > 0) { bytes = g_tModH.RxBuf[2]; /* 数据长度 字节数 */ switch (g_tModH.Reg01H) { case REG_D01: if (bytes == 1) { p = &g_tModH.RxBuf[3]; g_tVar.D01 = BEBufToUint16(p); p += 2; /* 寄存器 */ g_tVar.D02 = BEBufToUint16(p); p += 2; /* 寄存器 */ g_tVar.D03 = BEBufToUint16(p); p += 2; /* 寄存器 */ g_tVar.D04 = BEBufToUint16(p); p += 2; /* 寄存器 */ g_tModH.fAck01H = 1; } break; } } } /* ********************************************************************************************************* * 函 数 名: MODH_Read_02H * 功能说明: 分析02H指令的应答数据,读取输入状态,bit访问 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ static void MODH_Read_02H(void) { uint8_t bytes; uint8_t *p; if (g_tModH.RxCount > 0) { bytes = g_tModH.RxBuf[2]; /* 数据长度 字节数 */ switch (g_tModH.Reg02H) { case REG_T01: if (bytes == 6) { p = &g_tModH.RxBuf[3]; g_tVar.T01 = BEBufToUint16(p); p += 2; /* 寄存器 */ g_tVar.T02 = BEBufToUint16(p); p += 2; /* 寄存器 */ g_tVar.T03 = BEBufToUint16(p); p += 2; /* 寄存器 */ g_tModH.fAck02H = 1; } break; } } } /* ********************************************************************************************************* * 函 数 名: MODH_Read_04H * 功能说明: 分析04H指令的应答数据,读取输入寄存器,16bit访问 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ static void MODH_Read_04H(void) { uint8_t bytes; uint8_t *p; if (g_tModH.RxCount > 0) { bytes = g_tModH.RxBuf[2]; /* 数据长度 字节数 */ switch (g_tModH.Reg04H) { case REG_A01: if (bytes == 2) { p = &g_tModH.RxBuf[3]; g_tVar.A01 = BEBufToUint16(p); p += 2; /* 寄存器 */ g_tModH.fAck04H = 1; } break; } } } /* ********************************************************************************************************* * 函 数 名: MODH_Read_05H * 功能说明: 分析05H指令的应答数据,写入线圈状态,bit访问 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ static void MODH_Read_05H(void) { if (g_tModH.RxCount > 0) { if (g_tModH.RxBuf[0] == SlaveAddr) { g_tModH.fAck05H = 1; /* 接收到应答 */ } }; } /* ********************************************************************************************************* * 函 数 名: MODH_Read_06H * 功能说明: 分析06H指令的应答数据,写单个保存寄存器,16bit访问 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ static void MODH_Read_06H(void) { if (g_tModH.RxCount > 0) { if (g_tModH.RxBuf[0] == SlaveAddr) { g_tModH.fAck06H = 1; /* 接收到应答 */ } } } /* ********************************************************************************************************* * 函 数 名: MODH_Read_03H * 功能说明: 分析03H指令的应答数据,读取保持寄存器,16bit访问 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ void MODH_Read_03H(void) { uint8_t bytes; uint8_t *p; if (g_tModH.RxCount > 0) { bytes = g_tModH.RxBuf[2]; /* 数据长度 字节数 */ switch (g_tModH.Reg03H) { case REG_P01: if (bytes == 4) { p = &g_tModH.RxBuf[3]; g_tVar.P01 = BEBufToUint16(p); p += 2; /* 寄存器 */ g_tVar.P02 = BEBufToUint16(p); p += 2; /* 寄存器 */ g_tModH.fAck03H = 1; } break; } } } /* ********************************************************************************************************* * 函 数 名: MODH_Read_10H * 功能说明: 分析10H指令的应答数据,写多个保存寄存器,16bit访问 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ void MODH_Read_10H(void) { /* 10H指令的应答: 从机地址 11 功能码 10 寄存器起始地址高字节 00 寄存器起始地址低字节 01 寄存器数量高字节 00 寄存器数量低字节 02 CRC校验高字节 12 CRC校验低字节 98 */ if (g_tModH.RxCount > 0) { if (g_tModH.RxBuf[0] == SlaveAddr) { g_tModH.fAck10H = 1; /* 接收到应答 */ } } } /* ********************************************************************************************************* * 函 数 名: MODH_ReadParam_01H * 功能说明: 单个参数. 通过发送01H指令实现,发送之后,等待从机应答。 * 形 参: 无 * 返 回 值: 1 表示成功。0 表示失败(通信超时或被拒绝) ********************************************************************************************************* */ uint8_t MODH_ReadParam_01H(uint16_t _reg, uint16_t _num) { int32_t time1; uint8_t i; for (i = 0; i < NUM; i++) { MODH_Send01H (SlaveAddr, _reg, _num); /* 发送命令 */ time1 = bsp_GetRunTime(); /* 记录命令发送的时刻 */ while (1) /* 等待应答,超时或接收到应答则break */ { bsp_Idle(); if (bsp_CheckRunTime(time1) > TIMEOUT) { break; /* 通信超时了 */ } if (g_tModH.fAck01H > 0) { break; /* 接收到应答 */ } } if (g_tModH.fAck01H > 0) { break; /* 循环NUM次,如果接收到命令则break循环 */ } } if (g_tModH.fAck01H == 0) { return 0; } else { return 1; /* 01H 读成功 */ } } /* ********************************************************************************************************* * 函 数 名: MODH_ReadParam_02H * 功能说明: 单个参数. 通过发送02H指令实现,发送之后,等待从机应答。 * 形 参: 无 * 返 回 值: 1 表示成功。0 表示失败(通信超时或被拒绝) ********************************************************************************************************* */ uint8_t MODH_ReadParam_02H(uint16_t _reg, uint16_t _num) { int32_t time1; uint8_t i; for (i = 0; i < NUM; i++) { MODH_Send02H (SlaveAddr, _reg, _num); time1 = bsp_GetRunTime(); /* 记录命令发送的时刻 */ while (1) { bsp_Idle(); if (bsp_CheckRunTime(time1) > TIMEOUT) { break; /* 通信超时了 */ } if (g_tModH.fAck02H > 0) { break; } } if (g_tModH.fAck02H > 0) { break; } } if (g_tModH.fAck02H == 0) { return 0; } else { return 1; /* 02H 读成功 */ } } /* ********************************************************************************************************* * 函 数 名: MODH_ReadParam_03H * 功能说明: 单个参数. 通过发送03H指令实现,发送之后,等待从机应答。 * 形 参: 无 * 返 回 值: 1 表示成功。0 表示失败(通信超时或被拒绝) ********************************************************************************************************* */ uint8_t MODH_ReadParam_03H(uint16_t _reg, uint16_t _num) { int32_t time1; uint8_t i; for (i = 0; i < NUM; i++) { MODH_Send03H (SlaveAddr, _reg, _num); time1 = bsp_GetRunTime(); /* 记录命令发送的时刻 */ while (1) { bsp_Idle(); if (bsp_CheckRunTime(time1) > TIMEOUT) { break; /* 通信超时了 */ } if (g_tModH.fAck03H > 0) { break; } } if (g_tModH.fAck03H > 0) { break; } } if (g_tModH.fAck03H == 0) { return 0; /* 通信超时了 */ } else { return 1; /* 写入03H参数成功 */ } } /* ********************************************************************************************************* * 函 数 名: MODH_ReadParam_04H * 功能说明: 单个参数. 通过发送04H指令实现,发送之后,等待从机应答。 * 形 参: 无 * 返 回 值: 1 表示成功。0 表示失败(通信超时或被拒绝) ********************************************************************************************************* */ uint8_t MODH_ReadParam_04H(uint16_t _reg, uint16_t _num) { int32_t time1; uint8_t i; for (i = 0; i < NUM; i++) { MODH_Send04H (SlaveAddr, _reg, _num); time1 = bsp_GetRunTime(); /* 记录命令发送的时刻 */ while (1) { bsp_Idle(); if (bsp_CheckRunTime(time1) > TIMEOUT) { break; /* 通信超时了 */ } if (g_tModH.fAck04H > 0) { break; } } if (g_tModH.fAck04H > 0) { break; } } if (g_tModH.fAck04H == 0) { return 0; /* 通信超时了 */ } else { return 1; /* 04H 读成功 */ } } /* ********************************************************************************************************* * 函 数 名: 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 < NUM; i++) { MODH_Send05H (SlaveAddr, _reg, _value); time1 = bsp_GetRunTime(); /* 记录命令发送的时刻 */ while (1) { bsp_Idle(); /* 超时大于 TIMEOUT,则认为异常 */ if (bsp_CheckRunTime(time1) > TIMEOUT) { break; /* 通信超时了 */ } if (g_tModH.fAck05H > 0) { break; } } if (g_tModH.fAck05H > 0) { break; } } if (g_tModH.fAck05H == 0) { return 0; /* 通信超时了 */ } else { return 1; /* 05H 写成功 */ } } /* ********************************************************************************************************* * 函 数 名: MODH_WriteParam_06H * 功能说明: 单个参数. 通过发送06H指令实现,发送之后,等待从机应答。循环NUM次写命令 * 形 参: 无 * 返 回 值: 1 表示成功。0 表示失败(通信超时或被拒绝) ********************************************************************************************************* */ uint8_t MODH_WriteParam_06H(uint16_t _reg, uint16_t _value) { int32_t time1; uint8_t i; for (i = 0; i < NUM; i++) { MODH_Send06H (SlaveAddr, _reg, _value); time1 = bsp_GetRunTime(); /* 记录命令发送的时刻 */ while (1) { bsp_Idle(); if (bsp_CheckRunTime(time1) > TIMEOUT) { break; } if (g_tModH.fAck06H > 0) { break; } } if (g_tModH.fAck06H > 0) { break; } } if (g_tModH.fAck06H == 0) { return 0; /* 通信超时了 */ } else { return 1; /* 写入06H参数成功 */ } } /* ********************************************************************************************************* * 函 数 名: MODH_WriteParam_10H * 功能说明: 单个参数. 通过发送10H指令实现,发送之后,等待从机应答。循环NUM次写命令 * 形 参: 无 * 返 回 值: 1 表示成功。0 表示失败(通信超时或被拒绝) ********************************************************************************************************* */ uint8_t MODH_WriteParam_10H(uint16_t _reg, uint8_t _num, uint8_t *_buf) { int32_t time1; uint8_t i; for (i = 0; i < NUM; i++) { MODH_Send10H(SlaveAddr, _reg, _num, _buf); time1 = bsp_GetRunTime(); /* 记录命令发送的时刻 */ while (1) { bsp_Idle(); if (bsp_CheckRunTime(time1) > TIMEOUT) { break; } if (g_tModH.fAck10H > 0) { break; } } if (g_tModH.fAck10H > 0) { break; } } if (g_tModH.fAck10H == 0) { return 0; /* 通信超时了 */ } else { return 1; /* 写入10H参数成功 */ } } /***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/