refactor(vd960Loop): 算法回退到 DLD154V4B,四通道适配

- 用 DLD154V4B vd1_task/per_channel 替换 vds_task 复杂算法
- 移除 FUNCTION_B/二次判断/快速变化/多重确认等增强特性
- 保留平坦性离开算法 (CN200910309382),每通道独立状态
- 灵敏度表改为 DLD154V4B 4级: {216,108,36,10} / {108,72,18,9}
- 清理废弃类型: FltHistoryManager, Loop_ACS_Info, StageRangeConfig 等
- 首次添加 vd960DBN 完整源码
This commit is contained in:
wangfq
2026-06-25 16:21:57 +08:00
parent 6fd4e564e3
commit 95808f9f25
966 changed files with 406958 additions and 84 deletions
@@ -0,0 +1,173 @@
/*
FreeRTOS V10.4.3 - Copyright (C) 2020 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
***************************************************************************
>>! NOTE: The modification to the GPL is included to allow you to !<<
>>! distribute a combined work that includes FreeRTOS without being !<<
>>! obliged to provide the source code for proprietary components !<<
>>! outside of the FreeRTOS kernel. !<<
***************************************************************************
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available on the following
link: http://www.freertos.org/a00114.html
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that is more than just the market leader, it *
* is the industry's de facto standard. *
* *
* Help yourself get started quickly while simultaneously helping *
* to support the FreeRTOS project by purchasing a FreeRTOS *
* tutorial book, reference manual, or both: *
* http://www.FreeRTOS.org/Documentation *
* *
***************************************************************************
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
the FAQ page "My application does not run, what could be wrong?". Have you
defined configASSERT()?
http://www.FreeRTOS.org/support - In return for receiving this top quality
embedded software for free we request you assist our global community by
participating in the support forum.
http://www.FreeRTOS.org/training - Investing in training allows your team to
be as productive as possible as early as possible. Now you can receive
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
Ltd, and the world's leading authority on the world's leading RTOS.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and commercial middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
1 tab == 4 spaces!
* Copyright notice & Disclaimer
*
* The software Board Support Package (BSP) that is made available to
* download from Artery official website is the copyrighted work of Artery.
* Artery authorizes customers to use, copy, and distribute the BSP
* software and its related documentation for the purpose of design and
* development in conjunction with Artery microcontrollers. Use of the
* software is governed by this copyright notice and the following disclaimer.
*
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
*
**************************************************************************
*/
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
#include <stdint.h>
#include "system_at32f421.h"
#endif
/*-----------------------------------------------------------
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
*
* See http://www.freertos.org/a00110.html.
*----------------------------------------------------------*/
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configCPU_CLOCK_HZ ( ( unsigned long ) system_core_clock )
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES ( 5 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 128 )
#define configSUPPORT_DYNAMIC_ALLOCATION 1
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 8 * 1024 ) )
#define configMAX_TASK_NAME_LEN ( 16 )
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 0
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetCurrentTaskHandle 1
/* Cortex-M specific definitions. */
#ifdef __NVIC_PRIO_BITS
/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
#define configPRIO_BITS __NVIC_PRIO_BITS
#else
#define configPRIO_BITS 4 /* 15 priority levels */
#endif
/* The lowest interrupt priority that can be used in a call to a "set priority"
function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x0f
/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 0x01
/* Interrupt priorities used by the kernel port layer itself. These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* Normal assert() semantics without relying on the provision of an assert.h
header file. */
#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }
/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
standard names. */
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
#endif /* FREERTOS_CONFIG_H */
@@ -0,0 +1,194 @@
/**
**************************************************************************
* @file TaskLoop.h
* @version v2.0
* @date 2025-09-08 (original), 2026-06-25 (rewrite: DLD154V4B algo × 4ch)
* @brief 四路线圈检测 — 移植自 DLD154V4B 算法
*
* 算法来源: DLD154V4B vd1_task() + 平坦性离开 (CN200910309382)
* 改动: 单路全局变量 → Loop154_Unit 结构体数组,四路独立
**************************************************************************
*/
#ifndef __TASKLOOP_H__
#define __TASKLOOP_H__
#include <stdint.h>
#include <stddef.h>
/*===========================================================================
* 时序参数(每 tick = 50ms,由 TMR15 5ms×10 产生)
*===========================================================================*/
#define HOLD_TIME (5 * 1200) // 有限存在保持(约 5 分钟)
#define LC_HOLD_TIME (4 * 1200) // 安全复位时间(约 4 分钟)
#define IN_DELAY 10 // 进入防抖 500ms
#define OUT_DELAY 10 // 离开防抖 500ms
#define PULSE_DELAY 10 // 脉冲宽度 500ms
/*===========================================================================
* 滤波参数
*===========================================================================*/
#define ALFA_CAP1 79 // IIR 指数平滑 α = 79/256 ≈ 0.31
#define STABLE_SAMPLES 128 // 稳定期样本数
/*===========================================================================
* 离开检测: 1 = 平坦性三条件 (CN200910309382), 0 = cnt_release 防抖
*===========================================================================*/
#define USE_FLATNESS_EXIT 1
/*===========================================================================
* 平坦性参数
*===========================================================================*/
#define K1 8
#define K2 8
#define SLOPE_FLAT_THRESH 100
#define MIN_DELTA2 5
#define MIN_DELTA3 2
#define FLAT_CONFIRM_CNT 3
#define WINDOW_ORIGIN 100 // 基线跟踪窗口
/*===========================================================================
* 频率测量
* MEASUREMENT_BASE = 2^17 ≈ 131072
* LPCNT = MEASUREMENT_BASE / Xn, 使 Value 归一化到 ~131072
*===========================================================================*/
#define MEASUREMENT_BASE 131072
/*===========================================================================
* 通道数量
*===========================================================================*/
#define LOOP_CAPTURE_MAX 4
/*===========================================================================
* 灵敏度表(4级: 0=低, 3=高)
* 进入阈值 = Origin × SensTable[SENS] / 65536
* 离开阈值 = Origin × SensTable_1[SENS] / 65536
*===========================================================================*/
extern const uint16_t SensTable[4];
extern const uint16_t SensTable_1[4];
/*===========================================================================
* Forward declaration
*===========================================================================*/
struct tskTaskControlBlock;
typedef struct tskTaskControlBlock* TaskHandle_t;
/*===========================================================================
* 单通道状态结构体 — 对齐 DLD154V4B 全局变量
*===========================================================================*/
typedef struct {
uint8_t loop_num; // 通道编号 0~3
/*--- 捕获 & 测量 ---*/
uint16_t loop_Xn; // 相邻边沿周期差
uint16_t loop_CapThis, loop_CapLast;
uint16_t loop_LPCNT, loop_CapCnt;
uint32_t loop_CapSum, loop_Value;
uint32_t loop_CAPVD; // IIR 滤波后的频率值
uint32_t loop_Origin; // 基线(无车参考值)
uint32_t loop_ORG_SUM;
uint16_t loop_ORG_CNT;
uint16_t loop_dlt_ORG; // 当前灵敏度阈值
uint8_t Flt_Reg; // IIR 滤波系数
/*--- 标志位 ---*/
uint8_t loop_INI_LOOP;
uint8_t loop_CAP_OK; // 新测量数据就绪
uint8_t loop_VD_FLAG; // 有车标志
uint8_t loop_VD_HOLD; // 有限存在计时启用
uint8_t loop_RF_FLAG; // 本 tick 收到线圈振荡边沿
uint8_t loop_LOOP_OK; // 线圈连接正常
uint8_t loop_LOOP_OK0; // 上周期连接状态
uint8_t loop_FLAG_IN; // 进入延时中
uint8_t loop_FLAG_OUT; // 离开延时中
uint8_t loop_FLAG_PLUSE; // 脉冲输出中
uint8_t loop_SensLevel; // 灵敏度等级 0~3
uint8_t loop_cnt_release; // 离开防抖计数
uint8_t loop_stable; // 数值已稳定
#if USE_FLATNESS_EXIT
/*--- 平坦性离开状态 ---*/
uint8_t exit_state; // 0=追踪斜率, 1=等待平坦
uint16_t max_slope; // 第一上升坡面最大 |f'|
uint16_t max_slope_rate; // 最大 |f''|
uint16_t delta2; // Δ2: 一阶平坦阈值
uint16_t delta3; // Δ3: 二阶平坦阈值
int32_t prev_capvd; // 上一帧 CAPVD
int32_t prev_first_deriv; // 上一帧一阶导数
uint8_t slope_flat_cnt; // 斜率趋零连续计数
uint8_t flat_ok_cnt; // 平坦条件满足连续计数
#endif
/*--- 计数器 ---*/
uint16_t Hold_CNT;
uint8_t INCNT, OUTCNT;
/*--- 输出配置 ---*/
uint8_t SET_PLUS; // 0=脉冲, 1=存在输出
uint8_t SET_DLY; // 离开延时: 0=无, 1=500ms
uint8_t SET_SAFE; // 1=安全复位
/*--- 安全复位 ---*/
uint8_t LC_HOLD;
uint8_t LC_Reset;
uint32_t LC_Hold_CNT;
/*--- 断开检测 ---*/
uint8_t power_up_state; // 上电后是否曾连接
uint8_t disconnect_count; // 断开次数 (0~3)
uint8_t disconnect_active; // 当前断开中
uint8_t fault_phase;
uint16_t fault_tick;
/*--- 稳定期 ---*/
uint16_t stable_cnt;
/*--- 调试 ---*/
uint32_t xn_counter;
} Loop154_Unit;
/*===========================================================================
* 全局状态
*===========================================================================*/
typedef struct {
uint32_t report_counter;
Loop154_Unit loop_unit[LOOP_CAPTURE_MAX];
} Loop154_States;
extern Loop154_States g_loop_states;
/*===========================================================================
* 全局变量
*===========================================================================*/
extern uint32_t g_sys_freq;
extern uint8_t g_input_div;
extern uint32_t g_safe_max_cnt;
/*===========================================================================
* 函数声明
*===========================================================================*/
void loop_task_function(void *pvParameters);
void usart_task_function(void *pvParameters);
void led_indicator_task_function(void *pvParameters);
void vd1_task_per_channel(Loop154_Unit *unit);
void init_vd_single(Loop154_Unit *unit);
void INIT_VDs(Loop154_States *loops);
void poll_red_pwm(void);
void poll_green_led(Loop154_Unit *unit);
void poll_yellow_led_single(Loop154_Unit *unit);
uint32_t get_flt_value(uint32_t new_value, uint32_t last_Value);
uint8_t update_moving_average(uint32_t* p_sum, uint16_t* p_cnt,
uint32_t* p_origin, uint32_t new_value,
uint8_t window);
void set_loops_relay_on(uint8_t loop_num);
void set_loops_relay_off(uint8_t loop_num);
void wdt_feed(void);
extern TaskHandle_t usart_task_handler;
#endif /* __TASKLOOP_H__ */
@@ -0,0 +1,44 @@
/**
**************************************************************************
* @file at32f421_clock.h
* @brief header file of clock program
**************************************************************************
* Copyright notice & Disclaimer
*
* The software Board Support Package (BSP) that is made available to
* download from Artery official website is the copyrighted work of Artery.
* Artery authorizes customers to use, copy, and distribute the BSP
* software and its related documentation for the purpose of design and
* development in conjunction with Artery microcontrollers. Use of the
* software is governed by this copyright notice and the following disclaimer.
*
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
*
**************************************************************************
*/
/* define to prevent recursive inclusion -------------------------------------*/
#ifndef __AT32F421_CLOCK_H
#define __AT32F421_CLOCK_H
#ifdef __cplusplus
extern "C" {
#endif
/* includes ------------------------------------------------------------------*/
#include "at32f421.h"
/* exported functions ------------------------------------------------------- */
void system_clock_config(void);
#ifdef __cplusplus
}
#endif
#endif /* __AT32F421_CLOCK_H */
@@ -0,0 +1,137 @@
/**
**************************************************************************
* @file at32f421_conf.h
* @brief at32f421 config header file
**************************************************************************
* Copyright notice & Disclaimer
*
* The software Board Support Package (BSP) that is made available to
* download from Artery official website is the copyrighted work of Artery.
* Artery authorizes customers to use, copy, and distribute the BSP
* software and its related documentation for the purpose of design and
* development in conjunction with Artery microcontrollers. Use of the
* software is governed by this copyright notice and the following disclaimer.
*
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
*
**************************************************************************
*/
/* define to prevent recursive inclusion -------------------------------------*/
#ifndef __AT32F421_CONF_H
#define __AT32F421_CONF_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief in the following line adjust the value of high speed external crystal (hext)
* used in your application
*
* tip: to avoid modifying this file each time you need to use different hext, you
* can define the hext value in your toolchain compiler preprocessor.
*
*/
#if !defined HEXT_VALUE
#define HEXT_VALUE ((uint32_t)12000000) /*!< value of the high speed external crystal in hz */
#endif
/**
* @brief in the following line adjust the high speed external crystal (hext) startup
* timeout value
*/
#define HEXT_STARTUP_TIMEOUT ((uint16_t)0x3000) /*!< time out for hext start up */
#define HICK_VALUE ((uint32_t)8000000) /*!< value of the high speed internal clock in hz */
#define LEXT_VALUE ((uint32_t)32768) /*!< value of the low speed external clock in hz */
/* module define -------------------------------------------------------------*/
#define CRM_MODULE_ENABLED
#define CMP_MODULE_ENABLED
#define TMR_MODULE_ENABLED
#define ERTC_MODULE_ENABLED
#define GPIO_MODULE_ENABLED
#define I2C_MODULE_ENABLED
#define USART_MODULE_ENABLED
#define PWC_MODULE_ENABLED
#define ADC_MODULE_ENABLED
#define SPI_MODULE_ENABLED
#define DMA_MODULE_ENABLED
#define DEBUG_MODULE_ENABLED
#define FLASH_MODULE_ENABLED
#define CRC_MODULE_ENABLED
#define WWDT_MODULE_ENABLED
#define WDT_MODULE_ENABLED
#define EXINT_MODULE_ENABLED
#define MISC_MODULE_ENABLED
#define SCFG_MODULE_ENABLED
/* includes ------------------------------------------------------------------*/
#ifdef CRM_MODULE_ENABLED
#include "at32f421_crm.h"
#endif
#ifdef CMP_MODULE_ENABLED
#include "at32f421_cmp.h"
#endif
#ifdef TMR_MODULE_ENABLED
#include "at32f421_tmr.h"
#endif
#ifdef ERTC_MODULE_ENABLED
#include "at32f421_ertc.h"
#endif
#ifdef GPIO_MODULE_ENABLED
#include "at32f421_gpio.h"
#endif
#ifdef I2C_MODULE_ENABLED
#include "at32f421_i2c.h"
#endif
#ifdef USART_MODULE_ENABLED
#include "at32f421_usart.h"
#endif
#ifdef PWC_MODULE_ENABLED
#include "at32f421_pwc.h"
#endif
#ifdef ADC_MODULE_ENABLED
#include "at32f421_adc.h"
#endif
#ifdef SPI_MODULE_ENABLED
#include "at32f421_spi.h"
#endif
#ifdef DMA_MODULE_ENABLED
#include "at32f421_dma.h"
#endif
#ifdef DEBUG_MODULE_ENABLED
#include "at32f421_debug.h"
#endif
#ifdef FLASH_MODULE_ENABLED
#include "at32f421_flash.h"
#endif
#ifdef CRC_MODULE_ENABLED
#include "at32f421_crc.h"
#endif
#ifdef WWDT_MODULE_ENABLED
#include "at32f421_wwdt.h"
#endif
#ifdef WDT_MODULE_ENABLED
#include "at32f421_wdt.h"
#endif
#ifdef EXINT_MODULE_ENABLED
#include "at32f421_exint.h"
#endif
#ifdef MISC_MODULE_ENABLED
#include "at32f421_misc.h"
#endif
#ifdef SCFG_MODULE_ENABLED
#include "at32f421_scfg.h"
#endif
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,56 @@
/**
**************************************************************************
* @file at32f421_int.h
* @brief header file of main interrupt service routines.
**************************************************************************
* Copyright notice & Disclaimer
*
* The software Board Support Package (BSP) that is made available to
* download from Artery official website is the copyrighted work of Artery.
* Artery authorizes customers to use, copy, and distribute the BSP
* software and its related documentation for the purpose of design and
* development in conjunction with Artery microcontrollers. Use of the
* software is governed by this copyright notice and the following disclaimer.
*
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
*
**************************************************************************
*/
/* define to prevent recursive inclusion -------------------------------------*/
#ifndef __AT32F421_INT_H
#define __AT32F421_INT_H
#ifdef __cplusplus
extern "C" {
#endif
/* includes ------------------------------------------------------------------*/
#include "at32f421.h"
/* exported types ------------------------------------------------------------*/
/* exported constants --------------------------------------------------------*/
/* exported macro ------------------------------------------------------------*/
/* exported functions ------------------------------------------------------- */
void NMI_Handler(void);
void HardFault_Handler(void);
void MemManage_Handler(void);
void BusFault_Handler(void);
void UsageFault_Handler(void);
void SVC_Handler(void);
void DebugMon_Handler(void);
void PendSV_Handler(void);
void SysTick_Handler(void);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,99 @@
/**
**************************************************************************
* @file cmcng.h
* @version v1.0
* @date 2025-09-08
* @brief һЩ
**************************************************************************
* Copyright notice & Disclaimer
* * Create 2025-09-08 by wangfq
* *
**************************************************************************
*/
#ifndef __CMCNG_H__
#define __CMCNG_H__
#include <stdio.h>
#include <stdint.h>
#define PRODUCT_MODEL "DLD960"
#define FIRMWARE_VER "1.00"
#define HARDWARE_VER "1.00"
#define FIRMWARE_VER_MAIN 0
#define FIRMWARE_VER_SUB 30
#define FIRMWARE_VER_SSUB 0
#define HARDWARE_VER_MAIN 1
#define HARDWARE_VER_SUB 0
#define HARDWARE_VER_SSUB 0
#define FUNCTION_A 0x01 // 二次判断
#define FUNCTION_B 0x02 // 二次判断增强条件判断
#define FUNCTION_C 0x04 //
#define FUNCTION_D 0x08 //
#ifdef DEBUG
#define PRINT(X...) printf(X)
#else
#define PRINT(X...)
#endif
#define LOOP_CAPTURE_MAX 4 // 4 loop capture
#define CMD_DEV_Ver 0x4A // Version
#define CMD_DBN_SET_MCJQ_PARAM 0x63 // 设置 车检器多路参数
#define CMD_DBN_GET_MCJQ_PARAM 0x64 // 读取 车检器多路参数
#define CMD_DBN_DEV_RESET 0x6D
#define CMD_DBN_LOOP_SAMPLE_PARAM 0x87
#define CMD_DBN_LOOP_BALANCE_PARAM 0x88
#define CMD_DBN_LOOP_RELEASE_PLANB 0x89
#define CMD_DBN_LOOP_SENS_LIST 0x8A
#define CMD_DBN_SET_CJQ_FACTORY 0x92
#define CMD_SUB_SENS_REPORT 0xC0 //设备主动上报传感信息
// #define CMD_REQUIRE_DEV_MAC_ADDR 0xC1
// #define CMD_CHANGE_DEV_ADDR_BY_MAC 0xC2
// #define CMD_SET_LED 0xC3
// #define CMD_SET_RELAY 0xC4
#define CMD_SENS_ACS_ENABLE 0xC5 // 设备主动上报 使能
typedef enum
{
SENS_NONE = 0,
SENS_SUB_INFO = 1, // 传感器设备信息
SENS_OBJ_DYNAMIC = 2, // 动态目标类型
SENS_SOUTPUT_STATUS = 3, // 当前开关量输出的状态
SENS_DETAIL_CNG = 4, // 详细配置
SENS_LOOP_DYNAMIC = 5, // 线圈动态信息
SENS_OBJ_BackGround = 6, //
SENS_OBJ_INSIDE = 7, //
SENS_LOOP_TREND,
SENS_OBJ_DYNAMIC_SIMPLE,
SENS_OBJ_STATIC_XuJing, //10, 0x0A
SENS_DOBULE_LOOP_ESTIMATE, //0x0B, 线圈环境评估
SENS_MULTI_LOOP_DYNAMIC, // 0x0C, 多路线圈环境动态信息
} SUB_SENS_TYPE; // 传感数据类型
#define BUFF_STACK_SIZE 64
// USART1
#define USART1_RX_BUFFER_SIZE BUFF_STACK_SIZE
extern char usart1_rx_buffer[USART1_RX_BUFFER_SIZE];
typedef struct _PKG_UART_
{
uint8_t flag;
uint8_t offset;
uint8_t len;
uint8_t pkg[BUFF_STACK_SIZE];
uint32_t tick;
}Pkg_Uart;
extern Pkg_Uart g_pkg_uart_1;
extern Pkg_Uart g_pkg_uart_report;
void uart_report_packet_loop_acs(uint8_t flag);
#endif
@@ -0,0 +1,83 @@
/**
**************************************************************************
* @file flash.h
* @brief flash header file
**************************************************************************
* Copyright notice & Disclaimer
*
* The software Board Support Package (BSP) that is made available to
* download from Artery official website is the copyrighted work of Artery.
* Artery authorizes customers to use, copy, and distribute the BSP
* software and its related documentation for the purpose of design and
* development in conjunction with Artery microcontrollers. Use of the
* software is governed by this copyright notice and the following disclaimer.
*
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
*
**************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __FLASH_H__
#define __FLASH_H__
#include "at32f421_board.h"
/** @addtogroup AT32F421_periph_examples
* @{
*/
#define DLD_BUFEER_SIZE 100 // byte number, sector
#define DLD_FLASH_ADDRESS_START (0x08000000 + 1024 * 63 + 512) // The last sector
#define DLD_FLASH_MAX_SIZE (0x08000000 + 1024 * 64)
#define MAX_Store_Size DLD_BUFEER_SIZE
/** @addtogroup 421_FLASH_write_read
* @{
*/
/** @defgroup FLASH_write_read_functions
* @{
*/
void flash_read(uint32_t read_addr, uint16_t *p_buffer, uint16_t num_read);
error_status flash_write_nocheck(uint32_t write_addr, uint16_t *p_buffer, uint16_t num_write);
error_status flash_write(uint32_t write_addr,uint16_t *p_Buffer, uint16_t num_write);
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#endif
@@ -0,0 +1,70 @@
/**
**************************************************************************
* @file iap.h
* @brief iap header file
**************************************************************************
* Copyright notice & Disclaimer
*
* The software Board Support Package (BSP) that is made available to
* download from Artery official website is the copyrighted work of Artery.
* Artery authorizes customers to use, copy, and distribute the BSP
* software and its related documentation for the purpose of design and
* development in conjunction with Artery microcontrollers. Use of the
* software is governed by this copyright notice and the following disclaimer.
*
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
*
**************************************************************************
*/
#ifndef __IAP_H__
#define __IAP_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "at32f421_board.h"
/** @addtogroup UTILITIES_examples
* @{
*/
/** @addtogroup USART_iap_bootloader
* @{
*/
/** @defgroup bootloader_definition
* @{
*/
/* app starting address */
#define APP_START_ADDR 0x08003400
/* the previous sector of app starting address is iap upgrade flag */
#define IAP_UPGRADE_FLAG_ADDR (APP_START_ADDR - 0x800)
#define UPGRADE_DAT_START_ADDR APP_START_ADDR //0x0800A000 // 0x0804B000 // 0x08080000
/* when app received cmd 0x5aa5 from pc-tool, will set up the flag,
indicates that an app upgrade will follow, see iap application note for more details */
#define IAP_UPGRADE_FLAG 0x41544B38
#define IAP_UPGRADE_FLAG_9F 0x444C4439 //0x41544B39 //use 9F Protocol
#define IAP_UPGRADE_TYPE_DEFAULT 0
#define IAP_UPGRADE_TYPE_9F 1
#define IAP_CMD_READY 0xA5
#define IAP_CMD_ADDR_START 0xA6
#define IAP_CMD_TRAN_PKG_WITH_BACK 0xA7
#define IAP_CMD_TRAN_PKG_WITHOUT_OKBACK 0xA8
#endif
@@ -0,0 +1,187 @@
/*
* storage.h
*
* Created on: Aug 27, 2024
* Author: Thinkpad
*/
#ifndef INCLUDE_STORAGE_H_
#define INCLUDE_STORAGE_H_
#include <stdint.h>
#include <string.h>
#include "cmcng.h"
#define Addr_Dev_Flag_Offset 0x00
#define Addr_Sens_Amount_Offset 0x0E
#define Addr_Smart_Mode_Offset 0x0F
#define Addr_Loop_Cng_Offset 0x10
#define Addr_Loop_PlanB_Cng_Offset 0x30
#define Addr_Flag_Sample_In 0x30
#define Addr_Sample_Max_Amplitude 0x31
#define Addr_Flag_Balance_Ori_In 0x33
#define Addr_Balance_Ori_In_Max_Cnt 0x34
#define Addr_Flag_Release_Ori_PlanB 0x36
#define Addr_Release_Ori_PlanB_TimeOut 0x37
#define Addr_Release_Ori_PlanB_Weight 0x38
#define Addr_Release_Ori_Amplitude 0x39
#define Addr_Flag_Release_Rate 0x3B
#define Addr_Release_Rate_First 0x3C
#define Addr_Release_Rate_Second 0x3D
#define Addr_Release_Rate_Weight 0x3E
#define Addr_Release_Rate_Mode 0x3F
#define Addr_Loop_Sens_List_Offset 0x40
#define Addr_Sens_Array_In 0x40
#define Addr_Sens_Array_Out 0x50
#define MAX_LOOP_SENS_AMOUNT 8 // 4 // 5
extern const uint16_t SensTable[MAX_LOOP_SENS_AMOUNT];
extern const uint16_t SensTable_1[MAX_LOOP_SENS_AMOUNT];
#pragma pack(1)
typedef struct _Loop_Sample_CNG_
{
uint8_t flag;
uint16_t max_amplitude; // 最大幅值
}Loop_Sample_Cng;
typedef struct _Loop_Balance_Ori_CNG_
{
uint8_t flag;
uint16_t max_cnt ; // 最大补偿次数
}Loop_Balance_Ori_Cng; // 漂移补偿
typedef struct _Loop_Release_Ori_PlanB_
{
uint8_t flag_weight;
uint16_t max_amplitude; //最大幅值
uint8_t timeout; // 单位:分钟
}Loop_Release_Ori_PlanB;
typedef struct _Loop_Release_Change_Rate_
{
uint8_t flag_weight;
uint8_t rate_first;
uint8_t rate_second;
uint8_t mode;
}Loop_Release_Change_Rate;
typedef struct _Loop_Balance_PlanB_
{
Loop_Sample_Cng sample_cng;
Loop_Balance_Ori_Cng balance_ori_cng;
Loop_Release_Ori_PlanB release_ori_planB;
Loop_Release_Change_Rate release_change_rate;
}Loop_Balance_PlanB;
extern Loop_Balance_PlanB g_loop_balance_planB;
#define SENS_Default_Amount 4
typedef enum
{
Freq_High = 0,
Freq_Middle_High,
Freq_Middle_Low,
Freq_Low
} Freq_Level;
typedef enum
{
Smart_Mode_Disable = 0,
Smart_Mode_Enable
} Freq_Smart_Mode;
typedef enum
{
LNum_1 = 0,
LNum_2,
LNum_3,
LNum_4
} Loop_Num;
typedef struct
{
uint8_t sensitvity; // 高四位表示灵敏度的数量,低四位表示当前灵敏度的序号(从0开始)
uint8_t delay_time;
uint8_t output_mode;
uint8_t direction_mode; // 方向判别模式,0 触发模式, 非0 表示方向判别模式
uint8_t loopFreq_Level; // 高低频 0 High, 1 Middle High; 2 Middle Low, 3 Low
uint8_t loopSafe_Timeout; // 线圈安全模式, 0表示关闭,非0表示开启,以10秒为单位
uint8_t exist_mode; // 0 永久存在,非0,表示有限存在的时间,单位为10秒
uint8_t rfu;
}Loop_Cng_Unit;
// extern Loop_Cng_Unit g_loop_cng_unit[LOOP_CAPTURE_MAX];
typedef struct
{
uint8_t smart_mode; // 0 disable
Loop_Cng_Unit loop_cng[LOOP_CAPTURE_MAX];
}Loop_Cng_Info;
extern Loop_Cng_Info g_loop_cng_info;
typedef struct
{
uint16_t sens_in;
uint16_t sens_out;
}Loop_Single_Sens;
typedef struct
{
uint8_t total;
Loop_Single_Sens sens[MAX_LOOP_SENS_AMOUNT];
}Loop_Sens_List;
extern Loop_Sens_List g_loop_sens_list;
typedef struct _DBN_BLE_STATE_
{
uint8_t flag; // if need to report
uint8_t enable; // if enable
uint8_t send_flag;
uint8_t obj_amount;
uint8_t cmd;
uint8_t sens_type;
uint8_t dat_len ;
uint8_t dat_offset;
uint8_t pkg_amount;
uint8_t pkg_seq;
uint16_t interval;
uint32_t counter;
uint8_t timeout_min; // minute
uint32_t timeout_counter;
} DBN_BLE_State;
#pragma pack()
#define HOLD_TIME 5*1200
#define LC_HOLD_TIME 4*1200 // 4 minute
#define IN_DELAY 10
#define OUT_DELAY 39
#define PLUSE_DELAY 10
void set_flp_level(uint8_t loop_num, uint8_t freq_level);
void set_factory_param(void);
void storage_dev(void);
void para_store_init(void);
void test_factory(void);
#endif /* INCLUDE_STORAGE_H_ */
@@ -0,0 +1,710 @@
#include "TaskLoop.h"
#include "at32f421_board.h"
#include "cmcng.h"
#include "FreeRTOS.h"
#include "task.h"
#include <stdlib.h>
#include <string.h>
/*===========================================================================
* 灵敏度表 — 对齐 DLD154V4B / M1H
* 进入阈值 = Origin × SensTable[SENS] / 65536
* 离开阈值 = Origin × SensTable_1[SENS] / 65536 (滞回 ~50%
* SENS: 0=低灵敏, 3=高灵敏
*===========================================================================*/
const uint16_t SensTable[4] = {216, 108, 36, 10};
const uint16_t SensTable_1[4] = {108, 72, 18, 9};
/*===========================================================================
* 全局状态
*===========================================================================*/
Loop154_States g_loop_states = {{0}, {{{0}}}};
uint32_t g_sys_freq = 0;
uint8_t g_input_div = 1;
uint32_t g_safe_max_cnt = LC_HOLD_TIME;
/*===========================================================================
* 调试
*===========================================================================*/
uint8_t g_flag_output = 0;
uint8_t g_flag_output2 = 0;
/*===========================================================================
* 一阶 IIR 低通滤波器(对齐 DLD154V4B
* CAPVD_new = α·new_value + (1-α)·CAPVD_old, α = Flt_Reg/256
*===========================================================================*/
uint32_t get_flt_value(uint32_t new_value, uint32_t last_Value)
{
uint32_t value_Flt;
uint32_t delta = (new_value > last_Value)
? (new_value - last_Value)
: (last_Value - new_value);
uint32_t scaled_delta = (delta * (uint32_t)Flt_Reg) >> 8;
if (new_value > last_Value) {
value_Flt = last_Value + scaled_delta;
} else {
value_Flt = last_Value - scaled_delta;
}
return value_Flt;
}
/*===========================================================================
* 滑动平均基线更新
*===========================================================================*/
uint8_t update_moving_average(uint32_t* p_sum, uint16_t* p_cnt,
uint32_t* p_origin, uint32_t new_value,
uint8_t window)
{
if (!p_sum || !p_cnt || !p_origin || window == 0) return 0;
*p_sum += new_value;
(*p_cnt)++;
if (*p_cnt >= window) {
*p_origin = *p_sum / window;
*p_cnt = 0;
*p_sum = 0;
return 1;
}
return 0;
}
/*===========================================================================
* 继电器控制
*===========================================================================*/
void set_loops_relay_on(uint8_t loop_num)
{
switch(loop_num) {
case 0: RLY1_ON; break;
case 1: RLY2_ON; break;
case 2: RLY3_ON; break;
case 3: RLY4_ON; break;
}
}
void set_loops_relay_off(uint8_t loop_num)
{
switch(loop_num) {
case 0: RLY1_OFF; break;
case 1: RLY2_OFF; break;
case 2: RLY3_OFF; break;
case 3: RLY4_OFF; break;
}
}
/*===========================================================================
* 单通道初始化
*===========================================================================*/
void init_vd_single(Loop154_Unit *unit)
{
unit->loop_INCNT = 0;
unit->loop_OUTCNT = 0;
unit->loop_CapCnt = 0;
unit->loop_CapLast = 0;
unit->loop_LPCNT = 0;
unit->loop_INI_LOOP = 1;
unit->loop_VD_FLAG = 0;
unit->loop_RF_FLAG = 0;
unit->loop_LOOP_OK = 1;
unit->loop_LOOP_OK0 = 0;
unit->loop_CAP_OK = 0;
unit->loop_CAPVD = 0;
unit->loop_SensLevel = 2; // 默认中灵敏度
unit->Flt_Reg = ALFA_CAP1;
unit->loop_ORG_CNT = 0;
unit->loop_ORG_SUM = 0;
unit->loop_FLAG_IN = 0;
unit->loop_FLAG_OUT = 0;
unit->loop_FLAG_PLUSE = 0;
unit->loop_cnt_release = 0;
unit->loop_stable = 0;
#if USE_FLATNESS_EXIT
unit->exit_state = 0;
unit->max_slope = 0;
unit->max_slope_rate = 0;
unit->delta2 = 0;
unit->delta3 = 0;
unit->prev_capvd = 0;
unit->prev_first_deriv = 0;
unit->slope_flat_cnt = 0;
unit->flat_ok_cnt = 0;
#endif
unit->LC_HOLD = 0;
unit->LC_Reset = 0;
unit->LC_Hold_CNT = 0;
unit->Hold_CNT = 0;
unit->power_up_state = 0;
unit->disconnect_count = 0;
unit->disconnect_active = 0;
unit->fault_phase = 0;
unit->fault_tick = 0;
unit->SET_PLUS = 1; // 存在输出
unit->SET_DLY = 0;
unit->SET_SAFE = 1;
unit->stable_cnt = 0;
unit->xn_counter = 0;
}
void INIT_VDs(Loop154_States *loops)
{
uint8_t i;
for (i = 0; i < LOOP_CAPTURE_MAX; i++) {
loops->loop_unit[i].loop_num = i;
init_vd_single(&loops->loop_unit[i]);
}
}
/*===========================================================================
* TMR3 输入捕获中断 — 四路线圈频率测量(对齐 DLD154V4B CAP0 ISR
*
* 每个通道独立捕获,使用 MEASUREMENT_BASE 自适应测量窗口。
* LPCNT = MEASUREMENT_BASE / Xn,使 Value ≈ 131072,无需后续 >> 移位。
*===========================================================================*/
void TMR3_GLOBAL_IRQHandler(void)
{
#define PROCESS_CHANNEL(ch_flag, ch_select, idx) \
if (tmr_interrupt_flag_get(TMR3, ch_flag) != RESET) { \
tmr_flag_clear(TMR3, ch_flag); \
uint16_t cap_this = tmr_channel_value_get(TMR3, ch_select); \
Loop154_Unit *unit = &g_loop_states.loop_unit[idx]; \
if (!unit->loop_RF_FLAG) { \
unit->loop_CapLast = cap_this; \
unit->loop_RF_FLAG = 1; \
} else { \
uint16_t xn; \
if (cap_this > unit->loop_CapLast) { \
xn = cap_this - unit->loop_CapLast; \
} else { \
xn = (0x10000 - unit->loop_CapLast) + cap_this; \
} \
unit->loop_Xn = xn; \
unit->xn_counter++; \
unit->loop_CapLast = cap_this; \
unit->loop_CapCnt++; \
if (unit->loop_INI_LOOP) { \
if (unit->loop_LPCNT == 0) { \
if (unit->loop_CapCnt > 10) { \
unit->loop_LPCNT = MEASUREMENT_BASE / xn; \
PRINT("Loop%d LPCNT:%d Xn:%d\n", idx+1, unit->loop_LPCNT, xn); \
if (unit->loop_LPCNT == 0) unit->loop_LPCNT = 100; \
unit->loop_CAPVD = 0; \
unit->loop_CapSum = 0; \
unit->loop_CapCnt = 0; \
} \
} else { \
unit->loop_CapSum += xn; \
if (unit->loop_CapCnt >= unit->loop_LPCNT) { \
unit->loop_CAPVD = unit->loop_CapSum; \
unit->loop_Origin = unit->loop_CAPVD; \
PRINT("Loop%d Origin:%d\n", idx+1, unit->loop_Origin); \
unit->loop_INI_LOOP = 0; \
unit->loop_CapSum = 0; \
unit->loop_Value = 0; \
unit->loop_CapCnt = 0; \
} \
} \
} else { \
unit->loop_CapSum += xn; \
if (unit->loop_CapCnt >= unit->loop_LPCNT) { \
unit->loop_Value = unit->loop_CapSum; \
unit->loop_CAP_OK = 1; \
unit->loop_CapSum = 0; \
unit->loop_CapCnt = 0; \
unit->loop_INI_LOOP = 0; \
} \
} \
} \
}
PROCESS_CHANNEL(TMR_C1_FLAG, TMR_SELECT_CHANNEL_1, 0)
PROCESS_CHANNEL(TMR_C2_FLAG, TMR_SELECT_CHANNEL_2, 1)
PROCESS_CHANNEL(TMR_C3_FLAG, TMR_SELECT_CHANNEL_3, 2)
PROCESS_CHANNEL(TMR_C4_FLAG, TMR_SELECT_CHANNEL_4, 3)
#undef PROCESS_CHANNEL
}
/*===========================================================================
* TMR15 定时器中断 — 5ms tick,主状态机(对齐 DLD154V4B Timer1 ISR
*
* 职责:
* 1. 50ms tick 分频
* 2. 四通道 进入/离开/脉冲 时序状态机
* 3. 有限存在超时 / 安全复位超时
* 4. 线圈载波检测 (RF_FLAG) 及继电器输出刷新
* 5. 呼吸灯、指示灯驱动
*===========================================================================*/
void TMR15_GLOBAL_IRQHandler(void)
{
static uint16_t _counter1_init = 0;
static uint8_t TM1cnt = 0;
uint8_t i;
if (tmr_interrupt_flag_get(TMR15, TMR_OVF_FLAG) != RESET) {
/*--- 上报计数器 ---*/
g_loop_states.report_counter++;
/*--- 50ms tick 分频 ---*/
TM1cnt++;
if (TM1cnt >= 10) {
TM1cnt = 0;
for (i = 0; i < LOOP_CAPTURE_MAX; i++) {
Loop154_Unit *unit = &g_loop_states.loop_unit[i];
/* FLAG_IN: 进入延时 500ms */
if (unit->loop_FLAG_IN) {
unit->INCNT++;
if (unit->INCNT > IN_DELAY) {
unit->loop_FLAG_IN = 0;
unit->INCNT = 0;
}
}
/* FLAG_OUT: 离开延时 → 脉冲 */
if (unit->loop_FLAG_OUT) {
if (!unit->SET_DLY) {
unit->OUTCNT++;
if (unit->OUTCNT > OUT_DELAY) {
unit->loop_FLAG_OUT = 0;
unit->loop_FLAG_PLUSE = 1;
unit->OUTCNT = 0;
}
} else {
unit->loop_FLAG_OUT = 0;
unit->loop_FLAG_PLUSE = 1;
unit->OUTCNT = 0;
}
}
/* FLAG_PLUSE: 脉冲宽度 500ms */
if (unit->loop_FLAG_PLUSE) {
unit->OUTCNT++;
if (unit->OUTCNT > PULSE_DELAY) {
unit->loop_FLAG_PLUSE = 0;
unit->OUTCNT = 0;
}
}
/* 有限存在超时 */
if (unit->loop_VD_HOLD) {
unit->Hold_CNT++;
if (unit->Hold_CNT > HOLD_TIME) {
unit->loop_VD_HOLD = 0;
unit->Hold_CNT = 0;
if (unit->loop_VD_FLAG) {
set_loops_relay_off(unit->loop_num);
}
}
}
/* 安全复位超时 */
if (unit->LC_HOLD) {
unit->LC_Hold_CNT++;
if (unit->LC_Hold_CNT > g_safe_max_cnt) {
unit->LC_Reset = 1;
unit->loop_INI_LOOP = 1;
unit->loop_LOOP_OK0 = 0;
unit->loop_stable = 0;
#if USE_FLATNESS_EXIT
unit->exit_state = 0;
unit->max_slope = 0;
unit->max_slope_rate = 0;
#endif
unit->LC_Hold_CNT = 0;
unit->loop_ORG_CNT = 0;
unit->loop_ORG_SUM = 0;
}
}
}
}
/*================================================================
* 线圈载波检测 & 继电器输出刷新(每 5ms)
*================================================================*/
for (i = 0; i < LOOP_CAPTURE_MAX; i++) {
Loop154_Unit *unit = &g_loop_states.loop_unit[i];
if (unit->loop_RF_FLAG) {
unit->loop_LOOP_OK = 1;
unit->loop_RF_FLAG = 0;
if (unit->LC_Reset == 0) {
if (unit->SET_PLUS) {
/* 存在输出模式:有车或离开延时中 */
if (unit->loop_VD_FLAG || unit->loop_FLAG_OUT)
set_loops_relay_on(unit->loop_num);
else
set_loops_relay_off(unit->loop_num);
} else {
/* 脉冲输出模式:脉冲期间吸合 */
if (unit->loop_FLAG_PLUSE)
set_loops_relay_on(unit->loop_num);
else
set_loops_relay_off(unit->loop_num);
}
}
} else {
unit->loop_LOOP_OK0 = unit->loop_LOOP_OK;
unit->loop_LOOP_OK = 0;
}
/*--- LED 指示 ---*/
poll_green_led(unit);
}
/*--- 呼吸灯 ---*/
poll_red_pwm();
tmr_flag_clear(TMR15, TMR_OVF_FLAG);
}
}
/*===========================================================================
* 绿灯指示 — 每通道独立
*
* 模式:
* 自检/稳定中 (loop_INI_LOOP || 未连 || !loop_stable):
* → 慢闪 (200ms 亮/灭)
* 正常工作:
* → 有车亮, 无车灭
*===========================================================================*/
void poll_green_led(Loop154_Unit *unit)
{
#define GREEN_SLOW_HALF 40 // 200ms (40 × 5ms)
static uint16_t _slow_tick[LOOP_CAPTURE_MAX] = {0};
uint8_t idx = unit->loop_num;
if (unit->disconnect_active) {
at32_led_off(idx);
_slow_tick[idx] = 0;
return;
}
if (unit->loop_INI_LOOP || !unit->power_up_state || !unit->loop_stable) {
_slow_tick[idx]++;
if (_slow_tick[idx] >= GREEN_SLOW_HALF) {
_slow_tick[idx] = 0;
at32_led_toggle(idx);
}
return;
}
_slow_tick[idx] = 0;
if (unit->loop_VD_FLAG)
at32_led_on(idx);
else
at32_led_off(idx);
}
/*===========================================================================
* vd1_task_per_channel — 核心检测算法(移植自 DLD154V4B vd1_task
*
* 每次 loop_CAP_OK 时调用。
* 流程:
* 1. IIR 滤波:CAPVD = α·Value + (1-α)·CAPVD
* 2. 稳定期:只跟踪基线,不检测车辆 (STABLE_SAMPLES=128)
* 3. 无车时:基线跟踪 + 进入检测(带基线污染保护)
* 4. 有车时:平坦性离开 (USE_FLATNESS_EXIT=1) 或 cnt_release 防抖
*===========================================================================*/
void vd1_task_per_channel(Loop154_Unit *unit)
{
if (unit->loop_Origin == 0) return;
/*--- 1. IIR 一阶低通滤波 ---*/
if (unit->loop_CAPVD == 0) {
unit->loop_CAPVD = unit->loop_Value;
} else {
uint8_t saved_flt_reg = Flt_Reg;
Flt_Reg = unit->Flt_Reg;
unit->loop_CAPVD = get_flt_value(unit->loop_Value, unit->loop_CAPVD);
Flt_Reg = saved_flt_reg;
}
/*--- 2. 稳定期:只跟踪基线,不检测车辆 ---*/
if (!unit->loop_stable) {
update_moving_average(&unit->loop_ORG_SUM, &unit->loop_ORG_CNT,
&unit->loop_Origin, unit->loop_CAPVD, WINDOW_ORIGIN);
unit->stable_cnt++;
if (unit->stable_cnt >= STABLE_SAMPLES) {
unit->loop_stable = 1;
PRINT("Loop%d stable, Origin:%d\n", unit->loop_num + 1, unit->loop_Origin);
}
return;
}
if (!unit->loop_VD_FLAG) {
/*================================================================
* 无车状态
*================================================================*/
/* 基线跟踪(有车时冻结)
* 保护: CAPVD 异常上升时暂停跟踪,防止基线被污染 */
unit->loop_dlt_ORG = ((uint32_t)unit->loop_Origin * SensTable[unit->loop_SensLevel]) >> 16;
{
int32_t dev = (int32_t)unit->loop_CAPVD - (int32_t)unit->loop_Origin;
if (dev < (int32_t)(unit->loop_dlt_ORG * 4)) {
update_moving_average(&unit->loop_ORG_SUM, &unit->loop_ORG_CNT,
&unit->loop_Origin, unit->loop_CAPVD, WINDOW_ORIGIN);
} else {
unit->loop_ORG_CNT = 0;
unit->loop_ORG_SUM = 0;
}
}
/* 进入检测 */
if (unit->loop_CAPVD < (unit->loop_Origin - unit->loop_dlt_ORG)) {
PRINT("Loop%d Car_In, Value:%d CAPVD:%d Origin:%d dlt:%d\n",
unit->loop_num + 1, unit->loop_Value, unit->loop_CAPVD,
unit->loop_Origin, unit->loop_dlt_ORG);
unit->loop_VD_FLAG = 1;
unit->loop_FLAG_IN = 1;
at32_led_on(unit->loop_num);
if (!unit->SET_SAFE) {
unit->LC_HOLD = 1;
} else {
unit->LC_HOLD = 0;
}
if (unit->LC_Reset)
unit->LC_Reset = 0;
unit->loop_ORG_CNT = 0;
unit->loop_ORG_SUM = 0;
#if USE_FLATNESS_EXIT
unit->exit_state = 0;
unit->max_slope = 0;
unit->max_slope_rate = 0;
unit->delta2 = 0;
unit->delta3 = 0;
unit->slope_flat_cnt = 0;
unit->flat_ok_cnt = 0;
#endif
}
} else {
#if USE_FLATNESS_EXIT
/*================================================================
* 有车状态 — 平坦性判定离开 (CN200910309382)
*================================================================*/
int32_t first_deriv, abs_fd, abs_sd, second_deriv;
first_deriv = (int32_t)unit->loop_CAPVD - unit->prev_capvd;
second_deriv = first_deriv - unit->prev_first_deriv;
abs_fd = (first_deriv >= 0) ? first_deriv : -first_deriv;
abs_sd = (second_deriv >= 0) ? second_deriv : -second_deriv;
if (unit->exit_state == 0) {
/* 追踪第一上升坡面最大斜率 */
if (abs_fd > unit->max_slope) unit->max_slope = abs_fd;
if (abs_sd > unit->max_slope_rate) unit->max_slope_rate = abs_sd;
if (abs_fd < SLOPE_FLAT_THRESH) {
unit->slope_flat_cnt++;
if (unit->slope_flat_cnt >= 3) {
unit->delta2 = unit->max_slope / K1;
unit->delta3 = unit->max_slope_rate / K2;
if (unit->delta2 < MIN_DELTA2) unit->delta2 = MIN_DELTA2;
if (unit->delta3 < MIN_DELTA3) unit->delta3 = MIN_DELTA3;
unit->exit_state = 1;
unit->flat_ok_cnt = 0;
}
} else {
unit->slope_flat_cnt = 0;
}
} else {
int32_t dev = (int32_t)unit->loop_CAPVD - (int32_t)unit->loop_Origin;
int32_t cond1 = (dev >= 0) ? dev : -dev;
unit->loop_dlt_ORG = ((uint32_t)unit->loop_Origin * SensTable_1[unit->loop_SensLevel]) >> 16;
if (cond1 < (int32_t)unit->loop_dlt_ORG && abs_fd < (int32_t)unit->delta2
&& abs_sd < (int32_t)unit->delta3) {
unit->flat_ok_cnt++;
if (unit->flat_ok_cnt >= FLAT_CONFIRM_CNT) {
PRINT("Loop%d Car_OFF_FLAT, CAPVD:%d Origin:%d d1:%d d2:%d d3:%d f':%d f'':%d\n",
unit->loop_num + 1, unit->loop_CAPVD, unit->loop_Origin,
unit->loop_dlt_ORG, unit->delta2, unit->delta3,
first_deriv, second_deriv);
unit->loop_VD_FLAG = 0;
unit->loop_FLAG_OUT = 1;
unit->loop_VD_HOLD = 0;
unit->LC_HOLD = 0;
unit->loop_ORG_CNT = 0;
unit->loop_ORG_SUM = 0;
unit->Hold_CNT = 0;
unit->flat_ok_cnt = 0;
unit->exit_state = 0;
}
} else {
unit->flat_ok_cnt = 0;
}
}
unit->prev_capvd = unit->loop_CAPVD;
unit->prev_first_deriv = first_deriv;
#else
/*================================================================
* 有车状态 — cnt_release 防抖离开
*================================================================*/
unit->loop_dlt_ORG = ((uint32_t)unit->loop_Origin * SensTable_1[unit->loop_SensLevel]) >> 16;
if ((unit->loop_Origin - unit->loop_dlt_ORG) < unit->loop_CAPVD) {
unit->loop_cnt_release++;
if (unit->loop_cnt_release >= 3) {
PRINT("Loop%d Car_OFF, Value:%d CAPVD:%d Origin:%d dlt:%d\n",
unit->loop_num + 1, unit->loop_Value, unit->loop_CAPVD,
unit->loop_Origin, unit->loop_dlt_ORG);
unit->loop_VD_FLAG = 0;
unit->loop_FLAG_OUT = 1;
unit->loop_VD_HOLD = 0;
unit->LC_HOLD = 0;
unit->loop_ORG_CNT = 0;
unit->loop_ORG_SUM = 0;
unit->Hold_CNT = 0;
unit->loop_cnt_release = 0;
}
} else {
if (unit->loop_cnt_release > 0) unit->loop_cnt_release = 0;
}
#endif
}
}
/*===========================================================================
* loop_task_function — FreeRTOS 主任务(对齐 DLD154V4B main 循环)
* 10ms 周期,独立处理每路线圈。
*===========================================================================*/
void loop_task_function(void *pvParameters)
{
uint8_t i;
g_sys_freq = g_crm_clocks_freq_struct.sclk_freq;
INIT_VDs(&g_loop_states);
while (1) {
for (i = 0; i < LOOP_CAPTURE_MAX; i++) {
Loop154_Unit *unit = &g_loop_states.loop_unit[i];
if (unit->loop_LOOP_OK) {
/* 线圈重连 */
if (!unit->loop_LOOP_OK0) {
unit->loop_LOOP_OK0 = 1;
unit->disconnect_active = 0;
unit->loop_CAPVD = 0; // 强制 IIR 重新收敛
}
if (unit->loop_CAP_OK) {
taskENTER_CRITICAL();
unit->loop_CAP_OK = 0;
taskEXIT_CRITICAL();
if (!unit->power_up_state) {
unit->power_up_state = 1;
}
/* 核心检测算法 */
vd1_task_per_channel(unit);
}
} else {
/* 线圈断开 */
set_loops_relay_off(unit->loop_num);
if (unit->power_up_state && !unit->disconnect_active) {
unit->disconnect_active = 1;
if (unit->disconnect_count < 3) {
unit->disconnect_count++;
}
unit->fault_phase = 0;
unit->fault_tick = 0;
}
}
}
wdt_feed();
vTaskDelay(10);
}
}
/*===========================================================================
* LED 指示灯后台任务 — 线圈未连接时的闪烁指示
*===========================================================================*/
void led_indicator_task_function(void *pvParameters)
{
uint8_t i;
static uint8_t led_step[LOOP_CAPTURE_MAX] = {0};
while (1) {
for (i = 0; i < LOOP_CAPTURE_MAX; i++) {
Loop154_Unit *unit = &g_loop_states.loop_unit[i];
if (unit->loop_LOOP_OK0 == 0) {
if (led_step[i] % 2 == 0) {
at32_led_toggle(i);
}
if (unit->loop_stable) {
unit->loop_LOOP_OK0 = 1;
continue;
}
led_step[i]++;
if (led_step[i] > 16) {
led_step[i] = 0;
unit->loop_LOOP_OK0 = 1;
at32_led_off(i);
}
}
}
vTaskDelay(200);
}
}
/*===========================================================================
* USART1 接收缓冲区 & 任务
*===========================================================================*/
char usart1_rx_buffer[USART1_RX_BUFFER_SIZE];
volatile uint16_t usart1_rx_head = 0;
volatile uint16_t usart1_rx_tail = 0;
TaskHandle_t usart_task_handler = NULL;
void usart_task_function(void *pvParameters)
{
while (1) {
if (g_pkg_uart_1.flag) {
manage_dbn_ble_default(g_pkg_uart_1.pkg, g_pkg_uart_1.offset);
InitPkgUart(&g_pkg_uart_1);
}
uart_report_packet_loop_acs(0);
#ifdef DEBUG
if (g_flag_output) {
g_flag_output = 0;
PRINT("xnC:%d,%d,%d,%d LPCNT:%d,%d,%d,%d CAPVD:%d,%d,%d,%d Origin:%d,%d,%d,%d VD:%d,%d,%d,%d\n",
g_loop_states.loop_unit[0].xn_counter, g_loop_states.loop_unit[1].xn_counter,
g_loop_states.loop_unit[2].xn_counter, g_loop_states.loop_unit[3].xn_counter,
g_loop_states.loop_unit[0].loop_LPCNT, g_loop_states.loop_unit[1].loop_LPCNT,
g_loop_states.loop_unit[2].loop_LPCNT, g_loop_states.loop_unit[3].loop_LPCNT,
g_loop_states.loop_unit[0].loop_CAPVD, g_loop_states.loop_unit[1].loop_CAPVD,
g_loop_states.loop_unit[2].loop_CAPVD, g_loop_states.loop_unit[3].loop_CAPVD,
g_loop_states.loop_unit[0].loop_Origin, g_loop_states.loop_unit[1].loop_Origin,
g_loop_states.loop_unit[2].loop_Origin, g_loop_states.loop_unit[3].loop_Origin,
g_loop_states.loop_unit[0].loop_VD_FLAG, g_loop_states.loop_unit[1].loop_VD_FLAG,
g_loop_states.loop_unit[2].loop_VD_FLAG, g_loop_states.loop_unit[3].loop_VD_FLAG);
g_loop_states.loop_unit[0].xn_counter = 0;
g_loop_states.loop_unit[1].xn_counter = 0;
g_loop_states.loop_unit[2].xn_counter = 0;
g_loop_states.loop_unit[3].xn_counter = 0;
}
#endif
vTaskDelay(10);
}
}
@@ -0,0 +1,97 @@
/**
**************************************************************************
* @file at32f421_clock.c
* @brief system clock config program
**************************************************************************
* Copyright notice & Disclaimer
*
* The software Board Support Package (BSP) that is made available to
* download from Artery official website is the copyrighted work of Artery.
* Artery authorizes customers to use, copy, and distribute the BSP
* software and its related documentation for the purpose of design and
* development in conjunction with Artery microcontrollers. Use of the
* software is governed by this copyright notice and the following disclaimer.
*
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
*
**************************************************************************
*/
/* includes ------------------------------------------------------------------*/
#include "at32f421_clock.h"
/**
* @brief system clock config program
* @note the system clock is configured as follow:
* system clock (sclk) = hext * pll_mult
* system clock source = pll (hext)
* - hext = HEXT_VALUE
* - sclk = 120000000
* - ahbdiv = 1
* - ahbclk = 120000000
* - apb2div = 1
* - apb2clk = 120000000
* - apb1div = 1
* - apb1clk = 120000000
* - pll_mult = 15
* - flash_wtcyc = 3 cycle
* @param none
* @retval none
*/
void system_clock_config(void)
{
/* reset crm */
crm_reset();
/* config flash psr register */
flash_psr_set(FLASH_WAIT_CYCLE_3);
crm_clock_source_enable(CRM_CLOCK_SOURCE_HEXT, TRUE);
/* wait till hext is ready */
while(crm_hext_stable_wait() == ERROR)
{
}
/* config pll clock resource */
crm_pll_config(CRM_PLL_SOURCE_HEXT, CRM_PLL_MULT_10);
/* enable pll */
crm_clock_source_enable(CRM_CLOCK_SOURCE_PLL, TRUE);
/* wait till pll is ready */
while(crm_flag_get(CRM_PLL_STABLE_FLAG) != SET)
{
}
/* config ahbclk */
crm_ahb_div_set(CRM_AHB_DIV_1);
/* config apb2clk, the maximum frequency of APB1/APB2 clock is 120 MHz */
crm_apb2_div_set(CRM_APB2_DIV_1);
/* config apb1clk, the maximum frequency of APB1/APB2 clock is 120 MHz */
crm_apb1_div_set(CRM_APB1_DIV_1);
/* enable auto step mode */
crm_auto_step_mode_enable(TRUE);
/* select pll as system clock source */
crm_sysclk_switch(CRM_SCLK_PLL);
/* wait till pll is used as system clock source */
while(crm_sysclk_switch_status_get() != CRM_SCLK_PLL)
{
}
/* disable auto step mode */
crm_auto_step_mode_enable(FALSE);
/* update system_core_clock global variable */
system_core_clock_update();
}
@@ -0,0 +1,142 @@
/**
**************************************************************************
* @file at32f421_int.c
* @brief main interrupt service routines.
**************************************************************************
* Copyright notice & Disclaimer
*
* The software Board Support Package (BSP) that is made available to
* download from Artery official website is the copyrighted work of Artery.
* Artery authorizes customers to use, copy, and distribute the BSP
* software and its related documentation for the purpose of design and
* development in conjunction with Artery microcontrollers. Use of the
* software is governed by this copyright notice and the following disclaimer.
*
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
*
**************************************************************************
*/
/* includes ------------------------------------------------------------------*/
#include "at32f421_int.h"
/** @addtogroup FreeRTOS_demo
* @{
*/
/**
* @brief this function handles nmi exception.
* @param none
* @retval none
*/
void NMI_Handler(void)
{
}
/**
* @brief this function handles hard fault exception.
* @param none
* @retval none
*/
void HardFault_Handler(void)
{
/* go to infinite loop when hard fault exception occurs */
while(1)
{
}
}
/**
* @brief this function handles memory manage exception.
* @param none
* @retval none
*/
void MemManage_Handler(void)
{
/* go to infinite loop when memory manage exception occurs */
while(1)
{
}
}
/**
* @brief this function handles bus fault exception.
* @param none
* @retval none
*/
void BusFault_Handler(void)
{
/* go to infinite loop when bus fault exception occurs */
while(1)
{
}
}
/**
* @brief this function handles usage fault exception.
* @param none
* @retval none
*/
void UsageFault_Handler(void)
{
/* go to infinite loop when usage fault exception occurs */
while(1)
{
}
}
/**
* @brief this function handles svcall exception.
* @param none
* @retval none
*/
//void SVC_Handler(void)
//{
//}
/**
* @brief this function handles debug monitor exception.
* @param none
* @retval none
*/
void DebugMon_Handler(void)
{
}
/**
* @brief this function handles pendsv_handler exception.
* @param none
* @retval none
*/
//void PendSV_Handler(void)
//{
//}
/**
* @brief this function handles systick handler.
* @param none
* @retval none
*/
//void SysTick_Handler(void)
//{
//}
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,195 @@
/**
**************************************************************************
* @file flash.c
* @brief flash program
**************************************************************************
* Copyright notice & Disclaimer
*
* The software Board Support Package (BSP) that is made available to
* download from Artery official website is the copyrighted work of Artery.
* Artery authorizes customers to use, copy, and distribute the BSP
* software and its related documentation for the purpose of design and
* development in conjunction with Artery microcontrollers. Use of the
* software is governed by this copyright notice and the following disclaimer.
*
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
*
**************************************************************************
*/
#include "at32f421_board.h"
#include "flash.h"
/** @addtogroup AT32F421_periph_examples
* @{
*/
/** @addtogroup 421_FLASH_write_read
* @{
*/
#define SECTOR_SIZE 512 //1024 /* this parameter depends on the specific model of the chip */
uint16_t flash_buf[SECTOR_SIZE / 2];
/**
* @brief read data using halfword mode
* @param read_addr: the address of reading
* @param p_buffer: the buffer of reading data
* @param num_read: the number of reading data
* @retval none
*/
void flash_read(uint32_t read_addr, uint16_t *p_buffer, uint16_t num_read)
{
uint16_t i;
for(i = 0; i < num_read; i++)
{
p_buffer[i] = *(uint16_t*)(read_addr);
read_addr += 2;
}
}
/**
* @brief write data using halfword mode without checking
* @param write_addr: the address of writing
* @param p_buffer: the buffer of writing data
* @param num_write: the number of writing data
* @retval result
*/
error_status flash_write_nocheck(uint32_t write_addr, uint16_t *p_buffer, uint16_t num_write)
{
uint16_t i;
flash_status_type status = FLASH_OPERATE_DONE;
for(i = 0; i < num_write; i++)
{
status = flash_halfword_program(write_addr, p_buffer[i]);
if(status != FLASH_OPERATE_DONE)
return ERROR;
write_addr += 2;
}
return SUCCESS;
}
/**
* @brief write data using halfword mode with checking
* @param write_addr: the address of writing
* @param p_buffer: the buffer of writing data
* @param num_write: the number of writing data
* @retval result
*/
error_status flash_write(uint32_t write_addr, uint16_t *p_buffer, uint16_t num_write)
{
uint32_t offset_addr = write_addr + DLD_FLASH_ADDRESS_START;
uint16_t i;
flash_status_type status = FLASH_OPERATE_DONE;
if(offset_addr < FLASH_BASE || (offset_addr + num_write) >= DLD_FLASH_MAX_SIZE){
return ERROR;
}
flash_unlock();
flash_read(DLD_FLASH_ADDRESS_START, flash_buf, DLD_BUFEER_SIZE);
/* wait for operation to be completed */
status = flash_operation_wait_for(ERASE_TIMEOUT);
if((status == FLASH_PROGRAM_ERROR) || (status == FLASH_EPP_ERROR))
flash_flag_clear(FLASH_PRGMERR_FLAG | FLASH_EPPERR_FLAG);
else if(status == FLASH_OPERATE_TIMEOUT)
return ERROR;
status = flash_sector_erase(DLD_FLASH_ADDRESS_START);
if(status != FLASH_OPERATE_DONE)
return ERROR;
for(i = 0; i < num_write; i++)
{
flash_buf[write_addr + i] = p_buffer[i];
}
if(flash_write_nocheck(DLD_FLASH_ADDRESS_START, flash_buf, SECTOR_SIZE / 2) != SUCCESS)
return ERROR;
flash_lock();
return SUCCESS;
}
error_status flash_write_old(uint32_t write_addr, uint16_t *p_buffer, uint16_t num_write)
{
uint32_t offset_addr;
uint32_t sector_position;
uint16_t sector_offset;
uint16_t sector_remain;
uint16_t i;
flash_status_type status = FLASH_OPERATE_DONE;
flash_unlock();
offset_addr = write_addr - FLASH_BASE;
sector_position = offset_addr / SECTOR_SIZE;
sector_offset = (offset_addr % SECTOR_SIZE) / 2;
sector_remain = SECTOR_SIZE / 2 - sector_offset;
if(num_write <= sector_remain)
sector_remain = num_write;
while(1)
{
flash_read(sector_position * SECTOR_SIZE + FLASH_BASE, flash_buf, SECTOR_SIZE / 2);
for(i = 0; i < sector_remain; i++)
{
if(flash_buf[sector_offset + i] != 0xFFFF)
break;
}
if(i < sector_remain)
{
/* wait for operation to be completed */
status = flash_operation_wait_for(ERASE_TIMEOUT);
if((status == FLASH_PROGRAM_ERROR) || (status == FLASH_EPP_ERROR))
flash_flag_clear(FLASH_PRGMERR_FLAG | FLASH_EPPERR_FLAG);
else if(status == FLASH_OPERATE_TIMEOUT)
return ERROR;
status = flash_sector_erase(sector_position * SECTOR_SIZE + FLASH_BASE);
if(status != FLASH_OPERATE_DONE)
return ERROR;
for(i = 0; i < sector_remain; i++)
{
flash_buf[i + sector_offset] = p_buffer[i];
}
if(flash_write_nocheck(sector_position * SECTOR_SIZE + FLASH_BASE, flash_buf, SECTOR_SIZE / 2) != SUCCESS)
return ERROR;
}
else
{
if(flash_write_nocheck(write_addr, p_buffer, sector_remain) != SUCCESS)
return ERROR;
}
if(num_write == sector_remain)
break;
else
{
sector_position++;
sector_offset = 0;
p_buffer += sector_remain;
write_addr += (sector_remain * 2);
num_write -= sector_remain;
if(num_write > (SECTOR_SIZE / 2))
sector_remain = SECTOR_SIZE / 2;
else
sector_remain = num_write;
}
}
flash_lock();
return SUCCESS;
}
/**
* @}
*/
/**
* @}
*/
@@ -0,0 +1,50 @@
/**
**************************************************************************
* @file include_port.c
* @brief include_port program
**************************************************************************
* Copyright notice & Disclaimer
*
* The software Board Support Package (BSP) that is made available to
* download from Artery official website is the copyrighted work of Artery.
* Artery authorizes customers to use, copy, and distribute the BSP
* software and its related documentation for the purpose of design and
* development in conjunction with Artery microcontrollers. Use of the
* software is governed by this copyright notice and the following disclaimer.
*
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
*
**************************************************************************
*/
/** @addtogroup UTILITIES_examples
* @{
*/
/** @addtogroup FreeRTOS_demo
* @{
*/
/* support ac5 and ac6 compiler */
#if (__ARMCC_VERSION > 6000000)
#include "..\..\..\middlewares\freertos\source\portable\GCC\ARM_CM3\port.c"
#else
#include "..\..\..\middlewares\freertos\source\portable\rvds\ARM_CM3\port.c"
#endif
/**
* @}
*/
/**
* @}
*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,233 @@
#include "storage.h"
#include "flash.h"
#include <stdlib.h>
#include "TaskLoop.h"
Loop_Balance_PlanB g_loop_balance_planB;
Loop_Cng_Info g_loop_cng_info = {0, {0}};
Loop_Sens_List g_loop_sens_list;
uint8_t loop_cng_default[8] = {2,1,0,0,4,0,0,0};
uint8_t loops_cng_default[LOOP_CAPTURE_MAX][8] = {
{2, 1, 0, 0, Freq_Low, 0, 0, 0 },
{2, 1, 0, 0, Freq_Middle_High, 0, 0, 0},
{2, 1, 0, 0, Freq_Middle_Low, 0, 0, 0 },
{2, 1, 0, 0, Freq_Low, 0, 0, 0 }
};
void set_factory_param(void)
{
uint8_t i;
g_loop_cng_info.smart_mode = Smart_Mode_Disable;
Loop_Cng_Unit *unit = g_loop_cng_info.loop_cng;
for(i = 0; i < LOOP_CAPTURE_MAX; i++)
{
memcpy(unit, loops_cng_default[i], 8);
unit++;
}
g_loop_sens_list.total = SENS_Default_Amount;
for(i = 0; i < g_loop_sens_list.total && i < 4; i++)
{
g_loop_sens_list.sens[i].sens_in = SensTable[i];
g_loop_sens_list.sens[i].sens_out = SensTable_1[i];
}
}
void storage_dev(void)
{
uint8_t i = 0, k = 0;
uint8_t *rBuf = (uint8_t *)malloc(MAX_Store_Size);
if(rBuf == NULL){
// PRINT("Not enough memory!!");
nvic_system_reset();
}
for(i = 0; i < MAX_Store_Size; i++){
rBuf[i] = 0;
}
PRINT("Will_storage_dev\r\n");
rBuf[0] = 0x33;
rBuf[1] = 0xBB;
rBuf[2] = 0xC3;
rBuf[3] = 0x3C;
// g_freq_sens = 1;
rBuf[Addr_Sens_Amount_Offset] = g_loop_sens_list.total;
rBuf[Addr_Smart_Mode_Offset] = g_loop_cng_info.smart_mode;
i = Addr_Loop_Cng_Offset;
memcpy(&rBuf[i], (uint8_t *)g_loop_cng_info.loop_cng, sizeof(Loop_Cng_Unit) * LOOP_CAPTURE_MAX );
i += sizeof(Loop_Cng_Unit) * LOOP_CAPTURE_MAX;
// i = Addr_Loop_PlanB_Cng_Offset;
// rBuf[i++] = g_loop_balance_planB.sample_cng.flag;
// rBuf[i++] = g_loop_balance_planB.sample_cng.max_amplitude;
// rBuf[i++] = g_loop_balance_planB.sample_cng.max_amplitude >> 8;
// rBuf[i++] = g_loop_balance_planB.balance_ori_cng.flag;
// rBuf[i++] = g_loop_balance_planB.balance_ori_cng.max_cnt;
// rBuf[i++] = g_loop_balance_planB.balance_ori_cng.max_cnt >> 8;
// rBuf[i++] = g_loop_balance_planB.release_ori_planB.flag_weight;
// rBuf[i++] = g_loop_balance_planB.release_ori_planB.max_amplitude;
// rBuf[i++] = g_loop_balance_planB.release_ori_planB.max_amplitude >> 8;
// rBuf[i++] = g_loop_balance_planB.release_ori_planB.timeout;
//
// rBuf[i++] = g_loop_balance_planB.release_change_rate.flag_weight;
// rBuf[i++] = g_loop_balance_planB.release_change_rate.rate_first;
// rBuf[i++] = g_loop_balance_planB.release_change_rate.rate_second;
// rBuf[i++] = g_loop_balance_planB.release_change_rate.mode;
i = Addr_Loop_Sens_List_Offset;
if(g_loop_sens_list.total > MAX_LOOP_SENS_AMOUNT)
{
g_loop_sens_list.total = MAX_LOOP_SENS_AMOUNT;
}
for(k = 0; k < MAX_LOOP_SENS_AMOUNT; k++)
{
rBuf[i++] = g_loop_sens_list.sens[k].sens_in;
rBuf[i++] = g_loop_sens_list.sens[k].sens_in >> 8;
rBuf[i++] = g_loop_sens_list.sens[k].sens_out;
rBuf[i++] = g_loop_sens_list.sens[k].sens_out >> 8;
}
// PRINT("Will_write: \n");
// for(i = 0; i < MAX_Store_Size; i++)
// {
// PRINT(" %02X", rBuf[i]);
// }
flash_write(Addr_Dev_Flag_Offset, (uint16_t *)rBuf, DLD_BUFEER_SIZE/2);
free(rBuf);
}
// set frequent level
void set_flp_level(uint8_t loop_num, uint8_t freq_level)
{
switch( freq_level)
{
case Freq_High: // 33nF
{
if(loop_num == 0) { FLPA1_HIGH; FLPA2_HIGH; }
else if(loop_num == 1){ FLPB1_HIGH; FLPB2_HIGH; }
else if(loop_num == 2){ FLPC1_HIGH; FLPC2_HIGH; }
else if(loop_num == 3){ FLPD1_HIGH; FLPD2_HIGH; }
} break;
case Freq_Middle_High: // 43nF
{
if(loop_num == 0) { FLPA1_HIGH; FLPA2_LOW; }
else if(loop_num == 1){ FLPB1_HIGH; FLPB2_LOW; }
else if(loop_num == 2){ FLPC1_HIGH; FLPC2_LOW; }
else if(loop_num == 3){ FLPD1_HIGH; FLPD2_LOW; }
} break;
case Freq_Middle_Low: // 66nF
{
if(loop_num == 0) { FLPA1_LOW; FLPA2_HIGH; }
else if(loop_num == 1){ FLPB1_LOW; FLPB2_HIGH; }
else if(loop_num == 2){ FLPC1_LOW; FLPC2_HIGH; }
else if(loop_num == 3){ FLPD1_LOW; FLPD2_HIGH; }
} break;
case Freq_Low: //76nF
{
if(loop_num == 0) { FLPA1_LOW; FLPA2_LOW; }
else if(loop_num == 1){ FLPB1_LOW; FLPB2_LOW; }
else if(loop_num == 2){ FLPC1_LOW; FLPC2_LOW; }
else if(loop_num == 3){ FLPD1_LOW; FLPD2_LOW; }
} break;
}
}
void para_store_init(void)
{
uint8_t i;
uint8_t *rBuf = (uint8_t *)malloc(MAX_Store_Size);
if(rBuf == NULL){
// PRINT("Not enough memory!!");
nvic_system_reset();
}
memset(rBuf, 0, MAX_Store_Size);
flash_read(DLD_FLASH_ADDRESS_START, (uint16_t *)rBuf, MAX_Store_Size/2);
PRINT("Read_Cng_Store:\n");
for(i = 0; i < MAX_Store_Size; i++){
PRINT("%02X ", rBuf[i]);
}
PRINT("\n");
if(rBuf[0] == 0x33 && rBuf[1] == 0xBB && rBuf[2] == 0xC3 && rBuf[3] == 0x3C){
g_loop_sens_list.total = rBuf[Addr_Sens_Amount_Offset];
g_loop_cng_info.smart_mode = rBuf[Addr_Smart_Mode_Offset];
memcpy(g_loop_cng_info.loop_cng, &rBuf[Addr_Loop_Cng_Offset], sizeof(Loop_Cng_Unit) * LOOP_CAPTURE_MAX);
memcpy(&g_loop_sens_list.sens, &rBuf[Addr_Loop_Sens_List_Offset], sizeof(g_loop_sens_list) - 1);
Loop_Cng_Unit *unitout = g_loop_cng_info.loop_cng;
for(i = 0; i < LOOP_CAPTURE_MAX; i++)
{
PRINT("loop_%d, sens:%d,delay:%d, exit_mode:%d, out_put:%d\n", i, unitout->sensitvity, unitout->delay_time, unitout->exist_mode, unitout->output_mode);
set_flp_level(i, unitout->loopFreq_Level);
// 同步灵敏度到检测单元
g_loop_states.loop_unit[i].loop_SensLevel = unitout->sensitvity & 0x03;
g_loop_states.loop_unit[i].SET_PLUS = unitout->output_mode & 0x01;
g_loop_states.loop_unit[i].SET_DLY = (unitout->output_mode >> 1) & 0x01;
unitout++;
}
// g_loop_out_delay = g_loop_cng_unit.delay_time * 2; // 定时器以 50ms 为单位, 延时以100ms为单位
// g_hold_time = g_loop_cng_unit.exist_mode * 30 * 20; //50ms/per, 30s
// g_safe_max_cnt = g_loop_cng_unit.loopSafe_Timeout * 10 * (1000 / 50);
// g_freq_level = g_loop_cng_unit.loopFreq_Level - 1;
// flt_mgr.max_cnt_flat_release = g_loop_cng_unit.delay_time * 20 /2;
// if(flt_mgr.max_cnt_flat_release < 40){ // 至少检查400毫秒
// flt_mgr.max_cnt_flat_release = 40;
// }
free(rBuf);
}
else{
free(rBuf);
//TODO: need to be normal
set_factory_param();
storage_dev();
//
delay_ms(10);
nvic_system_reset();
}
}
void test_factory(void)
{
set_factory_param();
storage_dev();
// delay_ms(10);
}