#include "download.h" #include "upload.h" #include "user_uart.h" #include "user_crc16.h" #include "base64.h" #include "string.h" #include "user_server.h" static uint32_t download_delay_count = 0; static bool coll_ready_stat = false; static uint16_t coll_sw_count = 0; static uint16_t check_download_count = 0; static download_work_stat_e download_work_stat = DOWNLOAD_DEV_TYPE; static uint32_t download_offline_timeout = 0; static bool download_offline_stat = true; static void set_download_offline(bool stat); modbus_work_s download_work = { .rtu_addr = COLL_UART_ADDR, .tx_size = 0, .rx_size = 0, .tx_buffer = {0}, .rx_buffer = {0}, .rtu_rec = {0}, .modbusRx_stat = false, .modbusTx_stat = false, }; /******************************************************************************* * @函数名称 downloadRx_receive * @函数说明 处理接收数据 * @输入参数 data:数据指针 size:数据长度 * @输出参数 无 * @返回参数 无 *******************************************************************************/ static void downloadRx_receive(uint8_t *data, uint16_t size) { memcpy(download_work.rx_buffer, data, size); download_work.rx_size = size; #if USE_BASE64 == 1 uint8_t data[MODBUS_DATA_SIZE] = {0}; if(download_work.rx_buffer[download_work.rx_size - 2] == '\r' && download_work.rx_buffer[download_work.rx_size - 1] == '\n') { download_work.rx_buffer[download_work.rx_size - 2] = '\0'; int len = base64_decode((char *)download_work.rx_buffer, data); memcpy((void *)&(download_work.rtu_rd), data, len); memcpy((void *)&(download_work.rtu_rd.crc), &(data[len - 2]), 2); memcpy((void *)&(download_work.rtu_rec), data, len); memcpy((void *)&(download_work.rtu_rec.crc), &(data[len - 2]), 2); download_work.rtu_rec.dataSize = len - 6; download_work.modbusRx_stat = true; } #else memcpy((void *)&(download_work.rtu_rd), download_work.rx_buffer, download_work.rx_size); memcpy((void *)&(download_work.rtu_rd.crc), &(download_work.rx_buffer[download_work.rx_size - 2]), 2); memcpy((void *)&(download_work.rtu_rec), download_work.rx_buffer, download_work.rx_size); memcpy((void *)&(download_work.rtu_rec.crc), &(download_work.rx_buffer[download_work.rx_size - 2]), 2); download_work.rtu_rec.dataSize = download_work.rx_size - 6; download_work.modbusRx_stat = true; #endif } /******************************************************************************* * @函数名称 downloadTx_send * @函数说明 发送数据 * @输入参数 无 * @输出参数 无 * @返回参数 无 *******************************************************************************/ static void downloadTx_send(uint8_t *data, int size) { #if USE_BASE64 == 1 base64_encode(data, (char *)download_work.tx_buffer, size); int len = strlen((char *)download_work.tx_buffer); download_work.tx_buffer[len] = '\r'; download_work.tx_buffer[len + 1] = '\n'; download_work.tx_buffer[len + 2] = '\0'; download_work.tx_size = len + 2; #else memcpy(download_work.tx_buffer, data, size); download_work.tx_size = size; #endif download_work.modbusTx_stat = true; vUser_usart1_send(download_work.tx_buffer, download_work.tx_size); } /******************************************************************************* * @函数名称 rtu_protocol_sd_dev_type * @函数说明 设置询问从机设备类型数据 * @输入参数 data:数据指针 * @输出参数 无 * @返回参数 无 *******************************************************************************/ static uint16_t rtu_protocol_sd_dev_type(uint8_t *data) { data[0] = download_work.rtu_addr; data[1] = CMD_RD_REG; data[2] = (uint8_t)(REG_DEV_TYPE_ADDR >> 8); data[3] = (uint8_t)REG_DEV_TYPE_ADDR; data[4] = 0x00; data[5] = 0x01; check_download_count++; return 6; } /******************************************************************************* * @函数名称 rtu_protocol_sd_coll_stat * @函数说明 设置询问从机就绪状态数据 * @输入参数 data:数据指针 * @输出参数 无 * @返回参数 无 *******************************************************************************/ static uint16_t rtu_protocol_sd_coll_stat(uint8_t *data) { data[0] = download_work.rtu_addr; data[1] = CMD_RD_REG; data[2] = (uint8_t)(REG_COLL_STAT_ADDR >> 8); data[3] = (uint8_t)REG_COLL_STAT_ADDR; data[4] = 0x00; data[5] = 0x01; return 6; } /******************************************************************************* * @函数名称 rtu_protocol_sd_coll_count * @函数说明 设置询问从机包含的主板总数数据 * @输入参数 data:数据指针 * @输出参数 无 * @返回参数 无 *******************************************************************************/ static uint16_t rtu_protocol_sd_coll_count(uint8_t *data) { data[0] = download_work.rtu_addr; data[1] = CMD_RD_REG; data[2] = (uint8_t)(REG_COLL_COUNT_ADDR >> 8); data[3] = (uint8_t)REG_COLL_COUNT_ADDR; data[4] = 0x00; data[5] = 0x01; return 6; } /******************************************************************************* * @函数名称 rtu_protocol_sd_sw_stat * @函数说明 设置询问从机包含的开关量数据 * @输入参数 data:数据指针 * @输出参数 无 * @返回参数 无 *******************************************************************************/ static uint16_t rtu_protocol_sd_sw_stat(uint8_t *data) { data[0] = download_work.rtu_addr; data[1] = CMD_RD_REG; data[2] = (uint8_t)(REG_COLL_SW_HIGH_STAT_ADDR >> 8); data[3] = (uint8_t)REG_COLL_SW_HIGH_STAT_ADDR; data[4] = 0x00; data[5] = 0x02; return 6; } /******************************************************************************* * @函数名称 rtu_protocol_send * @函数说明 发送数据 * @输入参数 data:数据指针 size:数据长度 * @输出参数 无 * @返回参数 无 *******************************************************************************/ static void rtu_protocol_send(uint8_t *data, int size) { uint16_t crc = 0xFFFF; crc = GetCRC16(data, size, crc); memcpy(&data[size], &crc, 2); downloadTx_send(data, size + 2); } /******************************************************************************* * @函数名称 rtu_protocol_sd_task * @函数说明 发送数据任务 * @输入参数 无 * @输出参数 无 * @返回参数 无 *******************************************************************************/ static void rtu_protocol_sd_task(void) { uint8_t data[MODBUS_DATA_SIZE] = {0}; uint16_t datasize = 0; switch(download_work_stat) { case DOWNLOAD_DEV_TYPE:datasize = rtu_protocol_sd_dev_type(data);break; case DOWNLOAD_COLL_REDAY_STAT:datasize = rtu_protocol_sd_coll_stat(data);break; case DOWNLOAD_COLL_COUNT:datasize = rtu_protocol_sd_coll_count(data);break; case DOWNLOAD_SW_STAT:datasize = rtu_protocol_sd_sw_stat(data);break; default:{ download_work_stat = DOWNLOAD_DEV_TYPE; datasize = rtu_protocol_sd_dev_type(data); }break; } rtu_protocol_send(data, datasize); } /******************************************************************************* * @函数名称 rtu_protocol_rd_dev_type_parsing * @函数说明 解析读取设备类型 * @输入参数 rd:数据 * @输出参数 无 * @返回参数 无 *******************************************************************************/ static bool rtu_protocol_rd_dev_type_parsing(rtu_rd_s *rd) { uint16_t temp = 0; temp = rd->data[0]; temp <<= 8; temp += rd->data[1]; if(temp == (uint16_t)COLL_UART_ADDR) { download_work_stat = DOWNLOAD_COLL_REDAY_STAT; check_download_count = 0; return true; } return false; } /******************************************************************************* * @函数名称 rtu_protocol_rd_coll_stat_parsing * @函数说明 解析读取设备就绪状态 * @输入参数 rd:数据 * @输出参数 无 * @返回参数 无 *******************************************************************************/ static bool rtu_protocol_rd_coll_stat_parsing(rtu_rd_s *rd) { uint16_t temp = 0; temp = rd->data[0]; temp <<= 8; temp += rd->data[1]; if(temp == COLL_READY_STAT) { download_work_stat = DOWNLOAD_COLL_COUNT; coll_ready_stat = true; return true; } return false; } /******************************************************************************* * @函数名称 rtu_protocol_rd_coll_count_parsing * @函数说明 解析读取下挂主板数量 * @输入参数 rd:数据 * @输出参数 无 * @返回参数 无 *******************************************************************************/ static bool rtu_protocol_rd_coll_count_parsing(rtu_rd_s *rd) { uint16_t temp = 0; temp = rd->data[0]; temp <<= 8; temp += rd->data[1]; if(temp < COLL_MAX_COUNT) { coll_sw_count = temp; download_work_stat = DOWNLOAD_SW_STAT; vUser_server_set_coll_stat(coll_sw_count); return true; } return false; } /******************************************************************************* * @函数名称 rtu_protocol_rd_sw_stat_parsing * @函数说明 解析读取下挂主板开关量状态 * @输入参数 rd:数据 * @输出参数 无 * @返回参数 无 *******************************************************************************/ static bool rtu_protocol_rd_sw_stat_parsing(rtu_rd_s *rd) { uint32_t temp = 0; if(rd->dataSize != 4) { return false; } temp = rd->data[0]; temp <<= 8; temp += rd->data[1]; temp <<= 8; temp += rd->data[2]; temp <<= 8; temp += rd->data[3]; vUser_server_set_download_sw_stat(temp); return true; } /******************************************************************************* * @函数名称 rtu_protocol_rd_reg_parsing * @函数说明 解析读指令返回的数据 * @输入参数 rd:数据 * @输出参数 无 * @返回参数 无 *******************************************************************************/ static bool rtu_protocol_rd_reg_parsing(rtu_rd_s *rd) { bool stat = false; switch(download_work_stat) { case DOWNLOAD_DEV_TYPE:stat = rtu_protocol_rd_dev_type_parsing(rd);break; case DOWNLOAD_COLL_REDAY_STAT:stat = rtu_protocol_rd_coll_stat_parsing(rd);break; case DOWNLOAD_COLL_COUNT:stat = rtu_protocol_rd_coll_count_parsing(rd);break; case DOWNLOAD_SW_STAT:stat = rtu_protocol_rd_sw_stat_parsing(rd);break; default:break; } return stat; } /******************************************************************************* * @函数名称 rtu_rd_protocol_parsing * @函数说明 读指令返回解析 * @输入参数 rd:数据 * @输出参数 无 * @返回参数 无 *******************************************************************************/ static bool rtu_rd_protocol_parsing(rtu_rd_s *rd) { uint16_t crc = 0xFFFF; crc = GetCRC16((uint8_t *)rd, rd->dataSize + 3, crc); if(crc != rd->crc) { return false; } if(rd->func == CMD_RD_REG) { if(true == rtu_protocol_rd_reg_parsing(rd)) { return true; } } return false; } /******************************************************************************* * @函数名称 rtu_protocol_wr_reg_parsing * @函数说明 写指令数据解析 * @输入参数 rec:数据 * @输出参数 无 * @返回参数 无 *******************************************************************************/ static bool rtu_protocol_wr_reg_parsing(rtu_rec_s *rec) { uint16_t reg_addr = 0; reg_addr = rec->regAddr[0]; reg_addr <<= 8; reg_addr += rec->regAddr[1]; switch(reg_addr) { default:break; } return false; } /******************************************************************************* * @函数名称 rtu_rec_protocol_parsing * @函数说明 写指令返回解析 * @输入参数 rec:数据 * @输出参数 无 * @返回参数 无 *******************************************************************************/ static bool rtu_rec_protocol_parsing(rtu_rec_s *rec) { uint16_t crc = 0xFFFF; crc = GetCRC16((uint8_t *)rec, rec->dataSize + 4, crc); if(crc != rec->crc) { return false; } if(rec->func == CMD_WR_REG) { if(true == rtu_protocol_wr_reg_parsing(rec)) { return true; } } return false; } /******************************************************************************* * @函数名称 rtu_protocol_parsing * @函数说明 返回数据解析 * @输入参数 无 * @输出参数 无 * @返回参数 无 *******************************************************************************/ static bool rtu_protocol_parsing(void) { if(download_work.rtu_rec.addr != download_work.rtu_addr) { return false; } if(download_work.rtu_rec.func == CMD_RD_REG) { if(true == rtu_rd_protocol_parsing(&(download_work.rtu_rd))) { set_download_offline(false); } } else if(download_work.rtu_rec.func == CMD_WR_REG) { if(true == rtu_rec_protocol_parsing(&(download_work.rtu_rec))) { set_download_offline(false); } } else{ download_work_stat = DOWNLOAD_DEV_TYPE; } } /************************************************ * 函数名:set_dowload_offline * 描述 :设置从机通讯状态灯 * 输入 :stat:通讯状态 * 输出 :无 * 注意 :无 ************************************************/ static void set_download_offline(bool stat) { if(stat == true) { download_offline_timeout = 5000; if(download_offline_stat == false) { download_offline_stat = true; } } else{ if(download_offline_stat == true) { download_offline_stat = false; } } } /************************************************ * 函数名:vDowload_tick * 描述 :任务计时器 * 输入 :无 * 输出 :无 * 注意 :无 ************************************************/ void vDownload_tick(void) { if(download_delay_count > 0) { download_delay_count--; } if(download_offline_timeout > 0) { download_offline_timeout--; } else{ set_download_offline(true); } } /************************************************ * 函数名:vDownload_pro * 描述 :执行任务 * 输入 :无 * 输出 :无 * 注意 :无 ************************************************/ void vDownload_pro(void) { if(download_delay_count == 0) { download_delay_count = 500; if(check_download_count >= MAX_REPLAY_COUNT) { vUser_server_set_coll_stat(0); } rtu_protocol_sd_task(); } if(download_work.modbusRx_stat == true) { download_work.modbusRx_stat = false; rtu_protocol_parsing(); } } /******************************************************************************* * @函数名称 vUpload_init * @函数说明 初始化 * @输入参数 无 * @输出参数 无 * @返回参数 无 *******************************************************************************/ void vDownload_init(void) { user_uart_param_s param = { .baudrate = 115200, .wordlength = USART_WordLength_8b, .stopbit = USART_StopBits_1, .parity = USART_Parity_No, }; vUser_usart1_init(¶m); vUser_usart1_set_data_upload_func(downloadRx_receive); }