基于GD32F2的光伏升压MPPT控制器
本帖最后由 Paderboy 于 2016-1-25 20:34 编辑一、方案名称:
基于GD32F207ZE的光伏升压MPPT控制器
二、方案介绍: 此方案是采用GD32F207ZE作为主控制器的太阳能光伏充电控制器,可对以下主要的类型电池组实现充电管理:(铅酸电池组,普通锂电池组,铁锂电池组….等等)并且使用LCD显示光伏板电压,电池组电压和控制器温度(因为年末时间比较少,就简化了控制器的附加高级功能。(例如:可以再添加电流传感器,实现功率可控-发电电量累计和手机APP查看和设置参数。以及通过wifi实时上传物联网平台。。))有喜欢的利用本方案自己再添加高级功能。。。本控制器使用串口输入设置参数,为了后期可以使用蓝牙模块配合APP预留的功能,本控制器具有电池过压保护,控制器过温保护功能,夜间防逆流功能,具有最大化利用光伏发电板,使其输出最大功率状态给电池组充电,实现绿色能源最大使用效益。。
三、方案结构框图:
四、设计应用描述及心得总结: 1. 使用的GD32F207资源配置:配置DMAIDLE方式接收串口数据,配置5个DMAADC通道获取数据,配置TIMER2 2个通道PWM输出控制,配置SPI1显示数据,配置内部FLASH作为设置参数的掉电存储
2. 使用SPI1驱动LCD引脚配置:PA5-SCL,PA7-SI,PA4-RES,PD0-RSX,PD1-CSX
3. 控制器供电使用了LM2596HVS降压12v给MOS驱动IR2110s供电以及(通过5v降压和3.3vLDO降压)提供单片机的供电。。最高支持60vDC输入(也可以使用XL7015替换,支持最高80VDC输入)
4. 不得不说,第一次使用GD32F系列的单片机,对GD32的库(使用非常方便,提供的历程也很多。有时间还是要继续再深入的学习)和STM32库的兼容性非常不错。可以节省很多的时间再去重新学习GD32的库使用函数了,再次感谢爱板网的活动和GD的开发板。。。
五、作品实物图+视频:
串口调试截图:
这个是小功率光伏板:
这个板子的功率非常小。。。电流只有180ma最大了。。。。。
移到楼下:换50w的光伏板
测试输入电压空载21v,输出23v电流:1.8a =41.4w的功率。。今天天气特别的好:loveliness:
视频里测试过程按了重启,为了方便观察mppt最大功率点的快速定位。。。
http://v.youku.com/v_show/id_XMTQ1NjUyNjE5Mg==.html?from=y1.7-1.2六、方案代码:
ADC DMA 配置:PC0 PC2 PC3 内部温度传感器和内部Vrefintvoid ADC_Configuration(void)
{
ADC_InitPara ADC_InitStructure;
ADC_InitStructure.ADC_Mode_Scan = ENABLE;
ADC_InitStructure.ADC_Mode_Continuous = ENABLE;
ADC_InitStructure.ADC_Trig_External = ADC_EXTERNAL_TRIGGER_MODE_NONE;
ADC_InitStructure.ADC_Data_Align = ADC_DATAALIGN_RIGHT;
ADC_InitStructure.ADC_Channel_Number = 5;
ADC_Init(ADC1,&ADC_InitStructure);
/* Configure ADC1 regular channel13 */
ADC_RegularChannel_Config(ADC1, ADC_CHANNEL_10, 1, ADC_SAMPLETIME_55POINT5);
ADC_RegularChannel_Config(ADC1, ADC_CHANNEL_12, 2, ADC_SAMPLETIME_55POINT5);
ADC_RegularChannel_Config(ADC1, ADC_CHANNEL_13, 3, ADC_SAMPLETIME_239POINT5);
ADC_RegularChannel_Config(ADC1, ADC_CHANNEL_16, 4, ADC_SAMPLETIME_239POINT5);
ADC_RegularChannel_Config(ADC1, ADC_CHANNEL_17, 5, ADC_SAMPLETIME_239POINT5);
ADC_TempSensorVrefint_Enable(ENABLE);
/* Enable ADC1 DMA */
ADC_DMA_Enable(ADC1,ENABLE);
/* Enable ADC1 */
ADC_Enable(ADC1,ENABLE);
ADC_Calibration(ADC1);
/* Start ADC1 Software Conversion */
ADC_SoftwareStartConv_Enable(ADC1,ENABLE);
}SPI 配置: PA4 PA5 PA6 PA7 D0 D1 驱动ST7858 LCDvoid SPI1_Configuration(void)
{
SPI_InitParaSPI_InitStructure;
SPI_InitStructure.SPI_TransType = SPI_TRANSTYPE_FULLDUPLEX;
SPI_InitStructure.SPI_Mode = SPI_MODE_MASTER;
SPI_InitStructure.SPI_FrameFormat = SPI_FRAMEFORMAT_8BIT;
SPI_InitStructure.SPI_SCKPL = SPI_SCKPL_HIGH;
SPI_InitStructure.SPI_SCKPH = SPI_SCKPH_2EDGE;
SPI_InitStructure.SPI_SWNSSEN = SPI_SWNSS_SOFT;
SPI_InitStructure.SPI_PSC = SPI_PSC_4;
SPI_InitStructure.SPI_FirstBit = SPI_FIRSTBIT_MSB;
SPI_InitStructure.SPI_CRCPOL = 10;
SPI_Init(SPI1, &SPI_InitStructure);
SPI_Enable(SPI1, ENABLE);
SPIx_ReadWriteByte(0xff);
}TIMER2 PWM输出配置:配置PA1 PA2void TIM_Configuration(void)
{
/* -----------------------------------------------------------------------
TIMER2 Configuration: generate 2 PWM signals with 2 different duty cycles:
TIMER2CLK = SystemCoreClock / 8 = 9MHz
TIMER2 frequency = 180/9M = 0.02ms
----------------------------------------------------------------------- */
TIMER_BaseInitPara TIMER_TimeBaseStructure;
TIMER_OCInitPara TIMER_OCInitStructure;
/* TIMER2 clock enable */
RCC_APB1PeriphClock_Enable(RCC_APB1PERIPH_TIMER2,ENABLE);
/* TIMER2configuration */
TIMER_DeInit(TIMER2);
TIMER_TimeBaseStructure.TIMER_Prescaler = 8-1;
TIMER_TimeBaseStructure.TIMER_CounterMode = TIMER_COUNTER_UP;
TIMER_TimeBaseStructure.TIMER_Period = 180-1;
TIMER_TimeBaseStructure.TIMER_ClockDivision = TIMER_CDIV_DIV1;
TIMER_BaseInit(TIMER2,&TIMER_TimeBaseStructure);
/* CH2,CH3 and CH4 Configuration in PWM mode */
TIMER_OCInitStructure.TIMER_OCMode = TIMER_OC_MODE_PWM1;
TIMER_OCInitStructure.TIMER_OCPolarity= TIMER_OC_POLARITY_HIGH;
TIMER_OCInitStructure.TIMER_OutputState = TIMER_OUTPUT_STATE_ENABLE;
TIMER_OCInitStructure.TIMER_OCIdleState = TIMER_OC_IDLE_STATE_RESET;
TIMER_OCInitStructure.TIMER_Pulse = 0;
TIMER_OC2_Init(TIMER2, &TIMER_OCInitStructure);
TIMER_OC2_Preload(TIMER2,TIMER_OC_PRELOAD_DISABLE);
TIMER_OCInitStructure.TIMER_Pulse = 0;
TIMER_OC3_Init(TIMER2, &TIMER_OCInitStructure);
TIMER_OC3_Preload(TIMER2,TIMER_OC_PRELOAD_DISABLE);
/* Auto-reload preload enable */
TIMER_CARLPreloadConfig(TIMER2,ENABLE);
/* TIMER enable counter*/
TIMER_Enable( TIMER2, ENABLE );
}FMC 存储数据函数:void FMC_savedate(void)
{
uint8_t p=0,n=0,flashflag={0};
if(flashdate==1)
{
if(ReadData>=PVMIN&&ReadData<=PVMAX){backupData=ReadData;flashflag=1;}else{/*printf("PV SETTING ERROR\n\r");*/}
if(ReadData>=BATMIN&&ReadData<=BATMAX){backupData=ReadData;flashflag=1;}else{/*printf("BAT SETTING ERROR\n\r");*/}
if(ReadData>=FANMIN&&ReadData<=FANMAX){backupData=ReadData;flashflag=1;}else{/*printf("FAN TEMP SETTING ERROR\n\r");*/}
for(p=0;p<Savenumber;p++){ReadData=0;}
if(flashflag==1&&flashflag==1&&flashflag==1)
{
FMC_Unlock();
/* Define the number of page to be erased */
NbrOfPage = (BANK1_WRITE_END_ADDR - BANK1_WRITE_START_ADDR) / FMC_PAGE_SIZE;
/* Clear All pending flags */
FMC_ClearBitState(FMC_FLAG_EOP | FMC_FLAG_WERR | FMC_FLAG_PERR );
/* Erase the FLASH pages */
for(EraseCounter = 0; EraseCounter < NbrOfPage; EraseCounter++)
{
FMCStatus = FMC_ErasePage(BANK1_WRITE_START_ADDR + (FMC_PAGE_SIZE * EraseCounter));
FMC_ClearBitState(FMC_FLAG_EOP | FMC_FLAG_WERR | FMC_FLAG_PERR );
}
FMC_Lock();
/* Unlock the Flash Bank1 Program Erase controller */
FMC_Unlock();
/* Define the number of page to be erased */
NbrOfPage = (BANK1_WRITE_END_ADDR - BANK1_WRITE_START_ADDR) / FMC_PAGE_SIZE;
/* Clear All pending flags */
FMC_ClearBitState(FMC_FLAG_EOP | FMC_FLAG_WERR | FMC_FLAG_PERR );
/* Program Flash Bank1 */
Address = BANK1_WRITE_START_ADDR;
for(save=0;save<Savenumber;save++)
{
FMCStatus = FMC_ProgramWord(Address, backupData);
FMC_ClearBitState(FMC_FLAG_EOP | FMC_FLAG_WERR | FMC_FLAG_PERR );
Address+=4;
}
FMC_Lock();
for(n=0;n<3;n++){flashflag=0;}
reset=1;
}
flashdate=0;
}
}串口DMA+IDLE中断接收数据void USART1_IRQHandler(void)
{
uint32_t tmp_flag = 0;
uint32_t temp;
tmp_flag=USART_GetIntBitState(USART1, USART_INT_IDLEF);
if(tmp_flag!= RESET)
{
DMA_Enable(DMA1_CHANNEL5, DISABLE);
temp = USART1->STR;
temp = USART1->DR;
temp= DMA_GetCurrDataCounter(DMA1_CHANNEL5);;
Length=BufferSize-temp;
flag=1;
DMA1_CHANNEL5->RCNT=BufferSize;
DMA_Enable(DMA1_CHANNEL5,ENABLE);
}
__nop();
}
32个赞,太好了! netlhx 发表于 2016-1-25 20:55 static/image/common/back.gif
32个赞,太好了!
:loveliness:多谢N神的鼓励啊。。。。。一定继续努力学习。。。。:handshake 唉,不置可否 不错不错!!! 亲,可以将内容一并发到经验频道,这是一个很好的系列,很有机会获得每月之星的呢http://jingyan.eeboard.com/ 这个有源码参考嘛
页:
[1]