为何LC谐振的特征阻抗是root(L/C)?

RLC是常见的电路模型,属于二阶电路。

通常,我们会关心几个重要的指标。
++++++++++++++++++++++++
串联谐振频率。
当发生串联谐振时,
电感阻抗和电容阻抗相等,
X_l = w0 * L,
X_c = 1/(w0 * C),
可以推导出,
w0^2 * LC = 1,
则,
w0 = 1/Root(L * C),
+++++++++++++++++++++++
串联谐振阻抗,
X_l = X_c = 1/Root(L*C) * L = Root(L/C),
+++++++++++++++++++++++
品质因数,
如果R是直接和C串联的,则
Q = X_l/R = Root(L/C) / Rs,

如果R是和C并联的,则可以通过串并转换公式,将RC并联转换成RC 串联后,再来按上式分析。
也可以直接使用并联Q的公式来分析。
Q=(1/X_c)/(1/Rp) = Rp/X_c= Rp/Root(L/C)。

当发生串联谐振时,
Q = V_c/U,
所以,如果Q过大,那么将在电容两端,出现远大于电源电压U的过冲电压。
所以需要RC snubber额外添加阻尼。
+++++++++++++++++++++++
阻尼系数,Damping Ratio
Q * DR = 0.5,
所以,
当DR = 1时, 临界阻尼,Q = 0.5,
当DR < 1时,欠阻尼,Q > 0.5,
当DR > 1时,过阻尼,Q < 0.5,
要防止RLC串联谐振,就需要增大阻尼系数,即减小Q。

从Q的公式可以看出,
减小L,
增大C,
增大Rs,(或减小Rp)
都可以减小Q,即增大DR。

减小L,只能通过优化布线,减小寄生电感。
另外的方法,就是增大R,

/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * Copyright (c) 2025 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 "adc.h" #include "dma.h" #include "spi.h" #include "tim.h" #include "usart.h" #include "gpio.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "BL0942.h" #include <stdio.h> #include <math.h> #define M_PI 3.14159265358979323846 #include <stdbool.h> #include "oled.h" #define SAMPLE_RATE 2500 // 采样率2500Hz #define SAMPLE_POINTS 200 // 每个周期50个采样点 #define SHUNT_RESISTOR 100.0f // 采样电阻100Ω #define CT_RATIO 2000.0f // 互感器变比2000:1 // 继电器控制阈值设定 #define THRESHOLD_MAX 8.11f #define THRESHOLD_MIN 0.0f #define MIN_OPERATE_CURRENT 0.1f // 最小操作电流(0.1A) //应用电能计算上 #define MIN_CURRENT 0.1f #define POWER_DEADZONE 0.5f // 0.1W以下视为无效 float voltage_offset = 0.0f; float current_A_offset = 0.0f, current_B_offset = 0.0f, current_C_offset = 0.0f; /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ // 添加ADC相关定义 #define ADC_CHANNELS 4 // 4个ADC通道 uint16_t adc_buf0[ADC_CHANNELS * SAMPLE_POINTS]= {0}; // DMA缓冲区 // ADC校准参数 float vref = 3.3f; // ADC参考电压 float offset = 1.65f; // 硬件偏置电压 float voltage_rms; // 添加相位差存储变量和标志位 float phase_diff_A, phase_diff_B, phase_diff_C; volatile bool data_ready = false; // 电压/电流值存储数组(真实值) float current_A[SAMPLE_POINTS]; float current_B[SAMPLE_POINTS]; float current_C[SAMPLE_POINTS]; float voltage[SAMPLE_POINTS]; // 添加滤波数组 float voltage_filtered[SAMPLE_POINTS]; float current_A_filtered[SAMPLE_POINTS]; float current_B_filtered[SAMPLE_POINTS]; float current_C_filtered[SAMPLE_POINTS]; static const char *loadType = "Non-resistive load"; // 初始值设为非阻性 // 新增电能计量相关全局变量 typedef struct { float active_energy; // 有功电能(单位:kWh) float apparent_energy; // 视在电能(单位:kVAh) float power_factor; // 实时功率因数 } EnergyMeter; EnergyMeter p_A, p_B, p_C; // 各相电能计量 float total_energy = 0.0f; // 总累计电能(kWh) float delta_t = 1.0f / SAMPLE_RATE; // 采样时间间隔(秒) float V_line; /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ //static uint8_t valid_count_A = 0; //static bool relay_engaged_A = false; //static uint8_t valid_count = 0; //static bool relay_engaged = false; static uint8_t valid_count_C = 0; //static bool relay_engaged_C = false; #define REQUIRED_CONSECUTIVE_HITS 3 // 需要连续5次有效点 //继电器定时切换 //static uint32_t relay_trigger_time_A = 0; //static bool relay_delay_active_A = false; //static uint32_t relay_trigger_time = 0; //static bool relay_delay_active = false; //static uint32_t relay_trigger_time_C = 0; //static bool relay_delay_active_C = false; #define RELAY_OPERATION_TIME 10000 // 10秒延时,修改这个修改继电器状态从断开到闭合的时间 //断电次数 int Power_Outage_Count_A = 0; int Power_Outage_Count_B = 0; int Power_Outage_Count_C = 0; #define POWER_THRESHOLD_A 2500.0f // A相功率阈值2500W #define POWER_THRESHOLD_B 2500.0f // B相功率阈值2500W #define POWER_THRESHOLD_C 2500.0f // C相功率阈值2500W /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ static uint8_t cmdbuf[2]= {0x58,0xaa}; uint8_t test[50]; uint8_t flag; BL0942_Data meter_data; /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ char display_buf[32]; // 用于格式化的显示缓冲区 float phase_A_1; float phase_B_1; float phase_C_1; float current_A_rms; float current_B_rms; float current_C_rms; bool OLED__Clear = 1; /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); /* USER CODE BEGIN PFP */ float CalculatePhaseDifferenceByPeak(float *voltage, float *current, int length); /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ // OLED显示浮点数函数 void OLED_ShowFloat(uint8_t x, uint8_t y, float num, uint8_t size) { sprintf(display_buf, "%.2f", num); // 保留1位小数 OLED_ShowString(x, y, (uint8_t*)display_buf, size, 1); } // OLED显示带标签的测量值 void DisplayMeasurements(void) { // 显示C相相位差 OLED_ShowChinese(0,0,0,16,1);//相 OLED_ShowChinese(18,0,1,16,1);//位 OLED_ShowChinese(36,0,2,16,1);//差 OLED_ShowChar(54, 0, ':', 16, 1); // 直接传入字符':' if (isnan(phase_C_1)) { OLED_ShowString(72, 2, (uint8_t*)"nan", 16, 1); if(OLED__Clear == 1) { OLED_Clear(); OLED__Clear = 0; } } else { OLED_ShowFloat(72, 2, phase_C_1, 16); OLED__Clear = 1; } // OLED_ShowFloat(72, 2, phase_C_1, 16); OLED_ShowChinese(0,17,3,16,1); OLED_ShowChinese(18,17,4,16,1); OLED_ShowChinese(36,17,5,16,1); OLED_ShowChar(54, 17, ':', 16, 1); OLED_ShowFloat(72, 17, current_C_rms, 16); } // 平滑滤波函数 void SmoothFilter(float *input, float *output, int length) { const int window_size = SAMPLE_POINTS / 10; // const int window_size = 5; // 滑动窗口大小 const int half_window = window_size / 2; for(int i = 0; i < length; i++) { double sum = 0.0; int count = 0; // 滑动窗口累加 for(int j = -half_window; j <= half_window; j++) { int idx = i + j; if(idx >= 0 && idx < length) { sum += input[idx]; count++; } } // 计算平均值并存储结果 output[i] = sum / (double)count; } } // 相位差计算函数 float CalculatePhaseDifference(float *voltage, float *current, int length) { float v_zero = -1.0f; float i_zero = -1.0f; // 电流有效值检查 float sum_sq = 0.0f; for(int i=0; i<length; i++) { sum_sq += current[i] * current[i]; } float current_rms = sqrtf(sum_sq / length); // 电流小于阈值直接返回NAN if (current_rms < 0.05f) { // 阈值根据噪声调整 return NAN; } // 电压过零点检测(负→正,带趋势确认) for(int i=1; i < length-2; i++) { if(voltage[i] <0 && voltage[i+1] >=0) { if(voltage[i-1] <0 && voltage[i+2] >0) { // 趋势条件放宽 float delta = voltage[i+1] - voltage[i]; float fraction = (0 - voltage[i]) / delta; v_zero = i + fraction; break; } } } // 电流过零点检测(负→正,带趋势确认) for(int i=1; i < length-2; i++) { if(current[i] <0 && current[i+1] >=0) { if(current[i-1] <0 && current[i+2] >0) { float delta = current[i+1] - current[i]; float fraction = (0 - current[i]) / delta; i_zero = i + fraction; break; } } } if(v_zero < 0 || i_zero < 0) { return NAN; } // 计算原始相位差(每个采样点7.2度) float phase_diff = (i_zero - v_zero) * 7.2f; // 相位归一化 if(phase_diff > 180.0f) { phase_diff -= 360.0f; } else if(phase_diff < -180.0f) { phase_diff += 360.0f; } return phase_diff; } /** * @brief 通过检测电压和电流信号的绝对峰值点计算相位差 * @param voltage: 已滤波的电压信号数组 * @param current: 已滤波的电流信号数组 * @param length: 数组长度(采样点数) * @retval 相位差(单位:度),正值表示电流滞后电压,负值表示电流超前 * @note 每个采样点对应7.2°(360°/50个采样点) * 当电流有效值过小时返回NAN(无效值) */ float CalculatePhaseDifferenceByPeak(float *voltage, float *current, int length) { float sum_sq = 0.0f; // 1. 计算电流有效值用于有效性检查 for(int i=0; i<length; i++) { sum_sq += current[i] * current[i]; } float current_rms = sqrtf(sum_sq / length); if (current_rms < 0.01f) { // 电流小于0.05A视为无效 return NAN; } // 2. 寻找电压绝对值的峰值点 int v_peak_index = 0; float v_max_abs = fabsf(voltage[0]); for(int i=1; i<length; i++) { float abs_val = fabsf(voltage[i]); if(abs_val > v_max_abs) { v_max_abs = abs_val; v_peak_index = i; } } // 3. 寻找电流绝对值的峰值点 int i_peak_index = 0; float i_max_abs = fabsf(current[0]); for(int i=1; i<length; i++) { float abs_val = fabsf(current[i]); if(abs_val > i_max_abs) { i_max_abs = abs_val; i_peak_index = i; } } // 4. 计算原始相位差(每个采样点7.2°) float phase_diff = (i_peak_index - v_peak_index) * 7.2f; // 5. 相位归一化到[-180°,180°] if(phase_diff > 180.0f) { phase_diff -= 360.0f; } else if(phase_diff < -180.0f) { phase_diff += 360.0f; } return phase_diff; } // RMS计算函数 float CalculateTrueCurrentRMS(float *voltage_samples) { float sum_squares = 0.0f; // 1. 计算电压平方和 for(int i=0; i<SAMPLE_POINTS; i++) { sum_squares += voltage_samples[i] * voltage_samples[i]; } // 2. 计算电压有效值(RMS) voltage_rms = sqrtf(sum_squares / SAMPLE_POINTS); // 3. 计算真实电流有效值 // 电流计算流程:电压有效值 → 二次侧电流 → 一次侧电流 float current_secondary = voltage_rms / SHUNT_RESISTOR; // 二次侧电流 float current_primary = current_secondary * CT_RATIO; // 一次侧电流 return current_primary; } // 数据处理函数 void ProcessADCData(uint16_t *buf) { /*-------------------------------------------------------相位差计算部分-------------------------------------------------------*/ // ADC原始数据转换 for(int i=0; i<SAMPLE_POINTS; i++) { current_A[i] = -((buf[i*ADC_CHANNELS + 0] - 2048) * vref / 4095); // 添加负号反转信号 current_B[i] = -((buf[i*ADC_CHANNELS + 1] - 2048) * vref / 4095); // 添加负号反转信号 current_C[i] = -((buf[i*ADC_CHANNELS + 2] - 2048) * vref / 4095); // 添加负号反转信号 voltage[i] = ((buf[i*ADC_CHANNELS + 3] - 2048) * vref / 4095); } // 信号滤波 SmoothFilter(voltage, voltage_filtered, SAMPLE_POINTS); SmoothFilter(current_A, current_A_filtered, SAMPLE_POINTS); SmoothFilter(current_B, current_B_filtered, SAMPLE_POINTS); SmoothFilter(current_C, current_C_filtered, SAMPLE_POINTS); // 相位差计算 float phase_A = CalculatePhaseDifference(voltage_filtered, current_A_filtered, SAMPLE_POINTS); float phase_B = CalculatePhaseDifference(voltage_filtered, current_B_filtered, SAMPLE_POINTS); float phase_C = CalculatePhaseDifference(voltage_filtered, current_C_filtered, SAMPLE_POINTS); // 修改为峰值检测法: phase_A_1 = CalculatePhaseDifferenceByPeak(voltage_filtered, current_A_filtered, SAMPLE_POINTS); phase_B_1 = CalculatePhaseDifferenceByPeak(voltage_filtered, current_B_filtered, SAMPLE_POINTS); phase_C_1 = CalculatePhaseDifferenceByPeak(voltage_filtered, current_C_filtered, SAMPLE_POINTS); // 电流有效值计算 current_A_rms = CalculateTrueCurrentRMS(current_A_filtered); current_B_rms = CalculateTrueCurrentRMS(current_B_filtered); current_C_rms = CalculateTrueCurrentRMS(current_C_filtered); // 电压、电流对应的采样电阻电压值 // printf("采样点 | 电压(V) | 电流A(V) | 电流B(V) | 电流C(V)\r\n"); for(int i=0; i<SAMPLE_POINTS; i++) { printf("[%02d] %7.3f %7.3f %7.3f %7.3f\r\n", i, voltage_filtered[i], current_A_filtered[i], current_B_filtered[i], current_C_filtered[i]); } // 输出:相位差,电流有效值 // printf("LA:%.1f°/%.2fA LB:%.1f°/%.2fA LC:%.1f°/%.2fA\n", // phase_A, current_A_rms, // phase_B, current_B_rms, // phase_C, current_C_rms); // 输出:峰值计算相位差,过零电计算相位差,电流有效值 // printf("LA:峰值相位差=%.1f° 过零相位差=%.1f°/%.2fA LB:峰值相位差=%.1f° 过零相位差=%.1f°/%.2fA LC:峰值相位差=%.1f° 过零相位差=%.1f°/%.2fA\n", // phase_A_1, phase_A, current_A_rms, // phase_B_1, phase_B, current_B_rms, // phase_C_1, phase_C, current_C_rms); /*-------------------------------------------------------非BL0942电能计量部分-------------------------------------------------------*/ // A、B、C三回路电能计量 for(int i=0; i<SAMPLE_POINTS; i++) { //数据遍历处理 // 仅当A电流有效值达标时积分 if(current_A_rms >= MIN_CURRENT + 0.3) { //电流有效性检测 V_line = (voltage_filtered[i] - voltage_offset) * 100.0f; //电压信号处理 float I_A_primary = (current_A_filtered[i]/SHUNT_RESISTOR - current_A_offset) * CT_RATIO; //电流信号处理 float P_inst_A = V_line * I_A_primary; //瞬时功率计算 // 死区过滤 if(fabsf(P_inst_A) > POWER_DEADZONE) { p_A.active_energy += P_inst_A * delta_t / 3600000.0f; //电能累加计算 } } // 仅当B电流有效值达标时积分 if(current_B_rms >= MIN_CURRENT) { V_line = (voltage_filtered[i] - voltage_offset) * 100.0f; float I_B_primary = (current_B_filtered[i]/SHUNT_RESISTOR - current_B_offset) * CT_RATIO; float P_inst_B = V_line * I_B_primary; // 死区过滤 if(fabsf(P_inst_B) > POWER_DEADZONE) { p_B.active_energy += P_inst_B * delta_t / 3600000.0f; } } // 仅当C电流有效值达标时积分 if(current_C_rms >= MIN_CURRENT) { V_line = (voltage_filtered[i] - voltage_offset) * 100.0f; float I_C_primary = (current_C_filtered[i]/SHUNT_RESISTOR - current_C_offset) * CT_RATIO; float P_inst_C = V_line * I_C_primary; // 死区过滤 if(fabsf(P_inst_C) > POWER_DEADZONE) { p_C.active_energy += P_inst_C * delta_t / 3600000.0f; } } } // 4. 计算功率因数(使用相位差) p_A.power_factor = cosf(fabsf(phase_A) * M_PI / 180.0f); p_B.power_factor = cosf(fabsf(phase_B) * M_PI / 180.0f); p_C.power_factor = cosf(fabsf(phase_C_1) * M_PI / 180.0f); // 5. 计算视在电能 p_A.apparent_energy += (current_A_rms * V_line) * delta_t / 3600.0f; p_B.apparent_energy += (current_B_rms * V_line) * delta_t / 3600.0f; p_C.apparent_energy += (current_C_rms * V_line) * delta_t / 3600.0f; // // 6. 更新总电能(转换为kWh) total_energy = (p_A.active_energy + p_B.active_energy + p_C.active_energy); // 7. 电能数据输出 // printf("\n电能计量:"); // printf("\nLA: %.9fkWh (PF=%.2f)", p_A.active_energy, p_A.power_factor); // printf("\nLB: %.9fkWh (PF=%.2f)", p_B.active_energy, p_B.power_factor); // printf("\nLC: %.9fkWh (PF=%.2f)", p_C.active_energy, p_C.power_factor); // printf("\n总电能: %.9fkWh\n", total_energy); if (fabsf(p_C.power_factor) >= 0.99f && fabsf(p_C.power_factor) <= 1.0f) { HAL_Delay(100); if (fabsf(p_C.power_factor) >= 0.99f && fabsf(p_C.power_factor) <= 1.0f) { valid_count_C++; if (valid_count_C > REQUIRED_CONSECUTIVE_HITS && (fabsf(p_C.power_factor) >= 0.99f && fabsf(p_C.power_factor) <= 1.0f)) { OLED_Clear(); OLED_ShowChinese(0,0,6,16,1);//阻 OLED_ShowChinese(18,0,7,16,1);//性 OLED_ShowChinese(36,0,8,16,1);//负 OLED_ShowChinese(52,0,9,16,1);//载 OLED_ShowChinese(70,0,6,16,1);//阻 OLED_ShowChinese(88,0,7,16,1);//性 OLED_ShowChinese(106,0,8,16,1);//负 OLED_ShowChinese(124,0,9,16,1);//载 loadType = "Resistive load"; // 设置为阻性负载 OLED_ShowChinese(0,17,6,16,1);//阻 OLED_ShowChinese(18,17,7,16,1);//性 OLED_ShowChinese(36,17,8,16,1);//负 OLED_ShowChinese(52,17,9,16,1);//载 OLED_ShowChinese(70,17,6,16,1);//阻 OLED_ShowChinese(88,17,7,16,1);//性 OLED_ShowChinese(106,17,8,16,1);//负 OLED_ShowChinese(124,17,9,16,1);//载 OLED_Refresh(); valid_count_C = 0; // HAL_Delay(100); // OLED_Clear(); } // if (valid_count_C > REQUIRED_CONSECUTIVE_HITS) { // valid_count_C = REQUIRED_CONSECUTIVE_HITS; // } } } else{ valid_count_C = 0; OLED_Clear(); } /*-------------------------------------------------------C相控制条件判断-------------------------------------------------------*/ // bool condition_met_C = (!isnan(phase_C)) && // (current_C_rms > MIN_OPERATE_CURRENT) && // (phase_C > THRESHOLD_MIN) && // (phase_C < THRESHOLD_MAX); // // 状态机逻辑 // if (condition_met_C) { //// HAL_Delay(100); // if (condition_met_C) { // // 条件满足时增加计数器 // valid_count_C++; // // 达到阈值,断开继电器 // if (valid_count_C >= REQUIRED_CONSECUTIVE_HITS && !relay_engaged_C) { // HAL_GPIO_WritePin(GPIOC, K1P_Pin, GPIO_PIN_SET); // HAL_GPIO_WritePin(GPIOC, K1N_Pin, GPIO_PIN_RESET); // relay_engaged_C = true; // Power_Outage_Count_C++; // } // // 记录触发时间并激活延时标志 // relay_trigger_time_C = HAL_GetTick(); // relay_delay_active_C = true; // // 防止计数器溢出 // if (valid_count_C > REQUIRED_CONSECUTIVE_HITS) { // valid_count_C = REQUIRED_CONSECUTIVE_HITS; // } // } // } // else { // // 条件不满足时重置计数器并闭合继电器 // valid_count_C = 0; // if (relay_delay_active_C && (HAL_GetTick() - relay_trigger_time_C >= RELAY_OPERATION_TIME)) { // HAL_GPIO_WritePin(GPIOC, K1P_Pin, GPIO_PIN_RESET); // HAL_GPIO_WritePin(GPIOC, K1N_Pin, GPIO_PIN_SET); // relay_engaged_C = false; // relay_delay_active_C = false; // } // } } /* 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_SPI2_Init(); MX_UART4_Init(); MX_USART1_UART_Init(); MX_USART2_UART_Init(); MX_ADC1_Init(); MX_TIM3_Init(); MX_TIM2_Init(); /* USER CODE BEGIN 2 */ HAL_UARTEx_ReceiveToIdle_DMA(&huart2, test, 50); HAL_TIM_Base_Start(&htim2); HAL_TIM_Base_Start(&htim3); // 初始化电能计量结构体 p_A.active_energy = 0; p_A.apparent_energy = 0; p_A.power_factor = 1.0; p_B.active_energy = 0; p_B.apparent_energy = 0; p_B.power_factor = 1.0; p_C.active_energy = 0; p_C.apparent_energy = 0; p_C.power_factor = 1.0; HAL_ADCEx_Calibration_Start(&hadc1); // 重新执行ADC校准 // 启用ADC DMA HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buf0, ADC_CHANNELS*SAMPLE_POINTS); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ OLED_Init(); OLED_ColorTurn(0); // 正常显示 OLED_DisplayTurn(0); // 不翻转屏幕 OLED_Clear(); while (1) {loadType = "Non-resistive load"; ProcessADCData(adc_buf0); if (flag==1) { flag=0; meter_data=Data_Processing(test); } HAL_UART_Transmit_DMA(&huart2,cmdbuf,2); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ // HAL_GPIO_WritePin(GPIOC, K1P_Pin, GPIO_PIN_RESET); // HAL_GPIO_WritePin(GPIOC, K1N_Pin, GPIO_PIN_SET); // HAL_Delay(500); // HAL_GPIO_WritePin(GPIOC, K1P_Pin, GPIO_PIN_SET); // HAL_GPIO_WritePin(GPIOC, K1N_Pin, GPIO_PIN_RESET); // HAL_Delay(500); // 显示测量值 DisplayMeasurements(); OLED_Refresh(); // HAL_Delay(50); // OLED_Clear(); HAL_Delay(50); } /* USER CODE END 3 */ } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; /** 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.HSEPredivValue = RCC_HSE_PREDIV_DIV1; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; 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_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) { Error_Handler(); } PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC; PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { Error_Handler(); } } /* USER CODE BEGIN 4 */ //USART2中断回调函数 void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) { if(huart->Instance == USART2) { if (Size==23) { flag=1; } HAL_UARTEx_ReceiveToIdle_DMA(&huart2, test, 50); } } //ADC中断回调函数 void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { static uint32_t last_tick = 0; uint32_t current_tick = HAL_GetTick(); // 计算实际采样间隔(应对可能的时序漂移) if (last_tick != 0) { delta_t = ((current_tick - last_tick) / 1000.0f) + 0.027f; } last_tick = current_tick; } /* 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 */ 如何检测负载时阻性负载还是非阻性负载。如果接入多个负载,其中有阻性负载,也有非阻性负载,又该如何分别出阻性负载
最新发布
07-05
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值