前言

电源方向资料免费开源到QQ群280730348,欢迎进群交流沟通。博客地址edadong.com,博文同步发布在知乎、bilibili,其中bilibili主要以视频为主。建议去B站听详细视频解说。

交流电压检测需要通过单片机ADC分点采集交流电压周期内多点电压,求均方根后才能求得。STM32F4系列单片机内部有DSP库,所以直接调用DSP库内函数就可以得到交流信号有效值,今天就是对F4系列单片机的交流电压采样进行代码分享。

交流电压检测代码思路

交流电压存在周期,我们需要设定如下思路,才能够还原交流电压信号的有效值:

  1. 确认PWM驱动波频率,如20KHz驱动情况下,采集交流信号的频率必须是这个频率的1/整数倍。通常我们在定时器中断中完成这个功能。
  2. 确认采样点数,一个周期内采样点数越高,得到的有效值就更稳定可靠。比如一个周期内采集200个点做均方根,但这个过程会出现一个问题,采样点数过高,系统运行过于缓慢,会影响到波形的产生,拉宽波形频率,并且在最终均方根运算的时候占用过多的时间。
  3. 确认ADC采样路数,采样时间,计算单次采样所需要的时间,避免时间不够无法获得最新的电压数据。
  4. 确认基准电压大小,减去对应基准电压值。
  5. 确认交流电压缩放倍数,用于还原对应真实交流电压大小。
  6. 采集到足够多的数据后,执行均方根算法。

以上就是采集交流电压的代码思路,那我们开始介绍每一段代码

(1)确认PWM驱动频率和采样点数,开启采集交流信号的对应频率中断,此处我们采取同频定时器,中断内部计数的方式。由于我们采样点数确认为200,交流正弦波输出为50Hz,交流信号频率为20KHz,所以一个完整周期会执行400次中断。每进入2次中断执行一次交流单点电压采集。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
//这个请在主函数中调用
Inverter_SPWM_Iint(20000,0);//两路SPWM波,频率为20KHZ,PC6,PA7(N) ,定时20KHZ,重装载值8400

void Inverter_SPWM_Iint(uint32_t pfreq, uint16_t psc)
{
//初始化GPIO
GPIO_InitTypeDef GPIO_InitStruct;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
//将输出通道2初始化为PWM模式1
TIM_OCInitTypeDef TIM_OCInitStruct;
//死区和刹车功能配置
TIM_BDTRInitTypeDef TIM_BDTRInitStruct;
NVIC_InitTypeDef NVIC_InitStructure;
//使能GPIO时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOA, ENABLE);

GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOC, &GPIO_InitStruct);

GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7;
GPIO_Init(GPIOA, &GPIO_InitStruct);

//GPIO复用
GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_TIM8);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_TIM8);

TimerPeriod = (SystemCoreClock / pfreq) - 1; //自动重装载周期值,168M/pfreq

//初始化定时器时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);

//初始化时具单元
TIM_DeInit(Inverter_TIMX);

TIM_TimeBaseInitStruct.TIM_ClockDivision = 0;
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_Period = TimerPeriod;
TIM_TimeBaseInitStruct.TIM_Prescaler = psc;
TIM_TimeBaseInit(Inverter_TIMX, &TIM_TimeBaseInitStruct);

TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStruct.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStruct.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStruct.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStruct.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
TIM_OCInitStruct.TIM_Pulse = TimerPeriod / 2 - 1;
TIM_OC1Init(Inverter_TIMX, &TIM_OCInitStruct);
//使能预装载寄存器
TIM_OC1PreloadConfig(Inverter_TIMX, TIM_OCPreload_Enable);


TIM_BDTRInitStruct.TIM_OSSIState = TIM_OSSIState_Disable;
TIM_BDTRInitStruct.TIM_OSSRState = TIM_OSSRState_Disable;
TIM_BDTRInitStruct.TIM_LOCKLevel = TIM_LOCKLevel_1;
TIM_BDTRInitStruct.TIM_DeadTime = 0;
TIM_BDTRInitStruct.TIM_BreakPolarity = TIM_BreakPolarity_Low;
TIM_BDTRInitStruct.TIM_Break = TIM_Break_Disable;
TIM_BDTRInitStruct.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
TIM_BDTRConfig(Inverter_TIMX, &TIM_BDTRInitStruct);

TIM_ITConfig(Inverter_TIMX, TIM_IT_Update, ENABLE); //允许定时器8更新中断

NVIC_InitStructure.NVIC_IRQChannel = TIM8_UP_TIM13_IRQn; //TIM8更新中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00; //抢占优先级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01; //子优先级1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

//使能自动重装载
TIM_ARRPreloadConfig(Inverter_TIMX, ENABLE);

//开启定时器
TIM_Cmd(Inverter_TIMX, ENABLE);

//主输出使能
TIM_CtrlPWMOutputs(Inverter_TIMX, ENABLE);
}

//定时器14中断服务函数
void TIM8_UP_TIM13_IRQHandler(void)
{
if(TIM_GetITStatus(Inverter_TIMX, TIM_IT_Update) == SET) //溢出中断
{
static u32 count=0;
if(count++%2)//一个周期内采样200个点
{
calculate_rms();
}
// if((master_swith & (0x01 << 15)) == 0x8000)
// {
// global_control();//开始运行系统
// }
}
TIM_ClearITPendingBit(Inverter_TIMX, TIM_IT_Update); //清除中断标志位
}

(2)配置ADC和高速DMA采集代码,一个通道输出,同时配置采样精度(也就是配置采样时间)

adc.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include "adc.h"
#include "stm32f4xx_adc.h"
#include "stm32f4xx_dma.h"

#define BufferSize (6*10)//传输六个通道的数据,可自由更改,每个通道的数据传输十次

static u16 DMA_Buf[BufferSize]={0};//设定DMA存储数组
u16 *adc_result=DMA_Buf;//利用这个变量在measure函数里面进行计算和工作

static void DMA_Config(void);//DMA的初始化函数
static void GPIO_Config(void);//所用到的IO口的函数
static void ADC1_CH3_CH4_CH14_Config(void);//ADC1通道的整体初始化
static void ADC2_CH5_CH6_CH15_Config(void);//ADC2通道的整体初始化
/*
初始化ADC,实验ADC1和ADC2双重模式,分别配置规则通道
(同时) (同时)
ADC1 CH3 PA3 ADC1 CH4 PA4 ADC1 CH14 PC4
ADC2 CH5 PA5 ADC2 CH6 PA6 ADC2 CH15 PC5

*/
void adc_init(void)
{
ADC_CommonInitTypeDef ADC_CommonInitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);

DMA_Config();//DMA初始化

GPIO_Config();//初始化IO口,设置为模拟输入模式

//对于f1而言,这是一个新的CCR寄存器,配置影响所有的ADC,所以要谨慎
ADC_CommonInitStructure.ADC_Mode = ADC_DualMode_RegSimult;//双重ADC通道模式
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;//时钟分频4,84M/4=21M
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1;//DMA模式1,双重模式下,第一个数据是ADC1的数据,第二个数据是ADC2的数据
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;//转换间隔时间5个采样周期,也就是0.23us
ADC_CommonInit(&ADC_CommonInitStructure);
ADC1_CH3_CH4_CH14_Config();//初始化ADC1上面的通道
ADC2_CH5_CH6_CH15_Config();//初始化ADC2上面的通道
ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);//转换完成以后继续转换另外一个通道的数据,ADC1和ADC2来回转换,总共转换三个来回
ADC_Cmd(ADC1, ENABLE);//使能ADC1
ADC_Cmd(ADC2, ENABLE);//使能ADC2
ADC_SoftwareStartConv(ADC1);//无外部触发,启动软件转换,两者数据传送全部由ADC1传送
}

static void DMA_Config(void)
{
DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_Channel = DMA_Channel_0;//数据流0,通道0
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&DMA_Buf;//内存地址,即数据地址
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(ADC1_BASE+0x300+0x8);//外设地址,多重模式通用数据寄存器的地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;//外设到内存模式
DMA_InitStructure.DMA_BufferSize = BufferSize; //待传输的数据个数,6通道每个通道10个即为60个
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址不递增
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//内存地址地址递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//外设每个数据的大小为半字即16位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//内存每个数据的大小为半字即16位
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//DMA开启循环模式,一直在传输数据和接收数据
DMA_InitStructure.DMA_Priority = DMA_Priority_High;//当前数据流优先级设置为高,因为只有一个通道,所以无所谓
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;//使能缓冲模式
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;//缓冲阈值为半字
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//内存单次触发
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//外设单次触发
DMA_Init(DMA2_Stream0, &DMA_InitStructure);//初始化DMA2
DMA_Cmd(DMA2_Stream0, ENABLE);//使能DMA2的通道0
}

static void GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* ADC12 Channel 3 -> PA3
ADC12 Channel 4 -> PA4
ADC12 Channel 5 -> PA5
ADC12 Channel 6 -> PA6
ADC12 Channel 14-> PC4
ADC12 Channel 15-> PC5
*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4 | GPIO_Pin_5;
GPIO_Init(GPIOC, &GPIO_InitStructure);
}


static void ADC1_CH3_CH4_CH14_Config(void)
{
ADC_InitTypeDef ADC_InitStructure;

ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; //半字,也就是12b
ADC_InitStructure.ADC_ScanConvMode = ENABLE;// 使能扫描模式
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//循环扫描
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;//不使用外部触发,用软件处罚
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;//不使用的话那么这条语句也就失去了作用
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//数据右对齐
ADC_InitStructure.ADC_NbrOfConversion = 3;//三个需要配置的数据通道
ADC_Init(ADC1, &ADC_InitStructure);

ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 1, ADC_SampleTime_56Cycles);//1÷21000000*68*60÷2=97.14us
ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 2, ADC_SampleTime_56Cycles);//特此注明,使用了双重模式,故两个通道可以同时转换数据而不产生冲突
ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 3, ADC_SampleTime_56Cycles);
}

/**
* @brief ADC2 regular channels 5, 6, 15 configuration
* @param None
* @retval None
*/
static void ADC2_CH5_CH6_CH15_Config(void)
{
ADC_InitTypeDef ADC_InitStructure;

ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 3;
ADC_Init(ADC2, &ADC_InitStructure);

ADC_RegularChannelConfig(ADC2, ADC_Channel_5, 1, ADC_SampleTime_56Cycles);
ADC_RegularChannelConfig(ADC2, ADC_Channel_6, 2, ADC_SampleTime_56Cycles);
ADC_RegularChannelConfig(ADC2, ADC_Channel_15, 3, ADC_SampleTime_56Cycles);
}

adc.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef ADC_H
#define ADC_H

#include "stm32f4xx.h"

/**
* @brief 初始化ADC,实验ADC1和ADC2双重模式,分别配置规则通道
ADC1 CH3 PA3 ADC1 CH4 PA4
ADC2 CH5 PA5 ADC2 CH6 PA6
* @param None
* @retval None
*/
void adc_init(void);

extern u16 *adc_result;

#endif

(3)定义基准电压和交流电压缩放倍数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//采集电量参数
//输出交流电压抬,PA4
float AC_Vout_vref=1.54650f;
float AC_Vout_ratio=50.4557f;
//输出交流电流,PC4
float AC_Iout_vref=1.51600f;
float AC_Iout_ratio=3.3333f;
//输入交流电压,PC5
float AC_Vin_verf=1.52400f;
float AC_Vin_ratio=51.2035f;
//输入直流电压,PA2
float DC_Vin_verf=0.0000f;
float DC_Vin_ratio=33.0655f;
//boost输入电流,PA3
float DC_Iin_verf=0.0000f;
float DC_Iin_ratio=1.2280f;

(4)定义采集函数

measure.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include "measure.h"
#include "adc.h"
#include "main.h"
#include "math.h"
#include "arm_math.h"
/*
ADC1 CH2 PA3 采集boost直流电压
ADC2 CH3 PA5 采集boost直流电流
ADC1 CH4 PA4 采集inverter交流输出电压
ADC2 CH6 PA6 采集inverter交流输出电流
ADC1 CH14 PC4 采集整流输入前的交流输入电压
ADC1 CH15 PC5
*/

#define COLS 6 //6个通道数,在单数组中用来计算
#define ROWS 10 //每个通道10个数据处理,在单数组中用来计算
#define SAMPLE_LEN 200 //采样的点数,经计算得知

rms_type AC_rms={0, 0, 0, 0, 0, 0};//存放rms_type的六个变量
float AC_sample_mat[6][SAMPLE_LEN]={0};//用来暂时保存各点采样值并最终将结果送入有效值中

void calculate_rms(void) //计算采样函数
{
static u32 count=0;
u32 temp=count %SAMPLE_LEN;
count++;
AC_sample_mat[0][temp]= get_dcv_in(); //PA3
AC_sample_mat[1][temp]= get_dci_in(); //PA5
AC_sample_mat[2][temp]= get_acv_out(); //PA4
AC_sample_mat[3][temp]= get_aci_out(); //PA6
AC_sample_mat[4][temp]= get_acv_in();//PC4
AC_sample_mat[5][temp]= get_aci_in(); //PC5
if(SAMPLE_LEN-1==temp)//如果检测到检测周期内的最后一个采样点
{
count=0;
arm_rms_f32(AC_sample_mat[0], SAMPLE_LEN, &AC_rms.VDC_rms);
arm_rms_f32(AC_sample_mat[1], SAMPLE_LEN, &AC_rms.IDC_rms);
arm_rms_f32(AC_sample_mat[2], SAMPLE_LEN, &AC_rms.Vout_rms);
arm_rms_f32(AC_sample_mat[3], SAMPLE_LEN, &AC_rms.Iout_rms);
arm_rms_f32(AC_sample_mat[4], SAMPLE_LEN, &AC_rms.Vin_rms);
arm_rms_f32(AC_sample_mat[5], SAMPLE_LEN, &AC_rms.Iin_rms);
}
}
//采集输入直流电压
float get_dcv_in(void)
{
float temp=0;
u32 sum=0;
int i;
for(i=0;i<ROWS;i++)
{
sum+=adc_result[i*COLS +0];//采集第一个通道,也就是第一个数据
}
temp =(double)sum/ROWS/4095*3.3;//将总值变成平均值
return (temp*DC_Vin_ratio);//返回直流电压大小,倍数乘以20.07倍(可测试得出)

}

//采集输入直流电流
float get_dci_in(void)
{
float temp=0;
u32 sum=0;
int i;
for(i=0;i<ROWS;i++)
{
sum+=adc_result[i*COLS +1];//采集第二个通道,也就是第二个数据
}
temp =(double)sum/ROWS/4095*3.3;//将总值变成平均值
return (temp*DC_Iin_ratio);//返回直流电流大小

}
//采集输出交流电压
float get_acv_out(void)
{
float temp=0;
u32 sum=0;
int i;
for(i=0;i<ROWS;i++)
{
sum+=adc_result[i*COLS +2];//采集第三个通道,也就是第三个数据
}
temp =(double)sum/ROWS/4095*3.3;//将总值变成平均值
return (temp-AC_Vout_vref)*AC_Vout_ratio;//返回交流输出电压大小

}
//采集输出交流电流
float get_aci_out(void)
{
float temp=0;
u32 sum=0;
int i;
for(i=0;i<ROWS;i++)
{
sum+=adc_result[i*COLS +3];//采集第四个通道,也就是第四个数据
}
temp =(double)sum/ROWS/4095*3.3;//将总值变成平均值
return (temp-AC_Iout_vref)*AC_Iout_ratio;//返回交流输出电流大小

}
//采集输入交流电压
float get_acv_in(void)
{
float temp=0;
u32 sum=0;
int i;
for(i=0;i<ROWS;i++)
{
sum+=adc_result[i*COLS +4];//采集第五个通道,也就是第一个数据
}
temp =(double)sum/ROWS/4095*3.3;//将总值变成平均值
return (temp-AC_Vin_verf)*AC_Vin_ratio;//返回直流电压大小,倍数乘以20.07倍(可测试得出)

}

float get_aci_in(void)
{
float temp=0;
u32 sum=0;
int i;
for(i=0;i<ROWS;i++)
{
sum+=adc_result[i*COLS +5];//采集第五个通道,也就是第一个数据
}
temp =(double)sum/ROWS/4095*3.3;//将总值变成平均值
return (temp-AC_Vin_verf)*AC_Vin_ratio;//返回直流电压大小,倍数乘以20.07倍(可测试得出)

}

float measure_rms(uint8_t i,uint8_t size)//均方根算法
{
float sum=0,result;
int j;

for(j=0;j<i;j++)
{
sum+=(float)(AC_sample_mat[size][j]*AC_sample_mat[size][j]);
}
sum=(double)(sum/i);
result=(float)(1.0*sqrt(sum));
return result;

}

measure.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#ifndef __MEASURE_H
#define __MEASURE_H
#include "stm32f4xx.h"

typedef struct _AC_RMS //定义有效值结构体
{
float Vin_rms; //输入交流电压有效值
float Vout_rms; //输出交流电压有效值
float Iout_rms; //输入交流电流有效值
float VDC_rms; //输出直流电压有效值
float IDC_rms; //输出直流电流有效值
float Iin_rms;
}rms_type;

extern rms_type AC_rms;
void calculate_rms(void); //总检测数据函数
float get_acv_in(void); //获得输入交流电压
float get_dcv_in(void); //获得输入直流电压
float get_acv_out(void); //获得输出交流电压
float get_dci_in(void); //获得输入直流电流
float get_aci_out(void); //获得输出交流电流
float get_aci_in(void); //获得输出交流电流
float measure_rms(uint8_t i,uint8_t size);//均方根算法,i代表我们采样的点数,size代表我们要采样的数据行


#endif
#ifndef __MEASURE_H
#define __MEASURE_H
#include "stm32f10x.h"

typedef struct _AC_RMS //定义有效值结构体
{
float V1_rms; //输入交流电压有效值
}rms_type;

extern rms_type AC_rms;
void calculate_rms(void);
u16 get_acv1_in(void);
float measure_rms(uint8_t i);//均方根算法,i代表我们采样的点数,size代表我们要采样的数据行


#endif

总结

代码资料如下

post9资料合集

链接: https://pan.baidu.com/s/12rAj4YzHQUONdo3RPmqAUA

提取码: c2em –来自百度网盘超级会员v6的分享