/* 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 */
如何检测负载时阻性负载还是非阻性负载。如果接入多个负载,其中有阻性负载,也有非阻性负载,又该如何分别出阻性负载
最新发布