// /** // ************************************************************************************************ // * @file air.c // * @author 国轩储能 // * @version V1.0 // * @date 2018-11-20 // * @brief 空调通讯 // * @attention // ************************************************************************************************ // **/ // #include "air.h" // #include "ModbusRtu.h" // #include "ff.h" // #include "i104_addr.h" // #include "os_my_var.h" // #include "uart1.h" // #include // union Data_Air_Union_TypeDef Data_Air[2]; // union Par_Set_Air_Union_TypeDef Par_Set_Air1; // 空调1 // union Par_Set_Air_Union_TypeDef Par_Set_Air2; // 空调2 // // 制冷设定温度 制冷设定灵敏度 高温告警点 低温告警点 加热设定温度 加热设定灵敏度 远程开空调 // const u16 ADDR_CONV_HMI2AIR[ADDR_CONV_COUNT][2] = {{0x1830, 0x8202}, {0x1832, 0x8204}, {0x1834, 0x0E}, {0x1836, 0x10}, {0x1838, 0x820B}, {0x183A, 0x1E}, {0x1840, 0x0202}}; // 空调参数设置,触摸屏、空调485地址转换 // // 制冷设定温度 制冷设定灵敏度 高温告警点 低温告警点 加热设定温度 加热设定灵敏度 远程开空调 // const u16 ADDR_CONV_104IEC2AIR1[ADDR_CONV_COUNT][2] = {{REMOTE_REGULATE_ADDR_COOL_TEMP_AIR1, 0x8202}, {REMOTE_REGULATE_ADDR_COOL_SEN_AIR1, 0x8204}, {0, 0x0E}, {0, 0x10}, {REMOTE_REGULATE_ADDR_HOT_TEMP_AIR1, 0x820B}, {REMOTE_REGULATE_ADDR_HOT_SEN_AIR1, 0x1E}, {24618, 0x0202}}; // 空调参数设置,104地址转空调485地址 // // 制冷设定温度 制冷设定灵敏度 高温告警点 低温告警点 加热设定温度 加热设定灵敏度 远程开空调 // const u16 ADDR_CONV_104IEC2AIR2[ADDR_CONV_COUNT][2] = {{25093, 0x8202}, {25094, 0x8204}, {0, 0x0E}, {0, 0x10}, {25095, 0x820B}, {25096, 0x1E}, {24620, 0x0202}}; // 空调参数设置,104地址转空调485地址 // //// 写单寄存器命令格式: 控制器地址 命令类型 寄存器起始地址H 寄存器起始地址L 数据1H 数据1L CRC-L CRC-H // // u8 frame_air_set[16] = {0x01, 0x06, 0x00, 0x01, 0x00, 0x00}; // const Modbus_Frame_TypeDef Air_Frame[AIR_FRAME_COUNT] = {{0x1000, 42, 3}, {0xA004, 1, 3}, {0xA013, 1, 3}, {0x0300, 17, 3}, {0x8202, 4, 3}, {0x000e, 4, 3}, {0x820b, 1, 3}, {0x1E, 1, 3}}; // void Air1_HandleFrame_1st(const u8 *p, u16 size); // void Air1_HandleFrame_2nd(const u8 *p, u16 size); // void Air1_HandleFrame_3rd(const u8 *p, u16 size); // void Air1_HandleFrame_4th(const u8 *p, u16 size); // void Air1_HandleFrame_5th(const u8 *p, u16 size); // void Air1_HandleFrame_6th(const u8 *p, u16 size); // void air1_handle_frame_7th(const u8 *p, u16 size); // void Air1_HandleFrame_8th(const u8 *p, u16 size); // void (*Func_AirHandleFrame[AIR_FRAME_COUNT])(const u8 *p, u16 size) = {Air1_HandleFrame_1st, Air1_HandleFrame_2nd, Air1_HandleFrame_3rd, Air1_HandleFrame_4th, // Air1_HandleFrame_5th, Air1_HandleFrame_6th, Air1_HandleFrame_7th, Air1_HandleFrame_8th}; // // extern os_mbx_declare(uart1_mailbox, 10); // 声明消息邮箱 读取空调数据 // /**************************************************** // * 函 数 名:ReadAirData // * 函数功能:读取空调数据 // * 入口参数:register_addr 寄存器地址 count 数量 p 缓冲区指针 // * 说 明:无 // *****************************************************/ // void CopyAirData(u16 register_addr, u16 count, u16 *p) // { // u16 offset, i; // offset = register_addr - MODBUS_ADDR_AIR_READ; // for (i = 0; i < count; i++) // *p++ = Data_Air[0].data_air_buf_u16[offset + i]; // } // /**************************************************** // * 函 数 名:CopyAirDataSet // * 函数功能:读取空调设置参数 // * 入口参数:register_addr 寄存器地址 count 浮点数据数量 p 缓冲区指针 // * 说 明:无 // *****************************************************/ // void CopyAirDataSet(u16 register_addr, u16 count, float *pFloat) // { // u16 offset, i; // u8 *pU8; // offset = register_addr - MODBUS_ADDR_AIR_WRITE; // pU8 = (u8 *)pFloat; // for (i = 0; i < count * 4; i++) // *pU8++ = Par_Set_Air1.par_buff_u8[4 * offset + i]; // 直接用par_buff_float赋值,硬件故障 // } // /**************************************************** // * 函 数 名:Air1_HandleFrame_1st // * 函数功能:处理空调第一帧 // * 入口参数: p 数据指针, size 数据个数 // * 说 明:无 // ****************************************************/ // void Air1_HandleFrame_1st(const u8 *p, u16 size) // { // u8 index = 0, slave_id = 0; // u8 temp1, temp2; // u16 crc; // // OS_ERR err; // // 空调返回命令格式: 控制器地址 命令类型 字节数n 数据1H 数据1L 数据2H 数据2L CRC-L CRC-H // crc = Count_CRC(p, size - 2); // if (crc != ((p[size - 1] << 8) + (p[size - 2]))) // return; // if (*p == 1) // { // slave_id = 0; // } // else // { // slave_id = 1; // } // p = p + 3; // for (index = 0; index < 14; index++) // 设备工作状态、室内风机状态、室外风机状态、压缩机状态 柜内回风温度 水泵状态 柜外温度 冷凝器温度...交流运行电流 // { // temp1 = *p++; // temp2 = *p++; // Data_Air[slave_id].data_air_buf_u16[index] = (temp1 << 8) + temp2; // p = p + 2; // } // // 设备运行时间、压缩机运行时间、内风机运行时间、压缩机运行次数 // for (; index < 22; index++) // { // temp1 = *p++; // temp2 = *p++; // Data_Air[slave_id].data_air_buf_u16[index++] = (temp1 << 8) + temp2; // temp1 = *p++; // temp2 = *p++; // Data_Air[slave_id].data_air_buf_u16[index] = (temp1 << 8) + temp2; // p += 4; // } // } // /**************************************************** // * 函 数 名:Air1_HandleFrame_2nd // * 函数功能:处理空调第一帧 // * 入口参数: p 数据指针, size 数据个数 // * 说 明:无 // ****************************************************/ // void Air1_HandleFrame_2nd(const u8 *p, u16 size) // { // u8 temp1, temp2, slave_id = 0; // u16 crc; // // 空调返回命令格式: 控制器地址 命令类型 字节数n 数据1H 数据1L 数据2H 数据2L CRC-L CRC-H // crc = Count_CRC(p, size - 2); // if (crc != ((p[size - 1] << 8) + (p[size - 2]))) // return; // if (*p == 1) // { // slave_id = 0; // } // else // { // slave_id = 1; // } // p = p + 3; // temp1 = (*p++); // temp2 = (*p++); // Data_Air[slave_id].data_air_buf_u16[22] = (temp1 << 8) + temp2; // } // /**************************************************** // * 函 数 名:Air1_HandleFrame_3rd // * 函数功能:处理空调第一帧 // * 入口参数: p 数据指针, size 数据个数 // * 说 明:无 // ****************************************************/ // void Air1_HandleFrame_3rd(const u8 *p, u16 size) // { // u8 temp1, temp2, slave_id = 0; // u16 crc; // // 空调返回命令格式: 控制器地址 命令类型 字节数n 数据1H 数据1L 数据2H 数据2L CRC-L CRC-H // crc = Count_CRC(p, size - 2); // if (crc != ((p[size - 1] << 8) + (p[size - 2]))) // return; // if (*p == 1) // { // slave_id = 0; // } // else // { // slave_id = 1; // } // p = p + 3; // temp1 = *p++; // temp2 = *p++; // Data_Air[slave_id].data_air_buf_u16[23] = (temp1 << 8) + temp2; // } // /**************************************************** // * 函 数 名:Air1_HandleFrame_4th // * 函数功能:处理空调第一帧 // * 入口参数: p 数据指针, size 数据个数 // * 说 明:无 // ****************************************************/ // void Air1_HandleFrame_4th(const u8 *p, u16 size) // { // u8 i, slave_id = 0, temp1 = 0, temp2 = 0; // u16 crc; // // 空调返回命令格式: 控制器地址 命令类型 字节数n 数据1H 数据1L 数据2H 数据2L CRC-L CRC-H // crc = Count_CRC(p, size - 2); // if (crc != ((p[size - 1] << 8) + (p[size - 2]))) // return; // if (*p == 1) // { // slave_id = 0; // } // else // { // slave_id = 1; // } // p = p + 3; // for (i = 0; i < 17; i++) // { // temp1 = (*p++); // temp2 = (*p++); // Data_Air[slave_id].data_air_buf_u16[24 + i] = (temp1 << 8) + temp2; // if (Data_Air[slave_id].data_air_buf_u16[24 + i] == 0x01) // { // Data_Air[slave_id].Data_Air_Union.serious_alarm = TRUE; // } // } // if (Data_Air[slave_id].Data_Air_Union.serious_alarm == TRUE) // { // bams_set_air_status(TRUE); // } // } // /**************************************************** // * 函 数 名:Air1_HandleFrame_5th // * 函数功能:处理空调第一帧 // * 入口参数: p 数据指针, size 数据个数 // * 说 明:无 // ****************************************************/ // void Air1_HandleFrame_5th(const u8 *p, u16 size) // { // u8 i; // u8 temp1, temp2; // u16 crc; // union Par_Set_Air_Union_TypeDef *param = NULL; // // 空调返回命令格式: 控制器地址 命令类型 字节数n 数据1H 数据1L 数据2H 数据2L CRC-L CRC-H // crc = Count_CRC(p, size - 2); // if (crc != ((p[size - 1] << 8) + (p[size - 2]))) // return; // if (*p == 1) // { // param = &Par_Set_Air1; // } // else // { // param = &Par_Set_Air2; // } // p = p + 3; // for (i = 0; i < 2; i++) // { // temp1 = *p++; // temp2 = *p++; // param->par_buff_float[i] = (float)((temp1 << 8) + temp2) / 10.0f; // p = p + 2; // } // } // /**************************************************** // * 函 数 名:Air1_HandleFrame_6th // * 函数功能:处理空调第一帧 // * 入口参数: p 数据指针, size 数据个数 // * 说 明:无 // ****************************************************/ // void Air1_HandleFrame_6th(const u8 *p, u16 size) // { // u8 i; // u8 temp1, temp2; // u16 crc; // union Par_Set_Air_Union_TypeDef *param = NULL; // // 空调返回命令格式: 控制器地址 命令类型 字节数n 数据1H 数据1L 数据2H 数据2L CRC-L CRC-H // crc = Count_CRC(p, size - 2); // if (crc != ((p[size - 1] << 8) + (p[size - 2]))) // return; // if (*p == 1) // { // param = &Par_Set_Air1; // } // else // { // param = &Par_Set_Air2; // } // p = p + 3; // for (i = 0; i < 2; i++) // { // temp1 = (*p++); // temp2 = (*p++); // param->par_buff_float[i + 2] = (float)((temp1 << 8) + temp2) / 10.0f; // p = p + 2; // } // } // /**************************************************** // * 函 数 名:air1_handle_frame_7th // * 函数功能:处理空调第一帧 // * 入口参数: p 数据指针, size 数据个数 // * 说 明:无 // ****************************************************/ // void air1_handle_frame_7th(const u8 *p, u16 size) // { // u8 temp1, temp2; // u16 crc; // union Par_Set_Air_Union_TypeDef *param = NULL; // // 空调返回命令格式: 控制器地址 命令类型 字节数n 数据1H 数据1L 数据2H 数据2L CRC-L CRC-H // crc = Count_CRC(p, size - 2); // if (crc != ((p[size - 1] << 8) + (p[size - 2]))) // return; // if (*p == 1) // { // param = &Par_Set_Air1; // } // else // { // param = &Par_Set_Air2; // } // p = p + 3; // temp1 = (*p++); // temp2 = (*p++); // param->par_buff_float[4] = ((temp1 << 8) + temp2) / 10.0f; // } // /**************************************************** // * 函 数 名:Air1_HandleFrame_7th // * 函数功能:处理空调第一帧 // * 入口参数: p 数据指针, size 数据个数 // * 说 明:无 // ****************************************************/ // void Air1_HandleFrame_8th(const u8 *p, u16 size) // { // u8 temp1, temp2; // u16 crc; // union Par_Set_Air_Union_TypeDef *param = NULL; // // 空调返回命令格式: 控制器地址 命令类型 字节数n 数据1H 数据1L 数据2H 数据2L CRC-L CRC-H // crc = Count_CRC(p, size - 2); // if (crc != ((p[size - 1] << 8) + (p[size - 2]))) // return; // if (*p == 1) // { // param = &Par_Set_Air1; // } // else // { // param = &Par_Set_Air2; // } // p = p + 3; // temp1 = (*p++); // temp2 = (*p++); // param->par_buff_float[5] = ((temp1 << 8) + temp2) / 10.0f; // } // /**************************************************** // * 函 数 名:SendFrame_SetAirParSingle // * 函数功能:设置空调运行参数 // * 入口参数:p 数据指针, register_addr 寄存器地址, count 数量 // * 说 明:无 // ****************************************************/ // void SendFrame_SetAirParSingle(float dat_float, u16 register_addr) // { // OS_RESULT result; // UartFrame_TypeDef *pMsg; // // 写单寄存器命令格式: 控制器地址 命令类型 寄存器起始地址H 寄存器起始地址L 数据1H 数据1L CRC-L CRC-H // // u8 frame_air_set[16] = {0x01, 0x06, 0x00, 0x01, 0x00, 0x00}; // u16 data = (u16)(dat_float * 10); // 下发给空调参数需放大10倍 // // 写多寄存器命令格式: 控制器地址 命令类型 寄存器起始地址H 寄存器起始地址L 寄存器个数H 寄存器个数L 字节数n 数据1H 数据1L 数据2H 数据2L CRC-L CRC-H // // 写单寄存器命令格式: 控制器地址 命令类型 寄存器起始地址H 寄存器起始地址L 数据1H 数据1L CRC-L CRC-H // os_mut_wait(&mutex_uart1, 0xffff); // 永久等待互斥资源 // ModbusRtu_SendFrame06(register_addr, data, Uart1DMA_SendData); // result = os_mbx_wait(&uart1_mailbox, (void *)&pMsg, TIME_200MS); // if (result == OS_R_OK || result == OS_R_MBX) // 成功获得消息 // { // pMsg = pMsg; // 添加该语句,防止if被优化掉 // } // os_mut_release(&mutex_uart1); // 释放互斥资源 // } // /**************************************************** // * 函 数 名:ReadAirData // * 函数功能:读取空调数据数据帧 // * 入口参数:register_addr 寄存器地址 count 数量 frame_style 报文类型 // * 说 明:无 // *****************************************************/ // void ReadAirData(void) // { // OS_RESULT result; // UartFrame_TypeDef *pMsg; // static u8 air1_index = 0; // 1#空调帧序号 // void (*ModbusSendFrame)(u16 register_addr, u16 count, void (*Func_Send)(const u8 *data, u16 count)); // const Modbus_Frame_TypeDef *air_frame; // air_frame = &Air_Frame[air1_index]; // ModbusSendFrame = Func_ModbusRtu_SendFrame[air_frame->frame_style]; // 指向具体发送帧函数 // ModbusSendFrame(air_frame->register_addr, air_frame->register_count, Uart1DMA_SendData); // 发送报文 // /* 等待uart1收到数据,不阻塞任务 */ // result = os_mbx_wait(&uart1_mailbox, (void *)&pMsg, TIME_200MS); // if (result == OS_R_OK || result == OS_R_MBX) // 成功获得消息 // { // if (pMsg->len > 2) // { // Func_AirHandleFrame[air1_index](pMsg->buf, pMsg->len); // 解析报文 // } // } // air1_index++; // if (air1_index >= AIR_FRAME_COUNT) // air1_index = 0; // } // /**************************************************** // * 函 数 名:Air_Find485Addr // * 函数功能:空调参数设置,触摸屏485地址转换到空调485地址 // * 入口参数:hmi_addr 触摸屏485地址 // * 返回参数:空调485地址 // * 说 明:0 没找到对应空调485地址 // *****************************************************/ // u16 AddrConv_Hmi2Air(u16 hmi_addr) // { // u8 i; // for (i = 0; i < ADDR_CONV_COUNT; i++) // { // if (ADDR_CONV_HMI2AIR[i][0] == hmi_addr) // { // return ADDR_CONV_HMI2AIR[i][1]; // } // } // return FALSE; // } // /**************************************************** // * 函 数 名:AddrConv_104IEC2Air1 // * 函数功能:空调1 104地址转换到485地址 // * 入口参数:i104_addr 104地址 // * 返回参数:空调485地址 // * 说 明:0 没找到对应空调485地址 // *****************************************************/ // u16 AddrConv_104IEC2Air1(u16 i104_addr) // { // u8 i; // for (i = 0; i < ADDR_CONV_COUNT; i++) // { // if (ADDR_CONV_104IEC2AIR1[i][0] == i104_addr) // { // return ADDR_CONV_104IEC2AIR1[i][1]; // } // } // return FALSE; // } // /**************************************************** // * 函 数 名:AddrConv_104IEC2Air2 // * 函数功能:空调2 104地址转换到485地址 // * 入口参数:i104_addr 104地址 // * 返回参数:空调485地址 // * 说 明:0 没找到对应空调485地址 // *****************************************************/ // u16 AddrConv_104IEC2Air2(u16 i104_addr) // { // u8 i; // for (i = 0; i < ADDR_CONV_COUNT; i++) // { // if (ADDR_CONV_104IEC2AIR2[i][0] == i104_addr) // { // return ADDR_CONV_104IEC2AIR2[i][1]; // } // } // return FALSE; // } // /**************************************************** // * 函 数 名:HMI_10Frame_ParSetAir // * 函数功能:HMI 10帧空调参数设置 // * 入口参数:register_addr 寄存器地址 p 缓冲区指针 // * 说 明:一次只能设置一个参数 // *****************************************************/ // void HMI_10Frame_ParSetAir(u16 register_addr, const float *pFloat) // { // u16 offset, addr_air; // offset = (register_addr - MODBUS_ADDR_AIR_WRITE) / 2; // 0x1830 0x1832 0x1834 0x1836 // memcpy((u8 *)&Par_Set_Air1.par_buff_float[offset], (u8 *)pFloat, 4); // addr_air = AddrConv_Hmi2Air(register_addr); // if (addr_air != DEF_FALSE) // SendFrame_SetAirParSingle(Par_Set_Air1.par_buff_float[offset], addr_air); // } // /**************************************************** // * 函 数 名:I104_ParSetAir1 // * 函数功能:104设置空调1参数 // * 入口参数:i104_addr: 104地址 data :参数 // * 说 明:无 // *****************************************************/ // void I104_ParSetAir1(u16 i104_addr, float data) // { // u16 addr_air; // addr_air = AddrConv_104IEC2Air1(i104_addr); // if (addr_air != DEF_FALSE) // SendFrame_SetAirParSingle(data, addr_air); // } // /**************************************************** // * 函 数 名:SendFrame_SwitchAir // * 函数功能:发送数据帧,开关空调 // * 入口参数:addr_device:空调设备地址 addr_air: 寄存器地址 data: 开关指令 // * 说 明:无 // *****************************************************/ // void SendFrame_SwitchAir(u8 addr_device, u16 addr_air, u16 data) // { // OS_RESULT result; // UartFrame_TypeDef *pMsg; // //// 写单寄存器命令格式: 控制器地址 命令类型 寄存器起始地址H 寄存器起始地址L 数据1H 数据1L CRC-L CRC-H // os_mut_wait(&mutex_uart1, 0xffff); // 永久等待互斥资源 // ModbusRtu_SendFrame06(addr_air, data, Uart1DMA_SendData); // result = os_mbx_wait(&uart1_mailbox, (void *)&pMsg, TIME_200MS); // if (result == OS_R_OK || result == OS_R_MBX) // 成功获得消息 // { // pMsg = pMsg; // 添加该语句,防止if被优化掉 // } // os_mut_release(&mutex_uart1); // 释放互斥资源 // } // /**************************************************** // * 函 数 名:HMI_10Frame_ParSetAir // * 函数功能:HMI开关空调 // * 入口参数:register_addr 寄存器地址 data 开关指令 // * 说 明:无 // *****************************************************/ // void HMI_10Frame_SwitchAir(u16 addr_hmi, u16 data) // { // u16 addr_air; // addr_air = AddrConv_Hmi2Air(addr_hmi); // if (addr_air != DEF_FALSE) // { // SendFrame_SwitchAir(1, addr_air, data); // } // } // /**************************************************** // * 函 数 名:I104_SwitchAir1 // * 函数功能:104开关空调1 // * 入口参数:addr_104: 104地址 data: 开关指令 // * 说 明:无 // *****************************************************/ // void I104_SwitchAir1(u16 addr_104, u8 data) // { // u16 addr_air; // addr_air = AddrConv_104IEC2Air1(addr_104); // if (addr_air != DEF_FALSE) // { // SendFrame_SwitchAir(1, addr_air, data); // } // } // /**************************************************** // * 函 数 名:Uart_air_test // * 函数功能:Uart1通信测试 // * 入口参数:addr_104: 104地址 data: 开关指令 // * 说 明:无 // *****************************************************/ // void Uart_air_test(void) // { // OS_RESULT result = OS_R_OK; // UartFrame_TypeDef *pMsg; // u8 uart1_test_buf[3] = {0}; // result = os_mbx_wait(&uart1_mailbox, (void *)&pMsg, TIME_1000MS); // if (result == OS_R_OK || result == OS_R_MBX) // 成功获得消息 // { // if ((pMsg->buf[0] == 0xAA) && (pMsg->buf[1] == 0xBB)) // { // uart1_test_buf[0] = 0xBB; // uart1_test_buf[1] = 0xAA; // Uart1DMA_SendData(uart1_test_buf, 2); // } // else if ((pMsg->buf[0] == 0xAB) && (pMsg->buf[1] == 0xAB)) // { // uart1_test_buf[0] = 0xBA; // uart1_test_buf[1] = 0xBA; // Uart1DMA_SendData(uart1_test_buf, 2); // bams_set_uart_flag(FALSE); // } // else if ((pMsg->buf[0] == 0x01) && (pMsg->buf[1] == 0xAA) && (pMsg->buf[2] == 0xBB)) // { // uart1_test_buf[0] = 0x01; // uart1_test_buf[1] = 0xBB; // uart1_test_buf[2] = 0xAA; // Uart1DMA_SendData(uart1_test_buf, 3); // } // } // }