#include "ltc2508_driver.h" #include // For memset // 全局变量定义 volatile uint16_t g_adc_data[NUM_LTC2508][LTC2508_DATA_LEN] = {0}; volatile uint8_t g_adc_data_ready_flag = 0; volatile uint8_t g_dma_complete_count = 0; // 错误统计信息 LTC2508_StatsTypeDef g_ltc2508_stats = {0}; // SPI 句柄指针 static SPI_HandleTypeDef *g_hspi1 = NULL; static SPI_HandleTypeDef *g_hspi2 = NULL; static SPI_HandleTypeDef *g_hspi3 = NULL; /** * @brief 初始化 LTC2508 驱动 * @param hspi1: SPI1 句柄指针 * @param hspi2: SPI2 句柄指针 * @param hspi3: SPI3 句柄指针 * @retval LTC2508_StatusTypeDef */ LTC2508_StatusTypeDef LTC2508_Init(SPI_HandleTypeDef *hspi1, SPI_HandleTypeDef *hspi2, SPI_HandleTypeDef *hspi3) { // 参数检查 if (hspi1 == NULL || hspi2 == NULL || hspi3 == NULL) { g_ltc2508_stats.error_count++; g_ltc2508_stats.last_error = LTC2508_ERROR_INIT; return LTC2508_ERROR_INIT; } g_hspi1 = hspi1; g_hspi2 = hspi2; g_hspi3 = hspi3; g_adc_data_ready_flag = 0; g_dma_complete_count = 0; memset((void*)g_adc_data, 0, sizeof(g_adc_data)); // 重置统计信息 memset(&g_ltc2508_stats, 0, sizeof(g_ltc2508_stats)); // 可以在这里添加对 LTC2508 的配置,如果需要通过 SPI 发送配置字 // 例如:HAL_SPI_Transmit(g_hspi1, &config_word, 1, 100); return LTC2508_OK; } /** * @brief 触发三路 SPI 通过 DMA 读取数据 * @param None * @retval LTC2508_StatusTypeDef */ LTC2508_StatusTypeDef LTC2508_TriggerDmaRead(void) { // 检查SPI句柄是否有效 if (g_hspi1 == NULL || g_hspi2 == NULL || g_hspi3 == NULL) { g_ltc2508_stats.error_count++; g_ltc2508_stats.last_error = LTC2508_ERROR_INIT; return LTC2508_ERROR_INIT; } if (g_adc_data_ready_flag == 0 && g_dma_complete_count == 0) // 确保上次数据已处理且 DMA 未在进行 { g_dma_complete_count = 0; // 重置计数 // SPI2 和 SPI3 作为从机只接收 if (HAL_SPI_Receive_DMA(g_hspi2, (uint8_t*)g_adc_data[1], LTC2508_DATA_LEN * 2) != HAL_OK) { g_ltc2508_stats.dma_error_count++; g_ltc2508_stats.error_count++; g_ltc2508_stats.last_error = LTC2508_ERROR_DMA; return LTC2508_ERROR_DMA; } if (HAL_SPI_Receive_DMA(g_hspi3, (uint8_t*)g_adc_data[2], LTC2508_DATA_LEN * 2) != HAL_OK) { g_ltc2508_stats.dma_error_count++; g_ltc2508_stats.error_count++; g_ltc2508_stats.last_error = LTC2508_ERROR_DMA; return LTC2508_ERROR_DMA; } // SPI1 作为主机收发,先发一个 dummy 数据触发时钟 uint16_t dummy_tx[LTC2508_DATA_LEN] = {0}; // 可以是任意值 if (HAL_SPI_TransmitReceive_DMA(g_hspi1, (uint8_t*)dummy_tx, (uint8_t*)g_adc_data[0], LTC2508_DATA_LEN * 2) != HAL_OK) { g_ltc2508_stats.dma_error_count++; g_ltc2508_stats.error_count++; g_ltc2508_stats.last_error = LTC2508_ERROR_DMA; return LTC2508_ERROR_DMA; } return LTC2508_OK; } return LTC2508_ERROR_TIMEOUT; // 上次数据未处理完成 } /** * @brief SPI DMA 传输完成回调函数 * @param hspi: SPI 句柄指针 * @retval None */ void LTC2508_DmaComplete_Callback(SPI_HandleTypeDef *hspi) { if (hspi == g_hspi1 || hspi == g_hspi2 || hspi == g_hspi3) { g_dma_complete_count++; if (g_dma_complete_count >= NUM_LTC2508) { g_adc_data_ready_flag = 1; g_dma_complete_count = 0; // 为下一次读取做准备 g_ltc2508_stats.total_samples++; } } } /** * @brief SPI DMA 传输错误回调函数 * @param hspi: SPI 句柄指针 * @retval None */ void LTC2508_ErrorCallback(SPI_HandleTypeDef *hspi) { if (hspi == g_hspi1 || hspi == g_hspi2 || hspi == g_hspi3) { g_ltc2508_stats.dma_error_count++; g_ltc2508_stats.error_count++; g_ltc2508_stats.last_error = LTC2508_ERROR_DMA; // 重置DMA状态 g_dma_complete_count = 0; g_adc_data_ready_flag = 0; } } /** * @brief 验证ADC数据有效性 * @param channel: ADC通道 (0-2) * @retval LTC2508_StatusTypeDef */ LTC2508_StatusTypeDef LTC2508_ValidateData(uint8_t channel) { if (channel >= NUM_LTC2508) { return LTC2508_ERROR_DATA_INVALID; } // 检查数据是否为全0或全1 (可能的错误状态) uint32_t combined_data = ((uint32_t)g_adc_data[channel][0] << 16) | g_adc_data[channel][1]; if (combined_data == 0x00000000 || combined_data == 0xFFFFFFFF) { g_ltc2508_stats.error_count++; g_ltc2508_stats.last_error = LTC2508_ERROR_DATA_INVALID; return LTC2508_ERROR_DATA_INVALID; } return LTC2508_OK; } /** * @brief 获取统计信息 * @param stats: 统计信息结构体指针 * @retval None */ void LTC2508_GetStats(LTC2508_StatsTypeDef *stats) { if (stats != NULL) { memcpy(stats, &g_ltc2508_stats, sizeof(LTC2508_StatsTypeDef)); } } /** * @brief 重置统计信息 * @param None * @retval None */ void LTC2508_ResetStats(void) { memset(&g_ltc2508_stats, 0, sizeof(LTC2508_StatsTypeDef)); }