zhoujie 4f8feccc06 feat(filesystem): 增强SD卡文件系统挂载与格式化逻辑
- 添加工作缓冲区以支持带参数的格式化操作
- 重构挂载逻辑,在挂载成功后验证文件系统类型和簇大小是否符合目标格式(FAT32,簇大小32KB)
- 将格式化条件判断与执行分离,提高代码可读性
- 使用宏定义目标簇大小和扇区大小参数,便于维护

🔧 chore(scripts): 重命名脚本文件并添加压缩包

- 将`atem_parse.py`重命名为`ATEMParse.py`以遵循命名规范
- 添加`ATEMParse.7z`压缩包文件
2026-03-07 13:54:52 +08:00

865 lines
25 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "dma.h"
#include "fatfs.h"
#include "sdio.h"
#include "spi.h"
#include "tim.h"
#include "usart.h"
#include "usb_device.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "ltc2508_driver.h"
#include "rs485_driver.h"
#include "data_packet.h"
#include "correction.h"
#include "data_storage.h"
#include "system_monitor.h"
#include "config_manager.h"
#include "gps_driver.h"
#include <stdio.h>
#include <string.h>
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
// 监控功能宏开关(统一控制串口输出和文件存储)
#define ENABLE_SYSTEM_MONITOR 1 // 系统监控开关
#define DEBUG_OUTPUT_INTERVAL_MS 30000 // 调试输出间隔(毫秒)
#define MONITOR_SAVE_INTERVAL_MS 30000 // 监控状态保存间隔(毫秒) - 30秒
// 数据输出模式选择运行时配置从SD卡加载
// 注意DATA_OUTPUT_MODE_UART 和 DATA_OUTPUT_MODE_STORAGE 已改为运行时配置
// 使用 Config_IsUartOutputEnabled() 和 Config_IsStorageEnabled() 来检查状态
// 配置文件0:/CONFIG.TXT
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
// 外部SPI句柄声明
extern SPI_HandleTypeDef hspi1;
extern SPI_HandleTypeDef hspi2;
extern SPI_HandleTypeDef hspi3;
extern TIM_HandleTypeDef htim2;
extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart3;
// 校正参数
CorrectionParams_t g_correction_params;
// 数据包
DataPacket_t g_data_packet;
CorrectedDataPacket_t g_corrected_packet;
CorrectedDataPacketWithGPS_t g_corrected_packet_with_gps; // 带GPS信息的数据包
// 数据存储句柄
DataStorageHandle_t g_data_storage;
// 系统状态
static uint8_t g_recording_enabled = 0;
// USB连接状态管理
static uint8_t g_usb_connected = 0;
static uint8_t g_fatfs_mounted_for_sampling = 0;
static uint32_t g_last_usb_check = 0;
// 性能监控和调试输出
static uint32_t g_last_debug_output = 0;
// 监控状态保存
static uint32_t g_last_monitor_save = 0;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
static void StartRecording(void);
static void StopRecording(void);
static void ProcessAdcData(void);
// USB连接状态管理函数
static uint8_t CheckUSBConnectionStatus(void);
static void HandleUSBConnectionChange(void);
static HAL_StatusTypeDef MountFileSystemForSampling(void);
static void UnmountFileSystemForSampling(void);
static void DebugOutput_Init(void);
static void DebugOutput_SendString(const char* str);
static void DebugOutput_PrintSystemStats(void);
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/**
* @brief 开始数据记录
* @retval None
*/
static void StartRecording(void)
{
if (!g_recording_enabled) {
if (DataStorage_StartRecording(&g_data_storage) == HAL_OK) {
g_recording_enabled = 1;
}
}
}
/**
* @brief 停止数据记录
* @retval None
*/
static void StopRecording(void)
{
if (g_recording_enabled) {
g_recording_enabled = 0;
DataStorage_StopRecording(&g_data_storage);
}
}
/**
* @brief 处理ADC数据
* @retval None
*/
static void ProcessAdcData(void)
{
// 检查ADC数据是否准备就绪
LTC2508_BufferTypeDef *ready_buffer = NULL;
if (LTC2508_GetReadyBuffer(&ready_buffer) == LTC2508_OK && ready_buffer != NULL)
{
// 检查存储缓冲区是否可用(用于决定是否存储数据)
uint8_t can_store_data = 0;
if (g_recording_enabled) {
uint32_t max_packet_size = sizeof(CorrectedDataPacketWithGPS_t); // 使用带GPS的数据包大小
can_store_data = DataStorage_IsBufferAvailable(&g_data_storage, max_packet_size);
}
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_IncrementSampleCount();
#endif
// 1. 从双缓冲区获取数据并合并 (高位16位在前)
int32_t raw_adc[NUM_LTC2508];
for (uint8_t i = 0; i < NUM_LTC2508; i++) {
raw_adc[i] = (int32_t)(((uint32_t)ready_buffer->data[i][0] << 16) | ready_buffer->data[i][1]);
}
// 2. 获取当前GPS数据
GPS_Data_t current_gps_data;
uint8_t gps_valid = GPS_GetData(&current_gps_data);
// 3. 应用校正算法
CorrectionResult_t correction_result;
uint8_t correction_applied = 0;
if (g_correction_params.params_valid &&
Apply_Correction(raw_adc[0], raw_adc[1], raw_adc[2],
&correction_result, &g_correction_params) == HAL_OK) {
// 4a. 打包校正后的数据带GPS关键信息仅经纬度
// float lat = gps_valid ? (float)current_gps_data.position.latitude : 0.0f;
// float lon = gps_valid ? (float)current_gps_data.position.longitude : 0.0f;
// float alt = gps_valid ? (float)current_gps_data.position.altitude : 0.0f;
float lat = (float)current_gps_data.position.latitude;
float lon = (float)current_gps_data.position.longitude;
float alt = (float)current_gps_data.position.altitude;
uint32_t gps_time = gps_valid ? (current_gps_data.time.hour * 10000 +
current_gps_data.time.minute * 100 +
current_gps_data.time.second) : 0;
PackCorrectedDataWithGPS(&g_corrected_packet_with_gps,
correction_result.corrected_x,
correction_result.corrected_y,
correction_result.corrected_z,
gps_time,
lat,
lon,
alt);
correction_applied = 1;
// 发送校正后的数据包到串口(运行时配置)
if (Config_IsUartOutputEnabled()) {
RS485_SendData((uint8_t*)&g_corrected_packet_with_gps, sizeof(CorrectedDataPacketWithGPS_t));
}
} else {
// 4b. 校正失败或未启用,使用原始数据
// float lat = gps_valid ? (float)current_gps_data.position.latitude : 0.0f;
// float lon = gps_valid ? (float)current_gps_data.position.longitude : 0.0f;
// float alt = gps_valid ? (float)current_gps_data.position.altitude : 0.0f;
float lat = (float)current_gps_data.position.latitude;
float lon = (float)current_gps_data.position.longitude;
float alt = (float)current_gps_data.position.altitude;
uint32_t gps_time = gps_valid ? (current_gps_data.time.hour * 10000 +
current_gps_data.time.minute * 100 +
current_gps_data.time.second) : 0;
PackData(&g_data_packet, raw_adc[0], raw_adc[1], raw_adc[2], gps_time, lat, lon, alt);
// 发送原始数据包到串口(运行时配置)
if (Config_IsUartOutputEnabled()) {
RS485_SendData((uint8_t*)&g_data_packet, sizeof(DataPacket_t));
}
}
// 6. 存储数据到SD卡 (如果启用记录且缓冲区可用,运行时配置)
if (Config_IsStorageEnabled() && g_recording_enabled) {
if (can_store_data) {
if (correction_applied) {
// 存储校正后的数据带GPS信息
DataStorage_WriteCorrectedData(&g_data_storage, (CorrectedDataPacket_t*)&g_corrected_packet_with_gps);
} else {
// 存储原始数据
DataStorage_WriteData(&g_data_storage, &g_data_packet);
}
} else {
// 缓冲区满,数据被丢弃
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_ReportDataDropped();
#endif
}
}
// 7. 释放已处理的缓冲区
LTC2508_ReleaseBuffer(LTC2508_GetCurrentReadBuffer());
} else {
}
}
/**
* @brief 初始化调试输出和GPS
* @retval None
*/
static void DebugOutput_Init(void)
{
// USART3现在用于GPS接收不再用于调试输出
// 初始化GPS驱动
if (GPS_Init() == HAL_OK) {
// GPS初始化成功
// 注意GPS初始化后USART3将用于接收GPS数据
}
}
/**
* @brief 通过USART3发送字符串已禁用USART3用于GPS
* @param str: 要发送的字符串
* @retval None
*/
static void DebugOutput_SendString(const char* str)
{
#if ENABLE_SYSTEM_MONITOR
// USART3现在用于GPS接收调试输出已禁用
// 如需调试输出请使用USART1或其他串口
(void)str; // 避免未使用参数警告
#endif
}
/**
* @brief 输出系统监控统计信息
* @retval None
*/
static void DebugOutput_PrintSystemStats(void)
{
#if ENABLE_SYSTEM_MONITOR
char buffer[256];
SystemMonitorStats_t sys_stats;
SystemMonitor_GetStats(&sys_stats);
// 打印基本统计信息
snprintf(buffer, sizeof(buffer),
"\r\n=== System Stats ===\r\n"
"Total Samples: %lu\r\n"
"Data Overflow: %lu\r\n",
sys_stats.total_samples,
sys_stats.data_overflow_count);
DebugOutput_SendString(buffer);
// 打印SD卡存储监控信息
snprintf(buffer, sizeof(buffer),
"=== SD Card Stats ===\r\n"
"SD Write Count: %lu\r\n"
"SD Write Errors: %lu\r\n"
"SD Buffer Full: %lu\r\n"
"SD Total Bytes: %lu\r\n"
"SD File Count: %lu\r\n"
"SD Data Dropped: %lu\r\n",
sys_stats.sd_write_count,
sys_stats.sd_write_error_count,
sys_stats.sd_buffer_full_count,
sys_stats.sd_total_bytes_written,
sys_stats.sd_file_count,
sys_stats.sd_data_dropped_count);
DebugOutput_SendString(buffer);
// 计算并打印统计指标
if (sys_stats.sd_write_count > 0) {
uint32_t avg_write_size = sys_stats.sd_total_bytes_written / sys_stats.sd_write_count;
snprintf(buffer, sizeof(buffer),
"Avg Write Size: %lu bytes\r\n",
avg_write_size);
DebugOutput_SendString(buffer);
}
if (sys_stats.sd_write_count + sys_stats.sd_write_error_count > 0) {
uint32_t total_attempts = sys_stats.sd_write_count + sys_stats.sd_write_error_count;
uint32_t error_rate = (sys_stats.sd_write_error_count * 100) / total_attempts;
snprintf(buffer, sizeof(buffer),
"Write Error Rate: %lu%%\r\n",
error_rate);
DebugOutput_SendString(buffer);
}
DebugOutput_SendString("====================\r\n");
#endif
}
/**
* @brief 检查USB连接状态
* @retval 1: USB已连接, 0: USB未连接
*/
static uint8_t CheckUSBConnectionStatus(void)
{
// 通过检查USB设备状态来判断是否连接到PC
extern USBD_HandleTypeDef hUsbDeviceFS;
// 检查USB设备是否已配置枚举完成
if (hUsbDeviceFS.dev_state == USBD_STATE_CONFIGURED) {
return 1; // USB已连接并配置
}
return 0; // USB未连接或未配置
}
/**
* @brief 处理USB连接状态变化
* @retval None
*/
static void HandleUSBConnectionChange(void)
{
uint8_t current_usb_status = CheckUSBConnectionStatus();
if (current_usb_status != g_usb_connected) {
g_usb_connected = current_usb_status;
if (g_usb_connected) {
// USB连接停止数据采集卸载文件系统用于USB存储
DebugOutput_SendString("USB Connected: Stopping data acquisition\r\n");
// 停止数据记录
StopRecording();
// 卸载用于采样的文件系统
UnmountFileSystemForSampling();
while(1)
{
;
}
} else {
// USB断开重新挂载文件系统开始数据采集
DebugOutput_SendString("USB Disconnected: Starting data acquisition\r\n");
// 挂载文件系统用于数据采集
if (MountFileSystemForSampling() == HAL_OK) {
// 重新初始化数据存储
if (DataStorage_Init(&g_data_storage) == HAL_OK) {
StartRecording();
}
}
}
}
}
/**
* @brief 为数据采集挂载文件系统
* @retval HAL_OK: 成功, HAL_ERROR: 失败
*/
static HAL_StatusTypeDef MountFileSystemForSampling(void)
{
extern FATFS SDFatFS;
extern char SDPath[4];
extern SD_HandleTypeDef hsd;
BYTE work[_MAX_SS];
if (g_fatfs_mounted_for_sampling) {
return HAL_OK; // 已经挂载
}
// 初始化SD卡
if (HAL_SD_Init(&hsd) != HAL_OK) {
DebugOutput_SendString("SD card init failed\r\n");
return HAL_ERROR;
}
// 目标格式参数FAT32簇大小32768字节512字节/扇区 × 64扇区/簇)
#define TARGET_CLUSTER_SIZE_BYTES 32768U
#define TARGET_SECTOR_SIZE_BYTES 512U
#define TARGET_SECTORS_PER_CLUSTER (TARGET_CLUSTER_SIZE_BYTES / TARGET_SECTOR_SIZE_BYTES) // 64
// 尝试挂载文件系统
FRESULT mount_result = f_mount(&SDFatFS, SDPath, 1);
uint8_t need_format = 0;
if (mount_result == FR_OK) {
// 挂载成功,验证文件系统类型和簇大小是否符合目标格式
if (SDFatFS.fs_type != FS_FAT32) {
DebugOutput_SendString("Not FAT32, reformatting...\r\n");
f_mount(NULL, SDPath, 0);
need_format = 1;
} else if (SDFatFS.csize != TARGET_SECTORS_PER_CLUSTER) {
DebugOutput_SendString("Cluster size mismatch, reformatting...\r\n");
f_mount(NULL, SDPath, 0);
need_format = 1;
}
} else if (mount_result == FR_NO_FILESYSTEM) {
DebugOutput_SendString("No filesystem found, formatting...\r\n");
need_format = 1;
} else {
DebugOutput_SendString("Mount failed with other error\r\n");
return HAL_ERROR;
}
if (need_format) {
FRESULT format_result = f_mkfs(SDPath, FM_FAT32, TARGET_CLUSTER_SIZE_BYTES, work, sizeof(work));
if (format_result == FR_OK) {
DebugOutput_SendString("Format successful, remounting...\r\n");
mount_result = f_mount(&SDFatFS, SDPath, 1);
if (mount_result != FR_OK) {
DebugOutput_SendString("Remount after format failed\r\n");
return HAL_ERROR;
}
} else {
DebugOutput_SendString("Format failed\r\n");
return HAL_ERROR;
}
}
g_fatfs_mounted_for_sampling = 1;
DebugOutput_SendString("Filesystem mounted for sampling\r\n");
return HAL_OK;
}
/**
* @brief 卸载用于数据采集的文件系统
* @retval None
*/
static void UnmountFileSystemForSampling(void)
{
extern FATFS SDFatFS;
extern char SDPath[4];
if (!g_fatfs_mounted_for_sampling) {
return; // 已经卸载
}
// 卸载文件系统
f_mount(NULL, SDPath, 0);
g_fatfs_mounted_for_sampling = 0;
DebugOutput_SendString("Filesystem unmounted for USB mode\r\n");
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
HAL_Delay(200);
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_SDIO_SD_Init();
MX_SPI1_Init();
MX_SPI2_Init();
MX_SPI3_Init();
MX_USART1_UART_Init();
MX_FATFS_Init();
MX_USB_DEVICE_Init();
MX_USART3_UART_Init();
MX_TIM2_Init();
MX_TIM1_Init();
/* USER CODE BEGIN 2 */
// 初始化系统监控
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_Init();
#endif
// 初始化调试输出
DebugOutput_Init();
// 初始化配置管理器(设置默认值)
Config_Init();
// 初始化RS485通信
RS485_Init(&huart1, RS485_DE_RE_PORT, RS485_DE_RE_PIN);
// 初始化校正参数
Init_CorrectionParams(&g_correction_params);
Load_CorrectionParams_FromFlash(&g_correction_params);
// 检查初始USB连接状态并相应初始化
HAL_Delay(2000);
g_usb_connected = CheckUSBConnectionStatus();
if (!g_usb_connected) {
// USB未连接挂载文件系统用于数据采集
if (MountFileSystemForSampling() == HAL_OK) {
// 从SD卡加载配置
if (Config_Load() == HAL_OK) {
DebugOutput_SendString("Config loaded from SD card\r\n");
} else {
DebugOutput_SendString("Using default config\r\n");
}
// 初始化数据存储
if (DataStorage_Init(&g_data_storage) == HAL_OK) {
// 开始数据记录(如果存储功能已启用)
if (Config_IsStorageEnabled()) {
StartRecording();
}
}
}
} else {
// USB已连接不进行数据采集
DebugOutput_SendString("USB connected at startup - data acquisition disabled\r\n");
while(1)
{
;
}
}
// #define NEED_FORMAT_SD
#ifdef NEED_FORMAT_SD
// Raw_Hardware_Test();
SDNAND_ForceFormat_and_Mount();
Run_SDNAND_SpeedTest_V2();
while(1)
{
;
}
#endif
// 启动TIM2定时器用于1ms周期的ADC数据处理
if (HAL_TIM_Base_Start_IT(&htim2) != HAL_OK) {
Error_Handler();
}
// 初始化LTC2508驱动
if (LTC2508_Init(&hspi1, &hspi2, &hspi3) != LTC2508_OK) {
Error_Handler();
}
// 输出时钟到ADC
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
// 触发信号引脚初始化
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
// 定期任务
uint32_t current_tick = HAL_GetTick();
// USB连接状态检测 (每500ms检测一次)
if (current_tick - g_last_usb_check >= 500) {
HandleUSBConnectionChange();
g_last_usb_check = current_tick;
}
// 处理数据存储后台任务 (轮询方式)
// 优化连续处理3次加快缓冲区刷新速度
if (g_recording_enabled) {
// for (int i = 0; i < 3; i++) {
DataStorage_ProcessBackgroundTasks(&g_data_storage);
// }
}
// GPS数据处理
GPS_Process();
// 定期输出调试信息 (每1秒输出一次)
#if ENABLE_SYSTEM_MONITOR
if (current_tick - g_last_debug_output >= DEBUG_OUTPUT_INTERVAL_MS) {
DebugOutput_PrintSystemStats();
g_last_debug_output = current_tick;
}
#endif
// 定期保存监控状态 (每1分钟保存一次)
#if ENABLE_SYSTEM_MONITOR
if (current_tick - g_last_monitor_save >= MONITOR_SAVE_INTERVAL_MS) {
SystemMonitor_SaveStatus();
g_last_monitor_save = current_tick;
}
#endif
// ADC采样由PA1外部中断触发不在主循环中触发
// 可以在这里添加其他低优先级任务
}
// 停止数据记录
StopRecording();
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
/**
* @brief 外部中断回调函数 - ADC数据就绪信号
* @param GPIO_Pin: 触发中断的GPIO引脚
* @retval None
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
static uint32_t cnt = 0;
if(LTC2508_IsInited() == 0) return;
cnt ++;
// if(cnt % 2 == 0)
{
// HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);
if (GPIO_Pin == ADC_DRY_Pin) {
// ADC数据就绪触发DMA读取
if(LTC2508_ERROR_TIMEOUT == LTC2508_TriggerDmaRead())
{
// 数据来不及处理
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_ReportDataOverflow();
#endif
}
}
// HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
}
}
/**
* @brief SPI DMA传输完成回调函数
* @param hspi: SPI句柄指针
* @retval None
*/
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
// 调用LTC2508驱动的DMA完成回调
LTC2508_DmaComplete_Callback(hspi);
}
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
{
// 调用LTC2508驱动的DMA完成回调
LTC2508_DmaComplete_Callback(hspi);
}
/**
* @brief SPI错误回调函数
* @param hspi: SPI句柄指针
* @retval None
*/
void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)
{
// 调用LTC2508驱动的错误回调
LTC2508_ErrorCallback(hspi);
}
/**
* @brief TIM2回调函数 - 1ms定时器中断处理ADC数据
* @param htim: TIM句柄指针
* @retval None
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM2) {
// ADC是4KHz采样率定时器是8KHz
// HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);
ProcessAdcData();
// HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
}
}
/**
* @brief UART传输完成回调函数
* @param huart: UART句柄指针
* @retval None
*/
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart == &huart1) {
// RS485传输完成回调
RS485_TxCpltCallback(huart);
}
}
/**
* @brief UART接收完成回调函数
* @param huart: UART句柄指针
* @retval None
*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart == &huart3) {
// GPS数据接收回调
GPS_UART_RxCpltCallback(huart);
}
}
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
// 停止所有DMA传输
HAL_SPI_DMAStop(&hspi1);
HAL_SPI_DMAStop(&hspi2);
HAL_SPI_DMAStop(&hspi3);
// 停止数据记录
g_recording_enabled = 0;
DataStorage_StopRecording(&g_data_storage);
// 禁用中断并进入无限循环
__disable_irq();
while (1)
{
// 可以在这里添加LED指示或其他错误指示
HAL_Delay(500);
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */