200 lines
6.0 KiB
C
200 lines
6.0 KiB
C
|
/*
|
||
|
* @Author: mypx
|
||
|
* @Date: 2025-09-18 09:52:47
|
||
|
* @LastEditTime: 2025-09-26 13:22:46
|
||
|
* @LastEditors: mypx mypx_coder@163.com
|
||
|
* @Description:
|
||
|
*/
|
||
|
#include "mb_interface.h"
|
||
|
#include "et_log.h"
|
||
|
#include "etk_byte_conv.h"
|
||
|
#include "mb_command.h"
|
||
|
#include "user_config.h"
|
||
|
#include <string.h>
|
||
|
|
||
|
/**
|
||
|
* @brief Initialize Modbus interface module
|
||
|
* 初始化Modbus接口模块
|
||
|
*/
|
||
|
void mb_interface_init(void)
|
||
|
{
|
||
|
mb_command_t *mb = get_command_instance();
|
||
|
if (mb)
|
||
|
{
|
||
|
// Clear history data in the protocol cache
|
||
|
if (mb->input_lock != RT_NULL)
|
||
|
rt_mutex_take(mb->input_lock, RT_WAITING_FOREVER);
|
||
|
memset(&mb->input_regs[0], 0, sizeof(mb->input_regs));
|
||
|
/* set device model and firmware version
|
||
|
* - Device model: pack up to 4 ASCII chars from PM_DEVICE_MODE into two 16-bit registers.
|
||
|
* Each register stores two bytes: high byte = char[i], low byte = char[i+1].
|
||
|
* - Firmware version: pack major/minor into INPUT_REG_FW_VERSION_H (major in high byte,
|
||
|
* minor in low byte). Pack rev/build into INPUT_REG_FW_VERSION_L similarly.
|
||
|
*/
|
||
|
{
|
||
|
const char *m = PM_DEVICE_MODE;
|
||
|
uint16_t dm_hi = 0, dm_lo = 0;
|
||
|
uint8_t c0 = (m[0] != '\0') ? (uint8_t)m[0] : 0;
|
||
|
uint8_t c1 = (m[1] != '\0') ? (uint8_t)m[1] : 0;
|
||
|
uint8_t c2 = (m[2] != '\0') ? (uint8_t)m[2] : 0;
|
||
|
uint8_t c3 = (m[3] != '\0') ? (uint8_t)m[3] : 0;
|
||
|
dm_hi = (uint16_t)((c0 << 8) | c1);
|
||
|
dm_lo = (uint16_t)((c2 << 8) | c3);
|
||
|
mb->input_regs[INPUT_REG_DEVICE_MODEL_H] = dm_hi;
|
||
|
mb->input_regs[INPUT_REG_DEVICE_MODEL_L] = dm_lo;
|
||
|
|
||
|
uint16_t fw_hi = (uint16_t)(((uint16_t)(PM_DEVICE_VER_MAJOR & 0xFF) << 8)
|
||
|
| (uint16_t)(PM_DEVICE_VER_MINOR & 0xFF));
|
||
|
uint16_t fw_lo = (uint16_t)(((uint16_t)(PM_DEVICE_VER_REV & 0xFF) << 8)
|
||
|
| (uint16_t)(PM_DEVICE_VER_BUILD & 0xFF));
|
||
|
mb->input_regs[INPUT_REG_FW_VERSION_H] = fw_hi;
|
||
|
mb->input_regs[INPUT_REG_FW_VERSION_L] = fw_lo;
|
||
|
}
|
||
|
if (mb->input_lock != RT_NULL)
|
||
|
rt_mutex_release(mb->input_lock);
|
||
|
}
|
||
|
|
||
|
ET_INFO("Modbus interface initialized successfully");
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Write current temperature data
|
||
|
* 写入当前温度数据
|
||
|
*
|
||
|
* @param temp Temperature value to write (°C)
|
||
|
*/
|
||
|
void mb_write_current_temp(float temp)
|
||
|
{
|
||
|
// Check temperature alarm conditions
|
||
|
if (temp > 100.0f || temp < -10.0f)
|
||
|
{
|
||
|
mb_sync_exception_reg(PM_EXCEPTION_TEMPERATURE, true);
|
||
|
ET_WARN("Temperature out of range: %.2f°C", temp);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
mb_sync_exception_reg(PM_EXCEPTION_TEMPERATURE, false);
|
||
|
}
|
||
|
mb_sync_realtime_temp(temp);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Write current rotation data
|
||
|
* 写入当前旋光度数据
|
||
|
*
|
||
|
* @param rotation Rotation value to write (°)
|
||
|
*/
|
||
|
void mb_write_current_rotation(float rotation)
|
||
|
{
|
||
|
// Update protocol cache via sync helper (which converts and writes under lock)
|
||
|
mb_sync_realtime_rotation(rotation);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Write measurement result
|
||
|
* 写入测量结果
|
||
|
*
|
||
|
* @param mode Measurement mode (0-3)
|
||
|
* @param value Measurement value
|
||
|
* @param temp Temperature at measurement time (°C)
|
||
|
*/
|
||
|
void mb_write_measurement_result(uint8_t mode, float value, float temp)
|
||
|
{
|
||
|
// Update protocol cache via sync helper (atomic under lock)
|
||
|
mb_sync_result(mode, value, temp);
|
||
|
// mark measurement complete in running state
|
||
|
//mb_sync_running_state(PM_READY_STATE);
|
||
|
// Save to history (writes into protocol cache directly)
|
||
|
mb_save_to_history(value, temp);
|
||
|
ET_INFO("Measurement result updated: mode=%d, value=%.4f, temp=%.2f\u00b0C", mode, value, temp);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Get current target temperature
|
||
|
* 获取当前目标温度设置
|
||
|
*
|
||
|
* @return Target temperature value (°C)
|
||
|
*/
|
||
|
float mb_get_target_temp(void)
|
||
|
{
|
||
|
mb_command_t *mb = get_command_instance();
|
||
|
if (!mb)
|
||
|
return 0.0f;
|
||
|
// target temp is held in holding regs (regs array) at HOLD_REG_TARGET_TEMP_H/L
|
||
|
uint16_t h = mb->regs[HOLD_REG_TARGET_TEMP_H];
|
||
|
uint16_t l = mb->regs[HOLD_REG_TARGET_TEMP_L];
|
||
|
return et_mb_to_float_abcd(h, l);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Get current tube length setting
|
||
|
* 获取当前旋光管长度设置
|
||
|
*
|
||
|
* @return Tube length value (mm)
|
||
|
*/
|
||
|
float mb_get_tube_length(void)
|
||
|
{
|
||
|
mb_command_t *mb = get_command_instance();
|
||
|
if (!mb)
|
||
|
return 0.0f;
|
||
|
uint16_t h = mb->regs[HOLD_REG_TUBE_LEN];
|
||
|
|
||
|
return h;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Get current measurement mode
|
||
|
* 获取当前测量模式
|
||
|
*
|
||
|
* @return Measurement mode code (0-3)
|
||
|
*/
|
||
|
uint8_t mb_get_measure_mode(void)
|
||
|
{
|
||
|
mb_command_t *mb = get_command_instance();
|
||
|
if (!mb)
|
||
|
return 0;
|
||
|
return (uint8_t)(mb->regs[HOLD_REG_MEAS_MODE] & 0xFF);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Get current auto measurement count
|
||
|
* 获取当前自动测量次数设置
|
||
|
*
|
||
|
* @return Auto measurement count (1-255)
|
||
|
*/
|
||
|
uint8_t mb_get_auto_measure_count(void)
|
||
|
{
|
||
|
mb_command_t *mb = get_command_instance();
|
||
|
if (!mb)
|
||
|
return 0;
|
||
|
return (uint8_t)(mb->regs[HOLD_REG_AUTO_MEAS_CNT] & 0xFF);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Get current running state
|
||
|
* 获取当前运行状态
|
||
|
*
|
||
|
* @return Running state code
|
||
|
*/
|
||
|
PmRunningState mb_get_running_state(void)
|
||
|
{
|
||
|
mb_command_t *mb = get_command_instance();
|
||
|
if (!mb)
|
||
|
return PM_READY_STATE;
|
||
|
return (PmRunningState)(mb->input_regs[INPUT_REG_DEV_RUNNING_STATE] & 0xFF);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Check if measurement is complete
|
||
|
* 检查测量是否完成
|
||
|
*
|
||
|
* @return 1 if complete, 0 otherwise
|
||
|
*/
|
||
|
uint8_t mb_is_measure_complete(void)
|
||
|
{
|
||
|
mb_command_t *mb = get_command_instance();
|
||
|
if (!mb)
|
||
|
return 0;
|
||
|
return (uint8_t)(mb->input_regs[INPUT_REG_MEAS_DONE_FLAG] & 0xFF);
|
||
|
}
|