✨ feat(adc): 重构ADC数据处理架构,引入1ms定时器中断处理

- 新增TIM2定时器配置,用于1ms周期的ADC数据处理中断
- 将主循环中的ADC数据处理逻辑移至定时器中断回调函数中
- 新增ProcessAdcData函数,封装完整的ADC数据处理流程
- 优化数据缓冲区大小,从2增加到64,提升数据处理能力
- 调整DMA中断优先级,优化系统实时性

🔧 chore(config): 更新STM32CubeMX项目配置

- 在IOC配置文件中添加TIM2定时器配置
- 更新NVIC中断优先级配置
- 调整DMA中断优先级设置
- 更新项目初始化函数调用顺序

📦 build(storage): 优化数据存储缓冲区配置

- 将数据存储缓冲区大小从1024字节增加到32768字节
- 提升数据写入效率,减少文件系统操作频率
This commit is contained in:
2026-01-25 21:20:15 +08:00
parent 2cbd4a152d
commit 082ea96e88
9 changed files with 270 additions and 121 deletions
+1
View File
@@ -58,6 +58,7 @@ void SysTick_Handler(void);
void EXTI1_IRQHandler(void);
void DMA1_Stream0_IRQHandler(void);
void DMA1_Stream3_IRQHandler(void);
void TIM2_IRQHandler(void);
void DMA2_Stream0_IRQHandler(void);
void DMA2_Stream3_IRQHandler(void);
void OTG_FS_IRQHandler(void);
+3
View File
@@ -34,11 +34,14 @@ extern "C" {
extern TIM_HandleTypeDef htim1;
extern TIM_HandleTypeDef htim2;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_TIM1_Init(void);
void MX_TIM2_Init(void);
void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);
+6 -6
View File
@@ -45,22 +45,22 @@ void MX_DMA_Init(void)
/* DMA interrupt init */
/* DMA1_Stream0_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 1, 0);
HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);
/* DMA1_Stream3_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 1, 0);
HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn);
/* DMA2_Stream0_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 1, 0);
HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
/* DMA2_Stream3_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 3, 0);
HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 10, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
/* DMA2_Stream6_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 3, 0);
HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 10, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn);
/* DMA2_Stream7_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream7_IRQn, 6, 0);
HAL_NVIC_SetPriority(DMA2_Stream7_IRQn, 12, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream7_IRQn);
}
+150 -98
View File
@@ -64,6 +64,7 @@
extern SPI_HandleTypeDef hspi1;
extern SPI_HandleTypeDef hspi2;
extern SPI_HandleTypeDef hspi3;
extern TIM_HandleTypeDef htim2;
extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart3;
@@ -83,6 +84,7 @@ static uint32_t g_sample_count = 0;
static uint32_t g_last_debug_output = 0;
static uint8_t g_debug_output_enabled = ENABLE_UART_DEBUG_OUTPUT;
static SystemPerfStats_t g_perf_stats;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
@@ -90,7 +92,8 @@ void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
static void StartRecording(void);
static void StopRecording(void);
static HAL_StatusTypeDef ValidateSystemHealth(void);
static void ProcessAdcData(void);
static void DebugOutput_Init(void);
static void DebugOutput_SendString(const char* str);
static void DebugOutput_PrintSystemStats(void);
@@ -129,6 +132,111 @@ static void StopRecording(void)
}
}
/**
* @brief 处理ADC数据
* @retval None
*/
static void ProcessAdcData(void)
{
// 检查ADC数据是否准备就绪
LTC2508_BufferTypeDef *ready_buffer = NULL;
if (LTC2508_GetReadyBuffer(&ready_buffer) == LTC2508_OK && ready_buffer != NULL)
{
PerformanceMonitor_TaskStart(PERF_TASK_ADC_PROCESSING);
SystemMonitor_SetState(SYSTEM_STATE_SAMPLING);
g_sample_count++;
// 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]);
}
PerformanceMonitor_TaskEnd(PERF_TASK_ADC_PROCESSING);
// 2. 验证数据有效性
uint8_t data_valid = 1;
for (uint8_t i = 0; i < NUM_LTC2508; i++) {
if (LTC2508_ValidateData(ready_buffer, i) != LTC2508_OK) {
SystemMonitor_ReportError(SYSTEM_ERROR_ADC);
data_valid = 0;
break; // 如果有任何通道数据无效,跳过整个样本
}
}
if (!data_valid) {
// 释放缓冲区并返回
LTC2508_ReleaseBuffer(LTC2508_GetCurrentReadBuffer());
SystemMonitor_SetState(SYSTEM_STATE_IDLE);
return;
}
// 3. 应用校正算法
CorrectionResult_t correction_result;
uint8_t correction_applied = 0;
PerformanceMonitor_TaskStart(PERF_TASK_CORRECTION);
if (g_correction_params.params_valid &&
Apply_Correction(raw_adc[0], raw_adc[1], raw_adc[2],
&correction_result, &g_correction_params) == HAL_OK) {
PerformanceMonitor_TaskEnd(PERF_TASK_CORRECTION);
// 4a. 打包校正后的数据
PerformanceMonitor_TaskStart(PERF_TASK_DATA_PACKET);
PackCorrectedData(&g_corrected_packet,
correction_result.corrected_x,
correction_result.corrected_y,
correction_result.corrected_z);
PerformanceMonitor_TaskEnd(PERF_TASK_DATA_PACKET);
correction_applied = 1;
// 发送校正后的数据包
PerformanceMonitor_TaskStart(PERF_TASK_RS485_TX);
if (RS485_SendData((uint8_t*)&g_corrected_packet, sizeof(CorrectedDataPacket_t)) != HAL_OK) {
SystemMonitor_ReportError(SYSTEM_ERROR_COMMUNICATION);
}
PerformanceMonitor_TaskEnd(PERF_TASK_RS485_TX);
} else {
PerformanceMonitor_TaskEnd(PERF_TASK_CORRECTION);
// 4b. 校正失败或未启用,使用原始数据
PerformanceMonitor_TaskStart(PERF_TASK_DATA_PACKET);
PackData(&g_data_packet, raw_adc[0], raw_adc[1], raw_adc[2]);
PerformanceMonitor_TaskEnd(PERF_TASK_DATA_PACKET);
// 发送原始数据包
PerformanceMonitor_TaskStart(PERF_TASK_RS485_TX);
if (RS485_SendData((uint8_t*)&g_data_packet, sizeof(DataPacket_t)) != HAL_OK) {
SystemMonitor_ReportError(SYSTEM_ERROR_COMMUNICATION);
}
PerformanceMonitor_TaskEnd(PERF_TASK_RS485_TX);
}
// 6. 存储数据到SD卡 (如果启用记录)
if (g_recording_enabled) {
SystemMonitor_SetState(SYSTEM_STATE_RECORDING);
PerformanceMonitor_TaskStart(PERF_TASK_FATFS_WRITE);
if (correction_applied) {
// 存储校正后的数据
if (DataStorage_WriteCorrectedData(&g_data_storage, &correction_result) != HAL_OK) {
SystemMonitor_ReportError(SYSTEM_ERROR_STORAGE);
}
} else {
// 存储原始数据
if (DataStorage_WriteData(&g_data_storage, &g_data_packet) != HAL_OK) {
SystemMonitor_ReportError(SYSTEM_ERROR_STORAGE);
}
}
PerformanceMonitor_TaskEnd(PERF_TASK_FATFS_WRITE);
}
// 7. 释放已处理的缓冲区
LTC2508_ReleaseBuffer(LTC2508_GetCurrentReadBuffer());
SystemMonitor_SetState(SYSTEM_STATE_IDLE);
}
}
/**
* @brief 初始化调试输出
* @retval None
@@ -267,6 +375,7 @@ int main(void)
MX_FATFS_Init();
MX_USB_DEVICE_Init();
MX_USART3_UART_Init();
MX_TIM2_Init();
/* USER CODE BEGIN 2 */
// 初始化系统监控
SystemMonitor_Init();
@@ -296,9 +405,18 @@ int main(void)
SystemMonitor_ReportError(SYSTEM_ERROR_STORAGE);
}
// 开始数据记录
StartRecording();
// 系统初始化完成
SystemMonitor_SetState(SYSTEM_STATE_IDLE);
// 启动TIM2定时器用于1ms周期的ADC数据处理
if (HAL_TIM_Base_Start_IT(&htim2) != HAL_OK) {
SystemMonitor_ReportError(SYSTEM_ERROR_CRITICAL);
Error_Handler();
}
// 触发信号引脚初始化
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
@@ -321,105 +439,10 @@ int main(void)
g_last_monitor_update = current_tick;
}
// 检查ADC数据是否准备就绪
LTC2508_BufferTypeDef *ready_buffer = NULL;
if (LTC2508_GetReadyBuffer(&ready_buffer) == LTC2508_OK && ready_buffer != NULL)
{
PerformanceMonitor_TaskStart(PERF_TASK_ADC_PROCESSING);
SystemMonitor_SetState(SYSTEM_STATE_SAMPLING);
g_sample_count++;
// ADC数据处理已移至1ms定时器中断中处理
// 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]);
}
PerformanceMonitor_TaskEnd(PERF_TASK_ADC_PROCESSING);
// 2. 验证数据有效性
uint8_t data_valid = 1;
for (uint8_t i = 0; i < NUM_LTC2508; i++) {
if (LTC2508_ValidateData(ready_buffer, i) != LTC2508_OK) {
SystemMonitor_ReportError(SYSTEM_ERROR_ADC);
data_valid = 0;
break; // 如果有任何通道数据无效,跳过整个样本
}
}
if (!data_valid) {
// 释放缓冲区并继续下一次循环
LTC2508_ReleaseBuffer(g_current_read_buffer);
SystemMonitor_SetState(SYSTEM_STATE_IDLE);
continue;
}
// 3. 应用校正算法
CorrectionResult_t correction_result;
uint8_t correction_applied = 0;
PerformanceMonitor_TaskStart(PERF_TASK_CORRECTION);
if (g_correction_params.params_valid &&
Apply_Correction(raw_adc[0], raw_adc[1], raw_adc[2],
&correction_result, &g_correction_params) == HAL_OK) {
PerformanceMonitor_TaskEnd(PERF_TASK_CORRECTION);
// 4a. 打包校正后的数据
PerformanceMonitor_TaskStart(PERF_TASK_DATA_PACKET);
PackCorrectedData(&g_corrected_packet,
correction_result.corrected_x,
correction_result.corrected_y,
correction_result.corrected_z);
PerformanceMonitor_TaskEnd(PERF_TASK_DATA_PACKET);
correction_applied = 1;
// 发送校正后的数据包
PerformanceMonitor_TaskStart(PERF_TASK_RS485_TX);
if (RS485_SendData((uint8_t*)&g_corrected_packet, sizeof(CorrectedDataPacket_t)) != HAL_OK) {
SystemMonitor_ReportError(SYSTEM_ERROR_COMMUNICATION);
}
PerformanceMonitor_TaskEnd(PERF_TASK_RS485_TX);
} else {
PerformanceMonitor_TaskEnd(PERF_TASK_CORRECTION);
// 4b. 校正失败或未启用,使用原始数据
PerformanceMonitor_TaskStart(PERF_TASK_DATA_PACKET);
PackData(&g_data_packet, raw_adc[0], raw_adc[1], raw_adc[2]);
PerformanceMonitor_TaskEnd(PERF_TASK_DATA_PACKET);
// 发送原始数据包
PerformanceMonitor_TaskStart(PERF_TASK_RS485_TX);
if (RS485_SendData((uint8_t*)&g_data_packet, sizeof(DataPacket_t)) != HAL_OK) {
SystemMonitor_ReportError(SYSTEM_ERROR_COMMUNICATION);
}
PerformanceMonitor_TaskEnd(PERF_TASK_RS485_TX);
}
// 6. 存储数据到SD卡 (如果启用记录)
if (g_recording_enabled) {
SystemMonitor_SetState(SYSTEM_STATE_RECORDING);
PerformanceMonitor_TaskStart(PERF_TASK_FATFS_WRITE);
if (correction_applied) {
// 存储校正后的数据
if (DataStorage_WriteCorrectedData(&g_data_storage, &correction_result) != HAL_OK) {
SystemMonitor_ReportError(SYSTEM_ERROR_STORAGE);
}
} else {
// 存储原始数据
if (DataStorage_WriteData(&g_data_storage, &g_data_packet) != HAL_OK) {
SystemMonitor_ReportError(SYSTEM_ERROR_STORAGE);
}
}
PerformanceMonitor_TaskEnd(PERF_TASK_FATFS_WRITE);
}
// 7. 释放已处理的缓冲区
LTC2508_ReleaseBuffer(g_current_read_buffer);
SystemMonitor_SetState(SYSTEM_STATE_IDLE);
}
// 处理数据存储后台任务
// 处理数据存储后台任务 (轮询方式)
if (g_recording_enabled) {
DataStorage_ProcessBackgroundTasks(&g_data_storage);
}
@@ -434,6 +457,10 @@ int main(void)
// ADC采样由PA1外部中断触发,不在主循环中触发
// 可以在这里添加其他低优先级任务
}
// 停止数据记录
StopRecording();
/* USER CODE END 3 */
}
@@ -528,6 +555,31 @@ void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)
SystemMonitor_ReportError(SYSTEM_ERROR_ADC);
}
/**
* @brief TIM2回调函数 - 1ms定时器中断处理ADC数据
* @param htim: TIM句柄指针
* @retval None
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM2) {
// ADC是4KHz采样率,定时器是1KHz,需要在每次1ms中断中处理多个ADC数据
// 循环处理所有可用的ADC数据,直到没有新数据为止
uint8_t processed_count = 0;
const uint8_t max_process_per_interrupt = 8; // 限制每次中断最多处理的数据量,避免中断时间过长
while (processed_count < max_process_per_interrupt) {
LTC2508_BufferTypeDef *ready_buffer = NULL;
if (LTC2508_GetReadyBuffer(&ready_buffer) == LTC2508_OK && ready_buffer != NULL) {
ProcessAdcData();
processed_count++;
} else {
break; // 没有更多数据可处理
}
}
}
}
/**
* @brief UART传输完成回调函数
* @param huart: UART句柄指针
+15
View File
@@ -63,6 +63,7 @@ extern DMA_HandleTypeDef hdma_sdio_tx;
extern DMA_HandleTypeDef hdma_spi1_rx;
extern DMA_HandleTypeDef hdma_spi2_rx;
extern DMA_HandleTypeDef hdma_spi3_rx;
extern TIM_HandleTypeDef htim2;
extern DMA_HandleTypeDef hdma_usart1_tx;
/* USER CODE BEGIN EV */
extern SPI_HandleTypeDef hspi1;
@@ -251,6 +252,20 @@ void DMA1_Stream3_IRQHandler(void)
/* USER CODE END DMA1_Stream3_IRQn 1 */
}
/**
* @brief This function handles TIM2 global interrupt.
*/
void TIM2_IRQHandler(void)
{
/* USER CODE BEGIN TIM2_IRQn 0 */
/* USER CODE END TIM2_IRQn 0 */
HAL_TIM_IRQHandler(&htim2);
/* USER CODE BEGIN TIM2_IRQn 1 */
/* USER CODE END TIM2_IRQn 1 */
}
/**
* @brief This function handles DMA2 stream0 global interrupt.
*/
+70
View File
@@ -25,6 +25,7 @@
/* USER CODE END 0 */
TIM_HandleTypeDef htim1;
TIM_HandleTypeDef htim2;
/* TIM1 init function */
void MX_TIM1_Init(void)
@@ -95,6 +96,46 @@ void MX_TIM1_Init(void)
/* USER CODE END TIM1_Init 2 */
HAL_TIM_MspPostInit(&htim1);
}
/* TIM2 init function */
void MX_TIM2_Init(void)
{
/* USER CODE BEGIN TIM2_Init 0 */
/* USER CODE END TIM2_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
/* USER CODE BEGIN TIM2_Init 1 */
/* USER CODE END TIM2_Init 1 */
htim2.Instance = TIM2;
htim2.Init.Prescaler = 83;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 999;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM2_Init 2 */
/* USER CODE END TIM2_Init 2 */
}
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
@@ -111,6 +152,21 @@ void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
/* USER CODE END TIM1_MspInit 1 */
}
else if(tim_baseHandle->Instance==TIM2)
{
/* USER CODE BEGIN TIM2_MspInit 0 */
/* USER CODE END TIM2_MspInit 0 */
/* TIM2 clock enable */
__HAL_RCC_TIM2_CLK_ENABLE();
/* TIM2 interrupt Init */
HAL_NVIC_SetPriority(TIM2_IRQn, 3, 0);
HAL_NVIC_EnableIRQ(TIM2_IRQn);
/* USER CODE BEGIN TIM2_MspInit 1 */
/* USER CODE END TIM2_MspInit 1 */
}
}
void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle)
{
@@ -154,6 +210,20 @@ void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
/* USER CODE END TIM1_MspDeInit 1 */
}
else if(tim_baseHandle->Instance==TIM2)
{
/* USER CODE BEGIN TIM2_MspDeInit 0 */
/* USER CODE END TIM2_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM2_CLK_DISABLE();
/* TIM2 interrupt Deinit */
HAL_NVIC_DisableIRQ(TIM2_IRQn);
/* USER CODE BEGIN TIM2_MspDeInit 1 */
/* USER CODE END TIM2_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */