在DC-AC单相全桥逆变电路中,使用stm32f103RCT6(DMA没有自带双缓冲模式?),软件部分,SPWM.c中我采用外部程序生成正弦表的1600个数据点,(由于是中央对齐模式2,使用CC1触发DMA,故每个TIM1周期更新两个CCR数据值,那么一个正弦波周期就是800个数据点)通过TIM1的中央对齐模式2(ARR=1800-1,PSC=1-1,时序:0-->ARR-->0),每个TIM1周期为50us,每个TIM1周期更新两次CCR(向上计数时CNT=CCR_A和向下计数CNT=CCR_B时),使用TIM1_CC1触发DMA1的通道二将正弦表中的数据依次搬运到TIM1_CCR1中完成SPWM的生成,我只需要用到一路主路PWM和互补PWM(即CH1和CH1N,因为我使用的驱动使IR2104,它只有一个输入端IN,两片IR2104,一片输入CH1另一片输入CH1N,它就是这么使用的)。ADC.c中打算采用TIM1_CC2触发ADC(同样是每个TIM1周期会采到两个样点,因为时序:0-->ARR-->0过程中会触发两次CC2)(双ADC同步规则分别采电压和电流)+DMA搬运进uint32_t数组ADC_Dual_Value[Buffersize]中(这里Buffersize为1600,前800个数据点是采到的一个完整正弦周期的数据点,后800个点也是采到的完整的正弦周期的数据点,我打算使用滑动窗口计算Rms而不是等待采完一整个正弦周期20ms才能计算一次Rms送入pid,由于数据量太大,每个周期虽然实际采了800个点,但是我实际只取100个点(800个点里每8个数据取1个),但是我一旦在TIM3触发的定时中断里执行Control_Loop()时,OLED就会黑屏不显示(使用的0.96寸4针脚(VCC、GND、SCL(PB8)、SDA(PB9))OLED显示屏,),但是注释掉TIM3_Init()时就恢复正常,应该时计算量太大了影响到OLED通信了?我该怎么办?或者换个思路使用一个定时器定时中断专门在中断里显示OLED刷新和显示的部分?代码如下,帮我分析分析,谢谢:
Main.c:#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "MYDAC.h"
#include "ADC_DMA.h"
#include "OLED.h"
#include "OLED_Data.h"
#include "PID.h"
#include "SPWM.h"
#include "Serial.h"
uint8_t temp = 0;
uint16_t Sam_Vol,Sam_Cur,vol_DAC;
int main(void) //PA8输出主PWM PB13输出互补PWM PB0采电压 PB1采电流
{
OLED_Init();
Timer3_Init();
TIM4_Init();
ADC_DMAInit();
SPWM_BDTR_Init();
//PID_Init(0.15,0.01,0,0,0,0);
//Serial_DMA_Init();
OLED_ShowString(0,0,"电压值:",OLED_8X16);
OLED_ShowString(0,16,"ADC电压:",OLED_8X16);
OLED_ShowString(0,32,"输出电流:",OLED_8X16);
OLED_Update();
while(1)
{
if(Control_Flag)
{
Control_Loop();
Control_Flag = 0;
}
// Sent_Data_to_Vofa();
}
}
SPWM.c:#include "stm32f10x.h" // Device header
#include "Serial.h"
#include "PID.h"
#include <math.h>
#include "ADC_DMA.h"
#include "SPWM.h"
//DMA传输正弦表进TIM1_CCR1中的数据量
#define BufferSize_Sample 1600 //
uint8_t TIM_DeadTime = 50; //待确定
//用于串口的定时中断采CCR1送入上位机,此为预备数组
//#define Sample_CCR_Num 100
//uint16_t Sample_Ready_CCR1[100];//TIM1_CCR1的采样,缓冲采样数组1,采样完毕后转移进Serial.c中的Buffer_to_Sent[]中
//uint16_t Sample_Ready_CCR2[100];//TIM1_CCR1的采样,缓冲采样数组2,采样完毕后转移进Serial.c中的Buffer_to_Sent[]中
//volatile uint16_t *Current_CCR_Buffer = Sample_Ready_CCR1;
//volatile uint8_t Buffer_Ready_Flag = 0; //采满200个样点的标志位
volatile uint16_t *Current_SPWM_ReadyBuffer; //指向当前就绪SPWM缓冲区,用于更新SPWM新表
volatile uint8_t SPWM_BufferReady_Flag = 0; //SPWM缓冲区就绪标志位
volatile uint16_t* const DMA_RemainIndex = (volatile uint16_t*)(&DMA1_Channel1->CNDTR); //DMA1_Channel1(搬运ADC)当前剩余数据
volatile Rms_Windows rms_windows = {0,0,0};
uint16_t DMA_CurrentIndex; //DMA1_Channel1当前索引
uint8_t Can_Get_RmsFlag = 0; //可获取有效值标志位
uint16_t SPWM_Data[BufferSize_Sample] = //SPWM的CCR值,大缓冲数组,每800个点为一个正弦周期(20ms),每个TIM1周期更新两个点
{
900,906,912,918,925,931,937,943,950,956,962,969,975,981,987,994,
1000,1006,1012,1018,1025,1031,1037,1043,1049,1056,1062,1068,1074,1080,1086,1092,
1098,1105,1111,1117,1123,1129,1135,1141,1147,1153,1159,1165,1170,1176,1182,1188,
1194,1200,1206,1211,1217,1223,1229,1234,1240,1246,1251,1257,1263,1268,1274,1279,
1285,1290,1296,1301,1307,1312,1317,1323,1328,1333,1339,1344,1349,1354,1360,1365,
1370,1375,1380,1385,1390,1395,1400,1405,1409,1414,1419,1424,1429,1433,1438,1443,
1447,1452,1456,1461,1465,1470,1474,1478,1483,1487,1491,1495,1500,1504,1508,1512,
1516,1520,1524,1528,1532,1535,1539,1543,1547,1550,1554,1558,1561,1565,1568,1572,
1575,1578,1582,1585,1588,1591,1594,1597,1601,1604,1607,1609,1612,1615,1618,1621,
1623,1626,1629,1631,1634,1636,1639,1641,1643,1646,1648,1650,1652,1654,1656,1658,
1660,1662,1664,1666,1668,1669,1671,1673,1674,1676,1677,1679,1680,1682,1683,1684,
1685,1686,1688,1689,1690,1691,1692,1692,1693,1694,1695,1695,1696,1697,1697,1698,
1698,1698,1699,1699,1699,1699,1699,1699,1700,1699,1699,1699,1699,1699,1699,1698,
1698,1698,1697,1697,1696,1695,1695,1694,1693,1692,1692,1691,1690,1689,1688,1686,
1685,1684,1683,1682,1680,1679,1677,1676,1674,1673,1671,1669,1668,1666,1664,1662,
1660,1658,1656,1654,1652,1650,1648,1646,1643,1641,1639,1636,1634,1631,1629,1626,
1623,1621,1618,1615,1612,1609,1607,1604,1601,1597,1594,1591,1588,1585,1582,1578,
1575,1572,1568,1565,1561,1558,1554,1550,1547,1543,1539,1535,1532,1528,1524,1520,
1516,1512,1508,1504,1500,1495,1491,1487,1483,1478,1474,1470,1465,1461,1456,1452,
1447,1443,1438,1433,1429,1424,1419,1414,1409,1405,1400,1395,1390,1385,1380,1375,
1370,1365,1360,1354,1349,1344,1339,1333,1328,1323,1317,1312,1307,1301,1296,1290,
1285,1279,1274,1268,1263,1257,1251,1246,1240,1234,1229,1223,1217,1211,1206,1200,
1194,1188,1182,1176,1170,1165,1159,1153,1147,1141,1135,1129,1123,1117,1111,1105,
1098,1092,1086,1080,1074,1068,1062,1056,1049,1043,1037,1031,1025,1018,1012,1006,
1000,994,987,981,975,969,962,956,950,943,937,931,925,918,912,906,
900,893,887,881,874,868,862,856,849,843,837,830,824,818,812,805,
799,793,787,781,774,768,762,756,750,743,737,731,725,719,713,707,
701,694,688,682,676,670,664,658,652,646,640,634,629,623,617,611,
605,599,593,588,582,576,570,565,559,553,548,542,536,531,525,520,
514,509,503,498,492,487,482,476,471,466,460,455,450,445,439,434,
429,424,419,414,409,404,399,394,390,385,380,375,370,366,361,356,
352,347,343,338,334,329,325,321,316,312,308,304,299,295,291,287,
283,279,275,271,267,264,260,256,252,249,245,241,238,234,231,227,
224,221,217,214,211,208,205,202,198,195,192,190,187,184,181,178,
176,173,170,168,165,163,160,158,156,153,151,149,147,145,143,141,
139,137,135,133,131,130,128,126,125,123,122,120,119,117,116,115,
114,113,111,110,109,108,107,107,106,105,104,104,103,102,102,101,
101,101,100,100,100,100,100,100,100,100,100,100,100,100,100,101,
101,101,102,102,103,104,104,105,106,107,107,108,109,110,111,113,
114,115,116,117,119,120,122,123,125,126,128,130,131,133,135,137,
139,141,143,145,147,149,151,153,156,158,160,163,165,168,170,173,
176,178,181,184,187,190,192,195,198,202,205,208,211,214,217,221,
224,227,231,234,238,241,245,249,252,256,260,264,267,271,275,279,
283,287,291,295,299,304,308,312,316,321,325,329,334,338,343,347,
352,356,361,366,370,375,380,385,390,394,399,404,409,414,419,424,
429,434,439,445,450,455,460,466,471,476,482,487,492,498,503,509,
514,520,525,531,536,542,548,553,559,565,570,576,582,588,593,599,
605,611,617,623,629,634,640,646,652,658,664,670,676,682,688,694,
701,707,713,719,725,731,737,743,750,756,762,768,774,781,787,793,
799,805,812,818,824,830,837,843,849,856,862,868,874,881,887,893,
900,906,912,918,925,931,937,943,950,956,962,969,975,981,987,994,
1000,1006,1012,1018,1025,1031,1037,1043,1049,1056,1062,1068,1074,1080,1086,1092,
1098,1105,1111,1117,1123,1129,1135,1141,1147,1153,1159,1165,1170,1176,1182,1188,
1194,1200,1206,1211,1217,1223,1229,1234,1240,1246,1251,1257,1263,1268,1274,1279,
1285,1290,1296,1301,1307,1312,1317,1323,1328,1333,1339,1344,1349,1354,1360,1365,
1370,1375,1380,1385,1390,1395,1400,1405,1409,1414,1419,1424,1429,1433,1438,1443,
1447,1452,1456,1461,1465,1470,1474,1478,1483,1487,1491,1495,1500,1504,1508,1512,
1516,1520,1524,1528,1532,1535,1539,1543,1547,1550,1554,1558,1561,1565,1568,1572,
1575,1578,1582,1585,1588,1591,1594,1597,1601,1604,1607,1609,1612,1615,1618,1621,
1623,1626,1629,1631,1634,1636,1639,1641,1643,1646,1648,1650,1652,1654,1656,1658,
1660,1662,1664,1666,1668,1669,1671,1673,1674,1676,1677,1679,1680,1682,1683,1684,
1685,1686,1688,1689,1690,1691,1692,1692,1693,1694,1695,1695,1696,1697,1697,1698,
1698,1698,1699,1699,1699,1699,1699,1699,1700,1699,1699,1699,1699,1699,1699,1698,
1698,1698,1697,1697,1696,1695,1695,1694,1693,1692,1692,1691,1690,1689,1688,1686,
1685,1684,1683,1682,1680,1679,1677,1676,1674,1673,1671,1669,1668,1666,1664,1662,
1660,1658,1656,1654,1652,1650,1648,1646,1643,1641,1639,1636,1634,1631,1629,1626,
1623,1621,1618,1615,1612,1609,1607,1604,1601,1597,1594,1591,1588,1585,1582,1578,
1575,1572,1568,1565,1561,1558,1554,1550,1547,1543,1539,1535,1532,1528,1524,1520,
1516,1512,1508,1504,1500,1495,1491,1487,1483,1478,1474,1470,1465,1461,1456,1452,
1447,1443,1438,1433,1429,1424,1419,1414,1409,1405,1400,1395,1390,1385,1380,1375,
1370,1365,1360,1354,1349,1344,1339,1333,1328,1323,1317,1312,1307,1301,1296,1290,
1285,1279,1274,1268,1263,1257,1251,1246,1240,1234,1229,1223,1217,1211,1206,1200,
1194,1188,1182,1176,1170,1165,1159,1153,1147,1141,1135,1129,1123,1117,1111,1105,
1098,1092,1086,1080,1074,1068,1062,1056,1049,1043,1037,1031,1025,1018,1012,1006,
1000,994,987,981,975,969,962,956,950,943,937,931,925,918,912,906,
900,893,887,881,874,868,862,856,849,843,837,830,824,818,812,805,
799,793,787,781,774,768,762,756,750,743,737,731,725,719,713,707,
701,694,688,682,676,670,664,658,652,646,640,634,629,623,617,611,
605,599,593,588,582,576,570,565,559,553,548,542,536,531,525,520,
514,509,503,498,492,487,482,476,471,466,460,455,450,445,439,434,
429,424,419,414,409,404,399,394,390,385,380,375,370,366,361,356,
352,347,343,338,334,329,325,321,316,312,308,304,299,295,291,287,
283,279,275,271,267,264,260,256,252,249,245,241,238,234,231,227,
224,221,217,214,211,208,205,202,198,195,192,190,187,184,181,178,
176,173,170,168,165,163,160,158,156,153,151,149,147,145,143,141,
139,137,135,133,131,130,128,126,125,123,122,120,119,117,116,115,
114,113,111,110,109,108,107,107,106,105,104,104,103,102,102,101,
101,101,100,100,100,100,100,100,100,100,100,100,100,100,100,101,
101,101,102,102,103,104,104,105,106,107,107,108,109,110,111,113,
114,115,116,117,119,120,122,123,125,126,128,130,131,133,135,137,
139,141,143,145,147,149,151,153,156,158,160,163,165,168,170,173,
176,178,181,184,187,190,192,195,198,202,205,208,211,214,217,221,
224,227,231,234,238,241,245,249,252,256,260,264,267,271,275,279,
283,287,291,295,299,304,308,312,316,321,325,329,334,338,343,347,
352,356,361,366,370,375,380,385,390,394,399,404,409,414,419,424,
429,434,439,445,450,455,460,466,471,476,482,487,492,498,503,509,
514,520,525,531,536,542,548,553,559,565,570,576,582,588,593,599,
605,611,617,623,629,634,640,646,652,658,664,670,676,682,688,694,
701,707,713,719,725,731,737,743,750,756,762,768,774,781,787,793,
799,805,812,818,824,830,837,843,849,856,862,868,874,881,887,893
};
void SPWM_BDTR_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //CH1为PA8
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; //CH1N互补为PB13
GPIO_Init(GPIOB,&GPIO_InitStructure);
DMA_DeInit(DMA1_Channel2); //TIM1_CC1映射在DMA1的通道2
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&TIM1 ->CCR1;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SPWM_Data;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = BufferSize_Sample;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel2,&DMA_InitStructure);
DMA_Cmd(DMA1_Channel2,ENABLE);
TIM1->CCR1 = SPWM_Data[0]; //先校正第一个CCR为数组SPWM_Data[0],使得第一次CC1事件触发时DMA搬运SPWM_Data[1]进CCR1
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
//中央对齐模式2,0-->ARR-->0的计数模式,向下计数阶段ARR-->0时CNT = 0时产生更新事件
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned2;
TIM_TimeBaseStructure.TIM_Period = 1800-1; //20k的频率,ARR = 3600-1
TIM_TimeBaseStructure.TIM_Prescaler = 1-1;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);
TIM_ClearFlag(TIM1,TIM_FLAG_CC1); //初始化前清除CC1标志位
TIM_ClearFlag(TIM2,TIM_FLAG_CC2); //初始化前清除CC2标志位
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //主路
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; //互补路
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
TIM_OC1Init(TIM1,&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //主路
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; //互补路
TIM_OCInitStructure.TIM_Pulse = 300;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
TIM_OC2Init(TIM1,&TIM_OCInitStructure);
TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;
TIM_BDTRInitStructure.TIM_DeadTime = TIM_DeadTime;
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable; //先不使用刹车
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High; //刹车触发极性,低电平
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Disable; //故障后不自动恢复输出,需自行手动恢复
TIM_BDTRConfig(TIM1,&TIM_BDTRInitStructure);
// NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn; //0 0
// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
// NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
// NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
// NVIC_Init(&NVIC_InitStructure);
// TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
DMA_ITConfig(DMA1_Channel2, DMA_IT_TC | DMA_IT_HT, ENABLE);
NVIC_EnableIRQ(DMA1_Channel2_IRQn); // 启用DMA中断通道2
TIM_DMACmd(TIM1,TIM_DMA_CC1,ENABLE); //TIM1的CC1事件更新时触发DMA
TIM_ARRPreloadConfig(TIM1,ENABLE); //预装载ARR
TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable); //预装载
TIM_SelectOutputTrigger(TIM1,TIM_TRGOSource_OC2Ref); //TIM1_CC2触发ADC
TIM_CtrlPWMOutputs(TIM1,ENABLE); //使能输出主PWM
TIM_Cmd(TIM1,ENABLE);
}
void PWM_SetCCR(TIM_TypeDef* TIMx,uint8_t CHx,uint16_t Compare,uint16_t Upper_LimitCCR) //占空比设置
{
if(CHx<1||CHx>4)
return;
if(Compare > Upper_LimitCCR)
Compare = Upper_LimitCCR;
switch (CHx)
{
case 1:TIM_SetCompare1(TIMx,Compare);break;
case 2:TIM_SetCompare2(TIMx,Compare);break;
case 3:TIM_SetCompare3(TIMx,Compare);break;
case 4:TIM_SetCompare4(TIMx,Compare);break;
}
}
uint16_t PWM_GetCCR(TIM_TypeDef* TIMx,uint8_t CHx) //参数1:定时器TIMX 参数2:通道,可为1~4
{
if(CHx<1||CHx>4)
return 0;
uint16_t CCR;
switch (CHx)
{
case 1:CCR =TIM_GetCapture1(TIMx);break;
case 2:CCR =TIM_GetCapture2(TIMx);break;
case 3:CCR =TIM_GetCapture3(TIMx);break;
case 4:CCR =TIM_GetCapture4(TIMx);break;
}
return CCR;
}
void SPWM_Update(float Gain,volatile uint16_t *Ready_Buffer) //正弦表更新,传入Current_SPWM_ReadyBuffer指向待写入的缓冲区
{
static float last_Gain = 1.0f;
int Offset_Val,New_Val;
if(SPWM_BufferReady_Flag&&fabs(Gain - last_Gain)>0.005f)
{
SPWM_BufferReady_Flag = 0;
for(uint16_t i=0;i<800;i++ )
{
Offset_Val = (int16_t)(Ready_Buffer[i] -900);
New_Val = (int16_t)((Offset_Val * Gain) + 900);
if(New_Val < 60) New_Val = 60;
else if(New_Val > 1740) New_Val = 1740;
Ready_Buffer[i] = (uint16_t)New_Val;
}
last_Gain = Gain;
}
}
void Rms_WindowsInit(void)
{
rms_windows.Volt_SquareSum = 0;
rms_windows.Cur_SquareSum = 0;
rms_windows.Count = 0;
}
void Rms_WindowsUpdate(void)
{
uint16_t DMA_Remain = *DMA_RemainIndex; //DMA传输剩余数据量
DMA_CurrentIndex = ADC_DMA_BufferSize - DMA_Remain; //DMA当前索引
//需移除点的索引,一个正弦周期(20ms)共采800个点,每8个点取一个点,实际一共仅取100个采样点
uint16_t Old_Index = (DMA_CurrentIndex - DMA_CurrentIndex%8 + ADC_DMA_BufferSize - ADC_BufferSize)%ADC_DMA_BufferSize;
uint16_t New_Index = DMA_CurrentIndex - DMA_CurrentIndex%8;
uint32_t Old_Value = ADC_Dual_Value[Old_Index]; //需移除的点的32位值
uint32_t New_Value = ADC_Dual_Value[New_Index];
//解析需移除的点的值为高16位的电流值和低16位的电压值
uint16_t New_Volt = New_Value & 0xFFFF;
uint16_t New_Cur = New_Value >> 16;
uint16_t Old_Volt = Old_Value & 0xFFFF;
uint16_t Old_Cur = Old_Value >> 16;
//更新新的平方和
rms_windows.Volt_SquareSum += (New_Volt * New_Volt - Old_Volt * Old_Volt);
rms_windows.Cur_SquareSum += (New_Cur * New_Cur - Old_Cur * Old_Cur);
}
float Get_Volt_RmsValue(void)
{
if(Can_Get_RmsFlag)
{
return sqrtf((float)rms_windows.Volt_SquareSum / ADC_BufferSize *3.3f/4095.0f);
}
else return 0;
}
float Get_Cur_RmsValue(void)
{
if(Can_Get_RmsFlag)
{
return sqrtf((float)rms_windows.Cur_SquareSum / ADC_BufferSize *3.3f/4095.0f);
}
else return 0;
}
void DMA1_Channel2_IRQHandler(void)
{
if(DMA_GetITStatus(DMA1_IT_HT2)) //上半缓冲传输完成,上次的表已经传输完了,该传输上次表传输完成之前PID已生成好的新表了
{
SPWM_BufferReady_Flag = 1; //置上半缓冲就绪1,该传输下半缓冲区了
Current_SPWM_ReadyBuffer = SPWM_Data; //当前源地址的指针指向下半缓冲区,将上次PID已更新好的数据写入TIM1_CC1
DMA_ClearITPendingBit(DMA1_IT_HT2);
}
if(DMA_GetITStatus(DMA1_IT_TC2)) //下半缓冲完成,上次的表已经传输完了,该传输上次表传输完成之前PID已生成好的新表了
{
SPWM_BufferReady_Flag = 2; //置下半缓冲就绪2,该传输上半缓冲区了
Current_SPWM_ReadyBuffer = SPWM_Data+ 800; //当前源地址的指针指向上半缓冲区,将上次PID已更新好的数据写入TIM1_CC1
DMA_ClearITPendingBit(DMA1_IT_TC2);
}
}
//void TIM1_UP_IRQHandler(void)
//{
//// static uint8_t TIM_Count_Sample_CCR = 0;
//// static uint8_t Sample_Num = 0;
// if(TIM_GetITStatus(TIM1,TIM_IT_Update))
// {
// // ADC_SoftwareStartConvCmd(ADC1,ENABLE); //每个TIM1中断软件触发ADC采样
// Window_UpdateFlag = 1;
//
// TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
//
//
// //if(++cycle_count >= 16000) //16000个TIM1中断时复位DMA
// // {
// // DMA_Cmd(DMA1_Channel2, DISABLE); //先关闭才能配置DMA
// // DMA1_Channel2->CNDTR = BufferSize_Sample;
// // DMA1_Channel2->CMAR = (uint32_t)SPWM_Data;
// // TIM1->CCR1 = SPWM_Data[0]; //校正第一个CCR为数组SPWM_Data[0],使得第一次CC1事件触发时DMA搬运SPWM_Data[1]进CCR1
// // DMA_Cmd(DMA1_Channel2, ENABLE);
// // cycle_count = 0;
// // }
//
//
//
//// if(++TIM_Count_Sample_CCR >= 40) //每40次定时中断(0.2ms)就采一次CCR1进数组Sample_CCR【】中
//// {
//// TIM_Count_Sample_CCR = 0;
////__disable_irq(); //原子保护,禁止中断
//// if(Sample_Num < Sample_CCR_Num) //如果数组没填满到Sample_CCR_Num这个次数,那就将CCR1存进去
//// {
//// Current_CCR_Buffer[Sample_Num] = TIM1->CCR1;
//// Sample_Num++;
//// }
////__enable_irq(); //原子保护恢复,允许中断
//// if(Sample_Num >= Sample_CCR_Num) //如果数组已经采满Sample_CCR_Num这个次数,就产生标志位
//// {
////__disable_irq(); //原子保护,禁止中断
//// if(Current_CCR_Buffer == Sample_Ready_CCR1) //寻找当前指向哪个缓冲区
//// {
//// Current_CCR_Buffer = Sample_Ready_CCR2; //缓冲区1满,切换缓冲区2
//// Buffer_Ready_Flag = 1; //标志位置1
//// }
//// else
//// {
//// Current_CCR_Buffer = Sample_Ready_CCR1; //缓冲区2满,切换缓冲区1
//// Buffer_Ready_Flag = 2; //标志位置2
//// }
//// Sample_Num = 0; //将Sample_Num复位
////__enable_irq(); //原子保护恢复,允许中断
////
//// }
//// }
//
// }
//
//}
//
//
//
//
ADC_DMA.c:#include "stm32f10x.h"
#include "PID.h"
#include "Delay.h"
#include "ADC_DMA.h"
#include "SPWM.h"
#include "OLED.h"
#include "OLED_Data.h"
#include<math.h>
#define ChannelNum 1
uint32_t ADC_Dual_Value[ADC_DMA_BufferSize]; //使用双ADC规则同步 32位的ADC1_DR存数据,低16位为ADC1 高16位为ADC2
uint16_t Volt_Value[SimplifyADC_BufferSize];
uint16_t Cur_Value[SimplifyADC_BufferSize];
float Void_Gain = 11;
float Cur_Gain = 1.47205;
volatile uint8_t ADC_DMA_CompleteFlag = 0; // DMA缓冲区就绪标志
volatile uint32_t *Current_ADC_Buffer; //指向当前就绪缓冲区
void TIM2_PWM_Init(void) //TIM2的通道1产生的PWM用于开关,通道2产生的PWM用于触发ADC采样
{
// 时基参数配置(产生100kHz PWM)
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //PA0输出PWM用于开关
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 定时器配置
TIM_TimeBaseStructure.TIM_Period = 1000-1; // ARR = 1000
TIM_TimeBaseStructure.TIM_Prescaler = 8-1; // PSC = 71
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
// PWM通道2配置(PA1)用于触发ADC
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // 时序:---------_____(采样)_____
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 300; // 75%占空比时采样(此处处于mos关断中间时刻)
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC2Init(TIM2, &TIM_OCInitStructure);
// 配置定时器触发输出
// TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_OC2Ref);
// TIM_CtrlPWMOutputs(TIM2, ENABLE);
// TIM_Cmd(TIM2, ENABLE); // 启动定时器
}
void TIM4_Init(void) //用于中断刷新OLED
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
// 时基参数配置
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// 定时器配置
TIM_TimeBaseStructure.TIM_Period = 10000-1; // ARR
TIM_TimeBaseStructure.TIM_Prescaler = 720-1; // PSC
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
TIM_InternalClockConfig(TIM4);
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 5;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM4, ENABLE); // 启动定时器
}
void ADC_DMA_Init(void) //双ADC规则同步采样,PB0采电压,PB1采电流
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
DMA_InitTypeDef DMA1_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// 使能时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_ADC1| RCC_APB2Periph_ADC2, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
// 配置PB0(ADC1通道8)采电压、PB1(ADC1通道9)采电流为模拟输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; //
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// DMA配置
DMA_DeInit(DMA1_Channel1);
DMA1_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
DMA1_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC_Dual_Value; //ADC_DMA_BufferSize个数据的大缓冲数组
DMA1_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA1_InitStructure.DMA_BufferSize = ADC_DMA_BufferSize;
DMA1_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA1_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA1_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA1_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
DMA1_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA1_InitStructure.DMA_Priority = DMA_Priority_High;
DMA1_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA1_InitStructure);
DMA_Cmd(DMA1_Channel1, ENABLE);
//配置ADC1,主ADC
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = ENABLE; // 启用扫描模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //单次转换
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC2; //使用T1_CC2触发
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
DMA_ITConfig(DMA1_Channel1, DMA_IT_TC | DMA_IT_HT, ENABLE);
NVIC_EnableIRQ(DMA1_Channel1_IRQn); // 启用DMA中断通道1
ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_55Cycles5); // 配置通道顺序(通道8) PB0对应序列1采电压
ADC_DMACmd(ADC1, ENABLE);
//配置ADC2,从ADC,配置与ADC1相同
ADC_Init(ADC2, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC2, ADC_Channel_9, 1, ADC_SampleTime_55Cycles5); //// 配置通道顺序(通道9) PB1对应序列1采电流
//操作ADC1_CR1寄存器之前先关闭ADC1和ADC2
ADC_Cmd(ADC1, DISABLE);
ADC_Cmd(ADC2, DISABLE);
//操作ADC1_CR1的位19:16位[3:0] = 0110 为规则同步模式
uint32_t tmp = ADC1->CR1;
tmp &= 0xFFF0FFFF;
tmp |= 0x00060000;
ADC1->CR1 = tmp;
// 先ADC2校准
ADC_Cmd(ADC2, ENABLE);
Delay_us(1);
ADC_ResetCalibration(ADC2);
while(ADC_GetResetCalibrationStatus(ADC2));
ADC_StartCalibration(ADC2);
while(ADC_GetCalibrationStatus(ADC2));
// ADC1校准
ADC_Cmd(ADC1, ENABLE);
Delay_us(1);
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
// 启用外部触发
ADC_ExternalTrigConvCmd(ADC1, ENABLE);
ADC_ExternalTrigConvCmd(ADC2, ENABLE);
}
void ADC_DMAInit(void)
{
// TIM2_PWM_Init(); //全桥不需TIM2_CC2触发ADC采样,需要TIM1_CC1触发ADC
ADC_DMA_Init();
}
void Get_ADC_Value(volatile uint32_t *ADC_Value) //解析32位采样数据,暂不用
{
for(int i=0;i<ADC_BufferSize;i++)
{
Volt_Value[i] = ADC_Value[i] & 0xFFFF;
Cur_Value[i] = ADC_Value[i] >>16;
}
}
void DMA1_Channel1_IRQHandler(void)
{
if(DMA_GetITStatus(DMA1_IT_HT1)) //DMA半传输完成标志位
{
Can_Get_RmsFlag = 1; //标记前半缓冲区就绪,前400个数据已就绪,可以调用float Get_Volt_RmsValue()和float Get_Cur_RmsValue();
//ADC_DMA_CompleteFlag = 1; // 标记前半缓冲区就绪,前400个数据已就绪
// Current_ADC_Buffer = &ADC_Dual_Value[0]; //指针指向缓冲区【0】
DMA_ITConfig(DMA1_Channel1, DMA_IT_TC | DMA_IT_HT, DISABLE); //第一次采满一个周期就关闭中断,此后方可调用float Get_Volt_RmsValue()和float Get_Cur_RmsValue();
DMA_ClearITPendingBit(DMA1_IT_HT1);
}
//if(DMA_GetITStatus(DMA1_IT_TC1)) //DMA全部传输完成标志位
//{
// ADC_DMA_CompleteFlag = 2; // 标记后半缓冲区就绪,后400个数据已就绪
// Current_ADC_Buffer = &ADC_Dual_Value[200]; //指针指向缓冲区【400】
// DMA_ClearITPendingBit(DMA1_IT_TC1);
// }
}
void TIM4_UP_IRQHandler(void)
{
if(TIM_GetITStatus(TIM4,TIM_IT_Update))
{
Sam_Vol = (uint16_t)(filtered_ADC_volt(Volt_Value)*1000); //采样电压,到时去实验测阻值比来乘上系数得到输出电压
// Sam_Cur = (uint16_t)(filtered_ADC_volt(Cur_Value)*1000/Cur_Gain); //采样电流的
// vol_DAC = (uint16_t)(filtered_ADC_volt(Volt_Value)*1000*Void_Gain);//输出电压
//
// OLED_ShowNum(56, 0,vol_DAC/10000,1,OLED_8X16); //十位
// OLED_ShowNum(64, 0,vol_DAC%10000/1000,1,OLED_8X16); //个位
// OLED_ShowChar(72, 0,'.',OLED_8X16);
// OLED_ShowNum(80, 0,vol_DAC%1000/100,1,OLED_8X16); //十分位
// OLED_ShowNum(88, 0,vol_DAC%100/10,1,OLED_8X16); //百分位
// OLED_ShowNum(96, 0,vol_DAC%10,1,OLED_8X16); //千分位
// OLED_ShowChar(112,0,'V',OLED_8X16);
OLED_ShowNum(72,16,Sam_Vol/10000,1,OLED_8X16); //十位
OLED_ShowNum(80,16,Sam_Vol%10000/1000,1,OLED_8X16); //个位
OLED_ShowChar(88,16,'.',OLED_8X16);
OLED_ShowNum(96,16,Sam_Vol%1000/100,1,OLED_8X16); //十分位
OLED_ShowNum(104,16,Sam_Vol%100/10,1,OLED_8X16); //百分位
OLED_ShowNum(112,16,Sam_Vol%10,1,OLED_8X16); //千分位
OLED_ShowChar(120,16,'V',OLED_8X16);
// OLED_ShowNum(72, 32,Sam_Cur/10000,1,OLED_8X16); //十位
// OLED_ShowNum(80, 32,Sam_Cur%10000/1000,1,OLED_8X16); //个位
// OLED_ShowChar(88, 32,'.',OLED_8X16);
// OLED_ShowNum(96, 32,Sam_Cur%1000/100,1,OLED_8X16); //十分位
// OLED_ShowNum(104, 32,Sam_Cur%100/10,1,OLED_8X16); //百分位
// OLED_ShowNum(112, 32,Sam_Cur%10,1,OLED_8X16); //千分位
// OLED_ShowChar(120,32,'A',OLED_8X16);
// OLED_ShowNum(0,48,PWM_GetCCR(TIM1,1),4,OLED_8X16);
//OLED_Update();
// OLED_UpdateArea(0,16,128,16);
TIM_ClearITPendingBit(TIM4,TIM_IT_Update);
}
}
PID.c:#include "stm32f10x.h" // Device header
#include "PID.h"
#include "SPWM.h"
#include <math.h>
#include "ADC_DMA.h"
#include <string.h>
#define Volt_Target 2.0f //目标电压
#define Cur_Max 5.0f
#define Steady_State_rate 0.0007f // 1%变化视为稳态
#define Enter_Steady_Count 10 // 连续20次在阈值内视为稳态
#define Max_Steady_Step 8 // 稳态时CCR最大步长(0.001占空比步长)
#define SAMPLE_SIZE 64 // 采样数组大小
float Gain = 1.0f; //SPWM幅值缩放因子
uint8_t Control_Flag =0;
PIDController pid = {.in_steady_state = 0, .steady_count = 0};
void Timer3_Init(void) //使用TIM3做定时中断
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
TIM_InternalClockConfig(TIM3);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 4000-1; //2ms的定时中断
TIM_TimeBaseInitStructure.TIM_Prescaler = 72-1;
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);
TIM_ClearFlag(TIM3,TIM_IT_Update);
TIM_ITConfig(TIM3,TIM_EventSource_Update,ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM3,ENABLE);
}
void PID_Init(float Volt_Kp,float Volt_Ki, float Volt_Kd,float Cur_Kp,float Cur_Ki, float Cur_Kd) {
// 初始PID参数(需调试优化)
pid.Volt_Kp = Volt_Kp; // 电压比例系数
pid.Volt_Ki = Volt_Ki; // 电压积分系数
pid.Volt_Kd = Volt_Kd; // 电压微分系数
pid.Cur_Kp = Cur_Kp; // 电压比例系数
pid.Cur_Ki = Cur_Ki; // 电压积分系数
pid.Cur_Kd = Cur_Kd; // 电压微分系数
pid.Volt_integral_sum = 0; //电压积分累加项
pid.Cur_integral_sum = 0; //电流积分累加项
pid.Max_Current = 0; //最大电流有效值
pid.Cur_Vref = 0;
pid.Volt_prev_error = 0; //电压上次误差
pid.Cur_prev_error = 0; //电流上次误差
// 输出限幅
pid.output_min = 0.1f;
pid.output_max = 1.05f;
Timer3_Init();
}
float PID_Compute(float Volt_Rms ,float Cur_Rms) {
// 计算当前误差 (电压误差)
float Volt_error = Volt_Target - Volt_Rms;
float error_threshold = Volt_Target * Steady_State_rate; //进入稳态误差的小小误差
if(fabs(Volt_error) <= error_threshold) //判断误差值连续20次<0.01V的电压时进入稳态
{
pid.steady_count++;
}
else
{
pid.steady_count = 0;
pid.in_steady_state = 0;
}
if(pid.steady_count >= Enter_Steady_Count)
{
pid.in_steady_state = 1;
}
// 计算P项
float Volt_P = pid.Volt_Kp * Volt_error;
// 计算I项
if(pid.in_steady_state) // 稳态时仅当|error|较大时才积分
{
if(fabs(Volt_error) > Steady_State_rate* Volt_Target/1)
{
pid.Volt_integral_sum += Volt_error;
}
}
else // 动态变化中正常积分
{
pid.Volt_integral_sum += Volt_error;
}
float Volt_I = pid.Volt_Ki * pid.Volt_integral_sum;
// 计算D项 (基于误差变化率)
float error_derivative = (Volt_error - pid.Volt_prev_error);
float Volt_D = pid.Volt_Kd * error_derivative;
// 计算电压外环输出
pid.Cur_Vref = Volt_P + Volt_I + Volt_D;
// 输出限幅处理
if(pid.Cur_Vref > pid.Max_Current)
{
pid.Cur_Vref = pid.Max_Current;
}
else if(pid.Cur_Vref < 0)
{
pid.Cur_Vref = 0;
}
pid.Volt_prev_error = Volt_error;
float Cur_error = pid.Cur_Vref - Cur_Rms;
//内环P
float Cur_P = pid.Cur_Kp * Cur_error;
//内环I
pid.Cur_integral_sum += Cur_error;
float Cur_I = pid.Cur_Ki * pid.Cur_integral_sum;
//内环D
float Cur_D = pid.Cur_Kd * (Cur_error - pid.Cur_prev_error);
float output = Cur_P + Cur_I + Cur_D;
pid.Cur_prev_error = Cur_error;
//输出限幅
if(output > pid.output_max)
{
output = pid.output_max;
if(Cur_error > 0)pid.Cur_integral_sum -= Cur_error; //超则回退积分
}
if(output < pid.output_min)
{
output = pid.output_min;
if(Cur_error < 0)pid.Cur_integral_sum -= Cur_error;
}
return output;
}
float filtered_ADC_volt(uint16_t *adc_values) //中值滤波函数,滤波采样数组中的数据
{
uint16_t temp[SAMPLE_SIZE];
// 1.
for(uint8_t i=0; i<SAMPLE_SIZE; i++)
{
temp[i] = adc_values[i];
}
// 2. 排序
for(uint8_t i=0; i<SAMPLE_SIZE-1; i++) {
for(uint8_t j=0; j<SAMPLE_SIZE-1-i; j++) {
if(temp[j] > temp[j+1]) {
uint16_t swap = temp[j];
temp[j] = temp[j+1];
temp[j+1] = swap;
}
}
}
// 3. 去掉最大最小值并计算均值
uint32_t sum = 0;
for(uint8_t i=5; i<SAMPLE_SIZE-5; i++) // 掐头去尾(去掉最大最小值)
{
sum += temp[i];
}
float result = sum / (float)(SAMPLE_SIZE - 10);
return result*3.3f/4095.0; //返回数组中去除最大最小值后的平均值(注:该值为模拟量)
}
float Rms_ADC_Volt(uint16_t *adc_values)
{
uint32_t Sum = 0;
float volt;
for(uint16_t i=0;i<SAMPLE_SIZE;i+=4)
{
Sum += (uint32_t)(adc_values[i] * adc_values[i]);
Sum += (uint32_t)(adc_values[i+1] * adc_values[i+1]);
Sum += (uint32_t)(adc_values[i+2] * adc_values[i+2]);
Sum += (uint32_t)(adc_values[i+3] * adc_values[i+3]);
}
volt = 3.3f*sqrt((float)Sum/SAMPLE_SIZE)/4095.0f;
return volt;
}
void Control_Loop(void)
{
Rms_WindowsUpdate(); //更新平方和
float Volt_Rms = Get_Volt_RmsValue();
float Cur_Rms =Get_Cur_RmsValue();
Gain = PID_Compute(Volt_Rms,Cur_Rms); //求采样有效值(0~3.3V)送入PID,返回缩放增益Gain
SPWM_Update(Gain,Current_SPWM_ReadyBuffer);
}
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
{
Control_Flag = 1;
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
}
}
请检查代码并分析,谢谢
最新发布