/****************************************************************************** * file Core/Src/position.c * author Changjiale * version 1.0.0 * date 18-Sep-2023 * brief This file provides all the position related operation functions. ****************************************************************************** * Attention * *

© COPYRIGHT(c) 2023 LandPower

* * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of WTOE nor the names of its contributors may be used to * endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ******************************************************************************/ /* Includes ------------------------------------------------------------------*/ #include "stdio.h" #include "string.h" #include "usart.h" #include "dev_config.h" #include "ADC_collect.h" #include "position.h" #include "flash_if.h" /* Private define ------------------------------------------------------------*/ #define POSITION_THRESHOLD_MIN 5 //5mv #define POSITION_THRESHOLD_MAX 995 //995mv #define POSITION_RX_TIMEOUT 500 //500ms #define POSITION_TX_DELAY 100 //两条命令之间需要间隔50ms以上 /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ position_buf_list_t position_buf_list_rx; position_ctrl_t position_ctrl; static position_data_t position_data; static _position_ctrl_t _position_ctrl; UART_HandleTypeDef *position_usart = &huart1; //定位模块使用串口 /* Private function prototypes -----------------------------------------------*/ /* Internal functions --------------------------------------------------------*/ /*发送命令消息函数*/ static HAL_StatusTypeDef _position_transmit(uint8_t *data, uint16_t len) { DBG(DBG_M_POSITION, "Send(%d:%d):\r\n", len, HAL_GetTick()); if (dbg_stat_get(DBG_M_POSITION)) { buf_print(data, POSITION_MIN(len, 32)); vty_print("\r\n"); } /* 开启串口空闲接收 */ HAL_UARTEx_ReceiveToIdle_DMA(position_usart, position_ctrl.dma_rx_buf, POSITION_CMD_BUF_LEN); osDelay(POSITION_TX_DELAY); /* 打开485Tx引脚 */ HAL_GPIO_WritePin(RS485_A_DE_GPIO_Port, RS485_A_DE_Pin, GPIO_PIN_SET); return HAL_UART_Transmit_DMA(position_usart, data, len); } /* 检查校验值 */ static uint8_t _position_pkt_chk(void) { uint16_t chk_len = _position_ctrl.cmd_buf_index - 2; //数据长度 uint8_t *buf = _position_ctrl.cmd_receive_buf + 1; uint8_t chk = 0; uint16_t i = 0; /* 设备进入复位状态后不再处理报文. */ if (IS_MONITOR_BIT_SET(system_init_flag, SYS_INIT_RESET)) { vty_print("@0\r\n"); /* 这里挂住线程是因为重启时如果有收包, 会导致收包出错, 从而让设备进入休眠状态. */ osDelay(portMAX_DELAY); return FALSE; } if (buf[3] != _position_ctrl.pkt_id) { vty_print("POSITION ID: %d %d\r\n", buf[3], _position_ctrl.pkt_id); return FALSE; } for (i = 0; i < chk_len; i++) { chk += buf[i]; } if (chk == buf[chk_len]) { return TRUE; } else { return FALSE; } } /* 收包函数 */ static HAL_StatusTypeDef _position_pkt_wait(void) { uint8_t *buf = NULL; uint8_t *pkt_head = &_position_ctrl.cmd_receive_buf[0]; uint16_t len = 0; uint16_t *pkt_len = (uint16_t*)(&_position_ctrl.cmd_receive_buf[1]); uint32_t notify_value = 0; uint32_t time = HAL_GetTick(); position_buf_list_t *buf_l = &position_buf_list_rx; while(1) { /* 收包超时. */ if ((HAL_GetTick() - time) > POSITION_RX_TIMEOUT) { return HAL_TIMEOUT; } /* 等待 DMA 空闲收包中断. */ notify_value = ulTaskNotifyTake(pdTRUE, POSITION_RX_TIMEOUT); if (0 == notify_value) { continue; } /* 遍历所有有效的 buf. */ while(buf_l->current != buf_l->valid) { buf = buf_l->buf[buf_l->current]; len = buf_l->buf_cnt[buf_l->current]; /* 更新 buf index. */ buf_l->current++; if (POSITION_BUF_LIST_LEN == buf_l->current) { buf_l->current = 0; } /* 收包总长大于报文长度 */ if (_position_ctrl.cmd_buf_index >= 3 && (_position_ctrl.cmd_buf_index + len) > (*pkt_len + 3)) { _position_ctrl.cmd_buf_index = 0; _position_ctrl.pkt_state = POSITION_PKT_NONE; /* 如果收包状态为完成, 舍弃之前的包后接收最新的包 */ if (POSITION_PKT_COMPLETE != _position_ctrl.pkt_state) { continue; } } /* 如果收包大于协议报文长度, 认为报文错误. */ if (_position_ctrl.cmd_buf_index + len > POSITION_CMD_BUF_LEN) { _position_ctrl.cmd_buf_index = 0; _position_ctrl.pkt_state = POSITION_PKT_NONE; continue; } memcpy(&_position_ctrl.cmd_receive_buf[_position_ctrl.cmd_buf_index], buf, len); _position_ctrl.cmd_buf_index += len; if (_position_ctrl.cmd_buf_index < 3) { continue; } if (POSITION_PKT_NONE == _position_ctrl.pkt_state) { if (*pkt_head != 0xa5 || (*pkt_len + 3 > POSITION_CMD_BUF_LEN)) { _position_ctrl.cmd_buf_index = 0; continue; } if (_position_ctrl.cmd_buf_index < *pkt_len + 3) { _position_ctrl.pkt_state = POSITION_PKT_HALF; continue; } } else if (POSITION_PKT_HALF == _position_ctrl.pkt_state) { if (_position_ctrl.cmd_buf_index < *pkt_len + 3) { continue; } } if (_position_pkt_chk()) { _position_ctrl.pkt_state = POSITION_PKT_COMPLETE; } else { _position_ctrl.cmd_buf_index = 0; _position_ctrl.pkt_state = POSITION_PKT_NONE; } } if (POSITION_PKT_COMPLETE == _position_ctrl.pkt_state) { DBG(DBG_M_POSITION, "Recv(%d):\r\n", _position_ctrl.cmd_buf_index); if (dbg_stat_get(DBG_M_POSITION)) { buf_print(_position_ctrl.cmd_receive_buf, POSITION_MIN(_position_ctrl.cmd_buf_index, 32)); vty_print("\r\n"); } _position_ctrl.cmd_buf_index = 0; _position_ctrl.pkt_state = POSITION_PKT_NONE; return HAL_OK; } } } /* 填充报文 */ static void _position_packed(uint8_t cmd, uint16_t len) { uint8_t *buf = _position_ctrl.cmd_send_buf; uint16_t pkt_len = len - 3; uint8_t *chk = buf + pkt_len + 2; uint8_t i = 0; buf[0] = 0xa5; // 报文头. *(uint16_t*)(&buf[1]) = pkt_len; // 报文长度. buf[3] = 0; // 设备 id, 单板为 0. buf[4] = _position_ctrl.pkt_id; // 报文序列号. buf[5] = cmd; // 报文命令字. /* 填充校验值 */ *chk = 0; for (i = 1; i <= pkt_len + 1; i++) { *chk += buf[i]; } } /* 命令0的收包处理函数 */ static HAL_StatusTypeDef _position_pkt_state(void) { uint8_t *buf = _position_ctrl.cmd_receive_buf; uint8_t *data = buf + POSITION_HEAD_LEN; if (buf[1] != 0x29 || buf[2] != 0 || buf[5] != POSITION_STATE) { return HAL_ERROR; } /* 新行波数据 */ if (IS_MONITOR_BIT_SET(*data, 2) || IS_MONITOR_BIT_SET(*data, 1)) { position_ctrl.new = TRUE; } data++; position_data.vol = *(uint16_t*)data; //设备电压 data += 2; position_data.temperature = *(uint16_t*)data; //设备温度 _position_ctrl.pkt_id++; return HAL_OK; } /* 命令1的收包处理函数 */ static HAL_StatusTypeDef _position_pkt_cfg(void) { uint8_t *buf = _position_ctrl.cmd_receive_buf; if (buf[1] != 0x05 || buf[2] != 0 || buf[5] != POSITION_CFG || buf[6] != 0) { return HAL_ERROR; } _position_ctrl.pkt_id++; return HAL_OK; } /* 命令2的收包处理函数 */ static HAL_StatusTypeDef _position_pkt_query(void) { uint8_t *buf = _position_ctrl.cmd_receive_buf; _position_data_t *data = (_position_data_t *)(buf + POSITION_HEAD_LEN); if (buf[1] != 0x34 || buf[2] != 0 || buf[5] != POSITION_QUERY) { return HAL_ERROR; } /* 新行波数据 */ if (position_data.wave_info.file_s != data->file_s || position_data.wave_info.file_ns != data->file_ns) { for (uint8_t i = 0; i < POSITION_SUM; i++) { if (((data->wave_info[i].s == data->file_s) && (data->wave_info[i].ns >= data->file_ns)) || (data->wave_info[i].s > data->file_s)) { position_data.wave_info.v[i] = data->wave_info[i].v; position_data.wave_info.s[i] = data->wave_info[i].s; position_data.wave_info.ns[i] = data->wave_info[i].ns; } else { position_data.wave_info.v[i] = 0.0; position_data.wave_info.s[i] = 0; position_data.wave_info.ns[i] = 0; } } position_data.wave_info.file_s = data->file_s; position_data.wave_info.file_ns = data->file_ns; position_data.wave_info.file_feq = data->file_feq; /* 写 FLASH */ position_write(&position_data); /* 写日志 */ flash_log_write(FLASH_LOG_TYPE_INFO, "\r%f %d %d\r %f %d %d\r %f %d %d\r %d %d %d\r\n", position_data.wave_info.v[0], position_data.wave_info.s[0], position_data.wave_info.ns[0], position_data.wave_info.v[1], position_data.wave_info.s[1], position_data.wave_info.ns[1], position_data.wave_info.v[2], position_data.wave_info.s[2], position_data.wave_info.ns[2], position_data.wave_info.file_s, position_data.wave_info.file_ns, position_data.wave_info.file_feq); } _position_ctrl.pkt_id++; return HAL_OK; } /* 命令3的收包处理函数 */ static int16_t _position_pkt_wave(uint8_t *data) { uint8_t *buf = _position_ctrl.cmd_receive_buf; uint8_t *wave_data = buf + POSITION_HEAD_LEN; uint16_t pkt_len = 0; if (buf[5] != POSITION_WAVE) { return -1; } pkt_len = *(uint16_t*)(&_position_ctrl.cmd_receive_buf[1]); _position_ctrl.pkt_id++; memcpy(data, wave_data, pkt_len - 4); return pkt_len - 4; } /* 发送命令0函数 */ static HAL_StatusTypeDef _position_state(void) { uint8_t *buf = _position_ctrl.cmd_send_buf; _position_packed(POSITION_STATE, POSITION_STATE_LEN); if (_position_transmit(buf, POSITION_STATE_LEN) != HAL_OK) { return HAL_ERROR; } if (_position_pkt_wait() == HAL_OK) { if (_position_pkt_state() != HAL_OK) { return HAL_ERROR; } } else { return HAL_TIMEOUT; } return HAL_OK; } /* 发送命令1函数 */ static HAL_StatusTypeDef _position_cfg(void) { uint8_t *buf = _position_ctrl.cmd_send_buf; uint8_t *data = buf + POSITION_HEAD_LEN; float threshold = 0; if (dev_config.wave_threshold < POSITION_THRESHOLD_MIN) { threshold = POSITION_THRESHOLD_MIN; } else if (dev_config.wave_threshold > POSITION_THRESHOLD_MAX) { threshold = POSITION_THRESHOLD_MAX; } else { threshold = (float)dev_config.wave_threshold; } memcpy(data, &threshold, sizeof(float)); data += 4; *(uint32_t*)data = 0; _position_packed(POSITION_CFG, POSITION_CFG_LEN); if (_position_transmit(buf, POSITION_CFG_LEN) != HAL_OK) { return HAL_ERROR; } if (_position_pkt_wait() == HAL_OK) { if (_position_pkt_cfg() != HAL_OK) { return HAL_ERROR; } } else { return HAL_TIMEOUT; } return HAL_OK; } /* 发送命令2函数 */ static HAL_StatusTypeDef _position_query(void) { uint8_t *buf = _position_ctrl.cmd_send_buf; _position_packed(POSITION_QUERY, POSITION_QUERY_LEN); if (_position_transmit(buf, POSITION_QUERY_LEN) != HAL_OK) { return HAL_ERROR; } if (_position_pkt_wait() == HAL_OK) { if (_position_pkt_query() != HAL_OK) { return HAL_ERROR; } } else { return HAL_TIMEOUT; } return HAL_OK; } static void _position_err(void) { if (position_ctrl.position_wave_up) { position_ctrl.position_wave_up = FALSE; } else if (position_ctrl.cfg) { position_ctrl.cfg = FALSE; } else if (position_ctrl.new) { position_ctrl.new = FALSE; } /* 串口通讯错误 */ else { position_ctrl.offline = TRUE; } position_ctrl.send_cnt = 0; position_ctrl.err_cnt++; } /* Interface functions -------------------------------------------------------*/ /* 故障定位轮询函数 */ HAL_StatusTypeDef position_start(void) { HAL_StatusTypeDef rv = HAL_OK; while(1) { if (position_ctrl.send_cnt > POSITION_ERR_MAX) { _position_err(); break; } if (position_ctrl.cfg) { rv = _position_cfg(); if (HAL_OK == rv) { position_ctrl.cfg = FALSE; } else { position_ctrl.send_cnt++; continue; } } rv = _position_state(); if (HAL_OK != rv) { position_ctrl.send_cnt++; continue; } if (position_ctrl.new) { rv = _position_query(); if (HAL_OK == rv) { position_ctrl.new = FALSE; } else { position_ctrl.send_cnt++; continue; } } else { break; } } position_ctrl.complete = TRUE; if (HAL_OK == rv) { position_ctrl.offline = FALSE; position_ctrl.send_cnt = 0; position_ctrl.err_cnt = 0; return HAL_OK; } else { return HAL_ERROR; } } /* 发送命令3函数 */ HAL_StatusTypeDef position_wave(uint8_t *wl_data, uint16_t index, uint16_t *data_len, uint32_t file_s, uint32_t file_ns) { if (position_ctrl.send_cnt > POSITION_ERR_MAX) { _position_err(); return HAL_ERROR; } uint8_t *buf = _position_ctrl.cmd_send_buf; int16_t ret = 0; uint8_t *data = buf + POSITION_HEAD_LEN; *(uint32_t*)data = file_s; data += 4; *(uint32_t*)data = file_ns; data += 4; *(uint32_t*)data = index * DEBUG_DATA_SIZE; _position_packed(POSITION_WAVE, POSITION_WAVE_LEN); if (_position_transmit(buf, POSITION_WAVE_LEN) != HAL_OK) { return HAL_ERROR; } if (_position_pkt_wait() == HAL_OK) { ret = _position_pkt_wave(wl_data); if (ret != -1) { *data_len = ret; return HAL_OK; } else { return HAL_BUSY; } } else { return HAL_TIMEOUT; } } /* 故障定位初始化 */ void position_init(void) { position_ctrl.complete = FALSE; position_ctrl.cfg = TRUE; if (dev_config.wave_threshold == 0) { dev_config.wave_threshold = POSITION_THRESHOLD_MAX; } position_read(position_id, &position_data); /* 重新初始化串口波特率为115200 */ HAL_UARTEx_ReceiveToIdle_DMA(position_usart, position_ctrl.dma_rx_buf, POSITION_CMD_BUF_LEN); MX_USART1_UART_ReInit(); /* 开启485芯片电源 */ HAL_GPIO_WritePin(SENSOR_EN_GPIO_Port, SENSOR_EN_Pin, GPIO_PIN_SET); }