一乐电子

一乐电子百科

 找回密码
 请使用微信账号登录和注册会员

QQ登录

只需一步,快速开始

快捷登录

手机号码,快捷登录

搜索
查看: 5042|回复: 29
收起左侧

[STM8/STM32] 太陽能板充電控制器

[复制链接]
发表于 2014-9-21 13:44 | 显示全部楼层 |阅读模式
買了一片太陽能板又買了一個控制器,看看功能 自己寫一下程式看看功能可以不可以取代!! 飛利浦黑晶爐的控制電路外加 MOS 作為充電和放電...
85W 17V太陽板
IMG_20140717_115537.jpg

IMG_20140717_115553.jpg

IMG_20140717_115404.jpg

IMG_20140717_115422.jpg

我的電路
太陽電池充電電路.jpg

太陽電池控制器04.JPG

太陽電池控制器01.JPG

太陽電池控制器02.JPG

太陽電池控制器03.JPG

電壓監控 電流監控 時間輸出控制 日落狀態控制輸出 輸出時間可調整

/*
20140813 修改部分程式
1.電池電壓修正把電流檢出造成的壓差扣除
2.內定輸出時間設為480分鐘
3.電流檢出修正 3.0A 顯示3.50A的問題
20140821 ricky chian 建議ON4OFF1秒充電以增加 電池的活性
*/
#include "STM8s.h"
#include "stm8s_tim1.h"
#include "stm8s_tim6.h"
#include "stm8s_adc1.h"
#define BUZZER GPIO_PIN_0
#define DCVoltage ADC1_CHANNEL_0
#define DCCurrent ADC1_CHANNEL_1
#define DCTemperature ADC1_CHANNEL_2
#define OUT_PUT_MOS GPIO_PIN_2//pin 5
#define OUT_PUT_MOS_PORT GPIOA
#define CHARGE_PORT GPIOB
#define CHARGE1_MOS GPIO_PIN_6
//#define CHARGE2_MOS GPIO_PIN_7
#define PV_PORT GPIOF //太陽電池狀態接腳 0730
#define PV_INPUT GPIO_PIN_4  //0730
#define NORM_Repair_Select GPIOB//----20140908 modify hi-normal Lo-repair
#define NORM_Repair_PIN GPIO_PIN_7//----20140908 modify hi-normal Lo-repair
u8pcdis[]={0xd6,0x14,0xcc,0x5c,0x1e,0x5a,0xda,0x14,0xde,0x5e};//定義pc port 顯示的值
u8pedis[]={0x01,0x00,0x01,0x01,0x00,0x01,0x01,0x01,0x01,0x01};//定義pe port 顯示的值對應于7段顯示
unsigned const inttempresist[]={28709,27421,26200,25042,23943,22899,21908, 20967, 20072, 19221,18412, 17642, 16910,16213, 15549,14916,14314,13740,13192,12670,12172,11696,11243, 10809, 10395,10000,9622,9261, 8916, 8585, 8269,7967,7677,7400,7135,
6880, 6637, 6403, 6179, 5964, 5758, 5561,5371, 5189, 5014, 4846, 4685, 4530, 4381, 4238, 4101, 3968, 3841, 3719,
3601, 3487, 3378, 3273, 3172, 3074, 2980,2890, 2803, 2718, 2637, 2559, 2483, 2411, 2340, 2272, 2207, 2144, 2082, 2023,1966, 1911, 1858, 1807, 1757, 1709, 1662, 1617, 1573, 1531, 1491, 1451, 1413,
1376, 1340, 1305, 1271, 1239, 1207, 1177,1147, 1118, 1090, 1063,1037, 1011,987,963,939,917,895,874,853,833,813,794,776,758
};//b3435 25 10k NTC電阻=((1024count/NTCcount)-1)/10k
u16 Real_Voltagea;//太陽電池的電壓
u16 Real_Voltage;//作為充電電壓放電電壓讀出
u16 Real_Current;//充電電流讀出
u16 Turn_off_Time;//倒數計時分鐘
u8 Hundreds,Tens,Units;//顯示百位十位個位
u16 voltage;//
u8 count6;//timer 6
u8 adc_update_flag;//ADC 更新1次的旗標
u8 display_time;//interrupt for display
u8 Start_Flag=0;
u16 Voltage_AD_count;  //電壓AD
u16 Current_AD_count;   //電流AD
u16 Temperature_AD_count;    //電阻AD
u8 AD_read_count;//0~3 輪流read out AD count
u16 ADCValue[10]={0};//電壓值平均用減少誤差雜訊
u16 DataADC=0;//最後的電壓值
u16 NTCvalue;//10K溫度電阻
u8 Degree_C,Degree_0C;//小數點
u8 PWM_Cycle_Complete;
u8 PWM_Time_Count;
u8 One_Sec_Flag;
u8 PWM_On_Count;
u8 PWM_Off_Count;
u8 PWM_Do;
u8PhotoVoltaic_Status;//--------------------0730
u8 Turn_MOS_Out_Flag;
u8 OutPut_Mode=0;//select for on auto off
u8 One_Tenth_Count;//1/10 second
u8 One_Sec_Count;
u8 One_Minute_Count;
u16 Store_Turn_off_Time;
u8 Low_Bat_Flag;//Flag low battery voltage10.8V
u8 One_Tenth_Flag;
u8 One_Minute_Flag;
u8 Night_Mode_Status;
u8 MOS2_Status;
u8 One_Hour_Flag;
u8 Discharge_Low =113;//放電下限電壓
u8 Charge_High_Limit =159;//146;
u8 Full_Charge =145;//135;
u16 Current_Limit =400;
u8 Charge_High_Limit_Top =162;
u8 NORM_Repair_flag; //if hi NORMAL condition14.5V Lo repaircondition 15.9V
void AD_Data_Update(void);
unsigned int ADC1Set(ADC1_Channel_TypeDefADC_Channel);
void delay(unsigned int time);
void GPIOinit(void);
void GPIOflash(void);
void GPIO10flash(void);
void tim1init(void);//匯總 TIM1
void tim1svc(void);//中斷服務程式 閃爍10
unsigned int NTCresist(void);
void ADC_Temperature(void);
void KeyScan(void);
void delay(unsigned int time);
void TransData(void);
void Display(void);
void GPIOinit(void);
void tim1init(void);
void tim1svc(void);
void tim6init(void);
void tim6svc(void);
void ADConvert(void);
void DigitalFiltering(void);
unsigned char Compare_tempres(unsigned intTR);
void Display_Time(void);
voidCHARGE_OUTPUT_Init(void);//----20140723 充電用
void Charge_MOS1(FunctionalState NewState);
void Charge_MOS2(FunctionalState NewState);
void Turn_MOS_OutPut(FunctionalStateNewState);
void Charge_MOS1_PWM_Mode(void);
void PV_Down_Work (void);
void FORCE_Turn_MOS_ON(void);
void FORCE_Turn_MOS_OFF(void);
void Charge_Condition_Work(void);
@far @interrupt void TIM1_OVF_IRQ(void);
@far @interrupt void TIM6_OVF_IRQ(void);
void main(void)
{
        GPIOinit();//顯示用
        CHARGE_OUTPUT_Init();//充電&輸出 太陽電池狀態用 0730
        tim1init();  
tim6init();
        rim();        
        Turn_off_Time=120;
        Store_Turn_off_Time=400;
        if(NORM_Repair_flag==0)//Low condition repair mode
        {
         Charge_High_Limit =159;//146;
  Full_Charge =145;//135;
  Current_Limit =400;
        }
        else
        {
         Charge_High_Limit =146;//146;
  Full_Charge =135;
         Current_Limit =400;
        }
        while(1)
        {
                AD_Data_Update();
        switch(Start_Flag)//顯示用
        {              
                case0: voltage = Real_Current;
                                                break;
                case1:      voltage = Real_Voltage;
                                          break;  
                case2:ADC_Temperature();
                                                break;
                case3:Display_Time();
                                          break;
                default:break;            
        }
        if(Real_Voltage< Discharge_Low)//電池過放電保護
                {
                Low_Bat_Flag=1;   
                FORCE_Turn_MOS_OFF();
                }
                else
                Low_Bat_Flag=0;//低壓旗標  
        
        switch(OutPut_Mode)//手動on 自動手動off
        {
                case0: PV_Down_Work ();//太陽下山的自動開啟動作
                                                break;
                case1: FORCE_Turn_MOS_OFF();
                                          break;  
                case2: FORCE_Turn_MOS_ON();
                                                break;
                default:break;            
        }      
  
Charge_Condition_Work();//執行相關充電模式
}
}
void KeyScan(void)
{
        GPIO_WriteLow(GPIOD,GPIO_PIN_2);
        GPIO_WriteLow(GPIOD,GPIO_PIN_3);
        GPIO_WriteLow(GPIOD,GPIO_PIN_4);
        GPIO_WriteLow(GPIOD,GPIO_PIN_5);      
        GPIO_Init(GPIOC,(GPIO_PIN_6|GPIO_PIN_7),GPIO_MODE_IN_PU_NO_IT);//變更 sw4 sw5 成為 input
        if(GPIO_ReadInputPin(GPIOC,GPIO_PIN_7)==0)//PC7press sw4
        {
        delay(50);
        if(GPIO_ReadInputPin(GPIOC,GPIO_PIN_7)==0)
        {
                while(GPIO_ReadInputPin(GPIOC,GPIO_PIN_7)==0);
                if(Start_Flag==3)
                {
                Store_Turn_off_Time-=10;
                if(Store_Turn_off_Time> 500)//0803
                Store_Turn_off_Time=0;
                Turn_off_Time= Store_Turn_off_Time;
                Night_Mode_Status=0;
                }
        }      
  }  
        if(GPIO_ReadInputPin(GPIOB,GPIO_PIN_3)==0)//sw3
        {
        delay(50);
        if(GPIO_ReadInputPin(GPIOB,GPIO_PIN_3)==0)
        {
                while(GPIO_ReadInputPin(GPIOB,GPIO_PIN_3)==0);
                Start_Flag++;
                if(Start_Flag > 3)
                Start_Flag=0;
        }
}   
        if(GPIO_ReadInputPin(GPIOA,GPIO_PIN_1)==0)
        {
        delay(50);
        if(GPIO_ReadInputPin(GPIOA,GPIO_PIN_1)==0)//sw1
        {
                while(GPIO_ReadInputPin(GPIOA,GPIO_PIN_1)==0);
                if(Start_Flag==3)
                {
                Store_Turn_off_Time+=1;
                if(Store_Turn_off_Time> 510)//0803
                Store_Turn_off_Time=0;
                Turn_off_Time= Store_Turn_off_Time;
                Night_Mode_Status=0;
                }
                if(Start_Flag< 2)//-顯示電壓電流都可以手動輸出------------0728
                {
                OutPut_Mode++;//ON-- AUTO -- OFF
                if(OutPut_Mode> 2)
                OutPut_Mode=0;
                }
                        
        }
}
        if(GPIO_ReadInputPin(GPIOA,GPIO_PIN_3)==0)//sw2
        {
        delay(50);
        if(GPIO_ReadInputPin(GPIOA,GPIO_PIN_3)==0)
        {
                while(GPIO_ReadInputPin(GPIOA,GPIO_PIN_3)==0);
                if(Start_Flag==3)
                {Turn_off_Time;
                Store_Turn_off_Time+=10;
                if(Store_Turn_off_Time> 510)//0803
                Store_Turn_off_Time=0;
                Turn_off_Time= Store_Turn_off_Time;
                Night_Mode_Status=0;
                }
        }
}
        if(GPIO_ReadInputPin(GPIOC,GPIO_PIN_6)==0)//PC6press sw5
        {
        delay(50);
        if(GPIO_ReadInputPin(GPIOC,GPIO_PIN_6)==0)
        {
                while(GPIO_ReadInputPin(GPIOC,GPIO_PIN_6)==0);
                if(Start_Flag==3)
                {
                Store_Turn_off_Time-=1;
                if(Store_Turn_off_Time> 510)//0803
                Store_Turn_off_Time=0;
                Turn_off_Time= Store_Turn_off_Time;
                Night_Mode_Status=0;
                }
        
        }      
  }
}
void delay(unsigned int time)
{
        while(time--);
}
void TransData(void)//顯示用的轉換
{      
if(Start_Flag==2)
{      //溫度顯示
        Hundreds=(Degree_C%100)/10;
        Tens=Degree_C%10;
        Units=Degree_0C;
}
else
        {//電壓電流顯示
        Hundreds=voltage/100;
        Tens=(voltage%100)/10;
        Units=voltage%10;
}
}
void Display(void)
{      
        GPIO_Init(GPIOC,GPIO_PIN_ALL,GPIO_MODE_OUT_PP_HIGH_FAST);//DISPLAY7SEGMENT
        GPIO_WriteLow(GPIOE,GPIO_PIN_5);
        if(Hundreds>0)
        {
                GPIO_Write(GPIOC,pcdis[Hundreds]);
                        if(pedis[Hundreds])
                                GPIO_WriteHigh(GPIOE,GPIO_PIN_5);
                                else
                                GPIO_WriteLow(GPIOE,GPIO_PIN_5);
                        }
                else
                {
                GPIO_Write(GPIOC,0x00);//百位消零
                GPIO_WriteLow(GPIOE,GPIO_PIN_5);//去除A
    }
                        GPIO_Write(GPIOD,0x10);//趨動百位數
  if(Start_Flag==0)//電流加上小數點
            GPIO_WriteHigh(GPIOC,GPIO_PIN_5);//加上小數點
                        delay(500);               
                        GPIO_WriteLow(GPIOC,GPIO_PIN_ALL);
                        delay(5);
       GPIO_Write(GPIOC,pcdis[Tens]);
        if(pedis[Tens])
        GPIO_WriteHigh(GPIOE,GPIO_PIN_5);
        else
         GPIO_WriteLow(GPIOE,GPIO_PIN_5);
                        GPIO_Write(GPIOD,0x08);//趨動十位數
if((Start_Flag==1)||(Start_Flag==2))//溫度加上小數點
            GPIO_WriteHigh(GPIOC,GPIO_PIN_5);//加上小數點
                        delay(500);
                        GPIO_WriteLow(GPIOC,GPIO_PIN_ALL);
                        delay(5);   
        GPIO_Write(GPIOC,pcdis[Units]);
        if(pedis[Units])//消除a節問題
        GPIO_WriteHigh(GPIOE,GPIO_PIN_5);
        else
         GPIO_WriteLow(GPIOE,GPIO_PIN_5);
                        GPIO_Write(GPIOD,0x04);//趨動個位數
                        delay(500);
                        GPIO_WriteLow(GPIOC,GPIO_PIN_ALL);//消除殘影
                        delay(5);   
}
void GPIOinit(void)
{
        GPIO_Init(GPIOC,GPIO_PIN_ALL,GPIO_MODE_OUT_PP_HIGH_FAST);//DISPLAY7SEGMENT
        GPIO_Init(GPIOD,GPIO_PIN_ALL,GPIO_MODE_OUT_PP_HIGH_FAST);//DISPLAY3DIGIT
        GPIO_Init(GPIOE,GPIO_PIN_5,GPIO_MODE_OUT_PP_HIGH_FAST);//DISPLAYSEGMENT A
        GPIO_WriteLow(GPIOE,GPIO_PIN_5);
        GPIO_Init(GPIOA,GPIO_PIN_1|GPIO_PIN_3,GPIO_MODE_IN_PU_NO_IT);//INPUT+/- TIME
        GPIO_Init(GPIOB,GPIO_PIN_3,GPIO_MODE_IN_PU_NO_IT);//INPUT+ FIRE POWER
        }
void tim1init(void)//11計數
{
TIM1_TimeBaseInit(19,TIM1_COUNTERMODE_UP,10000,0);//2M/20=100khz10000=10hz
TIM1_ITConfig(TIM1_IT_UPDATE,ENABLE);
TIM1_GenerateEvent(TIM1_EVENTSOURCE_UPDATE);
TIM1_Cmd(ENABLE);
}
void tim1svc(void)//1/101計數
{
        //-------1/10 作一次的工作 One_Tenth_Flag --> AD轉換
//-------1 作一次的工作 One_Sec_Flag --> 計秒 PWM 開關
        //-------1分鐘作一次的工作 One_Minute_Flag --> 倒數計時關 MOS_OUTPUT      檢查日落
        //-------1小時作一次的工作 One_Hour_Flag  --> 計時
One_Tenth_Flag=1;
One_Tenth_Count++;
if(One_Tenth_Count == 10)
{
         One_Sec_Flag=1;
         One_Tenth_Count=0;
        //PhotoVoltaic_Status=(GPIO_ReadInputPin(PV_PORT,PV_INPUT));//太陽電池lo就是下山
         One_Sec_Count++;
         if(One_Sec_Count == 60)//----------------60
         {
                 One_Sec_Count=0;
                 One_Minute_Flag=1;
                 One_Minute_Count++;
                 PhotoVoltaic_Status=(GPIO_ReadInputPin(PV_PORT,PV_INPUT));//太陽電池lo就是下山
                 if(One_Minute_Count==60)
                 {
                         One_Minute_Count=0;
                         One_Hour_Flag=1;
                 }
         }
}
adc_update_flag=1;//ADC轉換一次以避免過度忙碌
if(PWM_Do)//中斷中執行pwm 充電
{
         Charge_MOS1_PWM_Mode();
}
        TIM1_ClearFlag(TIM1_FLAG_UPDATE);
}
void tim6init(void)
{
        TIM6_TimeBaseInit(TIM6_PRESCALER_32,250);//TIM6_PRESCALER_8TIM6_TimeBaseInit
        TIM6_SetCounter(250);
        TIM6_ITConfig(TIM6_IT_UPDATE,ENABLE);//2Mhz/8/250
        TIM6_Cmd(ENABLE);
}
void tim6svc(void)
{
display_time++;
if(display_time==3)
{
        if(Start_Flag< 3)
        TransData();
        Display();
display_time=0;
  }   
count6++;
if(count6==50)//250>>25
{
KeyScan();
count6=0;
}
if(Turn_off_Time==1)//倒數計時到1分鐘
GPIO_WriteReverse(GPIOD,BUZZER);
        TIM6_ClearITPendingBit(TIM6_IT_UPDATE);
}
unsigned int NTCresist(void)
{
unsigned int resist;
resist=(unsigned int)((unsignedlong)(Temperature_AD_count)*10000/(1000-Temperature_AD_count));
return resist;
}
void ADConvert(void)
{
        unsignedchar ADCcount =0;
        ADC1->CR1|=0x02;
        ADC1_StartConversion();
        while(ADCcount<10)
        {
                while(ADC1_GetFlagStatus(ADC1_FLAG_EOC)==RESET);
                ADC1_ClearFlag(ADC1_FLAG_AWS0);
                ADCValue[ADCcount]=ADC1_GetConversionValue();
                ADCcount++;
        }
        ADC1->CR1&= ~0x02;
}
void DigitalFiltering(void)
{
        unsignedchar i,j;
        unsignedchar cptemp;
        
        for(i=10;i>=1;i--)
        {
                for(j-0;j<(i-1);j++)
                {
                        if(ADCValue[j]>ADCValue[j+1])
                        {
                                cptemp=ADCValue[j];
                                ADCValue[j]=ADCValue[j+1];
                                ADCValue[j+1]=cptemp;
                        }
                }
        }
        DataADC=0;
        for(i=2;i<=7;i++)
        {
                DataADC+=ADCValue;
        }
        DataADC/=6;
        
}
        unsignedchar Compare_tempres(unsigned int TR)//電阻查表成為溫度
{
unsigned char cmp_cnt;
cmp_cnt =0;
while (TR<tempresist[cmp_cnt])
{
  cmp_cnt++;
  if(cmp_cnt>140)
break;
}
return cmp_cnt;
}
void ADC_Temperature(void)
{
//DataADC= Temperature_AD_count;//把溫度更新值
NTCvalue=NTCresist();//溫度AD值轉換成溫度電阻
Degree_C = Compare_tempres(NTCvalue);//溫度電阻查表成溫度值
Degree_0C= ((tempresist[Degree_C-1]-NTCvalue)*10)/(tempresist[Degree_C-1]-tempresist[Degree_C]);//差分成小數
}
void Display_Time(void)//顯示時間
{
        Hundreds=Turn_off_Time/100;
        Tens=(Turn_off_Time%100)/10;
        Units=Turn_off_Time%10;        
}
//改成電壓電流 溫度每秒讀取一次用為系統及時需要
void AD_Data_Update(void)
{
if(adc_update_flag==1)//定時更新減少mcu負擔
{
switch(AD_read_count)
  {
          case 0:Current_AD_count = ADC1Set(DCCurrent);
                                        Real_Current=(unsignedint)((unsigned long)Current_AD_count*2600/1023);//電流有誤差約大0.2a使用.1*2歐姆電阻顯示1.00A 3000.2600            
                                break;                     
      case 1:Voltage_AD_count =ADC1Set(DCVoltage);
                                        Real_Voltagea=(unsignedint)((unsigned long)Voltage_AD_count*200/1023);//電壓ok 顯示12.0v
                                        Real_Voltage=Real_Voltagea-(Real_Current*2/100);
                                break;      
          case 2:Temperature_AD_count =ADC1Set(DCTemperature);
                                break;                              
          default: break;      
  }
AD_read_count++;
if(AD_read_count > 2)
   AD_read_count = 0;
}
adc_update_flag=0;
}
unsigned int ADC1Set(ADC1_Channel_TypeDefADC_Channel)//讀取不同的AD通道
{
u16 ADresult;
{
ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS,ADC_Channel,ADC1_PRESSEL_FCPU_D2,ADC1_EXTTRIG_TIM,DISABLE,ADC1_ALIGN_RIGHT,ADC1_SCHMITTTRIG_CHANNEL0,DISABLE);
ADConvert();
DigitalFiltering();
ADresult=DataADC;
DataADC=0;
adc_update_flag=0;
}
return ADresult;
}
void CHARGE_OUTPUT_Init(void)
{
        //#defineNORM_Repair_Select GPIOB //----20140908 modify hi-normal Lo-repair
//#define NORM_Repair GPIO_PIN_7 //----20140908 modify hi-normalLo-repair
        //u8NORM_Repair_flag
                GPIO_Init(CHARGE_PORT,CHARGE1_MOS,GPIO_MODE_OUT_PP_LOW_SLOW);
                GPIO_WriteLow(CHARGE_PORT,CHARGE1_MOS);
   //GPIO_Init(CHARGE_PORT,CHARGE2_MOS,GPIO_MODE_OUT_PP_LOW_SLOW );
         // GPIO_WriteLow(CHARGE_PORT,CHARGE2_MOS);
                GPIO_Init(OUT_PUT_MOS_PORT,OUT_PUT_MOS,GPIO_MODE_OUT_PP_LOW_SLOW);
                GPIO_WriteLow(OUT_PUT_MOS_PORT,OUT_PUT_MOS);
                GPIO_Init(PV_PORT,PV_INPUT,GPIO_MODE_IN_FL_NO_IT);//-----------0730
                GPIO_Init(NORM_Repair_Select,NORM_Repair_PIN,GPIO_MODE_IN_FL_NO_IT);//-----------
                PWM_Cycle_Complete=1;
        }
void Charge_MOS1(FunctionalState NewState)
{
        if(NewState!=DISABLE)
        GPIO_WriteHigh(CHARGE_PORT,CHARGE1_MOS);
        else
        GPIO_WriteLow(CHARGE_PORT,CHARGE1_MOS);
}
/*
void Charge_MOS2(FunctionalState NewState)
{
        if(NewState!=DISABLE)
        GPIO_WriteHigh(CHARGE_PORT,CHARGE2_MOS);
        else
        GPIO_WriteLow(CHARGE_PORT,CHARGE2_MOS);
}
*/
void Turn_MOS_OutPut(FunctionalStateNewState)//sw1--ON sw2--OFF---0803
{
        if(NewState!=DISABLE)
        {
        GPIO_WriteHigh(OUT_PUT_MOS_PORT,OUT_PUT_MOS);
        }
        else
        {
        GPIO_WriteLow(OUT_PUT_MOS_PORT,OUT_PUT_MOS);
        }
}
void Charge_MOS1_PWM_Mode(void)
{
if(One_Sec_Flag)//One_Sec_Flag
{
if(PWM_On_Count != 0)
   {
                 PWM_On_Count--;
                 One_Sec_Flag=0;
                 if(PWM_On_Count == 0)
                 {
                 Charge_MOS1(DISABLE);
                        }
         }
         if(PWM_On_Count==0)
           {
                         PWM_Off_Count--;
                         One_Sec_Flag=0;
                 }            
         }
         if(PWM_Off_Count==0)
         {
                 PWM_Cycle_Complete=1;
                 PWM_Do=0;
         }
        }
//----------------0801--------------
  void PV_Down_Work (void)
        {
        if((PhotoVoltaic_Status==0)&(Low_Bat_Flag==0))//太陽電池lo就是下山&電壓正常
              {
             if (Night_Mode_Status ==0)//第一次重新載入
                     {
                       Night_Mode_Status =1;
                                  Turn_off_Time = Store_Turn_off_Time;
                                 }
                                if(One_Minute_Flag ==1)
                                {
                                        One_Minute_Flag=0;
                                        if(Turn_off_Time== 0)
                                                {
                                                        Turn_MOS_OutPut(DISABLE);
                                                        MOS2_Status=0;
                                                }
                                        else
                                                {
                                                        Turn_off_Time--;
                                                        FORCE_Turn_MOS_ON();//----0803
                                                }                              
                                }
        //-------------------------------------
                        }
                        else//電池電壓過低
                                 {
                                        Turn_MOS_OutPut(DISABLE);
                             MOS2_Status=0;
                 }      
  if(PhotoVoltaic_Status!=0)//  
                {
                Turn_off_Time= Store_Turn_off_Time;
                Night_Mode_Status=0;//可以再次設定定時
                        }
        }
        
void FORCE_Turn_MOS_ON(void)
{
        if(Low_Bat_Flag==0)
    {
                                if(MOS2_Status!=1)
                      {
                                Turn_MOS_OutPut(ENABLE);
                                MOS2_Status=1;
                                }
                }
        else
        {
        Turn_MOS_OutPut(DISABLE);
        MOS2_Status=0;
        }      
}
void FORCE_Turn_MOS_OFF(void)
{
        if(MOS2_Status!= 0)
        {
        Turn_MOS_OutPut(DISABLE);
        MOS2_Status=0;     
  }
}
void Charge_Condition_Work(void)
{
        //充電部分;比較假如電池電壓高於15.9v就不輸出切斷充電,14.5v就進入 pwm 模式,低於14.5v就全輸出不控制電流
        //放電部分;若低於11.5v就停止輸出
        //pwm模式就要作部份的分割可以分成5
        if((Real_Voltage> Charge_High_Limit)||(Real_Current > Current_Limit))//tune off chargingoperation overcurrent or overvoltage
        {
                Charge_MOS1(DISABLE);
                PWM_Do=0;
        }
        if((Real_Voltage<= Charge_High_Limit) && (Real_Voltage > Full_Charge))//PWM Mode
         {
               
                 PWM_Do = 1;//start PWM charging in Timer mode
                if(PWM_Cycle_Complete==1)
    {
                        PWM_On_Count=(unsignedchar)(Charge_High_Limit - Real_Voltage)+1;//146-
                        PWM_Off_Count=(unsignedchar)(Real_Voltage - Full_Charge)+1;//135
                        Charge_MOS1(ENABLE);
                        PWM_Cycle_Complete=0;
                }
        }
        if(Real_Voltage<= Full_Charge)//145
        {
          Charge_MOS1(ENABLE);
                PWM_Do=0;
        }
}
/*
void Charge_Condition_Work(void)
{ //RICKY CHIANG 建議的脈衝充電模式on4off1 20140821
        //充電部分;比較假如電池電壓高於16.2v就不輸出切斷充電,13.5v就進入 pwm 模式,低於13.5v就全輸出不控制電流
        //放電部分;若低於11.0v就停止輸出
        //pwm模式就要作部份的分割可以分成5
        if(Real_Voltage> Charge_High_Limit_Top)//||(Real_Current > Current_Limit))//146-->162tune off charging operation overcurrent or overvoltage
        {
                Charge_MOS1(DISABLE);
                PWM_Do=0;
        }
        if((Real_Voltage<= Charge_High_Limit_Top) && (Real_Voltage > Full_Charge))//PWMMode 小於162大於135
         {
               
                 PWM_Do = 1;//start PWM charging in Timer mode
                if(PWM_Cycle_Complete==1)
    {
                        PWM_On_Count=4;//(unsignedchar)(Charge_High_Limit - Real_Voltage)+1;//146-
                        PWM_Off_Count=2;//(unsignedchar)(Real_Voltage - Full_Charge)+1;//135
                        Charge_MOS1(ENABLE);
                        PWM_Cycle_Complete=0;
                }
        }
        if(Real_Voltage<= Full_Charge)//<135
        {
          Charge_MOS1(ENABLE);
                PWM_Do=0;
        }
}
*/
//--------------------------------------------------------------------------
@far @interrupt void TIM1_OVF_IRQ(void)
{
        tim1svc();
}
@far @interrupt void TIM6_OVF_IRQ(void)
{
        tim6svc();
}
//Degree_0C=((tempresist[Degree_C-1]-NTCvalue)*10)/(tempresist[Degree_C-1]-(tempresist[Degree_C]);
/*
unsigned intGet_ADCCH_Value(ADC1_Channel_TypeDef ADC_Channel)//網路上的例子
{
ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS,ADC_Channel,ADC1_PRESSEL_FCPU_D2,\
    ADC1_EXTTRIG_TIM, DISABLE, ADC1_ALIGN_RIGHT, ADC1_SCHMITTTRIG_ALL,DISABLE);
   //你也可以用操作寄存器的方式代码如下,但未验证。
ADC1_ConversionConfig(ADC1_CONVERSIONMODE_CONTINUOUS,ADC_Channel,ADC1_ALIGN_RIGHT);
    ADC_CR1 |= 0x01;      //开始启动转换
            while(ADC1_GetFlagStatus()==RESET);   //等待转换结束
   return ADC1_GetConversionValue(); //返回ADC结果
}
//这个初始化代码很重要,不能省,每次切换通道都要初始化一次!
//main函数中直接调用
// TempADC=Get_ADCCH_Value(ADC1_CHANNEL_1); //获取AD转化值
*/
#ifdef USE_FULL_ASSERT
/**
  *@brief  Reports the name of the sourcefile and the source line number
*   where the assert_param errorhas occurred.
  *@param file: pointer to the source file name
  *@param line: assert_param error line source number
  *@retval : None
  */
void assert_faiLED(u8* file, u32 line)
{
  /*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) */
  /*Infinite loop */
while (1)
  {
  }
}
#endif
/******************* (C) COPYRIGHT 2011STMicroelectronics *****END OF FILE****/



评分

参与人数 3一乐金币 +60 收起 理由
356053261 + 20 很好很强大,代码太长我就不看了,有空折腾.
gaojxp + 20 赞一个!
xiaomage + 20 楼主高手,共享程序,值得钦佩!

查看全部评分

发表于 2014-9-21 14:21 | 显示全部楼层
额,怎么又是“飛利浦黑晶爐的控制電路”???
发表于 2014-9-21 15:13 | 显示全部楼层
来自宝岛的坛友,程序够长的。注释比较少,整体设计的说明也没有。资料能共享出来就要顶一下!
 楼主| 发表于 2014-9-21 16:54 | 显示全部楼层
ksd 发表于 2014-9-21 15:13
来自宝岛的坛友,程序够长的。注释比较少,整体设计的说明也没有。资料能共享出来就要顶一下!

20140801大改寫程式中斷定時器1作為1/10 1 1 1 計數並且把輸出 電流電壓顯示時候可以選擇三種模式on auto off
auto 在太陽下山時候會自動輸出
太陽下山的檢查每隔1分鐘一次 並檢查是否電壓過低若過低則切斷輸出若太陽輸出則也關斷輸出
因為這電路板的IO位置無法使用內建的PWM(正常PC1PC2)
所以改用PB6控制輸出MOS  PB7控制充電MOS1  PA2控制充電MOS2
11.6V 停放 14.5v 停充 13.5v~14.5 PWM 控制 13.5V以下全充
在電壓電流模式按鍵SW1SW2 輸出ON/OFF
計時倒數終止時關閉輸出MOS
太陽板輸入電壓停止時(沒有陽光) 輸出MOS 時間由設定值決定,當倒數計時完畢後回覆原設定
  20140722


 楼主| 发表于 2014-9-21 17:08 | 显示全部楼层
xwj 发表于 2014-9-21 14:21
额,怎么又是“飛利浦黑晶爐的控制電路”???

因為回收廠拿到5~6套所以就一腳踏入 STM8的世界!! 摸索中...以前都用洞洞板焊接 DIL的 8952 或是 STC15F204EA 第一次使用 STM8S903K3 新領域新學習!!
 楼主| 发表于 2014-9-21 17:13 | 显示全部楼层
這個程式有分 一般模式跟電池脈衝模式 主要的差別在於 電瓶內阻變高時候充不進去(我也沒辦法) 所以把電壓升高!!
发表于 2014-9-21 22:09 | 显示全部楼层
不错啊,既废物利用,又增加了DIY的乐趣,还开源!
发表于 2014-9-21 22:35 | 显示全部楼层
我一看 怎么是敏体字的。。。怪怪 原来台湾坛友作品
发表于 2014-9-21 22:44 | 显示全部楼层
看你家房子像小别墅嘛!还要省这点电?
发表于 2014-9-21 22:55 | 显示全部楼层
太阳能控制器的线路简单了些。我在光伏公司上班,充电控制板大把,你要吗?¥30/个,邮费实收。带MPPT的,还有2个USB输出(1A)
IMG_20140921_224834.jpg
IMG_20140921_224844.jpg
IMG_20140921_224915.jpg

评分

参与人数 1一乐金币 +2 收起 理由
antlu + 2 很给力!

查看全部评分

本版积分规则

QQ|一淘宝店|手机版|商店|电子DIY套件|一乐电子 ( 粤ICP备09076165号 ) 公安备案粤公网安备 44522102000183号

GMT+8, 2024-5-11 21:33 , Processed in 0.091647 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表