#include "CJT188.h" #include "string.h" #include "timer.h" #include "gateway_message.h" #include "tcp_server.h" #include "data_task.h" CTJBus_t ctjData; void cjt_callback(UART_HandleTypeDef *husart) { if(__HAL_UART_GET_FLAG(husart, UART_FLAG_RXNE) && __HAL_UART_GET_IT_SOURCE(husart, UART_IT_RXNE)) { if (ctjData.rxIndex < _CJT_RXSIZE - 1) { ctjData.rxBuf[ctjData.rxIndex] = husart->Instance->DR; ctjData.rxIndex++; } else { uint8_t data = husart->Instance->DR; } } if ((ctjData.rxIndex > 0) && RESET != __HAL_UART_GET_FLAG(husart, USART_FLAG_IDLE) && __HAL_UART_GET_IT_SOURCE(husart, UART_IT_IDLE)) { uint8_t i; ctjData.done = 1; i = husart->Instance->SR; i = husart->Instance->DR; return; } ctjData.rxTime = gettick(); } // ################################################################################################## bool cjt_sendRaw(uint8_t *data, uint16_t size, uint32_t timeout) { GATEWAY_PARAMS *get; get= get_gateway_config_params(); while(ctjData.txBusy == 1) delay_ms(1); ctjData.txBusy = 1; memset(ctjData.rxBuf, 0, _CJT_RXSIZE); ctjData.rxIndex = 0; ctjData.done = 0; uint32_t startTime = gettick(); portENTER_CRITICAL(); if(get->comProtocol){ // get->protocol 1:232 0:485 USART_232_Send(data,size); }else{ USART_485_Send(data,size); } portEXIT_CRITICAL(); ctjData.done=0; ctjData.txBusy = 0; return true; } // ################################################################################################## uint16_t cjt_receiveRaw(uint32_t timeout) { uint32_t startTime = gettick(); while (1) { if (gettick() - startTime> timeout * 1000) return 0; if (ctjData.done == 1) { return ctjData.rxIndex; } delay_ms(5); } } bool cjt_init(uint32_t timeout) { // HAL_GPIO_WritePin(_MMODBUS_CTRL_GPIO, _MMODBUS_CTRL_PIN, GPIO_PIN_RESET); 此处初始化在485 init过 HAL_GPIO_WritePin(_CTJ_CTRL_GPIO, _CTJ_CTRL_PIN,GPIO_PIN_RESET); memset(&ctjData, 0, sizeof(ctjData)); ctjData.timeout = timeout; return true; } /* ********************************************************************************************************* * 函 数 名: bool cjt_read_meter_data(uint8_t* slaveAddress, uint8_t *data, uint8_t protocol) * 功能说明: 读取仪表上的数据 * 形 参1: slaveAddress:读取的地址 * 形 参2: data:接收的内存地址 * 形 参3: protocol:读取的仪表类型 0x10(水表) 0x30(燃气表) 0x40(电表) * 返 回 值: true: 成功 false:失败 ********************************************************************************************************* */ bool cjt_read_meter_data(uint8_t* slaveAddress, double* data, uint8_t protocol) { uint8_t txData[19]; txData[0] = 0xFE; txData[1] = 0xFE; txData[2] = 0xFE; // 引导符 txData[3] = 0x68; // 起始帧 if(protocol == 0x10) // 水表 txData[4] = 0x10; else if(protocol == 0x30) // 燃气表 txData[4] = 0x30; else if(protocol == 0x40) // 电表 txData[4] = 0x40; txData[5] = slaveAddress[0]; // 地址 生产流水号最低字节 txData[6] = slaveAddress[1]; // 地址 生产流水号次高字节 txData[7] = slaveAddress[2]; // 地址 生产流水号最高字节 txData[8] = slaveAddress[3]; // 地址 表计生产月份 txData[9] = slaveAddress[4]; // 地址 表计生产年份 txData[10] = slaveAddress[5]; // 地址 生产厂商代码低字节 txData[11] = slaveAddress[6]; // 地址 生产厂商代码高字节 txData[12] = 0x01; // 控制码 CTR_0 txData[13] = 0x03; // 数据域长度 txData[14] = 0x90; // 数据标识DI0 txData[15] = 0x1F; // 数据标识DI1 txData[16] = 0x01; // 序列号 uint8_t crc = 0; for(uint8_t i = 0; i < 14; i++) { crc += txData[i + 3]; } txData[17] = crc; txData[18] = 0x16; // 结束帧 cjt_sendRaw(txData, 19, 100); uint16_t recLen = cjt_receiveRaw(ctjData.timeout); if (recLen == 0) return false; for(uint8_t i = 0; i < 12; i++) { if(ctjData.rxBuf[i] != txData[i]) return false; } if (ctjData.rxBuf[12] != txData[12] + 0x80) return false; if (ctjData.rxBuf[14] != txData[14]) return false; if (ctjData.rxBuf[15] != txData[15]) return false; crc = 0; for(uint8_t i = 0; i < 20; i++) { crc += ctjData.rxBuf[i + 3]; } if (ctjData.rxBuf[23] != crc) return false; if (ctjData.rxBuf[24] != txData[18]) return false; if(TransparentModeFlag) return true; *data = data_translate_to_float(ctjData.rxBuf); return true; } /* ********************************************************************************************************* * 函 数 名: bool cjt_set_addr(uint8_t *addr) * 功能说明: 设置仪表地址 * 形 参: addr:需要设置的新地址 * 返 回 值: true: 成功 false:失败 ********************************************************************************************************* */ bool cjt_set_addr(uint8_t *addr) { uint8_t txData[26]; txData[0] = 0xFE; txData[1] = 0xFE; txData[2] = 0xFE; // 引导符 txData[3] = 0x68; // 起始帧 txData[4] = 0xAA; // 水表、燃气表、电表 txData[5] = 0xAA; txData[6] = 0xAA; txData[7] = 0xAA; txData[8] = 0xAA; txData[9] = 0xAA; txData[10] = 0xAA; txData[11] = 0xAA; txData[12] = 0x15; // 控制码 CTR_3 txData[13] = 0x0A; // 数据域长度 txData[14] = 0x18; // 数据标识DI0 txData[15] = 0xA0; // 数据标识DI1 txData[16] = 0x00; // 序列号 txData[17] = addr[6]; // 新地址 txData[18] = addr[5]; // 新地址 txData[19] = addr[4]; // 新地址 txData[20] = addr[3]; // 新地址 txData[21] = addr[2]; // 新地址 txData[22] = addr[1]; // 新地址 txData[23] = addr[0]; // 新地址 uint8_t crc = 0; for(uint8_t i = 0; i < 21; i++) { crc += txData[i + 3]; } txData[24] = crc; txData[25] = 0x16; cjt_sendRaw(txData, 26, 100); uint16_t recLen = cjt_receiveRaw(ctjData.timeout); if (recLen == 0) return false; if (ctjData.rxBuf[3] != txData[3]) return false; for(uint8_t i = 0; i < 7; i++) { if(ctjData.rxBuf[i + 5] != txData[23 - i]) return false; } if(ctjData.rxBuf[12] != txData[12] + 0x80) return false; if(ctjData.rxBuf[14] != txData[14] && ctjData.rxBuf[15] != txData[15] ) return false; crc = 0; for(uint8_t i = 0; i < 14; i++) { crc += ctjData.rxBuf[i + 3]; } if(ctjData.rxBuf[17] != crc) return false; if(ctjData.rxBuf[18] != txData[25]) return false; return true; } /* ********************************************************************************************************* * 函 数 名: bool cjt_read_addr(uint8_t *add) * 功能说明: 读取仪表地址 * 形 参: data:读取地址的存放地址 * 返 回 值: true: 成功 false:失败 ********************************************************************************************************* */ bool cjt_read_addr(uint8_t *add) { uint8_t txData[19]; txData[0] = 0xFE; txData[1] = 0xFE; txData[2] = 0xFE; // 引导符 txData[3] = 0x68; // 起始帧 txData[4] = 0xAA; // 水表、燃气表、电表 txData[5] = 0xAA; txData[6] = 0xAA; txData[7] = 0xAA; txData[8] = 0xAA; txData[9] = 0xAA; txData[10] = 0xAA; txData[11] = 0xAA; txData[12] = 0x03; // 控制码 txData[13] = 0x03; // 数据域长度 txData[14] = 0x81; // 数据标识DI0 txData[15] = 0x0A; // 数据标识DI1 txData[16] = 0x00; // 序列号 uint8_t crc = 0; for(uint8_t i = 0; i < 14; i++) { crc += txData[i + 3]; } txData[17] = crc; // crc txData[18] = 0x16; // 结束帧 cjt_sendRaw(txData, 19, 100); uint16_t recLen = cjt_receiveRaw(ctjData.timeout); if (recLen == 0) return false; if (ctjData.rxBuf[3] != txData[3]) return false; if (ctjData.rxBuf[12] != txData[12] + 0x80) return false; for(uint8_t i = 0; i < 4; i++) { if(ctjData.rxBuf[i + 13] != txData[i + 13]) return false; } crc = 0; for(uint8_t i = 0; i < 14; i++) { crc += ctjData.rxBuf[i + 3]; } if(ctjData.rxBuf[17] != crc) return false; if(ctjData.rxBuf[18] != txData[18]) return false; if(add != NULL) { for(uint8_t i = 0; i < 7; i++) { add[6 - i] = ctjData.rxBuf[i + 5]; } } return true; } // 将读取的数据转换成double型 double data_translate_to_float(uint8_t* msg) { int val; val += ((0xff & (msg[17]>>4))*10 +(0xf & msg[17])); val += ((0xff & (msg[18]>>4))*10 +(0xf & msg[18])) * my_pow(10,2); val += ((0xff & (msg[19]>>4))*10 +(0xf & msg[19])) * my_pow(10,4); val += ((0xff & (msg[20]>>4))*10 +(0xf & msg[20])) * my_pow(10,6); return (double)(val)/100.0; }