1062 lines
25 KiB
C
1062 lines
25 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 "board.h"
|
||
#include "entity.h"
|
||
#include "delay.h"
|
||
|
||
#include "filter.h"
|
||
void SystemClock_Config(void);
|
||
|
||
static BOOL driver_init_flag = FALSE;
|
||
|
||
static uint16_t board_cache[BOARD_CACHE_MAX]; ///< 调节缓存
|
||
static lpf_t lpf_temperature; ///< 温度滤波器
|
||
__IO static BOOL system_clock_config_flag = FALSE; ///< 系统时钟配置改变标志
|
||
|
||
__IO uint8_t app_preload_flag __attribute__((at(APP_PRELOAD_AREA))); // 预加载标志
|
||
__IO uint8_t app_preload_language_flag __attribute__((at(APP_PRELOAD_AREA + 1))); // 语言标志
|
||
__IO uint8_t app_preload_bootload_flag __attribute__((at(APP_PRELOAD_AREA + 2))); // 触发BOOTLOAD启动标志(在用户代码中接受代码文件)
|
||
__IO uint8_t app_preload_bootload_jump_flag __attribute__((at(APP_PRELOAD_AREA + 3))); // 触发BOOTLOAD跳转更新标志(在BOOTLOAD代码中更新用户代码)
|
||
__IO uint32_t app_preload_cupid_encrypt __attribute__((at(APP_PRELOAD_AREA + 4))); // 加密后的CPUID
|
||
/***************************************** 板卡初始化相关函数 *****************************************/
|
||
|
||
/**
|
||
* @brief LCD设计
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void lcd_design(void)
|
||
{
|
||
}
|
||
|
||
/**
|
||
* @brief LCD初始化
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void lcd_init(void)
|
||
{
|
||
// 设置功能引脚
|
||
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);
|
||
|
||
if (0 == LCD_IS_POWER_ON())
|
||
{
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief LCD反初始化
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void lcd_dinit(void)
|
||
{
|
||
}
|
||
|
||
/**
|
||
* @brief 功耗引脚初始化
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void driver_init(void)
|
||
{
|
||
// 标志位检查:driver_init_flag = TRUE,表示已经初始化
|
||
if (driver_init_flag == TRUE)
|
||
{
|
||
return;
|
||
}
|
||
driver_init_flag = TRUE;
|
||
|
||
pdctrl_run(); // 控制输出使能
|
||
PWM_START(TIM3, LL_TIM_CHANNEL_CH3); // PWM OUT使能
|
||
}
|
||
|
||
/**
|
||
* @brief 功耗引脚反初始化
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void driver_dinit(void)
|
||
{
|
||
// 标志位检查:driver_init_flag = FALSE,表示已经反初始化
|
||
if (driver_init_flag == FALSE)
|
||
{
|
||
return;
|
||
}
|
||
driver_init_flag = FALSE;
|
||
|
||
pdctrl_stop(); // 控制输出禁用
|
||
PWM_STOP(TIM3, LL_TIM_CHANNEL_CH3); // PWM OUT禁用
|
||
}
|
||
|
||
/**
|
||
* @brief 板卡初始化
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void board_init(void)
|
||
{
|
||
VIP_H_EN_DISABLE(); // IP禁用,满足条件时才使能
|
||
|
||
adc_init(ADCS_1, ADC1, DMA1, LL_DMA_CHANNEL_1, 30,
|
||
IN5 | IN6 | IN7 | IN8 | IN9 | IN11 | IN12 | IN13 | IN14 | INTEMP | INVREF); // 初始化ADC1通道,默认采集AD
|
||
|
||
adc_init(ADCS_2, ADC2, DMA1, LL_DMA_CHANNEL_2, 10,
|
||
IN5 | IN6); // 初始化ADC2通道,慢速采集通道
|
||
|
||
rtc_init(); // 初始化RTC
|
||
eeprom_m95_init(M95_1); // 初始化SPI EEPROM1
|
||
eeprom_m95_init(M95_2); // 初始化SPI EEPROM2
|
||
eeprom_fm24_init(); // 初始化 IIC EEPROM
|
||
eeprom_lc02b_init(); // 初始化 IIC EEPROM
|
||
leds_init(); // 初始化LED
|
||
|
||
lpf_init(&lpf_temperature);
|
||
system_clock_config_low();
|
||
// debug_freeze_watchdog(); // 冻结看门狗
|
||
}
|
||
|
||
void board_dinit(void)
|
||
{
|
||
adc_dinit(ADCS_1); // ADC反初始化
|
||
DISABLE_TIM(TIM6);
|
||
DISABLE_TIM(TIM7);
|
||
driver_dinit();
|
||
|
||
rtc_dinit(); // RTC反初始化
|
||
eeprom_m95_dinit(M95_1);
|
||
eeprom_m95_dinit(M95_2);
|
||
eeprom_fm24_dinit();
|
||
eeprom_lc02b_dinit();
|
||
leds_dinit(); // LED Deinitialization
|
||
lcd_dinit(); // LCD screen Deinitialization
|
||
}
|
||
|
||
/**
|
||
* @brief 板卡工作暂停
|
||
* @return {*}
|
||
* @note 在用户层处理bootload接收数据时需要暂时关闭一些应用层的处理
|
||
*/
|
||
void board_work_stop_or_run(void)
|
||
{
|
||
static BOOL stop_or_run_state = FALSE;
|
||
|
||
if (get_app_preload_bootload_flag() != stop_or_run_state)
|
||
{
|
||
// 如果stop_or_run_state是FALSE,那么app_preload_bootload_flag是TRUE,表示当前需要暂停工作
|
||
// 目前先暂停TIM7控制模块,TIM6的任务执行不受影响,因为任务模块会执行最简单的任务
|
||
if (stop_or_run_state == FALSE)
|
||
{
|
||
DISABLE_TIM(TIM7);
|
||
}
|
||
else
|
||
{
|
||
ENABLE_TIM(TIM7);
|
||
}
|
||
stop_or_run_state = get_app_preload_bootload_flag();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 缓存数据初始化
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void board_cache_reset(void)
|
||
{
|
||
for (uint8_t i = 0; i < BOARD_CACHE_MAX; i++)
|
||
{
|
||
board_cache[i] = 0;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 缓存数据获取
|
||
* @param {board_cache_e} index
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
uint16_t board_cache_get(board_cache_e index)
|
||
{
|
||
return board_cache[index];
|
||
}
|
||
|
||
/**
|
||
* @brief 系统时钟配置低频
|
||
* @return {*}
|
||
* @note 2M 默认使用系统时钟配置低频
|
||
*/
|
||
// static void system_clock_config_low_2m(void)
|
||
//{
|
||
// LL_FLASH_SetLatency(LL_FLASH_LATENCY_0);
|
||
// while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_0)
|
||
// {
|
||
// }
|
||
// LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1);
|
||
// while (LL_PWR_IsActiveFlag_VOS() != 0)
|
||
// {
|
||
// }
|
||
// LL_RCC_HSE_Enable();
|
||
|
||
// /* Wait till HSE is ready */
|
||
// while (LL_RCC_HSE_IsReady() != 1)
|
||
// {
|
||
// }
|
||
// LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_1, 8, LL_RCC_PLLR_DIV_2);
|
||
// LL_RCC_PLL_EnableDomain_SYS();
|
||
// LL_RCC_PLL_Enable();
|
||
|
||
// /* Wait till PLL is ready */
|
||
// while (LL_RCC_PLL_IsReady() != 1)
|
||
// {
|
||
// }
|
||
// LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);
|
||
|
||
// /* Wait till System clock is ready */
|
||
// while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL)
|
||
// {
|
||
// }
|
||
// LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_16);
|
||
// LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
|
||
// LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1);
|
||
|
||
// LL_Init1msTick(2000000);
|
||
|
||
// LL_SetSystemCoreClock(2000000);
|
||
//}
|
||
|
||
void system_clock_config_set_flag(BOOL flag)
|
||
{
|
||
system_clock_config_flag = flag;
|
||
}
|
||
|
||
/**
|
||
* @brief 系统时钟配置低频
|
||
* @return {*}
|
||
* @note 4M 默认使用系统时钟配置低频
|
||
*/
|
||
void system_clock_config_low(void)
|
||
{
|
||
if (system_clock_config_flag == FALSE)
|
||
{
|
||
return;
|
||
}
|
||
system_clock_config_set_flag(FALSE);
|
||
|
||
// if (udevice.dev_algorithm_mode == MODE_VARIABLE_FREQUENCY_CONTROL_ALGORITHM)
|
||
// {
|
||
// system_clock_config_low_2m();
|
||
// }
|
||
// else
|
||
// {
|
||
// SystemClock_Config();
|
||
// }
|
||
SystemClock_Config();
|
||
|
||
uint32_t hclk = SystemCoreClock / 1000000;
|
||
delay_init(hclk);
|
||
uint16_t pres = (hclk * 100) - 1;
|
||
if (LL_TIM_GetPrescaler(TIM6) != pres)
|
||
{
|
||
LL_TIM_SetPrescaler(TIM6, pres);
|
||
}
|
||
if (LL_TIM_GetPrescaler(TIM7) != pres)
|
||
{
|
||
LL_TIM_SetPrescaler(TIM7, pres);
|
||
}
|
||
uint32_t reload = (hclk * 1000) - 1;
|
||
pdctrl_pwm_set_arr(reload);
|
||
if (LL_TIM_GetAutoReload(TIM3) != reload)
|
||
{
|
||
LL_TIM_SetAutoReload(TIM3, reload);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 系统时钟配置高频
|
||
* @return {*}
|
||
* @note 16M
|
||
*/
|
||
void system_clock_config_hight(void)
|
||
{
|
||
if (system_clock_config_flag == FALSE)
|
||
{
|
||
return;
|
||
}
|
||
|
||
LL_FLASH_SetLatency(LL_FLASH_LATENCY_0);
|
||
while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_0)
|
||
{
|
||
}
|
||
LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1);
|
||
while (LL_PWR_IsActiveFlag_VOS() != 0)
|
||
{
|
||
}
|
||
LL_RCC_HSE_Enable();
|
||
|
||
/* Wait till HSE is ready */
|
||
while (LL_RCC_HSE_IsReady() != 1)
|
||
{
|
||
}
|
||
LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_1, 8, LL_RCC_PLLR_DIV_2);
|
||
LL_RCC_PLL_EnableDomain_SYS();
|
||
LL_RCC_PLL_Enable();
|
||
|
||
/* Wait till PLL is ready */
|
||
while (LL_RCC_PLL_IsReady() != 1)
|
||
{
|
||
}
|
||
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);
|
||
|
||
/* Wait till System clock is ready */
|
||
while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL)
|
||
{
|
||
}
|
||
LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_2);
|
||
LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
|
||
LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1);
|
||
|
||
LL_Init1msTick(16000000);
|
||
|
||
LL_SetSystemCoreClock(16000000);
|
||
|
||
uint32_t hclk = SystemCoreClock / 1000000;
|
||
uint16_t pres = (hclk * 100) - 1;
|
||
if (LL_TIM_GetPrescaler(TIM6) != pres)
|
||
{
|
||
LL_TIM_SetPrescaler(TIM6, pres);
|
||
}
|
||
if (LL_TIM_GetPrescaler(TIM7) != pres)
|
||
{
|
||
LL_TIM_SetPrescaler(TIM7, pres);
|
||
}
|
||
uint32_t reload = (hclk * 1000) - 1;
|
||
pdctrl_pwm_set_arr(reload);
|
||
if (LL_TIM_GetAutoReload(TIM3) != reload)
|
||
{
|
||
LL_TIM_SetAutoReload(TIM3, reload);
|
||
}
|
||
}
|
||
|
||
/***************************************** 板卡LCD操作相关函数 *****************************************/
|
||
|
||
/**
|
||
* @brief LCD刷新
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void gui_flush(void)
|
||
{
|
||
|
||
}
|
||
|
||
/**
|
||
* @brief LCD刷新并清除缓存
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void gui_flush_Clear(void)
|
||
{
|
||
|
||
}
|
||
|
||
/**
|
||
* @brief LCD全屏清除
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void gui_clr(void)
|
||
{
|
||
|
||
}
|
||
|
||
/**
|
||
* @brief LCD设置清屏标志
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void gui_set_clear_flag(void)
|
||
{
|
||
|
||
}
|
||
|
||
/**
|
||
* @brief LCD获取清屏标志
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
BOOL gui_get_clear_flag(void)
|
||
{
|
||
return TRUE;
|
||
}
|
||
|
||
/**
|
||
* @brief LCD全屏填充
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void gui_full(void)
|
||
{
|
||
|
||
}
|
||
|
||
/**
|
||
* @brief LCD启动
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void gui_open()
|
||
{
|
||
|
||
}
|
||
|
||
/**
|
||
* @brief LCD关闭
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void gui_close()
|
||
{
|
||
|
||
}
|
||
|
||
/**
|
||
* @brief 设置扫描方向
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void gui_set_scandir(uint8_t 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)
|
||
{
|
||
float32 ftemp = 0;
|
||
|
||
// 根据阀位百分比计算对应的电流
|
||
ftemp = position_per;
|
||
ftemp *= 16;
|
||
ftemp += 400;
|
||
|
||
// 根据校准参数计算占空比
|
||
ftemp *= calib_param[CALIBPARA_VIP].value[0];
|
||
ftemp += calib_param[CALIBPARA_VIP].value[1];
|
||
|
||
// PWM输出
|
||
PWM_SET_DUTY(TIM2, 4, ftemp);
|
||
}
|
||
|
||
/**
|
||
* @brief 校准4-20mA输出电流
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void calib_loop(void)
|
||
{
|
||
#define MA4 (LOOP_CURRENT_MIN * 1000)
|
||
#define MA20 (LOOP_CURRENT_MAX * 1000)
|
||
uint16_t ma = 0, adc = 0;
|
||
float32 f;
|
||
// 计算校准参数
|
||
ma = MA20 - MA4;
|
||
adc = board_cache[BOARD_CACHE_2] - board_cache[BOARD_CACHE_1];
|
||
f = ma;
|
||
f = f / adc;
|
||
calib_param[CALIBPARA_LOOP].value[0] = f / 10;
|
||
f = f * board_cache[BOARD_CACHE_2];
|
||
calib_param[CALIBPARA_LOOP].value[1] = (MA20 - f) / 10;
|
||
|
||
calib_param[CALIBPARA_LOOP].is_calibration = TRUE;
|
||
}
|
||
|
||
/**
|
||
* @brief 校准压力表
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void calib_kpa(void)
|
||
{
|
||
#define PRESSURE_200_KPA 200.0f // 200kPa
|
||
#define PRESSURE_400_KPA 400.0f // 400kPa
|
||
uint16_t ma = 0, adc = 0;
|
||
float32 f;
|
||
// 计算校准参数
|
||
ma = PRESSURE_400_KPA - PRESSURE_200_KPA;
|
||
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] = PRESSURE_400_KPA - 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)
|
||
{
|
||
float32 ftmp = 0.0;
|
||
|
||
// 直行程位置反馈
|
||
ftmp = udevice.pos100_travel_vol - udevice.pos0_travel_vol;
|
||
calib_param[CALIBPARA_PSB].value[0] = 100 / ftmp;
|
||
|
||
ftmp = calib_param[CALIBPARA_PSB].value[0] * udevice.pos100_travel_vol;
|
||
calib_param[CALIBPARA_PSB].value[1] = 100 - ftmp;
|
||
calib_param[CALIBPARA_PSB].is_calibration = TRUE;
|
||
|
||
// 小回路
|
||
ftmp = udevice.pos100_minor_vol - udevice.pos0_minor_vol;
|
||
calib_param[CALIBPARA_IPSB].value[0] = 100 / ftmp;
|
||
|
||
ftmp = calib_param[CALIBPARA_IPSB].value[0] * udevice.pos100_minor_vol;
|
||
calib_param[CALIBPARA_IPSB].value[1] = 100 - ftmp;
|
||
|
||
calib_param[CALIBPARA_IPSB].is_calibration = TRUE;
|
||
}
|
||
|
||
/**
|
||
* @brief 获取当前实际行程ADC值
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
uint16_t get_actual_travel_adc(void)
|
||
{
|
||
adc_raw[ADC_PSB_CHANNEL] = adc_result_median(ADCS_1, ADC_PSB_CHANNEL);
|
||
return adc_raw[ADC_PSB_CHANNEL];
|
||
}
|
||
|
||
/**
|
||
* @brief 获取当前实际行程ADC值
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
uint16_t get_actual_travel_adc_average(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 * 1.0f;
|
||
// 计算当前位置
|
||
f *= calib_param[CALIBPARA_PSB].value[0];
|
||
f += calib_param[CALIBPARA_PSB].value[1];
|
||
if (f < 0)
|
||
{
|
||
f = 0;
|
||
}
|
||
if (f > 100)
|
||
{
|
||
f = 100;
|
||
}
|
||
|
||
return 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
|
||
{
|
||
raw = adc_result_average(ADCS_1, ADC_PSB_CHANNEL);
|
||
}
|
||
|
||
adc_raw[ADC_PSB_CHANNEL] = raw;
|
||
return actual_adc_convert_percent(raw);
|
||
}
|
||
|
||
/**
|
||
* @brief 获取当前实际行程
|
||
* @param {uint8_t} filter 1:平均 2:中值
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
float32 get_actual_travel_2(filter_e filter)
|
||
{
|
||
uint16_t raw = 0;
|
||
|
||
// 读取位置反馈ADC值
|
||
if (filter == FILTER_AVERAGE)
|
||
{
|
||
raw = adc_result_average(ADCS_2, ADC_PSB_CHANNEL);
|
||
}
|
||
else if (filter == FILTER_MEDIAN)
|
||
{
|
||
raw = adc_result_median(ADCS_2, ADC_PSB_CHANNEL);
|
||
}
|
||
else
|
||
{
|
||
raw = adc_result_average(ADCS_2, ADC_PSB_CHANNEL);
|
||
}
|
||
|
||
adc_raw[ADC_PSB_CHANNEL] = raw;
|
||
return actual_adc_convert_percent(raw);
|
||
}
|
||
|
||
/**
|
||
* @brief 获取当前回路电流
|
||
* @return {float32} 回路电流值
|
||
* @note
|
||
*/
|
||
float32 get_current(void)
|
||
{
|
||
float32 f = 0.0;
|
||
|
||
// 读取回路电流ADC值
|
||
adc_raw[ADC_LOOP_CHANNEL] = adc_result_average(ADCS_1, ADC_LOOP_CHANNEL);
|
||
f = adc_raw[ADC_LOOP_CHANNEL];
|
||
|
||
// 计算回路电流
|
||
f *= calib_param[CALIBPARA_LOOP].value[0];
|
||
f += calib_param[CALIBPARA_LOOP].value[1];
|
||
f = f / 100;
|
||
|
||
if (f < 0)
|
||
{
|
||
f = 0;
|
||
}
|
||
|
||
return 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 * 10) * 0.1f;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @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 = lpf_update(&lpf_temperature, tmp);
|
||
return tmp;
|
||
}
|
||
|
||
/**
|
||
* @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.4) * 600 / 1.6;
|
||
|
||
return v < 0 ? 0 : v;
|
||
}
|
||
|
||
/**
|
||
* @brief 获取当前压力
|
||
* @return {float32} 压力值
|
||
* @note
|
||
*/
|
||
float32 get_pressure(pressure_index_e id)
|
||
{
|
||
float32 f = 0.0;
|
||
|
||
switch (id)
|
||
{
|
||
case ADC_INDEX_PRESSSOURCE:
|
||
// 读取气源压力ADC
|
||
adc_raw[ADC_BP_CHANNEL] = adc_result_average(ADCS_1, ADC_BP_CHANNEL);
|
||
f = adc_raw[ADC_BP_CHANNEL];
|
||
// 计算气源压力
|
||
f *= calib_param[CALIBPARA_PS].value[0];
|
||
f += calib_param[CALIBPARA_PS].value[1];
|
||
rt_data.pressure_s = f;
|
||
break;
|
||
case ADC_INDEX_PRESSOUTA:
|
||
// 读取A路压力ADC
|
||
adc_raw[ADC_BPA_CHANNEL] = adc_result_average(ADCS_1, ADC_BPA_CHANNEL);
|
||
f = adc_raw[ADC_BPA_CHANNEL];
|
||
// 计算A路压力
|
||
f *= calib_param[CALIBPARA_PSB].value[0];
|
||
f += calib_param[CALIBPARA_PSB].value[1];
|
||
rt_data.pressure_a = f;
|
||
break;
|
||
case ADC_INDEX_PRESSOUTB:
|
||
// 读取B路压力ADC
|
||
adc_raw[ADC_BPB_CHANNEL] = adc_result_average(ADCS_1, ADC_BPB_CHANNEL);
|
||
f = adc_raw[ADC_BPB_CHANNEL];
|
||
// 计算B路压力
|
||
f *= calib_param[CALIBPARA_PB].value[0];
|
||
f += calib_param[CALIBPARA_PB].value[1];
|
||
rt_data.pressure_b = f;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
return f;
|
||
}
|
||
|
||
/***************************** 通过电阻测算,只在测试程序中使用 *****************************/
|
||
/**
|
||
* @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 * VREF_VALUE)) / 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] / (float32)(10 * 101);
|
||
return cur;
|
||
}
|
||
|
||
/**
|
||
* @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;
|
||
|
||
float32 duty = current / 30;
|
||
uint16_t count = duty * 4095;
|
||
PWM_CTRL_OUTPUT(count);
|
||
}
|
||
|
||
/**
|
||
* @brief 获取RTC时间
|
||
* @param {uDateTime_TypeDef} *time
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void get_timestamp(uDateTime_TypeDef *time)
|
||
{
|
||
uint8_t tmp[7];
|
||
rtc_get_clock_time(tmp);
|
||
|
||
time->Date.Year = tmp[6]; // 将年存储在data结构体的year字段中
|
||
time->Date.Month = tmp[5]; // 将月存储在data结构体的month字段中
|
||
time->Date.Day = tmp[4]; // 将日存储在data结构体的day字段中
|
||
time->Date.Hour = tmp[2]; // 将时存储在data结构体的hour字段中
|
||
time->Date.Minute = tmp[1]; // 将分存储在data结构体的minute字段中
|
||
time->Date.Second = tmp[0]; // 将秒存储在data结构体的second字段中
|
||
}
|
||
|
||
void get_real_time(uint8_t *year, uint8_t *month, uint8_t *day, uint8_t *hour, uint8_t *min, uint8_t *sec)
|
||
{
|
||
get_timestamp((uDateTime_TypeDef *)&rt_data.save.real_time);
|
||
*year = hex_format_dec(rt_data.save.real_time.Date.Year);
|
||
*month = hex_format_dec(rt_data.save.real_time.Date.Month);
|
||
*day = hex_format_dec(rt_data.save.real_time.Date.Day);
|
||
*hour = hex_format_dec(rt_data.save.real_time.Date.Hour);
|
||
*min = hex_format_dec(rt_data.save.real_time.Date.Minute);
|
||
*sec = hex_format_dec(rt_data.save.real_time.Date.Second);
|
||
}
|
||
|
||
void 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 = year,
|
||
.month = month,
|
||
.day = day,
|
||
.hour = hour,
|
||
.minute = min,
|
||
.second = sec,
|
||
.weekday = get_weekday(2000 + hex_format_dec(year),
|
||
hex_format_dec(month),
|
||
hex_format_dec(day)),
|
||
};
|
||
rtc_weekday_convert(&date.weekday);
|
||
rtc_set_clock_time(&date);
|
||
get_timestamp((uDateTime_TypeDef *)&rt_data.save.real_time);
|
||
}
|
||
|
||
/**
|
||
* @brief 设置输出PWM校准电流
|
||
* @return {*}
|
||
* @note 计算公式如下:
|
||
* > y = k*x + m (x表示电流,y表示PWM占空比) <p>
|
||
* > k = (TDuty20 - TDuty4) / (mA20 - mA4) <p>
|
||
* > m = TDuty20 - k * mA20 <p>
|
||
*/
|
||
|
||
void set_pwm_calib_current()
|
||
{
|
||
float32 mA4 = 400;
|
||
float32 mA20 = 2000;
|
||
float32 TDuty4 = udevice.output_4ma_duty;
|
||
float32 TDuty20 = udevice.output_20ma_duty;
|
||
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 读取4mA输入时的ADC电压
|
||
* @return {*}
|
||
*/
|
||
void set_loop_4ma(void)
|
||
{
|
||
board_cache[BOARD_CACHE_1] = adc_result_average(ADCS_1, ADC_LOOP_CHANNEL); // 获取4mA输入时adc值
|
||
}
|
||
|
||
/**
|
||
* @brief 读取20mA输入时的ADC值
|
||
* @return {*}
|
||
*/
|
||
void set_loop_20ma(void)
|
||
{
|
||
board_cache[BOARD_CACHE_2] = adc_result_average(ADCS_1, ADC_LOOP_CHANNEL);
|
||
}
|
||
|
||
/**
|
||
* @brief 读取200kPa输入时的ADC电压
|
||
* @return {*}
|
||
*/
|
||
void set_200kpa(void)
|
||
{
|
||
board_cache[BOARD_CACHE_1] = adc_result_average(ADCS_1, ADC_BP_CHANNEL); // 获取200kPa时adc值
|
||
}
|
||
|
||
/**
|
||
* @brief 读取400kPa输入时的ADC电压
|
||
* @return {*}
|
||
*/
|
||
void set_400kpa(void)
|
||
{
|
||
board_cache[BOARD_CACHE_2] = adc_result_average(ADCS_1, ADC_BP_CHANNEL);
|
||
}
|
||
|
||
/**
|
||
* @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 (app_preload_language_flag != flag)
|
||
{
|
||
app_preload_language_flag = flag;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 设置预加载BOOTLOAD标志位
|
||
* @param {uint8_t} flag
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void set_app_preload_bootload_flag(uint8_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
|
||
*/
|
||
BOOL get_app_preload_bootload_flag(void)
|
||
{
|
||
return app_preload_bootload_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;
|
||
}
|