1627 lines
42 KiB
C
1627 lines
42 KiB
C
/**
|
||
* @file board.c
|
||
* @author xxx
|
||
* @date 2023-09-12 13:52:37
|
||
* @brief
|
||
* @copyright Copyright (c) 2023 by xxx, All Rights Reserved.
|
||
*/
|
||
#include <stdlib.h>
|
||
#include <math.h>
|
||
#include "usart.h"
|
||
|
||
#include "board.h"
|
||
#include "entity.h"
|
||
#include "delay.h"
|
||
|
||
#include "filter.h"
|
||
#include "bootload.h"
|
||
#include "bsp.h"
|
||
#include "uarts.h"
|
||
#include "convert.h"
|
||
#include "params.h"
|
||
|
||
void SystemClock_Config(void);
|
||
|
||
board_data_t board_data; ///< 板卡数据
|
||
static BOOL driver_init_flag = FALSE;
|
||
lcd_t *lcd = NULL;
|
||
static kalman_t temperature_km; ///< 温度滤波器
|
||
static __IO BOOL _lcd_init = FALSE;
|
||
static __IO int8_t _uart1_idel_sec_count = 0;
|
||
// 注:ARM架构要求所有的数据都必须按照4字节对齐,也就是说,数据的地址必须是4的倍数
|
||
__IO uint16_t dbg_assert_line __attribute__((at(APP_PRELOAD_AREA))); // 调试行号
|
||
__IO uint16_t app_preload_bootload_flag __attribute__((at(APP_PRELOAD_AREA + 2))); // 触发BOOTLOAD启动标志(在用户代码中接受代码文件)
|
||
__IO uint16_t app_preload_bootload_jump_flag __attribute__((at(APP_PRELOAD_AREA + 4))); // 触发BOOTLOAD跳转更新标志(在BOOTLOAD代码中更新用户代码)
|
||
/***************************************** 板卡初始化相关函数 *****************************************/
|
||
// dma发送回调函数
|
||
static void lcd_dma_tx_cb(spi_t *handle)
|
||
{
|
||
DBG_ASSERT(handle != NULL __DBG_LINE);
|
||
DMA_ClEAR_FLAG(handle->dma, 5, handle->tx_dma_ok);
|
||
}
|
||
|
||
/**
|
||
* @brief LCD设计
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void lcd_design(void)
|
||
{
|
||
}
|
||
|
||
/**
|
||
* @brief LCD初始化
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void lcd_init(void)
|
||
{
|
||
if (_lcd_init == TRUE)
|
||
{
|
||
return;
|
||
}
|
||
|
||
// 设置功能引脚
|
||
GPIO_SET_OUTPUT(LCD_PWR_GPIO_Port, LCD_PWR_Pin);
|
||
GPIO_SET_OUTPUT(LCD_CS_GPIO_Port, LCD_CS_Pin);
|
||
GPIO_SET_OUTPUT(LCD_DISP_GPIO_Port, LCD_DISP_Pin);
|
||
|
||
// 打开LCD电源
|
||
LCD_POWER_ON();
|
||
|
||
// 创建LCD对象
|
||
if (lcd == NULL)
|
||
{
|
||
// 初始化LCD相关的GPIO
|
||
spi_gpio_group_t gpios;
|
||
gpios.cs = gpio_create(LCD_CS_GPIO_Port, LCD_CS_Pin);
|
||
gpios.mosi = gpio_create(LCD_MOSI_GPIO_Port, LCD_MOSI_Pin);
|
||
gpios.sck = gpio_create(LCD_SCK_GPIO_Port, LCD_SCK_Pin);
|
||
gpios.rst = gpio_create(NULL, 0);
|
||
gpios.rdy = gpio_create(NULL, 0);
|
||
gpios.miso = gpio_create(NULL, 0);
|
||
|
||
// 初始化LCD相关的SPI
|
||
lcd_info_t info = {
|
||
.type = LCD_SHARP, // 设置LCD类型为ST7525
|
||
.spi = spi_create(SPI_TYPE_LCD, gpios, 0), // 创建SPI总线
|
||
.dir = W_LCD, // 设置显示方向为横向
|
||
.width = COL_DOT_MAX_400, // 设置LCD最大宽度为400列
|
||
.height = LIN_DOT_MAX_240, // 设置LCD最大高度为240行
|
||
.retransmission_count = 3, // 设置重传次数为3次
|
||
.disp = gpio_create(LCD_DISP_GPIO_Port, LCD_DISP_Pin),
|
||
};
|
||
info.spi->interface.hardware_enable(info.spi, LCD_SPI);
|
||
info.spi->interface.dma_enable(info.spi, LCD_DMA, 0xffffffff, NULL, LCD_DMA_TX_CHANNEL, lcd_dma_tx_cb);
|
||
|
||
// 创建LCD对象
|
||
lcd = lcd_create(info);
|
||
DBG_ASSERT(lcd != NULL __DBG_LINE);
|
||
}
|
||
|
||
// 初始化LCD驱动
|
||
lcd->driver.init(lcd);
|
||
_lcd_init = TRUE;
|
||
}
|
||
|
||
/**
|
||
* @brief LCD反初始化
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void lcd_dinit(void)
|
||
{
|
||
if (_lcd_init == FALSE)
|
||
{
|
||
return;
|
||
}
|
||
|
||
// 关闭LCD显示
|
||
if (lcd != NULL)
|
||
{
|
||
gui_close();
|
||
}
|
||
// GPS3000 led 和 lcd 在一个屏幕上 不能关闭LCD电源
|
||
|
||
// LCD_POWER_OFF();
|
||
// 反初始化LCD相关引脚,降低板卡功耗
|
||
// GPIO_SET_ANALOG(LCD_PWR_GPIO_Port, LCD_PWR_Pin);
|
||
|
||
GPIO_SET_ANALOG(LCD_CS_GPIO_Port, LCD_CS_Pin);
|
||
GPIO_SET_ANALOG(LCD_DISP_GPIO_Port, LCD_DISP_Pin);
|
||
|
||
_lcd_init = FALSE;
|
||
}
|
||
|
||
/**
|
||
* @brief 功耗引脚初始化
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void driver_init(void)
|
||
{
|
||
// 标志位检查:driver_init_flag = TRUE,表示已经初始化
|
||
if (driver_init_flag == TRUE)
|
||
{
|
||
return;
|
||
}
|
||
driver_init_flag = TRUE;
|
||
|
||
pdctrl_run(); // 控制输出使能
|
||
}
|
||
|
||
/**
|
||
* @brief 功耗引脚反初始化
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void driver_dinit(void)
|
||
{
|
||
// 标志位检查:driver_init_flag = FALSE,表示已经反初始化
|
||
if (driver_init_flag == FALSE)
|
||
{
|
||
return;
|
||
}
|
||
driver_init_flag = FALSE;
|
||
|
||
pdctrl_stop(); // 控制输出禁用
|
||
}
|
||
|
||
/**
|
||
* @brief 板卡初始化
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void board_init(void)
|
||
{
|
||
VIP_H_EN_DISABLE(); // IP禁用,满足条件时才使能
|
||
system_clock_read(); // 读取系统时钟配置
|
||
|
||
// 过采样提高精度
|
||
adc_init(ADCS_1, ADC1, DMA1, LL_DMA_CHANNEL_1, 400,
|
||
IN5 | IN6 | IN7 | IN8 | IN9 | IN11 | IN12 | IN13 | IN14 | IN16 | INTEMP | INVREF); // 初始化ADC1通道,默认采集AD
|
||
leds_init(); // 初始化LED
|
||
rtc_init(TIME_1US); // 初始化RTC
|
||
eeprom_m95_init(M95_1); // 初始化SPI EEPROM1
|
||
eeprom_m95_init(M95_2); // 初始化SPI EEPROM2
|
||
eeprom_fm24_init(); // 初始化 IIC EEPROM
|
||
eeprom_lc02b_init(TIME_1US); // 初始化 IIC EEPROM
|
||
sht40_init(TIME_1US); // 初始化SHT40
|
||
dac161p997_init(TIME_1US); // 初始化DAC161
|
||
kalman_init(&temperature_km, 0.2f); // 温度突变的精度为0.2
|
||
}
|
||
|
||
void board_dinit(void)
|
||
{
|
||
adc_dinit(ADCS_1); // ADC反初始化
|
||
DISABLE_TIM(TASK_TIM);
|
||
DISABLE_TIM(MODE_TIM);
|
||
driver_dinit();
|
||
|
||
rtc_dinit(); // RTC反初始化
|
||
eeprom_m95_dinit(M95_1);
|
||
eeprom_m95_dinit(M95_2);
|
||
eeprom_fm24_dinit();
|
||
lcd_dinit(); // LCD screen Deinitialization
|
||
}
|
||
|
||
// 定时器周期
|
||
void timer_cycle_update(void)
|
||
{
|
||
// 定时器周期
|
||
rt_data.time_cycle.task = TIM_CYCLE(TASK_TIM);
|
||
rt_data.time_cycle.mode = TIM_CYCLE(MODE_TIM);
|
||
rt_data.time_cycle.mode_gathe = TIM_CYCLE(MODE_GATHE_TIM);
|
||
rt_data.time_cycle.hart = TIM_CYCLE(HART_TIM);
|
||
}
|
||
/**
|
||
* @brief 设置随机数种子
|
||
*
|
||
* 使用 get_seed() 函数获取的种子值来初始化随机数生成器的种子。
|
||
*
|
||
* @note 此函数应当在需要生成随机数之前被调用一次,以确保随机数的随机性。
|
||
*/
|
||
void board_srand(void)
|
||
{
|
||
srand(get_seed());
|
||
}
|
||
|
||
void dbg_assert_cb(uint16_t line)
|
||
{
|
||
dbg_assert_line = line;
|
||
sys_soft_reset(); // 复位行号保存在HART设备属性中的message
|
||
}
|
||
|
||
static uint32_t get_ahb_div(uint32_t sysclk)
|
||
{
|
||
if (sysclk == SYSTEM_CLOCK_CHANGE)
|
||
{
|
||
return LL_RCC_SYSCLK_DIV_1;
|
||
}
|
||
else
|
||
{
|
||
// 默认值或错误处理
|
||
return LL_RCC_SYSCLK_DIV_2;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 设置TIM的Hart输出
|
||
*
|
||
* 本函数用于设置TIM的Hart输出相关配置。
|
||
*
|
||
* @return 无返回值
|
||
*/
|
||
void set_tim_hart_out(uint32_t sysclk)
|
||
{
|
||
uint8_t arr = sysclk / (1000 * SYSTEM_HART_CLOCK);
|
||
LL_TIM_SetPrescaler(HART_OUT_TIM, 0);
|
||
LL_TIM_SetAutoReload(HART_OUT_TIM, arr - 1);
|
||
PWM_SET_COMPARE(HART_OUT_TIM, HART_OUT_TIM_CHANNEL, arr * 0.5f);
|
||
}
|
||
|
||
/**
|
||
* @brief 更新定时器的预分频值和自动重装载值以保持中断时间不变
|
||
* @param tim 定时器实例
|
||
* @param cfg 时钟配置结构体,包含系统时钟频率和最后一次的系统时钟频率
|
||
*/
|
||
static void update_timer_prescaler(TIM_TypeDef *tim, const clock_config_t *const cfg)
|
||
{
|
||
uint32_t hclk = cfg->sysclk / 1000000;
|
||
uint32_t prescaler = (hclk * 100) - 1;
|
||
LL_TIM_SetPrescaler(tim, prescaler);
|
||
}
|
||
|
||
/**
|
||
* @brief 系统时钟配置低频
|
||
* @return {*}
|
||
* @note 4M 默认使用系统时钟配置低频
|
||
*/
|
||
void system_clock_config_low(void)
|
||
{
|
||
#if LCD_DESIGN == FALSE
|
||
// 如果系统核心时钟与原始时钟配置中的系统时钟相同,则直接返回
|
||
if (SystemCoreClock == get_original_clock_config()->sysclk)
|
||
{
|
||
return;
|
||
}
|
||
|
||
// 恢复系统时钟
|
||
restore_system_clock();
|
||
|
||
// 更新定时器的预分频值和自动重装载值
|
||
LL_TIM_SetPrescaler(TIME_1US, (get_original_clock_config()->sysclk / 1000000));
|
||
update_timer_prescaler(TASK_TIM, get_original_clock_config());
|
||
update_timer_prescaler(MODE_TIM, get_original_clock_config());
|
||
update_timer_prescaler(HART_TIM, get_original_clock_config());
|
||
update_timer_prescaler(MODE_GATHE_TIM, get_original_clock_config());
|
||
|
||
set_tim_hart_out(get_original_clock_config()->sysclk);
|
||
|
||
MX_USART1_UART_Init();
|
||
uart_set_baudrate(HART_UART1, get_original_clock_config()->sysclk, HART_UART1_BAUDRATE);
|
||
MX_UART5_Init();
|
||
uart_set_baudrate(HART_UART2, get_original_clock_config()->sysclk, HART_UART2_BAUDRATE);
|
||
#endif
|
||
}
|
||
|
||
/**
|
||
* @brief 系统时钟配置高频
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void system_clock_config_high(void)
|
||
{
|
||
if (SystemCoreClock == SYSTEM_CLOCK_CHANGE)
|
||
{
|
||
return;
|
||
}
|
||
|
||
if (get_current_by_resistance() < SYSTEM_CLOCK_HIGHT_CURRENT_MIN)
|
||
{
|
||
return;
|
||
}
|
||
// 创建一个新的时钟配置
|
||
clock_config_t new_config = {
|
||
.pll_source = LL_RCC_PLLSOURCE_HSE,
|
||
.pll_m = LL_RCC_PLLM_DIV_2,
|
||
.pll_n = 12,
|
||
.pll_r = LL_RCC_PLLR_DIV_6,
|
||
.ahb_div = get_ahb_div(SYSTEM_CLOCK_CHANGE),
|
||
.apb1_div = LL_RCC_APB1_DIV_1,
|
||
.apb2_div = LL_RCC_APB2_DIV_1,
|
||
.sysclk = SYSTEM_CLOCK_CHANGE,
|
||
};
|
||
change_system_clock(&new_config);
|
||
|
||
// 更新定时器的预分频值和自动重装载值
|
||
LL_TIM_SetPrescaler(TIME_1US, (new_config.sysclk / 1000000));
|
||
update_timer_prescaler(TASK_TIM, &new_config);
|
||
update_timer_prescaler(MODE_TIM, &new_config);
|
||
update_timer_prescaler(HART_TIM, &new_config);
|
||
update_timer_prescaler(MODE_GATHE_TIM, &new_config);
|
||
|
||
set_tim_hart_out(new_config.sysclk);
|
||
|
||
MX_USART1_UART_Init();
|
||
uart_set_baudrate(HART_UART1, new_config.sysclk, HART_UART1_BAUDRATE);
|
||
MX_UART5_Init();
|
||
uart_set_baudrate(HART_UART2, new_config.sysclk, HART_UART2_BAUDRATE);
|
||
}
|
||
|
||
/***************************************** 板卡LCD操作相关函数 *****************************************/
|
||
|
||
/**
|
||
* @brief 判断GUI系统是否可以工作
|
||
*
|
||
* 根据当前电阻值判断GUI系统是否可以正常工作。
|
||
*
|
||
* @return 返回BOOL类型,如果电阻值大于或等于系统正常工作所需的最小电流值,则返回TRUE;否则返回FALSE。
|
||
*/
|
||
BOOL gui_can_work(void)
|
||
{
|
||
if (get_current_by_resistance() < GUI_RUN_CURRENT)
|
||
{
|
||
return FALSE;
|
||
}
|
||
else
|
||
{
|
||
return TRUE;
|
||
}
|
||
}
|
||
/**
|
||
* @brief 判断 GUI 是否处于空闲状态
|
||
*
|
||
* 检查 GUI 是否处于空闲状态。如果 GUI 空闲,则返回 TRUE;否则返回 FALSE。
|
||
*
|
||
* @return 如果 GUI 空闲,则返回 TRUE;否则返回 FALSE
|
||
*/
|
||
BOOL gui_is_idle(void)
|
||
{
|
||
return lcd->driver.idel;
|
||
}
|
||
/**
|
||
* @brief LCD刷新
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void gui_flush(void)
|
||
{
|
||
if (gui_is_idle() == TRUE)
|
||
{
|
||
lcd->driver.flush(lcd);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief LCD刷新并清除缓存
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void gui_flush_Clear(void)
|
||
{
|
||
if (gui_can_work() == TRUE)
|
||
{
|
||
if (gui_is_idle() == TRUE)
|
||
{
|
||
lcd->driver.flush_clear(lcd);
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief LCD全屏清除
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void gui_clr(void)
|
||
{
|
||
lcd->driver.clear(lcd);
|
||
}
|
||
|
||
/**
|
||
* @brief LCD设置清屏标志
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void gui_set_clear_flag(void)
|
||
{
|
||
lcd->driver.set_clear_flag(lcd);
|
||
}
|
||
|
||
/**
|
||
* @brief LCD获取清屏标志
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
BOOL gui_get_clear_flag(void)
|
||
{
|
||
return lcd->driver.get_clear_flag(lcd);
|
||
}
|
||
|
||
/**
|
||
* @brief LCD全屏填充
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void gui_full(void)
|
||
{
|
||
lcd->driver.full_fill(lcd, BLACK);
|
||
}
|
||
|
||
/**
|
||
* @brief LCD启动
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void gui_open()
|
||
{
|
||
lcd->driver.onoff(lcd, TRUE);
|
||
}
|
||
|
||
/**
|
||
* @brief LCD关闭
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void gui_close()
|
||
{
|
||
lcd->driver.onoff(lcd, FALSE);
|
||
}
|
||
|
||
/**
|
||
* @brief 读取 Flash 存储器数据
|
||
*
|
||
* 从指定的 Flash 地址开始,读取指定长度的数据到提供的缓冲区中。
|
||
*
|
||
* @param address Flash 存储器的起始地址
|
||
* @param data 用于存储读取数据的缓冲区指针
|
||
* @param length 要读取的数据长度(以字节为单位)
|
||
*
|
||
* @return 如果读取成功,返回 TRUE;否则返回 FALSE
|
||
*/
|
||
BOOL flash_read(uint32_t address, uint8_t *data, uint16_t length)
|
||
{
|
||
ErrorStatus rst = ERROR;
|
||
rst = LL_FLASH_Read(address, data, length);
|
||
return rst == SUCCESS ? TRUE : FALSE;
|
||
}
|
||
|
||
/**
|
||
* @brief 写入 Flash 存储器数据
|
||
*
|
||
* 将提供的数据写入 Flash 存储器的指定地址。
|
||
*
|
||
* @param address Flash 存储器的起始地址
|
||
* @param data 要写入的数据的缓冲区指针
|
||
* @param length 要写入的数据长度(以字节为单位)
|
||
*
|
||
* @return 如果写入成功,返回 TRUE;否则返回 FALSE
|
||
*/
|
||
BOOL flash_write(uint32_t address, const uint8_t *data, uint16_t length)
|
||
{
|
||
ErrorStatus rst = ERROR;
|
||
LL_FLASH_Unlock(FLASH);
|
||
rst = LL_FLASH_Program(address, (uint8_t *)data, length);
|
||
LL_FLASH_Lock(FLASH);
|
||
return rst == SUCCESS ? TRUE : FALSE;
|
||
}
|
||
|
||
/**
|
||
* @brief 擦除指定页的 Flash
|
||
*
|
||
* 擦除 Flash 中的指定页。
|
||
*
|
||
* @param page 要擦除的 Flash 页号
|
||
*
|
||
* @return 如果擦除成功,返回 TRUE;否则返回 FALSE
|
||
*/
|
||
BOOL flash_erase_page(uint32_t page)
|
||
{
|
||
ErrorStatus rst = ERROR;
|
||
LL_FLASH_Unlock(FLASH);
|
||
rst = LL_FLASH_ErasePage(page);
|
||
LL_FLASH_Lock(FLASH);
|
||
return rst == SUCCESS ? TRUE : FALSE;
|
||
}
|
||
|
||
/**
|
||
* @brief 设置扫描方向
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void gui_set_scandir(uint8_t dir)
|
||
{
|
||
lcd->driver.set_dir(lcd, dir);
|
||
}
|
||
|
||
/***************************************** 板卡参数相关函数 *****************************************/
|
||
/**
|
||
* @brief 根据目标行程计算DAC输出理论值
|
||
* @param {float32} output - 目标行程(百分比)
|
||
* @return {uint16_t} DAC输出理论值
|
||
* @note 计算公式如下:
|
||
* > (Osh-Osl)/(Ish-Isl)=(Ov-Osl)/(Iv-Isl) <p>
|
||
* > Ov=[(Osh-Osl)*(Iv-Isl)/(Ish-Isl)]+Osl <p>
|
||
*/
|
||
uint16_t get_dac(float32 output)
|
||
{
|
||
return ((udevice.output_max - udevice.output_min) * (output - 0) / (100 - 0)) + udevice.output_min;
|
||
}
|
||
|
||
/**
|
||
* @brief PWM输出阀位百分比
|
||
* @param {float32} position_per-阀位百分比
|
||
* @return {*}
|
||
* @note 阀位反馈输出, 0%输出4.00mA, 100.0%输出20.00mA
|
||
*> 0% - 4.0mA <p>
|
||
*> 10% - 5.6mA <p>
|
||
*> 20% - 7.2mA <p>
|
||
*> 30% - 8.8mA <p>
|
||
*> 40% - 10.4mA <p>
|
||
*> 50% - 12.0mA <p>
|
||
*> 55% - 12.8mA <p>
|
||
*> 60% - 13.6mA <p>
|
||
*> 70% - 15.2mA <p>
|
||
*> 80% - 16.8mA <p>
|
||
*> 90% - 18.4mA <p>
|
||
*> 100% - 20.0mA <p>
|
||
*/
|
||
void pwm_output_position(float32 position_per)
|
||
{
|
||
uint16_t adc = 0;
|
||
static float32 f_span = 0xffff;
|
||
float32 f = 0.0f;
|
||
calib_param_t *p = (calib_param_t *)&calib_param[CALIBPARA_VIP];
|
||
DBG_ASSERT(p != NULL __DBG_LINE);
|
||
if (p->is_calibration == IS_CALIBRATION)
|
||
{
|
||
return;
|
||
}
|
||
|
||
if (p->offset != udevice.output_offset || p->span != udevice.output_span || f_span == 0xffff)
|
||
{
|
||
if (f_span != 0xffff)
|
||
{
|
||
// 重新计算斜率
|
||
calib_param_calculate(CALIBPARA_VIP, udevice.output_offset, udevice.output_span, p->min, p->max);
|
||
}
|
||
|
||
f_span = (float32)(udevice.output_span) * 3 / (float32)(ABS(p->original_adc_value[1] - p->original_adc_value[0]));
|
||
}
|
||
|
||
// 计算输出电流
|
||
{
|
||
adc = calib_param[CALIBPARA_VIP].original_adc_value[0] +
|
||
(calib_param[CALIBPARA_VIP].original_adc_value[1] - calib_param[CALIBPARA_VIP].original_adc_value[0]) * position_per / 100;
|
||
f = p->min + adc_linear_conversion(CALIBPARA_VIP, adc);
|
||
|
||
if (f < 0)
|
||
{
|
||
f = 0.0f;
|
||
}
|
||
else
|
||
{
|
||
float32 tmp = CURRENT_PERCENT(f) * f_span * (p->max - p->min);
|
||
tmp = floorf(tmp * 100.f) / 100.f; // 保留小数点后两位小数
|
||
f -= tmp;
|
||
}
|
||
}
|
||
|
||
rt_data.output_current = floorf(f * 1000.f) / 1000.f;
|
||
dac161p997_output_current(rt_data.output_current);
|
||
}
|
||
|
||
/**
|
||
* @brief 校准4-20mA输入电流
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void calib_loop(void)
|
||
{
|
||
#define MA4 (LOOP_CURRENT_MIN * 1000)
|
||
#define MA20 (LOOP_CURRENT_MAX * 1000)
|
||
if (calib_param[CALIBPARA_LOOP].original_adc_value[0] == calib_param[CALIBPARA_LOOP].original_adc_value[1] ||
|
||
ABS(calib_param[CALIBPARA_LOOP].original_adc_value[1] - calib_param[CALIBPARA_LOOP].original_adc_value[0]) < 1000)
|
||
{
|
||
return;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 校准压力表
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void calib_kpa(void)
|
||
{
|
||
// uint16_t ma = 0, adc = 0;
|
||
// float32 f;
|
||
// // 计算校准参数
|
||
// ma = board_cache_set_value[BOARD_CACHE_2] - board_cache_set_value[BOARD_CACHE_1];
|
||
// adc = board_cache[BOARD_CACHE_2] - board_cache[BOARD_CACHE_1];
|
||
// f = ma;
|
||
// f = f / adc;
|
||
// calib_param[CALIBPARA_PS].value[0] = f;
|
||
// f = f * board_cache[BOARD_CACHE_2];
|
||
// calib_param[CALIBPARA_PS].value[1] = board_cache_set_value[BOARD_CACHE_2] - f;
|
||
|
||
// calib_param[CALIBPARA_PSB].value[0] = calib_param[CALIBPARA_PS].value[0];
|
||
// calib_param[CALIBPARA_PSB].value[1] = calib_param[CALIBPARA_PS].value[1];
|
||
|
||
// calib_param[CALIBPARA_PB].value[0] = calib_param[CALIBPARA_PS].value[0];
|
||
// calib_param[CALIBPARA_PB].value[1] = calib_param[CALIBPARA_PS].value[1];
|
||
}
|
||
|
||
/**
|
||
* @brief 校准4-20mA输出电流
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void calib_pwm_out(void)
|
||
{
|
||
// 计算校准参数
|
||
// float32 mA4 = 400;
|
||
// float32 mA20 = 2000;
|
||
// float32 TDuty4 = board_cache[BOARD_CACHE_1];
|
||
// float32 TDuty20 = board_cache[BOARD_CACHE_2];
|
||
// calib_param[CALIBPARA_VIP].value[0] = (TDuty20 - TDuty4) / (mA20 - mA4);
|
||
// calib_param[CALIBPARA_VIP].value[1] = TDuty20 - calib_param[CALIBPARA_VIP].value[0] * mA20;
|
||
}
|
||
/**
|
||
* @brief 校准阀门位置参数,电压转换成%(放大10倍,1位小数)
|
||
* @return {*}
|
||
* @note 计算公式如下:
|
||
* > k = (y2-y1) / (x2-x1) <p>
|
||
* > m = y2 - k * x2 <p>
|
||
*/
|
||
void calib_parapos_perent(void)
|
||
{
|
||
// 直行程位置反馈
|
||
{
|
||
calib_param[CALIBPARA_PSB].original_adc_value[0] = udevice.pos0_travel_vol;
|
||
calib_param[CALIBPARA_PSB].original_adc_value[1] = udevice.pos100_travel_vol;
|
||
calib_param_calculate(CALIBPARA_PSB, 0, 0, 0, 100);
|
||
}
|
||
|
||
// 小回路
|
||
{
|
||
calib_param[CALIBPARA_IPSB].original_adc_value[0] = udevice.pos0_minor_vol;
|
||
calib_param[CALIBPARA_IPSB].original_adc_value[1] = udevice.pos100_minor_vol;
|
||
calib_param_calculate(CALIBPARA_IPSB, 0, 0, 0, 100);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 获取当前实际行程ADC值
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
uint16_t get_actual_travel_adc(void)
|
||
{
|
||
adc_raw[ADC_PSB_CHANNEL] = adc_result_average(ADCS_1, ADC_PSB_CHANNEL);
|
||
return adc_raw[ADC_PSB_CHANNEL];
|
||
}
|
||
|
||
/**
|
||
* @brief 获取当前实际行程百分比
|
||
* @param {uint16_t} adc
|
||
* @return {*}
|
||
* @note 保留小数点后一位
|
||
*/
|
||
float32 actual_adc_convert_percent(uint16_t adc)
|
||
{
|
||
float32 f = adc_linear_conversion(CALIBPARA_PSB, adc);
|
||
|
||
if (f < 0)
|
||
{
|
||
f = 0;
|
||
}
|
||
if (f > 100)
|
||
{
|
||
f = 100;
|
||
}
|
||
|
||
return floorf(f * 100.f) / 100.f;
|
||
}
|
||
|
||
/**
|
||
* @brief 获取当前实际行程
|
||
* @param {uint8_t} filter 1:平均 2:中值
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
float32 get_actual_travel(filter_e filter)
|
||
{
|
||
uint16_t raw = 0;
|
||
|
||
// 读取位置反馈ADC值
|
||
if (filter == FILTER_AVERAGE)
|
||
{
|
||
raw = adc_result_average(ADCS_1, ADC_PSB_CHANNEL);
|
||
}
|
||
else if (filter == FILTER_MEDIAN)
|
||
{
|
||
raw = adc_result_median(ADCS_1, ADC_PSB_CHANNEL);
|
||
}
|
||
else if (filter == FILTER_MEDIAN_AVERAGE)
|
||
{
|
||
raw = adc_result_median_average(ADCS_1, ADC_PSB_CHANNEL);
|
||
}
|
||
else
|
||
{
|
||
raw = adc_result_average(ADCS_1, ADC_PSB_CHANNEL);
|
||
}
|
||
|
||
adc_raw[ADC_PSB_CHANNEL] = raw;
|
||
return actual_adc_convert_percent(raw);
|
||
}
|
||
|
||
/**
|
||
* @brief 获取电流,通过电阻计算
|
||
* @return {*}
|
||
* @note 获取当前电流通过AD采集值,计算电流值
|
||
*/
|
||
float32 get_current_by_resistance(void)
|
||
{
|
||
float32 tmp = 0.0f;
|
||
tmp = loop_current_convert(adc_result_average(ADCS_1, ADC_LOOP_CHANNEL));
|
||
return tmp;
|
||
}
|
||
|
||
/**
|
||
* @brief 获取当前回路电流
|
||
* @return {float32} 回路电流值
|
||
* @note
|
||
*/
|
||
float32 get_current(filter_e filter)
|
||
{
|
||
static float32 f_span = 0xffff;
|
||
float32 f = 0.0f;
|
||
calib_param_t *p = (calib_param_t *)&calib_param[CALIBPARA_LOOP];
|
||
// 读取回路电流ADC值
|
||
if (filter == FILTER_AVERAGE)
|
||
{
|
||
adc_raw[ADC_LOOP_CHANNEL] = adc_result_average(ADCS_1, ADC_LOOP_CHANNEL);
|
||
}
|
||
else if (filter == FILTER_MEDIAN)
|
||
{
|
||
adc_raw[ADC_LOOP_CHANNEL] = adc_result_median(ADCS_1, ADC_LOOP_CHANNEL);
|
||
}
|
||
else if (filter == FILTER_MEDIAN_AVERAGE)
|
||
{
|
||
adc_raw[ADC_LOOP_CHANNEL] = adc_result_median_average(ADCS_1, ADC_LOOP_CHANNEL);
|
||
}
|
||
else
|
||
{
|
||
adc_raw[ADC_LOOP_CHANNEL] = adc_result_average(ADCS_1, ADC_LOOP_CHANNEL);
|
||
}
|
||
|
||
if (p->offset != udevice.input_offset || p->span != udevice.input_span || f_span == 0xffff)
|
||
{
|
||
if (f_span != 0xffff)
|
||
{
|
||
// 重新计算斜率
|
||
calib_param_calculate(CALIBPARA_LOOP, udevice.input_offset, udevice.input_span, p->min, p->max);
|
||
}
|
||
|
||
f_span = (float32)(udevice.input_span) * 3 / (float32)(ABS(p->original_adc_value[1] - p->original_adc_value[0]));
|
||
}
|
||
|
||
// 计算回路电流
|
||
{
|
||
f = p->min + adc_linear_conversion(CALIBPARA_LOOP, adc_raw[ADC_LOOP_CHANNEL]);
|
||
|
||
if (f < 0)
|
||
{
|
||
f = 0.0f;
|
||
}
|
||
else
|
||
{
|
||
float32 tmp = CURRENT_PERCENT(f) * f_span * (p->max - p->min);
|
||
tmp = floorf(tmp * 100.f) / 100.f; // 保留小数点后两位小数
|
||
f -= tmp;
|
||
}
|
||
}
|
||
return floorf(f * 1000.f) / 1000.f;
|
||
}
|
||
|
||
/**
|
||
* @brief 获取当前回路电流,保留小数点后1位
|
||
* @param {float32} current
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
float32 get_current_deal(float32 current)
|
||
{
|
||
// 判断current小数点后第二位是否大于5
|
||
if ((uint16_t)(current * 100) % 10 >= 5)
|
||
{
|
||
return (uint16_t)(current * 10) * 0.1f + 0.1f;
|
||
}
|
||
else
|
||
{
|
||
return (uint16_t)(current * 100) * 0.01f;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 获取当前温度值
|
||
* @return {float32} 温度值
|
||
* @note
|
||
*/
|
||
float32 get_temperature(void)
|
||
{
|
||
float32 tmp = 0.0f;
|
||
// 采集ADC原始数据
|
||
adc_raw[ADC_NTC_CHANNEL] = adc_result_average(ADCS_1, ADC_NTC_CHANNEL);
|
||
|
||
// 使用NTC算法计算温度值
|
||
tmp = ntc_get_temp(adc_raw[ADC_NTC_CHANNEL]).f;
|
||
// tmp = kalman_update(&temperature_km, tmp);
|
||
tmp = temperature_c2unit(tmp, udevice.temp_unit);
|
||
return tmp;
|
||
}
|
||
|
||
/**
|
||
* @brief 获取当前CPU温度
|
||
* @return {float32} CPU温度
|
||
* @note
|
||
*/
|
||
float32 get_cpu_temperature(void)
|
||
{
|
||
float32 tmp = 0.0f;
|
||
adc_raw[ADC_TEMP_CHANNEL] = adc_result_average(ADCS_1, ADC_TEMP_CHANNEL);
|
||
tmp = adc_result_temperature(adc_raw[ADC_TEMP_CHANNEL]);
|
||
return tmp;
|
||
}
|
||
|
||
/**
|
||
* @brief 获取当前CPU电压
|
||
* @return {float32} CPU电压
|
||
* @note
|
||
*/
|
||
float32 get_cpu_volt(void)
|
||
{
|
||
float32 tmp = 0.0f;
|
||
adc_raw[ADC_INVREF_CHANNEL] = adc_result_average(ADCS_1, ADC_INVREF_CHANNEL);
|
||
tmp = adc_result_value_local(adc_raw[ADC_INVREF_CHANNEL]);
|
||
return tmp;
|
||
}
|
||
|
||
/**
|
||
* @brief 获取板载电流
|
||
*
|
||
* 该函数用于计算并返回板载电流值。 (DC_LOOP_7.5V - VDD_7.5V)*4/39
|
||
*
|
||
* @return 返回板载电流值,以 float32 类型表示 mA
|
||
*/
|
||
float32 get_board_current(void)
|
||
{
|
||
float32 tmp = 0.0f;
|
||
adc_raw[ADC_DCDC_CHANNEL] = adc_result_average(ADCS_1, ADC_DCDC_CHANNEL);
|
||
adc_raw[ADC_VDD_CHANNEL] = adc_result_average(ADCS_1, ADC_VDD_CHANNEL);
|
||
tmp = ((CPU_VREF * adc_raw[ADC_DCDC_CHANNEL] / ADC_MAX) - (CPU_VREF * adc_raw[ADC_VDD_CHANNEL] / ADC_MAX)) * 4 / 39;
|
||
return tmp * 1000;
|
||
}
|
||
|
||
/**
|
||
* @brief 获取死区
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
float32 get_dead_zone(void)
|
||
{
|
||
if (udevice.pid_index == 0)
|
||
{
|
||
return ABS(udevice.integral_db);
|
||
}
|
||
else
|
||
{
|
||
return ABS(udevice.spid_dead);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 获取当前流量
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
float32 get_flow(void)
|
||
{
|
||
float32 v = 0.0f;
|
||
adc_raw[ADC_FLOW] = adc_result_average(ADCS_1, ADC_BPB_CHANNEL);
|
||
v = ((CPU_VREF * adc_raw[ADC_FLOW] / ADC_MAX) - 0.4f) * 600 / 1.6f;
|
||
|
||
return v < 0 ? 0 : v;
|
||
}
|
||
|
||
/**
|
||
* @brief 获取当前压力
|
||
* @return {float32} 压力值
|
||
* @note
|
||
*/
|
||
float32 get_pressure(pressure_type_e id)
|
||
{
|
||
calib_param_t *p = NULL;
|
||
float32 f = 0.0;
|
||
// 通过线性的方式计算压力值有问题
|
||
switch (id)
|
||
{
|
||
case PRESSURE_PARAM_S: // 读取气源压力ADC
|
||
p = (calib_param_t *)&calib_param[CALIBPARA_PS];
|
||
DBG_ASSERT(p != NULL __DBG_LINE);
|
||
adc_raw[ADC_BP_CHANNEL] = adc_result_average(ADCS_1, ADC_BP_CHANNEL);
|
||
if (p->is_calibration == IS_CALIBRATION)
|
||
{
|
||
f = adc_raw[ADC_BP_CHANNEL];
|
||
// 计算气源压力
|
||
f = adc_linear_conversion(CALIBPARA_PS, f);
|
||
}
|
||
else
|
||
{
|
||
f = pressure_adc2kpa(adc_raw[ADC_BP_CHANNEL]);
|
||
}
|
||
break;
|
||
case PRESSURE_PARAM_A: // 读取A路压力ADC
|
||
p = (calib_param_t *)&calib_param[CALIBPARA_PA];
|
||
DBG_ASSERT(p != NULL __DBG_LINE);
|
||
adc_raw[ADC_BPA_CHANNEL] = adc_result_average(ADCS_1, ADC_BPA_CHANNEL);
|
||
if (p->is_calibration == IS_CALIBRATION)
|
||
{
|
||
f = adc_raw[ADC_BPA_CHANNEL];
|
||
// 计算A路压力
|
||
f = adc_linear_conversion(CALIBPARA_PA, f);
|
||
}
|
||
else
|
||
{
|
||
f = pressure_adc2kpa(adc_raw[ADC_BPA_CHANNEL]);
|
||
}
|
||
break;
|
||
case PRESSURE_PARAM_B: // 读取B路压力ADC
|
||
p = (calib_param_t *)&calib_param[CALIBPARA_PB];
|
||
DBG_ASSERT(p != NULL __DBG_LINE);
|
||
adc_raw[ADC_BPB_CHANNEL] = adc_result_average(ADCS_1, ADC_BPB_CHANNEL);
|
||
if (p->is_calibration == IS_CALIBRATION)
|
||
{
|
||
f = adc_raw[ADC_BPB_CHANNEL];
|
||
// 计算B路压力
|
||
f = adc_linear_conversion(CALIBPARA_PB, f);
|
||
}
|
||
else
|
||
{
|
||
f = pressure_adc2kpa(adc_raw[ADC_BPB_CHANNEL]);
|
||
}
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
return f < 0 ? 0 : f;
|
||
}
|
||
|
||
/**
|
||
* 获取实时数据的时间戳
|
||
*
|
||
* 该函数从实时数据结构体中获取当前的日期和时间,并将它们转换为自1970年1月1日以来的时间戳(秒数)。
|
||
*
|
||
* @return 返回的时间戳是自1970年1月1日以来的秒数。
|
||
*/
|
||
uint32_t rt_data_time_timestamp(void)
|
||
{
|
||
rtc_date_t date;
|
||
rtc_time_t time;
|
||
date.year = rt_save.real_time.date.year;
|
||
date.month = rt_save.real_time.date.month;
|
||
date.day = rt_save.real_time.date.day;
|
||
time.hour = rt_save.real_time.date.hour;
|
||
time.minute = rt_save.real_time.date.minute;
|
||
time.second = rt_save.real_time.date.second;
|
||
return time2stamp(&date, &time);
|
||
}
|
||
|
||
/***************************** 通过电阻测算,只在测试程序中使用 *****************************/
|
||
/**
|
||
* @brief 回路电流检测转换
|
||
* @param {uint16_t} adc
|
||
* @return {float32} 回路电流值
|
||
* @note 计算公式如下:
|
||
* > 压力和电流关系:(adc/4096)*VREF_VALUE/(5*20) = ma <p>
|
||
* > 简化后:adc*VREF_VALUE/409600 = ma <p>
|
||
*/
|
||
float32 loop_current_convert(uint16_t adc)
|
||
{
|
||
float32 f;
|
||
f = ((float32)(adc * CPU_VREF * 1000)) / 409600;
|
||
return f;
|
||
}
|
||
|
||
/**
|
||
* @brief DAC:IP输出电流值转换
|
||
* @param {uint16_t} dac
|
||
* @return {float32} IP输出电流值
|
||
* @note
|
||
*/
|
||
float32 ip_dac2current(uint16_t dac)
|
||
{
|
||
float32 vol = 0, cur = 0;
|
||
// 计算电压值 mv
|
||
vol = (float32)dac / 4096 * VREF_VALUE;
|
||
|
||
// 计算电流值 ma
|
||
cur = vol / (40 * 40);
|
||
|
||
// 如果电流值大于2.5,则设置为2.5
|
||
if (cur > 2.5f)
|
||
{
|
||
cur = 2.5;
|
||
}
|
||
|
||
return cur;
|
||
}
|
||
|
||
/**
|
||
* @brief IP输出电流值转换
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
float32 ip2current(void)
|
||
{
|
||
float32 cur = 0;
|
||
adc_raw[ADC_VIP_CHANNEL] = adc_result_average(ADCS_1, ADC_VIP_CHANNEL);
|
||
// 计算电流值 ma
|
||
cur = (float32)adc_raw[ADC_VIP_CHANNEL] * CPU_VREF * 1000 / (float32)(10 * 31 * ADC_MAX);
|
||
return cur;
|
||
}
|
||
|
||
/**
|
||
* @brief 压力输出kpa值转换
|
||
* @param {uint16_t} adc
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
float32 pressure_adc2kpa(uint16_t adc)
|
||
{
|
||
return ((CPU_VREF * adc / ADC_MAX) - 0.2755f) / 2.885f * 1000;
|
||
}
|
||
|
||
/**
|
||
* @brief PWM输出电流值转换
|
||
* @param {float32} current
|
||
* @return {*}
|
||
* @note: 计算公式如下:
|
||
* > I_OUT=3V*Duty/10K*100(mA)
|
||
*/
|
||
void pwm_duty2current(float32 cur_ma)
|
||
{
|
||
float32 current;
|
||
|
||
if (cur_ma < 4)
|
||
current = 4;
|
||
else if (cur_ma > 20)
|
||
current = 20;
|
||
else
|
||
current = cur_ma;
|
||
dac161p997_output_current(current);
|
||
}
|
||
|
||
/**
|
||
* @brief 获取RTC时间
|
||
* @param {date_time_t} *time
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
BOOL get_timestamp(date_time_t *time)
|
||
{
|
||
BOOL ret = FALSE;
|
||
uint8_t tmp[7];
|
||
ret = rtc_get_clock_time(tmp);
|
||
if (ret == FALSE)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
time->date.year = hex_format_dec(tmp[6]); // 将年存储在data结构体的year字段中
|
||
time->date.month = hex_format_dec(tmp[5]); // 将月存储在data结构体的month字段中
|
||
time->date.day = hex_format_dec(tmp[4]); // 将日存储在data结构体的day字段中
|
||
time->date.hour = hex_format_dec(tmp[2]); // 将时存储在data结构体的hour字段中
|
||
time->date.minute = hex_format_dec(tmp[1]); // 将分存储在data结构体的minute字段中
|
||
time->date.second = hex_format_dec(tmp[0]); // 将秒存储在data结构体的second字段中
|
||
return TRUE;
|
||
}
|
||
|
||
/**
|
||
* 从实时时钟(RTC)获取当前的日期和时间。
|
||
*
|
||
* @param date 指向rtc_date_t结构体的指针,用于存储日期(年、月、日)。
|
||
* @param time 指向rtc_time_t结构体的指针,用于存储时间(小时、分钟、秒)。
|
||
* @return 如果成功获取日期和时间,则返回TRUE;否则返回FALSE。
|
||
*
|
||
* 这个函数首先尝试更新实时时间,如果成功,则将日期和时间填充到传入的date和time结构体中。
|
||
* 如果更新实时时间失败,则不会修改date和time指向的结构体,并返回FALSE。
|
||
*/
|
||
BOOL rtc_get_datetime(rtc_date_t *const date, rtc_time_t *const time)
|
||
{
|
||
date_time_t real_time;
|
||
BOOL ret = FALSE;
|
||
ret = update_real_time(&real_time);
|
||
if (ret == TRUE)
|
||
{
|
||
date->year = real_time.date.year;
|
||
date->month = real_time.date.month;
|
||
date->day = real_time.date.day;
|
||
time->hour = real_time.date.hour;
|
||
time->minute = real_time.date.minute;
|
||
time->second = real_time.date.second;
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
// 从RAM中获取当前的日期和时间。
|
||
void rtc_get_datetime_ram(rtc_date_t *const date, rtc_time_t *const time)
|
||
{
|
||
date_time_t *real_time = (date_time_t *)&rt_save.real_time;
|
||
date->year = real_time->date.year;
|
||
date->month = real_time->date.month;
|
||
date->day = real_time->date.day;
|
||
time->hour = real_time->date.hour;
|
||
time->minute = real_time->date.minute;
|
||
time->second = real_time->date.second;
|
||
}
|
||
|
||
/**
|
||
* @brief 更新实时时间
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
BOOL update_real_time(date_time_t *real_time)
|
||
{
|
||
return get_timestamp(real_time);
|
||
}
|
||
|
||
/**
|
||
* @brief 从实时数据结构中获取日期和时间。
|
||
*
|
||
* 此函数从`rt_save.real_time`结构中获取实时日期和时间,并将各个组成部分(年、月、日、小时、分钟、秒)存储在提供的指针中。
|
||
*
|
||
* @param year 存储年份的指针。
|
||
* @param month 存储月份的指针。
|
||
* @param day 存储日期的指针。
|
||
* @param hour 存储小时的指针。
|
||
* @param min 存储分钟的指针。
|
||
* @param sec 存储秒数的指针。
|
||
*/
|
||
BOOL get_real_time(uint8_t *year, uint8_t *month, uint8_t *day, uint8_t *hour, uint8_t *min, uint8_t *sec)
|
||
{
|
||
date_time_t real_time;
|
||
BOOL ret = FALSE;
|
||
ret = update_real_time(&real_time);
|
||
*year = real_time.date.year;
|
||
*month = real_time.date.month;
|
||
*day = real_time.date.day;
|
||
*hour = real_time.date.hour;
|
||
*min = real_time.date.minute;
|
||
*sec = real_time.date.second;
|
||
|
||
return ret;
|
||
}
|
||
|
||
/**
|
||
* @brief 设置UART1空闲处理函数
|
||
*
|
||
* 当UART1处于空闲状态时,调用此函数进行空闲处理。
|
||
* 如果_uart1_idel_sec_count大于0,则将其减1。
|
||
*/
|
||
void uart1_set_idel_handle_1_sec(void)
|
||
{
|
||
if (_uart1_idel_sec_count > 0)
|
||
{
|
||
_uart1_idel_sec_count--;
|
||
}
|
||
}
|
||
/**
|
||
* @brief 设置UART1空闲状态
|
||
*
|
||
* 根据传入的布尔值设置UART1的空闲状态。当idel为TRUE时,将UART1的空闲秒数计数器重置为0;
|
||
* 当idel为FALSE时,将UART1的空闲秒数计数器设置为5。
|
||
*
|
||
* @param idel 空闲状态标志,TRUE表示空闲,FALSE表示非空闲
|
||
*/
|
||
void uart1_set_idel_status(BOOL idel)
|
||
{
|
||
if (idel == TRUE)
|
||
{
|
||
_uart1_idel_sec_count = 0;
|
||
}
|
||
else
|
||
{
|
||
_uart1_idel_sec_count = 30;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 获取 UART1 空闲状态
|
||
*
|
||
* 获取 UART1 的空闲状态。
|
||
*
|
||
* @return UART1 的空闲状态
|
||
* 如果 UART1 处于空闲状态,则返回 TRUE;否则返回 FALSE。
|
||
*/
|
||
BOOL uart1_get_idel_status(void)
|
||
{
|
||
return _uart1_idel_sec_count == 0 ? TRUE : FALSE;
|
||
}
|
||
|
||
/**
|
||
* @brief Sets the real-time clock (RTC) with the specified date and time.
|
||
*
|
||
* @param year The year value (0-99).
|
||
* @param month The month value (1-12).
|
||
* @param day The day value (1-31).
|
||
* @param hour The hour value (0-23).
|
||
* @param min The minute value (0-59).
|
||
* @param sec The second value (0-59).
|
||
*/
|
||
BOOL set_real_time(uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec)
|
||
{
|
||
rtc_date date = {
|
||
.year = dec_format_hex(year),
|
||
.month = dec_format_hex(month),
|
||
.day = dec_format_hex(day),
|
||
.hour = dec_format_hex(hour),
|
||
.minute = dec_format_hex(min),
|
||
.second = dec_format_hex(sec),
|
||
.weekday = get_weekday(BASE_YEAR + year,
|
||
month,
|
||
day),
|
||
};
|
||
rtc_weekday_convert(&date.weekday);
|
||
if (rtc_set_clock_time(&date) == FALSE)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/**
|
||
* @brief 读取4mA输入时的ADC电压
|
||
* @return {*}
|
||
*/
|
||
void set_loop_4ma(void)
|
||
{
|
||
calib_param_t *p = (calib_param_t *)&calib_param[CALIBPARA_LOOP];
|
||
p->original_adc_value[0] = adc_result_average(ADCS_1, ADC_LOOP_CHANNEL); // 获取4mA输入时adc值
|
||
calib_param_calculate(CALIBPARA_LOOP, udevice.input_offset, udevice.input_span, p->min, p->max);
|
||
}
|
||
|
||
/**
|
||
* @brief 读取20mA输入时的ADC值
|
||
* @return {*}
|
||
*/
|
||
void set_loop_20ma(void)
|
||
{
|
||
calib_param_t *p = (calib_param_t *)&calib_param[CALIBPARA_LOOP];
|
||
p->original_adc_value[1] = adc_result_average(ADCS_1, ADC_LOOP_CHANNEL);
|
||
calib_param_calculate(CALIBPARA_LOOP, udevice.input_offset, udevice.input_span, p->min, p->max);
|
||
}
|
||
|
||
/**
|
||
* @brief 设置压力最小值
|
||
*
|
||
* 根据给定的值和索引设置压力的最小值。
|
||
*
|
||
* @param set_value 要设置的值
|
||
* @param index 压力索引
|
||
*/
|
||
void set_pressure_min(uint8_t unit, float32 set_value, pressure_type_e index)
|
||
{
|
||
pressure_calib_param_t *p = NULL;
|
||
uint8_t channel = 0;
|
||
switch (index)
|
||
{
|
||
case PRESSURE_PARAM_S:
|
||
channel = ADC_BP_CHANNEL;
|
||
p = (pressure_calib_param_t *)&pressure_calib_param[PRESSURE_PARAM_S];
|
||
break;
|
||
case PRESSURE_PARAM_A:
|
||
channel = ADC_BPA_CHANNEL;
|
||
p = (pressure_calib_param_t *)&pressure_calib_param[PRESSURE_PARAM_A];
|
||
break;
|
||
case PRESSURE_PARAM_B:
|
||
channel = ADC_BPB_CHANNEL;
|
||
p = (pressure_calib_param_t *)&pressure_calib_param[PRESSURE_PARAM_B];
|
||
break;
|
||
default:
|
||
return;
|
||
}
|
||
p->min_set = pressure_unit2kpa(set_value, unit);
|
||
p->min_ad_value = adc_raw[channel];
|
||
eeprom_lc02b_write(PRRESSURE_CALIBRATION_ADDRESS, (uint8_t *)pressure_calib_param, sizeof(pressure_calib_param_t) * PRESSURE_PARAM_MAX);
|
||
calib_pressure(index);
|
||
}
|
||
|
||
/**
|
||
* @brief 校准压力传感器
|
||
*
|
||
* 根据传入的压力传感器类型,对相应的校准参数进行初始化并计算校准值。
|
||
*
|
||
* @param index 压力传感器类型,类型为pressure_type_e枚举
|
||
*/
|
||
void calib_pressure(pressure_type_e index)
|
||
{
|
||
calibration_e calib_index = CALIBPARA_MAX;
|
||
calib_param_t *p = NULL;
|
||
pressure_calib_param_t *pp = NULL;
|
||
if (index == PRESSURE_PARAM_S)
|
||
{
|
||
calib_index = CALIBPARA_PS;
|
||
p = (calib_param_t *)&calib_param[calib_index];
|
||
pp = &pressure_calib_param[PRESSURE_PARAM_S];
|
||
}
|
||
else if (index == PRESSURE_PARAM_A)
|
||
{
|
||
calib_index = CALIBPARA_PA;
|
||
p = (calib_param_t *)&calib_param[calib_index];
|
||
pp = &pressure_calib_param[PRESSURE_PARAM_A];
|
||
}
|
||
else if (index == PRESSURE_PARAM_B)
|
||
{
|
||
calib_index = CALIBPARA_PB;
|
||
p = (calib_param_t *)&calib_param[calib_index];
|
||
pp = &pressure_calib_param[PRESSURE_PARAM_B];
|
||
}
|
||
else
|
||
{
|
||
DBG_ASSERT(FALSE __DBG_LINE);
|
||
}
|
||
osel_memset((uint8_t *)p, 0, sizeof(calib_param_t));
|
||
|
||
p->original_adc_value[0] = pp->min_ad_value;
|
||
p->original_adc_value[1] = pp->max_ad_value;
|
||
calib_param_calculate(calib_index, 0, 0, pp->min_set, pp->max_set);
|
||
}
|
||
|
||
/**
|
||
* @brief 设置压力最大输入时的ADC电压
|
||
* @return {*}
|
||
*/
|
||
void set_pressure_max(uint8_t unit, float32 set_value, pressure_type_e index)
|
||
{
|
||
pressure_calib_param_t *p = NULL;
|
||
uint8_t channel = 0;
|
||
switch (index)
|
||
{
|
||
case PRESSURE_PARAM_S:
|
||
channel = ADC_BP_CHANNEL;
|
||
p = (pressure_calib_param_t *)&pressure_calib_param[PRESSURE_PARAM_S];
|
||
break;
|
||
case PRESSURE_PARAM_A:
|
||
channel = ADC_BPA_CHANNEL;
|
||
p = (pressure_calib_param_t *)&pressure_calib_param[PRESSURE_PARAM_A];
|
||
break;
|
||
case PRESSURE_PARAM_B:
|
||
channel = ADC_BPB_CHANNEL;
|
||
p = (pressure_calib_param_t *)&pressure_calib_param[PRESSURE_PARAM_B];
|
||
break;
|
||
default:
|
||
return;
|
||
}
|
||
p->max_set = pressure_unit2kpa(set_value, unit);
|
||
p->max_ad_value = adc_raw[channel];
|
||
|
||
eeprom_lc02b_write(PRRESSURE_CALIBRATION_ADDRESS, (uint8_t *)pressure_calib_param, sizeof(pressure_calib_param_t) * PRESSURE_PARAM_MAX);
|
||
calib_pressure(index);
|
||
}
|
||
|
||
/**
|
||
* @brief 记录输出4mA时的PWM值
|
||
* @return {*}
|
||
*/
|
||
void set_output_4ma_pwm(uint16_t value)
|
||
{
|
||
// board_cache[BOARD_CACHE_1] = value;
|
||
}
|
||
|
||
/**
|
||
* @brief 记录输出20mA时的PWM值
|
||
* @return {*}
|
||
*/
|
||
void set_output_20ma_pwm(uint16_t value)
|
||
{
|
||
// board_cache[BOARD_CACHE_2] = value;
|
||
}
|
||
|
||
/**
|
||
* @brief 设置语言预加载标志
|
||
* @param {uint8_t} language
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void set_app_preload_language_flag(uint8_t flag)
|
||
{
|
||
if (board_data.app_preload_language_flag != flag)
|
||
{
|
||
board_data.app_preload_language_flag = flag;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 设置工作页面索引
|
||
* @param {uint8_t} index
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void set_work_page_index(uint8_t index)
|
||
{
|
||
rt_save.work_menu_index = index;
|
||
}
|
||
|
||
/**
|
||
* @brief 获取工作页面索引
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
uint8_t get_work_page_index(void)
|
||
{
|
||
return rt_save.work_menu_index;
|
||
}
|
||
|
||
uint8_t get_language(void)
|
||
{
|
||
return udevice.display_language;
|
||
}
|
||
|
||
void set_language(uint8_t language)
|
||
{
|
||
udevice.display_language = language;
|
||
}
|
||
|
||
/**
|
||
* @brief 设置预加载BOOTLOAD标志位
|
||
* @param {uint8_t} flag
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void set_app_preload_bootload_flag(uint16_t flag)
|
||
{
|
||
if (app_preload_bootload_flag != flag)
|
||
{
|
||
app_preload_bootload_flag = flag;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief Get the application preload bootload flag
|
||
* @return The application preload bootload flag
|
||
*/
|
||
uint16_t get_app_preload_bootload_flag(void)
|
||
{
|
||
return app_preload_bootload_flag;
|
||
}
|
||
|
||
/**
|
||
* @brief Get the application preload language flag
|
||
* @return The application preload language flag
|
||
*/
|
||
uint8_t get_app_preload_language_flag(void)
|
||
{
|
||
return board_data.app_preload_language_flag;
|
||
}
|
||
|
||
/**
|
||
* @brief 设置预加载BOOTLOAD标志位
|
||
* @param {app_preload_bootload_jump_e} flag
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void set_app_preload_bootload_jump_flag(app_preload_bootload_jump_e flag)
|
||
{
|
||
if (app_preload_bootload_jump_flag != flag)
|
||
{
|
||
app_preload_bootload_jump_flag = flag;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief Get the application preload bootload jump flag
|
||
* @return The application preload bootload jump flag
|
||
*/
|
||
app_preload_bootload_jump_e get_app_preload_bootload_jump_flag(void)
|
||
{
|
||
return (app_preload_bootload_jump_e)app_preload_bootload_jump_flag;
|
||
}
|
||
|
||
/**
|
||
* @brief 获取种子值
|
||
*
|
||
* 返回一个用于随机数生成的种子值。
|
||
*
|
||
* @return 返回一个 32 位无符号整数作为种子值
|
||
*/
|
||
uint32_t get_seed(void)
|
||
{
|
||
uint32_t seed = (uint32_t)(adc_result_only_one(ADCS_1, ADC_LOOP_CHANNEL) | adc_result_only_one(ADCS_1, ADC_BP_CHANNEL) << 8 | adc_result_only_one(ADCS_1, ADC_NTC_CHANNEL) << 16) +
|
||
(uint32_t)(adc_result_only_one(ADCS_1, ADC_NTC_CHANNEL));
|
||
return seed;
|
||
}
|
||
|
||
/**
|
||
* @brief 判断是否使用了外接LCD板
|
||
*
|
||
* 此函数用于判断系统是否使用了外接LCD板。
|
||
*
|
||
* @return BOOL 如果使用了外接LCD板则返回FALSE,否则返回TRUE。
|
||
*/
|
||
BOOL is_lcd_ext_board(void)
|
||
{
|
||
if (LCD_DETECT() == TRUE)
|
||
{
|
||
return FALSE;
|
||
}
|
||
else
|
||
{
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
// 更新设备最小最大温度
|
||
void update_device_temp_min_max(float32 temperature)
|
||
{
|
||
if (udevice.min_temp == TEMP_MIN_DEFAULT)
|
||
{
|
||
udevice.min_temp = temperature;
|
||
}
|
||
|
||
if (udevice.max_temp == TEMP_MAX_DEFAULT)
|
||
{
|
||
udevice.max_temp = temperature;
|
||
}
|
||
|
||
if (udevice.min_temp > temperature)
|
||
{
|
||
udevice.min_temp = temperature;
|
||
}
|
||
if (udevice.max_temp < temperature)
|
||
{
|
||
udevice.max_temp = temperature;
|
||
}
|
||
}
|
||
|
||
// 判断是否可以工作无线模块
|
||
BOOL wireless_can_work(float32 loop_current)
|
||
{
|
||
BOOL rst = TRUE;
|
||
if (udevice.wireless_enable == TRUE)
|
||
{
|
||
if (udevice.zero_power_condition == VALVE_CLOSE)
|
||
{
|
||
// 零功率条件下,执行机构位置在下面
|
||
// 蓝牙启动需要6.0mA
|
||
if (loop_current < GUI_HIGHT_CURRENT_MIN)
|
||
{
|
||
rst = FALSE;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// 零功率条件下,执行机构位置在上面
|
||
// 蓝牙启动需要8.0mA
|
||
if (loop_current < BLE_CURRENT_WORK)
|
||
{
|
||
rst = FALSE;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
rst = FALSE;
|
||
}
|
||
return rst;
|
||
}
|
||
|
||
// 是否达到了运行的最大时间
|
||
BOOL is_run_max_time(void)
|
||
{
|
||
return rt_save.dev_run_time_h >= WORK_HOURS_MAX;
|
||
}
|