#include "ltc2508_driver.h" #include // For memset // 全局变量定义 - 双缓冲区实现 volatile LTC2508_BufferTypeDef g_adc_buffers[LTC2508_BUFFER_COUNT] = {0}; volatile uint8_t g_adc_data_ready_flag = 0; volatile uint8_t g_dma_complete_count = 0; volatile uint8_t g_current_write_buffer = 0; volatile uint8_t g_current_read_buffer = 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; g_current_write_buffer = 0; g_current_read_buffer = 0; // 初始化双缓冲区 for (int i = 0; i < LTC2508_BUFFER_COUNT; i++) { memset((void*)&g_adc_buffers[i], 0, sizeof(LTC2508_BufferTypeDef)); g_adc_buffers[i].state = LTC2508_BUFFER_EMPTY; g_adc_buffers[i].dma_complete_count = 0; } // 重置统计信息 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; } // 检查当前写入缓冲区是否可用 volatile LTC2508_BufferTypeDef *current_buffer = &g_adc_buffers[g_current_write_buffer]; if (current_buffer->state == LTC2508_BUFFER_EMPTY) { // 设置缓冲区状态为填充中 current_buffer->state = LTC2508_BUFFER_FILLING; current_buffer->dma_complete_count = 0; current_buffer->timestamp = HAL_GetTick(); // SPI2 和 SPI3 作为从机只接收 if (HAL_SPI_Receive_DMA(g_hspi2, (uint8_t*)current_buffer->data[1], LTC2508_DATA_LEN * 2) != HAL_OK) { current_buffer->state = LTC2508_BUFFER_EMPTY; 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*)current_buffer->data[2], LTC2508_DATA_LEN * 2) != HAL_OK) { current_buffer->state = LTC2508_BUFFER_EMPTY; 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*)current_buffer->data[0], LTC2508_DATA_LEN * 2) != HAL_OK) { current_buffer->state = LTC2508_BUFFER_EMPTY; 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) { volatile LTC2508_BufferTypeDef *current_buffer = &g_adc_buffers[g_current_write_buffer]; // 增加当前缓冲区的DMA完成计数 current_buffer->dma_complete_count++; // 检查是否所有SPI的DMA传输都完成 if (current_buffer->dma_complete_count >= NUM_LTC2508) { // 标记当前缓冲区为准备就绪 current_buffer->state = LTC2508_BUFFER_READY; g_ltc2508_stats.total_samples++; // 自动切换到下一个缓冲区 LTC2508_SwapBuffers(); } } } /** * @brief SPI DMA 传输错误回调函数 * @param hspi: SPI 句柄指针 * @retval None */ void LTC2508_ErrorCallback(SPI_HandleTypeDef *hspi) { if (hspi == g_hspi1 || hspi == g_hspi2 || hspi == g_hspi3) { volatile LTC2508_BufferTypeDef *current_buffer = &g_adc_buffers[g_current_write_buffer]; g_ltc2508_stats.dma_error_count++; g_ltc2508_stats.error_count++; g_ltc2508_stats.last_error = LTC2508_ERROR_DMA; // 重置当前缓冲区状态 current_buffer->state = LTC2508_BUFFER_EMPTY; current_buffer->dma_complete_count = 0; } } /** * @brief 验证ADC数据有效性 * @param buffer: 缓冲区指针 * @param channel: ADC通道 (0-2) * @retval LTC2508_StatusTypeDef */ LTC2508_StatusTypeDef LTC2508_ValidateData(LTC2508_BufferTypeDef *buffer, uint8_t channel) { if (buffer == NULL || channel >= NUM_LTC2508) { return LTC2508_ERROR_DATA_INVALID; } // 检查数据是否为全0或全1 (可能的错误状态) uint32_t combined_data = ((uint32_t)buffer->data[channel][0] << 16) | buffer->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)); } /** * @brief 缓冲区切换函数 * @param None * @retval LTC2508_StatusTypeDef */ LTC2508_StatusTypeDef LTC2508_SwapBuffers(void) { uint8_t next_write_buffer = (g_current_write_buffer + 1) % LTC2508_BUFFER_COUNT; // 检查下一个写入缓冲区是否可用 if (g_adc_buffers[next_write_buffer].state == LTC2508_BUFFER_EMPTY) { g_current_write_buffer = next_write_buffer; return LTC2508_OK; } // 如果下一个缓冲区不可用,说明缓冲区溢出 g_ltc2508_stats.buffer_overflow_count++; g_ltc2508_stats.error_count++; g_ltc2508_stats.last_error = LTC2508_ERROR_BUFFER_OVERFLOW; return LTC2508_ERROR_BUFFER_OVERFLOW; } /** * @brief 获取当前写入缓冲区索引 * @param None * @retval uint8_t 当前写入缓冲区索引 */ uint8_t LTC2508_GetCurrentWriteBuffer(void) { return g_current_write_buffer; } /** * @brief 获取当前读取缓冲区索引 * @param None * @retval uint8_t 当前读取缓冲区索引 */ uint8_t LTC2508_GetCurrentReadBuffer(void) { return g_current_read_buffer; } /** * @brief 检查指定缓冲区是否准备就绪 * @param buffer_index: 缓冲区索引 * @retval LTC2508_StatusTypeDef */ LTC2508_StatusTypeDef LTC2508_IsBufferReady(uint8_t buffer_index) { if (buffer_index >= LTC2508_BUFFER_COUNT) { return LTC2508_ERROR_DATA_INVALID; } if (g_adc_buffers[buffer_index].state == LTC2508_BUFFER_READY) { return LTC2508_OK; } return LTC2508_ERROR_TIMEOUT; } /** * @brief 获取准备好的数据缓冲区 * @param buffer: 返回缓冲区指针 * @retval LTC2508_StatusTypeDef */ LTC2508_StatusTypeDef LTC2508_GetReadyBuffer(LTC2508_BufferTypeDef **buffer) { if (buffer == NULL) { return LTC2508_ERROR_DATA_INVALID; } // 检查读取缓冲区是否有准备好的数据 if (g_adc_buffers[g_current_read_buffer].state == LTC2508_BUFFER_READY) { g_adc_buffers[g_current_read_buffer].state = LTC2508_BUFFER_PROCESSING; *buffer = (LTC2508_BufferTypeDef*)&g_adc_buffers[g_current_read_buffer]; return LTC2508_OK; } return LTC2508_ERROR_TIMEOUT; // 没有准备好的数据 } /** * @brief 释放缓冲区 * @param buffer_index: 缓冲区索引 * @retval None */ void LTC2508_ReleaseBuffer(uint8_t buffer_index) { if (buffer_index < LTC2508_BUFFER_COUNT) { g_adc_buffers[buffer_index].state = LTC2508_BUFFER_EMPTY; g_adc_buffers[buffer_index].dma_complete_count = 0; // 如果释放的是当前读取缓冲区,切换到下一个 if (buffer_index == g_current_read_buffer) { g_current_read_buffer = (g_current_read_buffer + 1) % LTC2508_BUFFER_COUNT; } } }