STM_ATEM/Core/Src/main.c
zhoujie 6297f3044d feat(adc): implement comprehensive ADC data acquisition and processing system
Add complete data acquisition pipeline with LTC2508 ADC drivers, correction algorithms,
data storage, and system monitoring. Includes ARM DSP optimized matrix operations for
sensor calibration, SD card data logging with USB mass storage, and robust error handling
with validation throughout the processing chain.

- Add LTC2508 multi-channel SPI driver with DMA support and error recovery
- Implement correction module with ARM DSP matrix operations for sensor calibration
- Add data storage system with SD card logging and configurable file management
- Integrate system monitor for health tracking and error reporting
- Enhance data packet structure with CRC validation and timestamps
- Add USB mass storage interface for SD card access
- Implement comprehensive error handling and statistics collection
2026-01-25 18:15:13 +08:00

298 lines
8.6 KiB
C
Raw 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"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
// 校正参数
CorrectionParams_t g_correction_params;
// 数据包
DataPacket_t g_data_packet;
// 数据存储句柄
DataStorageHandle_t g_data_storage;
// 系统状态
static uint32_t g_last_monitor_update = 0;
static uint8_t g_recording_enabled = 0;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* 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 */
/* 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_TIM1_Init();
MX_USART1_UART_Init();
MX_FATFS_Init();
MX_USB_DEVICE_Init();
MX_USART3_UART_Init();
/* USER CODE BEGIN 2 */
// 初始化系统监控
SystemMonitor_Init();
SystemMonitor_SetState(SYSTEM_STATE_INIT);
// 初始化LTC2508驱动
if (LTC2508_Init(&hspi1, &hspi2, &hspi3) != LTC2508_OK) {
SystemMonitor_ReportError(SYSTEM_ERROR_ADC);
Error_Handler();
}
// 初始化RS485通信
RS485_Init(&huart1, RS485_DE_RE_PORT, RS485_DE_RE_PIN);
// 初始化校正参数
Init_CorrectionParams(&g_correction_params);
Load_CorrectionParams_FromFlash(&g_correction_params);
// 初始化数据存储
if (DataStorage_Init(&g_data_storage) != HAL_OK) {
SystemMonitor_ReportError(SYSTEM_ERROR_STORAGE);
}
// 系统初始化完成
SystemMonitor_SetState(SYSTEM_STATE_IDLE);
// 触发信号引脚初始化
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 */
// 系统监控更新 (每100ms更新一次)
uint32_t current_tick = HAL_GetTick();
if (current_tick - g_last_monitor_update >= 100) {
SystemMonitor_Update();
g_last_monitor_update = current_tick;
}
// 检查ADC数据是否准备就绪
if (g_adc_data_ready_flag)
{
g_adc_data_ready_flag = 0; // 清除标志
SystemMonitor_SetState(SYSTEM_STATE_SAMPLING);
// 1. 合并数据 (高位16位在前)
int32_t raw_adc[NUM_LTC2508];
raw_adc[0] = (int32_t)(((uint32_t)g_adc_data[0][0] << 16) | g_adc_data[0][1]);
raw_adc[1] = (int32_t)(((uint32_t)g_adc_data[1][0] << 16) | g_adc_data[1][1]);
raw_adc[2] = (int32_t)(((uint32_t)g_adc_data[2][0] << 16) | g_adc_data[2][1]);
// 2. 验证数据有效性
for (uint8_t i = 0; i < NUM_LTC2508; i++) {
if (LTC2508_ValidateData(i) != LTC2508_OK) {
SystemMonitor_ReportError(SYSTEM_ERROR_ADC);
continue; // 跳过无效数据
}
}
// 3. 应用校正算法
CorrectionResult_t correction_result;
if (Apply_Correction(raw_adc[0], raw_adc[1], raw_adc[2],
&correction_result, &g_correction_params) == HAL_OK) {
// 4. 打包校正后的数据
PackData(&g_data_packet, (int32_t)correction_result.corrected_x,
(int32_t)correction_result.corrected_y,
(int32_t)correction_result.corrected_z);
} else {
// 校正失败,使用原始数据
PackData(&g_data_packet, raw_adc[0], raw_adc[1], raw_adc[2]);
}
// 5. 发送数据包
if (RS485_SendData((uint8_t*)&g_data_packet, sizeof(DataPacket_t)) != HAL_OK) {
SystemMonitor_ReportError(SYSTEM_ERROR_COMMUNICATION);
}
// 6. 存储数据到SD卡 (如果启用记录)
if (g_recording_enabled) {
SystemMonitor_SetState(SYSTEM_STATE_RECORDING);
if (DataStorage_WriteData(&g_data_storage, &g_data_packet) != HAL_OK) {
SystemMonitor_ReportError(SYSTEM_ERROR_STORAGE);
}
}
SystemMonitor_SetState(SYSTEM_STATE_IDLE);
}
// ADC采样由PA1外部中断触发不在主循环中触发
}
/* 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 */
/* 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 */
__disable_irq();
while (1)
{
}
/* 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 */