feat(system): 优化系统性能并简化监控模块

- 新增VSCode编辑器配置,启用保存时自动格式化
- 新增DMA2_Stream5和USART1中断处理函数,优化SPI传输性能
- 移除TIM1相关配置和性能监控模块,简化系统架构
- 优化GPIO配置,将ADC_SYNC和PA8引脚合并配置
- 简化系统监控模块,仅保留采样计数和数据溢出统计
- 优化SPI配置,使用16位数据宽度并提高DMA优先级
- 提高USART波特率(USART1:2Mbps, USART3:921600bps)
- 优化LTC2508驱动,增加初始化状态检查和缓冲区大小
- 修正数据存储模块,使用校正数据包而非校正结果结构体
- 优化RS485驱动,使用中断传输并添加传输完成回调
- 更新IOC配置文件,移除TIM1并调整中断优先级配置
- 新增系统监控简化说明文档,详细记录架构变更
This commit is contained in:
zhoujie 2026-02-06 22:45:25 +08:00
parent 87bdfa09d9
commit fee2e96eaa
24 changed files with 388 additions and 818 deletions

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"editor.formatOnSave": true
}

View File

@ -59,10 +59,12 @@ void EXTI1_IRQHandler(void);
void DMA1_Stream0_IRQHandler(void);
void DMA1_Stream3_IRQHandler(void);
void TIM2_IRQHandler(void);
void USART1_IRQHandler(void);
void SDIO_IRQHandler(void);
void DMA2_Stream0_IRQHandler(void);
void DMA2_Stream3_IRQHandler(void);
void OTG_FS_IRQHandler(void);
void DMA2_Stream5_IRQHandler(void);
void DMA2_Stream6_IRQHandler(void);
void DMA2_Stream7_IRQHandler(void);
/* USER CODE BEGIN EFP */

View File

@ -32,19 +32,14 @@ extern "C" {
/* USER CODE END Includes */
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);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */

View File

@ -56,6 +56,9 @@ void MX_DMA_Init(void)
/* DMA2_Stream3_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 10, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
/* DMA2_Stream5_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream5_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream5_IRQn);
/* DMA2_Stream6_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 10, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn);

View File

@ -52,7 +52,7 @@ void MX_GPIO_Init(void)
__HAL_RCC_GPIOD_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(ADC_SYNC_GPIO_Port, ADC_SYNC_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, ADC_SYNC_Pin|GPIO_PIN_8, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(RS485_CTL_GPIO_Port, RS485_CTL_Pin, GPIO_PIN_RESET);
@ -69,12 +69,12 @@ void MX_GPIO_Init(void)
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(ADC_DRY_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pin : ADC_SYNC_Pin */
GPIO_InitStruct.Pin = ADC_SYNC_Pin;
/*Configure GPIO pins : ADC_SYNC_Pin PA8 */
GPIO_InitStruct.Pin = ADC_SYNC_Pin|GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(ADC_SYNC_GPIO_Port, &GPIO_InitStruct);
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pin : RS485_CTL_Pin */
GPIO_InitStruct.Pin = RS485_CTL_Pin;

View File

@ -35,7 +35,6 @@
#include "correction.h"
#include "data_storage.h"
#include "system_monitor.h"
#include "performance_monitor.h"
#include <stdio.h>
#include <string.h>
/* USER CODE END Includes */
@ -53,7 +52,6 @@
// 监控功能宏开关
#define ENABLE_SYSTEM_MONITOR 1 // 系统监控开关
#define ENABLE_PERFORMANCE_MONITOR 1 // 性能监控开关
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
@ -80,9 +78,7 @@ CorrectedDataPacket_t g_corrected_packet;
// 数据存储句柄
DataStorageHandle_t g_data_storage;
// 系统状态
static uint32_t g_last_monitor_update = 0;
static uint8_t g_recording_enabled = 0;
static uint32_t g_sample_count = 0;
// USB连接状态管理
static uint8_t g_usb_connected = 0;
@ -92,7 +88,6 @@ static uint32_t g_last_usb_check = 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 */
@ -112,7 +107,6 @@ static void UnmountFileSystemForSampling(void);
static void DebugOutput_Init(void);
static void DebugOutput_SendString(const char* str);
static void DebugOutput_PrintSystemStats(void);
static void DebugOutput_PrintPerformanceStats(void);
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
@ -127,13 +121,6 @@ static void StartRecording(void)
if (!g_recording_enabled) {
if (DataStorage_StartRecording(&g_data_storage) == HAL_OK) {
g_recording_enabled = 1;
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_SetState(SYSTEM_STATE_RECORDING);
#endif
} else {
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_ReportError(SYSTEM_ERROR_STORAGE);
#endif
}
}
}
@ -147,9 +134,6 @@ static void StopRecording(void)
if (g_recording_enabled) {
g_recording_enabled = 0;
DataStorage_StopRecording(&g_data_storage);
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_SetState(SYSTEM_STATE_IDLE);
#endif
}
}
@ -163,145 +147,61 @@ static void ProcessAdcData(void)
LTC2508_BufferTypeDef *ready_buffer = NULL;
if (LTC2508_GetReadyBuffer(&ready_buffer) == LTC2508_OK && ready_buffer != NULL)
{
#if ENABLE_PERFORMANCE_MONITOR
PerformanceMonitor_TaskStart(PERF_TASK_ADC_PROCESSING);
#endif
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_SetState(SYSTEM_STATE_SAMPLING);
SystemMonitor_IncrementSampleCount();
#endif
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]);
}
#if ENABLE_PERFORMANCE_MONITOR
PerformanceMonitor_TaskEnd(PERF_TASK_ADC_PROCESSING);
#endif
// 2. 验证数据有效性
uint8_t data_valid = 1;
for (uint8_t i = 0; i < NUM_LTC2508; i++) {
if (LTC2508_ValidateData(ready_buffer, i) != LTC2508_OK) {
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_ReportError(SYSTEM_ERROR_ADC);
#endif
data_valid = 0;
break; // 如果有任何通道数据无效,跳过整个样本
}
}
if (!data_valid) {
// 释放缓冲区并返回
LTC2508_ReleaseBuffer(LTC2508_GetCurrentReadBuffer());
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_SetState(SYSTEM_STATE_IDLE);
#endif
return;
}
// 3. 应用校正算法
CorrectionResult_t correction_result;
uint8_t correction_applied = 0;
#if ENABLE_PERFORMANCE_MONITOR
PerformanceMonitor_TaskStart(PERF_TASK_CORRECTION);
#endif
if (g_correction_params.params_valid &&
Apply_Correction(raw_adc[0], raw_adc[1], raw_adc[2],
&correction_result, &g_correction_params) == HAL_OK) {
#if ENABLE_PERFORMANCE_MONITOR
PerformanceMonitor_TaskEnd(PERF_TASK_CORRECTION);
#endif
// 4a. 打包校正后的数据
#if ENABLE_PERFORMANCE_MONITOR
PerformanceMonitor_TaskStart(PERF_TASK_DATA_PACKET);
#endif
PackCorrectedData(&g_corrected_packet,
correction_result.corrected_x,
correction_result.corrected_y,
correction_result.corrected_z);
#if ENABLE_PERFORMANCE_MONITOR
PerformanceMonitor_TaskEnd(PERF_TASK_DATA_PACKET);
#endif
correction_applied = 1;
// 发送校正后的数据包
#if ENABLE_PERFORMANCE_MONITOR
PerformanceMonitor_TaskStart(PERF_TASK_RS485_TX);
#endif
if (RS485_SendData((uint8_t*)&g_corrected_packet, sizeof(CorrectedDataPacket_t)) != HAL_OK) {
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_ReportError(SYSTEM_ERROR_COMMUNICATION);
#endif
}
#if ENABLE_PERFORMANCE_MONITOR
PerformanceMonitor_TaskEnd(PERF_TASK_RS485_TX);
#endif
RS485_SendData((uint8_t*)&g_corrected_packet, sizeof(CorrectedDataPacket_t));
} else {
#if ENABLE_PERFORMANCE_MONITOR
PerformanceMonitor_TaskEnd(PERF_TASK_CORRECTION);
#endif
// 4b. 校正失败或未启用,使用原始数据
#if ENABLE_PERFORMANCE_MONITOR
PerformanceMonitor_TaskStart(PERF_TASK_DATA_PACKET);
#endif
PackData(&g_data_packet, raw_adc[0], raw_adc[1], raw_adc[2]);
#if ENABLE_PERFORMANCE_MONITOR
PerformanceMonitor_TaskEnd(PERF_TASK_DATA_PACKET);
#endif
// 发送原始数据包
#if ENABLE_PERFORMANCE_MONITOR
PerformanceMonitor_TaskStart(PERF_TASK_RS485_TX);
#endif
if (RS485_SendData((uint8_t*)&g_data_packet, sizeof(DataPacket_t)) != HAL_OK) {
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_ReportError(SYSTEM_ERROR_COMMUNICATION);
#endif
}
#if ENABLE_PERFORMANCE_MONITOR
PerformanceMonitor_TaskEnd(PERF_TASK_RS485_TX);
#endif
RS485_SendData((uint8_t*)&g_data_packet, sizeof(DataPacket_t));
}
// 6. 存储数据到SD卡 (如果启用记录)
if (g_recording_enabled) {
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_SetState(SYSTEM_STATE_RECORDING);
#endif
#if ENABLE_PERFORMANCE_MONITOR
PerformanceMonitor_TaskStart(PERF_TASK_FATFS_WRITE);
#endif
if (correction_applied) {
// 存储校正后的数据
if (DataStorage_WriteCorrectedData(&g_data_storage, &correction_result) != HAL_OK) {
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_ReportError(SYSTEM_ERROR_STORAGE);
#endif
}
DataStorage_WriteCorrectedData(&g_data_storage, &g_corrected_packet);
} else {
// 存储原始数据
if (DataStorage_WriteData(&g_data_storage, &g_data_packet) != HAL_OK) {
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_ReportError(SYSTEM_ERROR_STORAGE);
#endif
DataStorage_WriteData(&g_data_storage, &g_data_packet);
}
}
#if ENABLE_PERFORMANCE_MONITOR
PerformanceMonitor_TaskEnd(PERF_TASK_FATFS_WRITE);
#endif
}
// 7. 释放已处理的缓冲区
LTC2508_ReleaseBuffer(LTC2508_GetCurrentReadBuffer());
} else {
// 数据来不及处理
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_SetState(SYSTEM_STATE_IDLE);
SystemMonitor_ReportDataOverflow();
#endif
}
}
@ -343,70 +243,21 @@ static void DebugOutput_PrintSystemStats(void)
return;
}
char buffer[256];
char buffer[128];
SystemMonitorStats_t sys_stats;
SystemMonitor_GetStats(&sys_stats);
snprintf(buffer, sizeof(buffer),
"\r\n=== System Monitor Stats ===\r\n"
"State: %d, Uptime: %lu s\r\n"
"Total Samples: %lu, Errors: %lu\r\n"
"Memory Usage: %lu bytes\r\n"
"CPU Usage: %d%%, Temp: %d°C\r\n",
sys_stats.current_state,
sys_stats.uptime_seconds,
"\r\n=== System Stats ===\r\n"
"Total Samples: %lu\r\n"
"Data Overflow: %lu\r\n",
sys_stats.total_samples,
sys_stats.error_count,
sys_stats.memory_usage,
sys_stats.cpu_usage_percent,
sys_stats.temperature_celsius);
sys_stats.data_overflow_count);
DebugOutput_SendString(buffer);
#endif
}
/**
* @brief
* @retval None
*/
static void DebugOutput_PrintPerformanceStats(void)
{
#if ENABLE_PERFORMANCE_MONITOR
if (!g_debug_output_enabled) {
return;
}
char buffer[512];
PerformanceMonitor_GetStats(&g_perf_stats);
snprintf(buffer, sizeof(buffer),
"\r\n=== Performance Monitor Stats ===\r\n"
"Total CPU Usage: %lu%%\r\n"
"Free Heap: %lu bytes (Min: %lu)\r\n"
"Stack Usage: %lu%%\r\n",
g_perf_stats.total_cpu_usage_percent,
g_perf_stats.free_heap_size,
g_perf_stats.min_free_heap_size,
g_perf_stats.stack_usage_percent);
DebugOutput_SendString(buffer);
// 输出各任务性能统计
for (int i = 0; i < PERF_MON_MAX_TASKS; i++) {
if (g_perf_stats.tasks[i].call_count > 0) {
snprintf(buffer, sizeof(buffer),
"Task[%d]: Calls=%lu, Avg=%lu us, Max=%lu us, CPU=%.1f%%\r\n",
i,
g_perf_stats.tasks[i].call_count,
g_perf_stats.tasks[i].avg_time_us,
g_perf_stats.tasks[i].max_time_us,
g_perf_stats.tasks[i].cpu_usage_percent);
DebugOutput_SendString(buffer);
}
}
#endif
}
/**
* @brief USB连接状态
* @retval 1: USB已连接, 0: USB未连接
@ -444,10 +295,6 @@ static void HandleUSBConnectionChange(void)
// 卸载用于采样的文件系统
UnmountFileSystemForSampling();
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_SetState(SYSTEM_STATE_USB_MODE);
#endif
} else {
// USB断开重新挂载文件系统开始数据采集
DebugOutput_SendString("USB Disconnected: Starting data acquisition\r\n");
@ -459,10 +306,6 @@ static void HandleUSBConnectionChange(void)
StartRecording();
}
}
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_SetState(SYSTEM_STATE_IDLE);
#endif
}
}
}
@ -578,7 +421,6 @@ int main(void)
MX_SPI1_Init();
MX_SPI2_Init();
MX_SPI3_Init();
MX_TIM1_Init();
MX_USART1_UART_Init();
MX_FATFS_Init();
MX_USB_DEVICE_Init();
@ -593,25 +435,11 @@ int main(void)
// 初始化系统监控
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_Init();
SystemMonitor_SetState(SYSTEM_STATE_INIT);
#endif
// 初始化性能监控
#if ENABLE_PERFORMANCE_MONITOR
PerformanceMonitor_Init();
#endif
// 初始化调试输出
DebugOutput_Init();
// 初始化LTC2508驱动
if (LTC2508_Init(&hspi1, &hspi2, &hspi3) != LTC2508_OK) {
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_ReportError(SYSTEM_ERROR_ADC);
#endif
Error_Handler();
}
// 初始化RS485通信
RS485_Init(&huart1, RS485_DE_RE_PORT, RS485_DE_RE_PIN);
@ -629,15 +457,7 @@ int main(void)
if (DataStorage_Init(&g_data_storage) == HAL_OK) {
// 开始数据记录
StartRecording();
} else {
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_ReportError(SYSTEM_ERROR_STORAGE);
#endif
}
} else {
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_ReportError(SYSTEM_ERROR_STORAGE);
#endif
}
} else {
// USB已连接不进行数据采集
@ -649,22 +469,24 @@ int main(void)
}
}
// 系统初始化完成
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_SetState(SYSTEM_STATE_IDLE);
#endif
// 启动TIM2定时器用于1ms周期的ADC数据处理
if (HAL_TIM_Base_Start_IT(&htim2) != HAL_OK) {
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_ReportError(SYSTEM_ERROR_CRITICAL);
#endif
Error_Handler();
}
// 初始化LTC2508驱动
if (LTC2508_Init(&hspi1, &hspi2, &hspi3) != LTC2508_OK) {
Error_Handler();
}
// 触发信号引脚初始化
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 */
@ -674,21 +496,8 @@ int main(void)
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
// 系统监控更新 (每100ms更新一次)
// 定期任务
uint32_t current_tick = HAL_GetTick();
if (current_tick - g_last_monitor_update >= 100) {
#if ENABLE_PERFORMANCE_MONITOR
PerformanceMonitor_TaskStart(PERF_TASK_SYSTEM_MONITOR);
#endif
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_Update();
#endif
#if ENABLE_PERFORMANCE_MONITOR
PerformanceMonitor_Update();
PerformanceMonitor_TaskEnd(PERF_TASK_SYSTEM_MONITOR);
#endif
g_last_monitor_update = current_tick;
}
// USB连接状态检测 (每500ms检测一次)
if (current_tick - g_last_usb_check >= 500) {
@ -704,7 +513,6 @@ int main(void)
// 定期输出调试信息 (每1秒输出一次)
if (g_debug_output_enabled && (current_tick - g_last_debug_output >= DEBUG_OUTPUT_INTERVAL_MS)) {
DebugOutput_PrintSystemStats();
DebugOutput_PrintPerformanceStats();
g_last_debug_output = current_tick;
}
@ -772,13 +580,18 @@ void SystemClock_Config(void)
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
static uint32_t cnt = 0;
if(LTC2508_IsInited() == 0) return;
cnt ++;
// if(cnt % 5 == 0)
{
// HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);
if (GPIO_Pin == ADC_DRY_Pin) {
// ADC数据就绪触发DMA读取
if (LTC2508_TriggerDmaRead() != LTC2508_OK) {
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_ReportError(SYSTEM_ERROR_ADC);
#endif
LTC2508_TriggerDmaRead();
}
// HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
}
}
@ -808,9 +621,6 @@ void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)
{
// 调用LTC2508驱动的错误回调
LTC2508_ErrorCallback(hspi);
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_ReportError(SYSTEM_ERROR_ADC);
#endif
}
/**
@ -827,13 +637,10 @@ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
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) {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);
ProcessAdcData();
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
processed_count++;
} else {
break; // 没有更多数据可处理
}
}
}
}
@ -862,12 +669,6 @@ void Error_Handler(void)
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
// 设置系统状态为错误状态
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_SetState(SYSTEM_STATE_ERROR);
SystemMonitor_ReportError(SYSTEM_ERROR_CRITICAL);
#endif
// 停止所有DMA传输
HAL_SPI_DMAStop(&hspi1);
HAL_SPI_DMAStop(&hspi2);

View File

@ -28,6 +28,7 @@ SPI_HandleTypeDef hspi1;
SPI_HandleTypeDef hspi2;
SPI_HandleTypeDef hspi3;
DMA_HandleTypeDef hdma_spi1_rx;
DMA_HandleTypeDef hdma_spi1_tx;
DMA_HandleTypeDef hdma_spi2_rx;
DMA_HandleTypeDef hdma_spi3_rx;
@ -45,7 +46,7 @@ void MX_SPI1_Init(void)
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.DataSize = SPI_DATASIZE_16BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
@ -77,7 +78,7 @@ void MX_SPI2_Init(void)
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_SLAVE;
hspi2.Init.Direction = SPI_DIRECTION_2LINES_RXONLY;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.DataSize = SPI_DATASIZE_16BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT;
@ -108,7 +109,7 @@ void MX_SPI3_Init(void)
hspi3.Instance = SPI3;
hspi3.Init.Mode = SPI_MODE_SLAVE;
hspi3.Init.Direction = SPI_DIRECTION_2LINES_RXONLY;
hspi3.Init.DataSize = SPI_DATASIZE_8BIT;
hspi3.Init.DataSize = SPI_DATASIZE_16BIT;
hspi3.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi3.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi3.Init.NSS = SPI_NSS_SOFT;
@ -158,10 +159,10 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
hdma_spi1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_spi1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi1_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_spi1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_spi1_rx.Init.Mode = DMA_NORMAL;
hdma_spi1_rx.Init.Priority = DMA_PRIORITY_LOW;
hdma_spi1_rx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
hdma_spi1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_spi1_rx) != HAL_OK)
{
@ -170,6 +171,24 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
__HAL_LINKDMA(spiHandle,hdmarx,hdma_spi1_rx);
/* SPI1_TX Init */
hdma_spi1_tx.Instance = DMA2_Stream5;
hdma_spi1_tx.Init.Channel = DMA_CHANNEL_3;
hdma_spi1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_spi1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi1_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_spi1_tx.Init.Mode = DMA_NORMAL;
hdma_spi1_tx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
hdma_spi1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_spi1_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(spiHandle,hdmatx,hdma_spi1_tx);
/* USER CODE BEGIN SPI1_MspInit 1 */
/* USER CODE END SPI1_MspInit 1 */
@ -201,10 +220,10 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
hdma_spi2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_spi2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi2_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_spi2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_spi2_rx.Init.Mode = DMA_NORMAL;
hdma_spi2_rx.Init.Priority = DMA_PRIORITY_LOW;
hdma_spi2_rx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
hdma_spi2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_spi2_rx) != HAL_OK)
{
@ -244,10 +263,10 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
hdma_spi3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_spi3_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi3_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_spi3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_spi3_rx.Init.Mode = DMA_NORMAL;
hdma_spi3_rx.Init.Priority = DMA_PRIORITY_LOW;
hdma_spi3_rx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
hdma_spi3_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_spi3_rx) != HAL_OK)
{
@ -282,6 +301,7 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* spiHandle)
/* SPI1 DMA DeInit */
HAL_DMA_DeInit(spiHandle->hdmarx);
HAL_DMA_DeInit(spiHandle->hdmatx);
/* USER CODE BEGIN SPI1_MspDeInit 1 */
/* USER CODE END SPI1_MspDeInit 1 */

View File

@ -62,10 +62,12 @@ extern DMA_HandleTypeDef hdma_sdio_rx;
extern DMA_HandleTypeDef hdma_sdio_tx;
extern SD_HandleTypeDef hsd;
extern DMA_HandleTypeDef hdma_spi1_rx;
extern DMA_HandleTypeDef hdma_spi1_tx;
extern DMA_HandleTypeDef hdma_spi2_rx;
extern DMA_HandleTypeDef hdma_spi3_rx;
extern TIM_HandleTypeDef htim2;
extern DMA_HandleTypeDef hdma_usart1_tx;
extern UART_HandleTypeDef huart1;
/* USER CODE BEGIN EV */
extern SPI_HandleTypeDef hspi1;
extern SPI_HandleTypeDef hspi2;
@ -267,6 +269,20 @@ void TIM2_IRQHandler(void)
/* USER CODE END TIM2_IRQn 1 */
}
/**
* @brief This function handles USART1 global interrupt.
*/
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
/**
* @brief This function handles SDIO global interrupt.
*/
@ -323,6 +339,20 @@ void OTG_FS_IRQHandler(void)
/* USER CODE END OTG_FS_IRQn 1 */
}
/**
* @brief This function handles DMA2 stream5 global interrupt.
*/
void DMA2_Stream5_IRQHandler(void)
{
/* USER CODE BEGIN DMA2_Stream5_IRQn 0 */
/* USER CODE END DMA2_Stream5_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_spi1_tx);
/* USER CODE BEGIN DMA2_Stream5_IRQn 1 */
/* USER CODE END DMA2_Stream5_IRQn 1 */
}
/**
* @brief This function handles DMA2 stream6 global interrupt.
*/

View File

@ -24,79 +24,8 @@
/* USER CODE END 0 */
TIM_HandleTypeDef htim1;
TIM_HandleTypeDef htim2;
/* TIM1 init function */
void MX_TIM1_Init(void)
{
/* USER CODE BEGIN TIM1_Init 0 */
/* USER CODE END TIM1_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
/* USER CODE BEGIN TIM1_Init 1 */
/* USER CODE END TIM1_Init 1 */
htim1.Instance = TIM1;
htim1.Init.Prescaler = 0;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 83;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
sBreakDeadTimeConfig.DeadTime = 0;
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM1_Init 2 */
/* USER CODE END TIM1_Init 2 */
HAL_TIM_MspPostInit(&htim1);
}
/* TIM2 init function */
void MX_TIM2_Init(void)
{
@ -141,18 +70,7 @@ void MX_TIM2_Init(void)
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_baseHandle->Instance==TIM1)
{
/* USER CODE BEGIN TIM1_MspInit 0 */
/* USER CODE END TIM1_MspInit 0 */
/* TIM1 clock enable */
__HAL_RCC_TIM1_CLK_ENABLE();
/* USER CODE BEGIN TIM1_MspInit 1 */
/* USER CODE END TIM1_MspInit 1 */
}
else if(tim_baseHandle->Instance==TIM2)
if(tim_baseHandle->Instance==TIM2)
{
/* USER CODE BEGIN TIM2_MspInit 0 */
@ -161,56 +79,18 @@ void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
__HAL_RCC_TIM2_CLK_ENABLE();
/* TIM2 interrupt Init */
HAL_NVIC_SetPriority(TIM2_IRQn, 3, 0);
HAL_NVIC_SetPriority(TIM2_IRQn, 12, 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)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(timHandle->Instance==TIM1)
{
/* USER CODE BEGIN TIM1_MspPostInit 0 */
/* USER CODE END TIM1_MspPostInit 0 */
__HAL_RCC_GPIOA_CLK_ENABLE();
/**TIM1 GPIO Configuration
PA8 ------> TIM1_CH1
*/
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN TIM1_MspPostInit 1 */
/* USER CODE END TIM1_MspPostInit 1 */
}
}
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_baseHandle->Instance==TIM1)
{
/* USER CODE BEGIN TIM1_MspDeInit 0 */
/* USER CODE END TIM1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM1_CLK_DISABLE();
/* USER CODE BEGIN TIM1_MspDeInit 1 */
/* USER CODE END TIM1_MspDeInit 1 */
}
else if(tim_baseHandle->Instance==TIM2)
if(tim_baseHandle->Instance==TIM2)
{
/* USER CODE BEGIN TIM2_MspDeInit 0 */

View File

@ -41,7 +41,7 @@ void MX_USART1_UART_Init(void)
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.BaudRate = 2000000;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
@ -70,7 +70,7 @@ void MX_USART3_UART_Init(void)
/* USER CODE END USART3_Init 1 */
huart3.Instance = USART3;
huart3.Init.BaudRate = 115200;
huart3.Init.BaudRate = 921600;
huart3.Init.WordLength = UART_WORDLENGTH_8B;
huart3.Init.StopBits = UART_STOPBITS_1;
huart3.Init.Parity = UART_PARITY_NONE;
@ -130,6 +130,9 @@ void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
__HAL_LINKDMA(uartHandle,hdmatx,hdma_usart1_tx);
/* USART1 interrupt Init */
HAL_NVIC_SetPriority(USART1_IRQn, 6, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
/* USER CODE BEGIN USART1_MspInit 1 */
/* USER CODE END USART1_MspInit 1 */
@ -179,6 +182,9 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
/* USART1 DMA DeInit */
HAL_DMA_DeInit(uartHandle->hdmatx);
/* USART1 interrupt Deinit */
HAL_NVIC_DisableIRQ(USART1_IRQn);
/* USER CODE BEGIN USART1_MspDeInit 1 */
/* USER CODE END USART1_MspDeInit 1 */

View File

@ -8,7 +8,8 @@ Dma.Request2=SPI3_RX
Dma.Request3=SDIO_RX
Dma.Request4=SDIO_TX
Dma.Request5=USART1_TX
Dma.RequestsNb=6
Dma.Request6=SPI1_TX
Dma.RequestsNb=7
Dma.SDIO_RX.3.Direction=DMA_PERIPH_TO_MEMORY
Dma.SDIO_RX.3.FIFOMode=DMA_FIFOMODE_ENABLE
Dma.SDIO_RX.3.FIFOThreshold=DMA_FIFO_THRESHOLD_FULL
@ -38,32 +39,42 @@ Dma.SDIO_TX.4.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAl
Dma.SPI1_RX.0.Direction=DMA_PERIPH_TO_MEMORY
Dma.SPI1_RX.0.FIFOMode=DMA_FIFOMODE_DISABLE
Dma.SPI1_RX.0.Instance=DMA2_Stream0
Dma.SPI1_RX.0.MemDataAlignment=DMA_MDATAALIGN_BYTE
Dma.SPI1_RX.0.MemDataAlignment=DMA_MDATAALIGN_HALFWORD
Dma.SPI1_RX.0.MemInc=DMA_MINC_ENABLE
Dma.SPI1_RX.0.Mode=DMA_NORMAL
Dma.SPI1_RX.0.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
Dma.SPI1_RX.0.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD
Dma.SPI1_RX.0.PeriphInc=DMA_PINC_DISABLE
Dma.SPI1_RX.0.Priority=DMA_PRIORITY_LOW
Dma.SPI1_RX.0.Priority=DMA_PRIORITY_VERY_HIGH
Dma.SPI1_RX.0.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode
Dma.SPI1_TX.6.Direction=DMA_MEMORY_TO_PERIPH
Dma.SPI1_TX.6.FIFOMode=DMA_FIFOMODE_DISABLE
Dma.SPI1_TX.6.Instance=DMA2_Stream5
Dma.SPI1_TX.6.MemDataAlignment=DMA_MDATAALIGN_HALFWORD
Dma.SPI1_TX.6.MemInc=DMA_MINC_ENABLE
Dma.SPI1_TX.6.Mode=DMA_NORMAL
Dma.SPI1_TX.6.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD
Dma.SPI1_TX.6.PeriphInc=DMA_PINC_DISABLE
Dma.SPI1_TX.6.Priority=DMA_PRIORITY_VERY_HIGH
Dma.SPI1_TX.6.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode
Dma.SPI2_RX.1.Direction=DMA_PERIPH_TO_MEMORY
Dma.SPI2_RX.1.FIFOMode=DMA_FIFOMODE_DISABLE
Dma.SPI2_RX.1.Instance=DMA1_Stream3
Dma.SPI2_RX.1.MemDataAlignment=DMA_MDATAALIGN_BYTE
Dma.SPI2_RX.1.MemDataAlignment=DMA_MDATAALIGN_HALFWORD
Dma.SPI2_RX.1.MemInc=DMA_MINC_ENABLE
Dma.SPI2_RX.1.Mode=DMA_NORMAL
Dma.SPI2_RX.1.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
Dma.SPI2_RX.1.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD
Dma.SPI2_RX.1.PeriphInc=DMA_PINC_DISABLE
Dma.SPI2_RX.1.Priority=DMA_PRIORITY_LOW
Dma.SPI2_RX.1.Priority=DMA_PRIORITY_VERY_HIGH
Dma.SPI2_RX.1.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode
Dma.SPI3_RX.2.Direction=DMA_PERIPH_TO_MEMORY
Dma.SPI3_RX.2.FIFOMode=DMA_FIFOMODE_DISABLE
Dma.SPI3_RX.2.Instance=DMA1_Stream0
Dma.SPI3_RX.2.MemDataAlignment=DMA_MDATAALIGN_BYTE
Dma.SPI3_RX.2.MemDataAlignment=DMA_MDATAALIGN_HALFWORD
Dma.SPI3_RX.2.MemInc=DMA_MINC_ENABLE
Dma.SPI3_RX.2.Mode=DMA_NORMAL
Dma.SPI3_RX.2.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
Dma.SPI3_RX.2.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD
Dma.SPI3_RX.2.PeriphInc=DMA_PINC_DISABLE
Dma.SPI3_RX.2.Priority=DMA_PRIORITY_LOW
Dma.SPI3_RX.2.Priority=DMA_PRIORITY_VERY_HIGH
Dma.SPI3_RX.2.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode
Dma.USART1_TX.5.Direction=DMA_MEMORY_TO_PERIPH
Dma.USART1_TX.5.FIFOMode=DMA_FIFOMODE_DISABLE
@ -98,11 +109,10 @@ Mcu.CPN=STM32F405RGT6
Mcu.Family=STM32F4
Mcu.IP0=DMA
Mcu.IP1=FATFS
Mcu.IP10=TIM2
Mcu.IP11=USART1
Mcu.IP12=USART3
Mcu.IP13=USB_DEVICE
Mcu.IP14=USB_OTG_FS
Mcu.IP10=USART1
Mcu.IP11=USART3
Mcu.IP12=USB_DEVICE
Mcu.IP13=USB_OTG_FS
Mcu.IP2=NVIC
Mcu.IP3=RCC
Mcu.IP4=SDIO
@ -110,8 +120,8 @@ Mcu.IP5=SPI1
Mcu.IP6=SPI2
Mcu.IP7=SPI3
Mcu.IP8=SYS
Mcu.IP9=TIM1
Mcu.IPNb=15
Mcu.IP9=TIM2
Mcu.IPNb=14
Mcu.Name=STM32F405RGTx
Mcu.Package=LQFP64
Mcu.Pin0=PH0-OSC_IN
@ -138,16 +148,15 @@ Mcu.Pin27=PB5
Mcu.Pin28=VP_FATFS_VS_SDIO
Mcu.Pin29=VP_SYS_VS_Systick
Mcu.Pin3=PA1
Mcu.Pin30=VP_TIM1_VS_ClockSourceINT
Mcu.Pin31=VP_TIM2_VS_ClockSourceINT
Mcu.Pin32=VP_USB_DEVICE_VS_USB_DEVICE_MSC_FS
Mcu.Pin30=VP_TIM2_VS_ClockSourceINT
Mcu.Pin31=VP_USB_DEVICE_VS_USB_DEVICE_MSC_FS
Mcu.Pin4=PA2
Mcu.Pin5=PA5
Mcu.Pin6=PA6
Mcu.Pin7=PA7
Mcu.Pin8=PB10
Mcu.Pin9=PB11
Mcu.PinsNb=33
Mcu.PinsNb=32
Mcu.ThirdPartyNb=0
Mcu.UserConstants=
Mcu.UserName=STM32F405RGTx
@ -158,6 +167,7 @@ NVIC.DMA1_Stream0_IRQn=true\:5\:0\:true\:false\:true\:false\:true\:true
NVIC.DMA1_Stream3_IRQn=true\:5\:0\:true\:false\:true\:false\:true\:true
NVIC.DMA2_Stream0_IRQn=true\:5\:0\:true\:false\:true\:false\:true\:true
NVIC.DMA2_Stream3_IRQn=true\:10\:0\:true\:false\:true\:false\:true\:true
NVIC.DMA2_Stream5_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true
NVIC.DMA2_Stream6_IRQn=true\:10\:0\:true\:false\:true\:false\:true\:true
NVIC.DMA2_Stream7_IRQn=true\:12\:0\:true\:false\:true\:false\:true\:true
NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
@ -172,7 +182,8 @@ NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
NVIC.SDIO_IRQn=true\:9\:0\:true\:false\:true\:true\:true\:true
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.SysTick_IRQn=true\:0\:0\:true\:false\:true\:false\:true\:false
NVIC.TIM2_IRQn=true\:3\:0\:true\:false\:true\:true\:true\:true
NVIC.TIM2_IRQn=true\:12\:0\:true\:false\:true\:true\:true\:true
NVIC.USART1_IRQn=true\:6\:0\:true\:false\:true\:true\:true\:true
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
PA1.GPIOParameters=GPIO_Label
PA1.GPIO_Label=ADC_DRY
@ -198,7 +209,8 @@ PA6.Mode=Full_Duplex_Master
PA6.Signal=SPI1_MISO
PA7.Mode=Full_Duplex_Master
PA7.Signal=SPI1_MOSI
PA8.Signal=S_TIM1_CH1
PA8.Locked=true
PA8.Signal=GPIO_Output
PA9.Mode=Asynchronous
PA9.Signal=USART1_TX
PB10.Locked=true
@ -285,7 +297,7 @@ ProjectManager.ToolChainLocation=
ProjectManager.UAScriptAfterPath=
ProjectManager.UAScriptBeforePath=
ProjectManager.UnderRoot=true
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_SDIO_SD_Init-SDIO-false-HAL-true,5-MX_SPI1_Init-SPI1-false-HAL-true,6-MX_SPI2_Init-SPI2-false-HAL-true,7-MX_SPI3_Init-SPI3-false-HAL-true,8-MX_TIM1_Init-TIM1-false-HAL-true,9-MX_USART1_UART_Init-USART1-false-HAL-true,10-MX_FATFS_Init-FATFS-false-HAL-false,11-MX_USB_DEVICE_Init-USB_DEVICE-false-HAL-false,12-MX_USART3_UART_Init-USART3-false-HAL-true,13-MX_TIM2_Init-TIM2-false-HAL-true
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_SDIO_SD_Init-SDIO-false-HAL-true,5-MX_SPI1_Init-SPI1-false-HAL-true,6-MX_SPI2_Init-SPI2-false-HAL-true,7-MX_SPI3_Init-SPI3-false-HAL-true,8-MX_USART1_UART_Init-USART1-false-HAL-true,9-MX_FATFS_Init-FATFS-false-HAL-false,10-MX_USB_DEVICE_Init-USB_DEVICE-false-HAL-false,11-MX_USART3_UART_Init-USART3-false-HAL-true,12-MX_TIM2_Init-TIM2-false-HAL-true
RCC.48MHZClocksFreq_Value=48000000
RCC.AHBFreq_Value=168000000
RCC.APB1CLKDivider=RCC_HCLK_DIV4
@ -324,31 +336,31 @@ SDIO.HardwareFlowControl=SDIO_HARDWARE_FLOW_CONTROL_DISABLE
SDIO.IPParameters=ClockDiv,HardwareFlowControl
SH.GPXTI1.0=GPIO_EXTI1
SH.GPXTI1.ConfNb=1
SH.S_TIM1_CH1.0=TIM1_CH1,PWM Generation1 CH1
SH.S_TIM1_CH1.ConfNb=1
SPI1.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_4
SPI1.CalculateBaudRate=21.0 MBits/s
SPI1.DataSize=SPI_DATASIZE_16BIT
SPI1.Direction=SPI_DIRECTION_2LINES
SPI1.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,BaudRatePrescaler
SPI1.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,BaudRatePrescaler,DataSize
SPI1.Mode=SPI_MODE_MASTER
SPI1.VirtualType=VM_MASTER
SPI2.DataSize=SPI_DATASIZE_16BIT
SPI2.Direction=SPI_DIRECTION_2LINES_RXONLY
SPI2.IPParameters=VirtualType,Mode,Direction
SPI2.IPParameters=VirtualType,Mode,Direction,DataSize
SPI2.Mode=SPI_MODE_SLAVE
SPI2.VirtualType=VM_SLAVE
SPI3.DataSize=SPI_DATASIZE_16BIT
SPI3.Direction=SPI_DIRECTION_2LINES_RXONLY
SPI3.IPParameters=VirtualType,Mode,Direction
SPI3.IPParameters=VirtualType,Mode,Direction,DataSize
SPI3.Mode=SPI_MODE_SLAVE
SPI3.VirtualType=VM_SLAVE
TIM1.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1
TIM1.IPParameters=Channel-PWM Generation1 CH1,Period
TIM1.Period=83
TIM2.IPParameters=Prescaler,Period
TIM2.Period=999
TIM2.Prescaler=83
USART1.IPParameters=VirtualMode
USART1.BaudRate=2000000
USART1.IPParameters=VirtualMode,BaudRate
USART1.VirtualMode=VM_ASYNC
USART3.IPParameters=VirtualMode
USART3.BaudRate=921600
USART3.IPParameters=VirtualMode,BaudRate
USART3.VirtualMode=VM_ASYNC
USB_DEVICE.CLASS_NAME_FS=MSC
USB_DEVICE.IPParameters=VirtualMode-MSC_FS,VirtualModeFS,CLASS_NAME_FS,MSC_MEDIA_PACKET-MSC_FS
@ -361,8 +373,6 @@ VP_FATFS_VS_SDIO.Mode=SDIO
VP_FATFS_VS_SDIO.Signal=FATFS_VS_SDIO
VP_SYS_VS_Systick.Mode=SysTick
VP_SYS_VS_Systick.Signal=SYS_VS_Systick
VP_TIM1_VS_ClockSourceINT.Mode=Internal
VP_TIM1_VS_ClockSourceINT.Signal=TIM1_VS_ClockSourceINT
VP_TIM2_VS_ClockSourceINT.Mode=Internal
VP_TIM2_VS_ClockSourceINT.Signal=TIM2_VS_ClockSourceINT
VP_USB_DEVICE_VS_USB_DEVICE_MSC_FS.Mode=MSC_FS

View File

@ -0,0 +1,130 @@
# SystemMonitor 简化说明
## 简化目标
为了提高系统性能将SystemMonitor模块从复杂的状态机和多种错误类型简化为只统计两个关键指标
1. **采样样点数** - 记录总共采集的样本数量
2. **数据溢出次数** - 记录数据来不及处理的次数
## 简化前后对比
### 简化前的结构
```c
typedef struct {
SystemState_t current_state; // 系统状态
SystemError_t last_error; // 最后错误
uint32_t uptime_seconds; // 运行时间
uint32_t total_samples; // 总样本数
uint32_t error_count; // 错误计数
uint32_t memory_usage; // 内存使用
uint8_t cpu_usage_percent; // CPU使用率
uint8_t temperature_celsius; // 温度
} SystemMonitorStats_t;
```
包含多个函数:
- `SystemMonitor_SetState()` - 设置系统状态
- `SystemMonitor_ReportError()` - 报告各种错误
- `SystemMonitor_Update()` - 定期更新统计
- `SystemMonitor_IsHealthy()` - 健康检查
### 简化后的结构
```c
typedef struct {
uint32_t total_samples; // 总采样样点数
uint32_t data_overflow_count; // 数据来不及处理的次数
} SystemMonitorStats_t;
```
只保留3个核心函数
- [`SystemMonitor_Init()`](User/system_monitor.h:14) - 初始化
- [`SystemMonitor_IncrementSampleCount()`](User/system_monitor.h:15) - 增加采样计数
- [`SystemMonitor_ReportDataOverflow()`](User/system_monitor.h:16) - 报告数据溢出
- [`SystemMonitor_GetStats()`](User/system_monitor.h:17) - 获取统计信息
## 使用方式
### 1. 初始化
在系统启动时调用:
```c
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_Init();
#endif
```
### 2. 采样计数
在 [`ProcessAdcData()`](Core/Src/main.c:146) 中,每处理一个样本时调用:
```c
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_IncrementSampleCount();
#endif
```
### 3. 数据溢出报告
当检测到数据来不及处理时(缓冲区无可用数据但应该有数据):
```c
} else {
// 数据来不及处理
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_ReportDataOverflow();
#endif
}
```
### 4. 查看统计信息
通过调试输出查看:
```c
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);
```
## 性能优势
1. **减少函数调用开销** - 从多个状态设置和错误报告函数简化为2个简单的计数器操作
2. **减少内存占用** - 统计结构从8个字段减少到2个字段
3. **消除复杂逻辑** - 移除状态机、健康检查等复杂逻辑
4. **提高实时性** - 减少中断和关键路径中的处理时间
## 关键指标说明
### total_samples总采样样点数
- 每成功处理一个ADC样本时递增
- 用于监控系统采样率和运行状态
- 可以计算实际采样率:`samples / uptime`
### data_overflow_count数据溢出次数
- 当数据处理速度跟不上采样速度时递增
- 表示数据丢失或处理延迟的情况
- 理想情况下应该为0或非常小的值
## 调试输出示例
```
=== System Stats ===
Total Samples: 40000
Data Overflow: 0
```
这表示系统已采集40000个样本没有发生数据溢出系统运行正常。
如果看到:
```
=== System Stats ===
Total Samples: 40000
Data Overflow: 150
```
说明有150次数据来不及处理需要优化数据处理流程或降低采样率。

View File

@ -21,9 +21,9 @@ void Init_CorrectionParams(CorrectionParams_t *params)
// 初始化为单位矩阵
memset(params->correction_matrix, 0, sizeof(params->correction_matrix));
params->correction_matrix[0] = 1.0f; // [0,0]
params->correction_matrix[4] = 1.0f; // [1,1]
params->correction_matrix[8] = 1.0f; // [2,2]
params->correction_matrix[0] = 5.0f / 0x7FFFFFFF; // [0,0]
params->correction_matrix[4] = 5.0f / 0x7FFFFFFF; // [1,1]
params->correction_matrix[8] = 5.0f / 0x7FFFFFFF; // [2,2]
#if USE_ARM_DSP
// 初始化ARM DSP矩阵实例 (3x3矩阵)

View File

@ -109,14 +109,14 @@ HAL_StatusTypeDef DataStorage_WriteData(DataStorageHandle_t *handle, const DataP
}
/**
* @brief
* @brief
* @param handle:
* @param result:
* @param packet:
* @retval HAL_StatusTypeDef
*/
HAL_StatusTypeDef DataStorage_WriteCorrectedData(DataStorageHandle_t *handle, const CorrectionResult_t *result)
HAL_StatusTypeDef DataStorage_WriteCorrectedData(DataStorageHandle_t *handle, const CorrectedDataPacket_t *packet)
{
if (handle == NULL || result == NULL || !handle->initialized) {
if (handle == NULL || packet == NULL || !handle->initialized) {
return HAL_ERROR;
}
@ -127,7 +127,7 @@ HAL_StatusTypeDef DataStorage_WriteCorrectedData(DataStorageHandle_t *handle, co
DataBuffer_t *active_buf = &handle->buffers[handle->active_buffer];
// 检查当前活动缓冲区空间
if (active_buf->index + sizeof(CorrectionResult_t) > DATA_STORAGE_BUFFER_SIZE) {
if (active_buf->index + sizeof(CorrectedDataPacket_t) > DATA_STORAGE_BUFFER_SIZE) {
// 切换缓冲区
if (DataStorage_SwitchBuffer(handle) != HAL_OK) {
handle->stats.error_count++;
@ -137,8 +137,8 @@ HAL_StatusTypeDef DataStorage_WriteCorrectedData(DataStorageHandle_t *handle, co
}
// 复制校正后的数据到活动缓冲区
memcpy(&active_buf->data[active_buf->index], result, sizeof(CorrectionResult_t));
active_buf->index += sizeof(CorrectionResult_t);
memcpy(&active_buf->data[active_buf->index], packet, sizeof(CorrectedDataPacket_t));
active_buf->index += sizeof(CorrectedDataPacket_t);
active_buf->state = BUFFER_WRITING;
handle->stats.total_samples++;

View File

@ -10,9 +10,9 @@
// 数据存储配置
#define DATA_STORAGE_BUFFER_SIZE 32768 // 缓冲区大小(字节)
#define DATA_STORAGE_FILE_MAX_SIZE (10*1024*1024) // 单个文件最大10MB
#define DATA_STORAGE_PATH "0:/DATA1" // 数据存储路径
#define DATA_STORAGE_FILE_PREFIX "ADC_DATA_" // 文件名前缀
#define DATA_STORAGE_FILE_MAX_SIZE (20*1024*1024) // 单个文件最大20MB
#define DATA_STORAGE_PATH "0:/DATA2" // 数据存储路径
#define DATA_STORAGE_FILE_PREFIX "/ADC_DATA_" // 文件名前缀
// 缓冲区状态
typedef enum {
@ -63,7 +63,7 @@ HAL_StatusTypeDef DataStorage_Init(DataStorageHandle_t *handle);
HAL_StatusTypeDef DataStorage_StartRecording(DataStorageHandle_t *handle);
HAL_StatusTypeDef DataStorage_StopRecording(DataStorageHandle_t *handle);
HAL_StatusTypeDef DataStorage_WriteData(DataStorageHandle_t *handle, const DataPacket_t *packet);
HAL_StatusTypeDef DataStorage_WriteCorrectedData(DataStorageHandle_t *handle, const CorrectionResult_t *result);
HAL_StatusTypeDef DataStorage_WriteCorrectedData(DataStorageHandle_t *handle, const CorrectedDataPacket_t *result);
HAL_StatusTypeDef DataStorage_Flush(DataStorageHandle_t *handle);
void DataStorage_GetStats(DataStorageHandle_t *handle, DataStorageStats_t *stats);
HAL_StatusTypeDef DataStorage_CreateNewFile(DataStorageHandle_t *handle);

View File

@ -16,6 +16,17 @@ static SPI_HandleTypeDef *g_hspi1 = NULL;
static SPI_HandleTypeDef *g_hspi2 = NULL;
static SPI_HandleTypeDef *g_hspi3 = NULL;
/**
* @brief LTC2508
* @retval 0- 1-
*/
uint32_t LTC2508_IsInited()
{
return (g_hspi1 != NULL && g_hspi2 != NULL && g_hspi3 != NULL);
}
/**
* @brief LTC2508
* @param hspi1: SPI1
@ -81,27 +92,27 @@ LTC2508_StatusTypeDef LTC2508_TriggerDmaRead(void)
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)
if (HAL_SPI_Receive_DMA(g_hspi2, (uint8_t*)current_buffer->data[1], LTC2508_DATA_LEN) != 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_ERROR_DMA;
}
if (HAL_SPI_Receive_DMA(g_hspi3, (uint8_t*)current_buffer->data[2], LTC2508_DATA_LEN * 2) != HAL_OK)
if (HAL_SPI_Receive_DMA(g_hspi3, (uint8_t*)current_buffer->data[2], LTC2508_DATA_LEN) != 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_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)
if (HAL_SPI_TransmitReceive_DMA(g_hspi1, (uint8_t*)dummy_tx, (uint8_t*)current_buffer->data[0], LTC2508_DATA_LEN) != HAL_OK)
{
current_buffer->state = LTC2508_BUFFER_EMPTY;
g_ltc2508_stats.dma_error_count++;

View File

@ -10,7 +10,7 @@
#define NUM_LTC2508 3
// 双缓冲区定义
#define LTC2508_BUFFER_COUNT 64
#define LTC2508_BUFFER_COUNT 128
// 缓冲区状态定义
typedef enum {
@ -62,6 +62,7 @@ extern volatile uint8_t g_current_read_buffer;
extern LTC2508_StatsTypeDef g_ltc2508_stats;
// 函数原型
uint32_t LTC2508_IsInited();
LTC2508_StatusTypeDef LTC2508_Init(SPI_HandleTypeDef *hspi1, SPI_HandleTypeDef *hspi2, SPI_HandleTypeDef *hspi3);
LTC2508_StatusTypeDef LTC2508_TriggerDmaRead(void);
void LTC2508_DmaComplete_Callback(SPI_HandleTypeDef *hspi);

View File

@ -1,193 +0,0 @@
#include "performance_monitor.h"
#include <string.h>
#include <stdlib.h>
// 静态变量
static SystemPerfStats_t g_perf_stats = {0};
static uint32_t g_task_start_time[PERF_MON_MAX_TASKS] = {0};
static uint8_t g_task_active[PERF_MON_MAX_TASKS] = {0};
// 外部符号声明 (用于堆栈监控)
extern uint32_t _estack;
extern uint32_t _Min_Stack_Size;
/**
* @brief
* @param None
* @retval None
*/
void PerformanceMonitor_Init(void)
{
memset(&g_perf_stats, 0, sizeof(SystemPerfStats_t));
memset(g_task_start_time, 0, sizeof(g_task_start_time));
memset(g_task_active, 0, sizeof(g_task_active));
g_perf_stats.sample_period_ms = PERF_MON_SAMPLE_PERIOD_MS;
g_perf_stats.last_update_tick = HAL_GetTick();
// 初始化最小执行时间为最大值
for (int i = 0; i < PERF_MON_MAX_TASKS; i++) {
g_perf_stats.tasks[i].min_time_us = UINT32_MAX;
}
}
/**
* @brief
* @param task_id: ID
* @retval None
*/
void PerformanceMonitor_TaskStart(PerfTaskID_t task_id)
{
if (task_id >= PERF_MON_MAX_TASKS) return;
g_task_start_time[task_id] = HAL_GetTick() * 1000; // 转换为微秒
g_task_active[task_id] = 1;
}
/**
* @brief
* @param task_id: ID
* @retval None
*/
void PerformanceMonitor_TaskEnd(PerfTaskID_t task_id)
{
if (task_id >= PERF_MON_MAX_TASKS || !g_task_active[task_id]) return;
uint32_t end_time = HAL_GetTick() * 1000; // 转换为微秒
uint32_t execution_time = end_time - g_task_start_time[task_id];
TaskPerfStats_t *task_stats = &g_perf_stats.tasks[task_id];
// 更新统计信息
task_stats->total_time_us += execution_time;
task_stats->call_count++;
// 更新最大最小时间
if (execution_time > task_stats->max_time_us) {
task_stats->max_time_us = execution_time;
}
if (execution_time < task_stats->min_time_us) {
task_stats->min_time_us = execution_time;
}
// 计算平均时间
task_stats->avg_time_us = task_stats->total_time_us / task_stats->call_count;
g_task_active[task_id] = 0;
}
/**
* @brief
* @param None
* @retval None
*/
void PerformanceMonitor_Update(void)
{
uint32_t current_tick = HAL_GetTick();
// 检查是否到了更新周期
if (current_tick - g_perf_stats.last_update_tick < g_perf_stats.sample_period_ms) {
return;
}
// 计算CPU使用率
uint32_t total_cpu_time = 0;
for (int i = 0; i < PERF_MON_MAX_TASKS; i++) {
if (g_perf_stats.tasks[i].call_count > 0) {
// 计算每个任务的CPU使用率
uint32_t task_time_per_period = g_perf_stats.tasks[i].avg_time_us *
(1000 / g_perf_stats.sample_period_ms);
g_perf_stats.tasks[i].cpu_usage_percent =
(float)task_time_per_period / 10000.0f; // 转换为百分比
total_cpu_time += task_time_per_period;
}
}
// 更新总CPU使用率
g_perf_stats.total_cpu_usage_percent = total_cpu_time / 100;
// 更新内存使用情况
g_perf_stats.free_heap_size = PerformanceMonitor_GetFreeHeapSize();
if (g_perf_stats.min_free_heap_size == 0 ||
g_perf_stats.free_heap_size < g_perf_stats.min_free_heap_size) {
g_perf_stats.min_free_heap_size = g_perf_stats.free_heap_size;
}
// 更新栈使用率
g_perf_stats.stack_usage_percent = PerformanceMonitor_GetStackUsage();
g_perf_stats.last_update_tick = current_tick;
}
/**
* @brief
* @param stats:
* @retval None
*/
void PerformanceMonitor_GetStats(SystemPerfStats_t *stats)
{
if (stats != NULL) {
memcpy(stats, &g_perf_stats, sizeof(SystemPerfStats_t));
}
}
/**
* @brief
* @param None
* @retval None
*/
void PerformanceMonitor_ResetStats(void)
{
memset(&g_perf_stats, 0, sizeof(SystemPerfStats_t));
g_perf_stats.sample_period_ms = PERF_MON_SAMPLE_PERIOD_MS;
g_perf_stats.last_update_tick = HAL_GetTick();
// 重新初始化最小执行时间
for (int i = 0; i < PERF_MON_MAX_TASKS; i++) {
g_perf_stats.tasks[i].min_time_us = UINT32_MAX;
}
}
/**
* @brief
* @param None
* @retval ()
*/
uint32_t PerformanceMonitor_GetFreeHeapSize(void)
{
// 简单的堆内存检测方法
// 在实际应用中,可能需要更复杂的内存管理
void *ptr = malloc(1);
if (ptr != NULL) {
free(ptr);
// 这里返回一个估算值,实际项目中需要更精确的实现
return 32768; // 假设有32KB空闲堆内存
}
return 0;
}
/**
* @brief 使
* @param None
* @retval 使
*/
uint32_t PerformanceMonitor_GetStackUsage(void)
{
// 获取当前栈指针
uint32_t current_sp;
__asm volatile ("mov %0, sp" : "=r" (current_sp));
// 计算栈使用量
uint32_t stack_top = (uint32_t)&_estack;
uint32_t min_stack_size = (uint32_t)&_Min_Stack_Size;
uint32_t stack_used = stack_top - current_sp;
// 计算使用率百分比
if (min_stack_size > 0) {
return (stack_used * 100) / min_stack_size;
}
return 0;
}

View File

@ -1,54 +0,0 @@
#ifndef PERFORMANCE_MONITOR_H
#define PERFORMANCE_MONITOR_H
#include "main.h"
#include <stdint.h>
// 性能监控配置
#define PERF_MON_MAX_TASKS 8
#define PERF_MON_SAMPLE_PERIOD_MS 100
// 任务ID定义
typedef enum {
PERF_TASK_ADC_PROCESSING = 0,
PERF_TASK_CORRECTION,
PERF_TASK_DATA_PACKET,
PERF_TASK_RS485_TX,
PERF_TASK_FATFS_WRITE,
PERF_TASK_USB_PROCESS,
PERF_TASK_SYSTEM_MONITOR,
PERF_TASK_IDLE
} PerfTaskID_t;
// 任务性能统计
typedef struct {
uint32_t total_time_us; // 总执行时间(微秒)
uint32_t max_time_us; // 最大执行时间
uint32_t min_time_us; // 最小执行时间
uint32_t call_count; // 调用次数
uint32_t avg_time_us; // 平均执行时间
float cpu_usage_percent; // CPU使用率百分比
} TaskPerfStats_t;
// 系统性能统计
typedef struct {
TaskPerfStats_t tasks[PERF_MON_MAX_TASKS];
uint32_t total_cpu_usage_percent;
uint32_t free_heap_size;
uint32_t min_free_heap_size;
uint32_t stack_usage_percent;
uint32_t sample_period_ms;
uint32_t last_update_tick;
} SystemPerfStats_t;
// 函数声明
void PerformanceMonitor_Init(void);
void PerformanceMonitor_TaskStart(PerfTaskID_t task_id);
void PerformanceMonitor_TaskEnd(PerfTaskID_t task_id);
void PerformanceMonitor_Update(void);
void PerformanceMonitor_GetStats(SystemPerfStats_t *stats);
void PerformanceMonitor_ResetStats(void);
uint32_t PerformanceMonitor_GetFreeHeapSize(void);
uint32_t PerformanceMonitor_GetStackUsage(void);
#endif // PERFORMANCE_MONITOR_H

View File

@ -26,9 +26,33 @@ HAL_StatusTypeDef RS485_SendData(uint8_t *pData, uint16_t Size)
g_rs485_tx_busy = 1;
HAL_GPIO_WritePin(g_de_re_port, g_de_re_pin, GPIO_PIN_SET); // 设置为发送模式
ret = HAL_UART_Transmit(g_huart_485, pData, Size, 0xffff);
HAL_GPIO_WritePin(g_de_re_port, g_de_re_pin, GPIO_PIN_RESET); // 切换回接收模式
ret = HAL_UART_Transmit_IT(g_huart_485, pData, Size);
// 注意:不能在这里立即切换回接收模式!
// DMA传输是非阻塞的需要在传输完成回调中切换
if (ret != HAL_OK)
{
// 如果启动DMA失败需要清除忙标志并切换回接收模式
HAL_GPIO_WritePin(g_de_re_port, g_de_re_pin, GPIO_PIN_RESET);
g_rs485_tx_busy = 0;
}
// 等待数据传输完成
while(g_rs485_tx_busy)
{
;
}
return ret;
}
// UART DMA传输完成回调函数
void RS485_TxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart == g_huart_485)
{
// DMA传输完成后切换回接收模式
HAL_GPIO_WritePin(g_de_re_port, g_de_re_pin, GPIO_PIN_RESET);
g_rs485_tx_busy = 0;
}
}

View File

@ -3,7 +3,6 @@
// 静态变量
static SystemMonitorStats_t g_system_stats = {0};
static uint32_t g_last_update_tick = 0;
/**
* @brief
@ -13,71 +12,26 @@ static uint32_t g_last_update_tick = 0;
void SystemMonitor_Init(void)
{
memset(&g_system_stats, 0, sizeof(SystemMonitorStats_t));
g_system_stats.current_state = SYSTEM_STATE_INIT;
g_last_update_tick = HAL_GetTick();
}
/**
* @brief
* @brief
* @param None
* @retval None
*/
void SystemMonitor_Update(void)
void SystemMonitor_IncrementSampleCount(void)
{
uint32_t current_tick = HAL_GetTick();
// 更新运行时间
if (current_tick >= g_last_update_tick) {
g_system_stats.uptime_seconds = current_tick / 1000;
}
// 获取LTC2508统计信息
LTC2508_StatsTypeDef ltc_stats;
LTC2508_GetStats(&ltc_stats);
g_system_stats.total_samples = ltc_stats.total_samples;
// 检查ADC错误
if (ltc_stats.error_count > 0) {
SystemMonitor_ReportError(SYSTEM_ERROR_ADC);
}
g_last_update_tick = current_tick;
g_system_stats.total_samples++;
}
/**
* @brief
* @brief
* @param None
* @retval SystemState_t
*/
SystemState_t SystemMonitor_GetState(void)
{
return g_system_stats.current_state;
}
/**
* @brief
* @param new_state:
* @retval None
*/
void SystemMonitor_SetState(SystemState_t new_state)
void SystemMonitor_ReportDataOverflow(void)
{
g_system_stats.current_state = new_state;
}
/**
* @brief
* @param error:
* @retval None
*/
void SystemMonitor_ReportError(SystemError_t error)
{
g_system_stats.last_error = error;
g_system_stats.error_count++;
// 根据错误类型设置系统状态
if (error == SYSTEM_ERROR_CRITICAL) {
g_system_stats.current_state = SYSTEM_STATE_ERROR;
}
g_system_stats.data_overflow_count++;
}
/**
@ -91,23 +45,3 @@ void SystemMonitor_GetStats(SystemMonitorStats_t *stats)
memcpy(stats, &g_system_stats, sizeof(SystemMonitorStats_t));
}
}
/**
* @brief
* @param None
* @retval uint8_t: 1-, 0-
*/
uint8_t SystemMonitor_IsHealthy(void)
{
// 检查系统状态
if (g_system_stats.current_state == SYSTEM_STATE_ERROR) {
return 0;
}
// 检查错误计数
if (g_system_stats.error_count > 10) {
return 0;
}
return 1; // 系统健康
}

View File

@ -2,51 +2,18 @@
#define SYSTEM_MONITOR_H
#include "main.h"
#include "ltc2508_driver.h"
#include "data_storage.h"
#include <stdint.h>
// 系统状态定义
typedef enum {
SYSTEM_STATE_INIT = 0,
SYSTEM_STATE_IDLE,
SYSTEM_STATE_SAMPLING,
SYSTEM_STATE_RECORDING,
SYSTEM_STATE_ERROR,
SYSTEM_STATE_MAINTENANCE,
SYSTEM_STATE_USB_MODE
} SystemState_t;
// 系统错误类型
typedef enum {
SYSTEM_ERROR_NONE = 0,
SYSTEM_ERROR_ADC,
SYSTEM_ERROR_STORAGE,
SYSTEM_ERROR_USB,
SYSTEM_ERROR_COMMUNICATION,
SYSTEM_ERROR_MEMORY,
SYSTEM_ERROR_CRITICAL
} SystemError_t;
// 系统监控统计信息
// 简化的系统监控统计信息
typedef struct {
SystemState_t current_state;
SystemError_t last_error;
uint32_t uptime_seconds;
uint32_t total_samples;
uint32_t error_count;
uint32_t memory_usage;
uint8_t cpu_usage_percent;
uint8_t temperature_celsius;
uint32_t total_samples; // 总采样样点数
uint32_t data_overflow_count; // 数据来不及处理的次数
} SystemMonitorStats_t;
// 函数声明
void SystemMonitor_Init(void);
void SystemMonitor_Update(void);
SystemState_t SystemMonitor_GetState(void);
void SystemMonitor_SetState(SystemState_t new_state);
void SystemMonitor_ReportError(SystemError_t error);
void SystemMonitor_IncrementSampleCount(void);
void SystemMonitor_ReportDataOverflow(void);
void SystemMonitor_GetStats(SystemMonitorStats_t *stats);
uint8_t SystemMonitor_IsHealthy(void);
#endif // SYSTEM_MONITOR_H