Solar V5.0 Source

STC12C5204AD  AD  E2PROM GSM 混合充电项目


#include<reg52.h>    
#include<stdio.h>    
#include<intrins.h>  
#define uchar unsigned char    
#define uint  unsigned int   
  
/* 
串口中断函数 
信息内容数组 
*/  
volatile char EFlag = -1;  
  
typedef unsigned char byte;  
typedef unsigned int word;  
unsigned char buff[5];  
  
   
void delay(uint xms);    
sbit DQ = P1^2;     //DS18B20    
byte TPH;                           //存放温度值的高字节  
byte TPL;  
  
     
uint temp;    //整型温度数据    
float f_temp;     //浮点型温度数据    
     
/* G S M */  
sbit GsmPin = P1^7;  
  
  
unsigned char RxData;  
/*AT+CNMI=2,1    短信提示*/  
code unsigned char ICMD1[13] = {0x41 ,0x54 ,0x2B ,0x43 ,0x4E ,0x4D ,0x49 ,0x3D ,0x32 ,0x2C ,0x31 ,0x0D ,0x0A};  
/*AT+CMGF=1     英文方式发送*/  
code unsigned char ICMD2[11] = {0x41 ,0x54 ,0x2B ,0x43 ,0x4D ,0x47 ,0x46 ,0x3D ,0x31 ,0x0D ,0x0A};  
/*AT+CMGD=1,4  短信删除*/  
code unsigned char DCMD[13] = {0x41 ,0x54 ,0x2B ,0x43 ,0x4D ,0x47 ,0x44 ,0x3D ,0x31 ,0x2C ,0x34 ,0x0D ,0x0A};  
/* 短信读取 */  
code unsigned char RCMD1[8] = {0x41 , 0x54 , 0x2B , 0x43 , 0x4D , 0x47 , 0x52 , 0x3D};  
unsigned char RCMD2[5] = {0xff, 0xff, 0xff, 0xff, 0xff}; // 改回000  
code unsigned char RCMD3[2] = {0x0D, 0x0A};  
  
  
volatile unsigned char MsgAddBegin = 0;  
volatile unsigned char MsgAddEnd = 0;  
volatile unsigned char MsgAddSvCur = 0;  
volatile unsigned char MsgAdd[5];  
volatile unsigned char MsgContentSvCur = 0;  
volatile unsigned char MsgContentBegin = 0;  
volatile unsigned char MsgContentEnd = 0;  
volatile unsigned char MsgContent[10]; //volatile unsigned char MsgContent[240];  
  
code unsigned char Yes[8] = {'o', 'p', 'e', 'n', '3', '6','9'};  
code unsigned char No[8] = {'c', 'l', 'o', 's', 'e', '4', '2'};  
  
volatile unsigned char HeadCur = 0;  
#define HeadCnt 3  
code volatile unsigned char Head[HeadCnt + 1] = {0x2B , 0x43 , 0x4D, 0xff};  // +CM  
volatile unsigned char AddHeadCur = 0;  
#define AddHeadCnt 9  
code volatile unsigned char AddHead[AddHeadCnt + 1] = {0x54 ,0x49 ,0x3A ,0x20 ,0x22 ,0x53 ,0x4D ,0x22 ,0x2C, 0xff}; //TI: "SM",  
volatile unsigned char AddTailCur = 0;  
#define AddTailCnt 2  
code volatile unsigned char AddTail[AddTailCnt] = {0x0D, 0x0A};  
volatile unsigned char ContentHeadCur = 0;  
#define ContentHeadCnt 2  
code volatile unsigned char ContentHead[ContentHeadCnt + 1] = {0x47 ,0x52 ,0xff}; //GR:  0x47 ,0x52 ,0x3A ,0x20, 0xff  
volatile unsigned char QuotationMarkCnt = 0; //  8  
  
  
/* U S A R T */    
void initSCI(void)        
{        
    SM0 = 0;      /*Step 1 :  确定串口通信方式*/          
    SM1 = 1;          
              
    TMOD = 0x20;  /*step 2: 根据串口通信方式 确定是否设置波特率*/           
    TH1  = 0xfd;          
    TL1  = 0xfd;          
              
    TR1  = 1;     /*step 3 :启动*/          
    REN  = 1;          
          
    EA = 1;       /*step 4: 是否启用中断函数*/          
    ES = 1;      
    delay(100);       
}        
       
void putChar (unsigned char chr)//发送一个字符        
{        
    SBUF = chr;        
    while(!TI); delay(3); TI=0; delay(3);                                                         
}        
     
void putStr(char *s)      
{      
    while(*s)      
    {      
        putChar(*s++);      
    }      
}   
  
  
   
  
  
/*    D   S   1   8   B   2   0   */  
  
  
void DelayXus(byte n)  
{  
    while (n--)  
    {  
        _nop_();  
        _nop_();  
    }  
}  
  
/************************************** 
复位DS18B20,并检测设备是否存在 
**************************************/  
void DS18B20_Reset()  
{  
    CY = 1;  
    while (CY)  
    {  
        DQ = 0;                     //送出低电平复位信号  
        DelayXus(240);              //延时至少480us  
        DelayXus(240);  
        DQ = 1;                     //释放数据线  
        DelayXus(60);               //等待60us  
        CY = DQ;                    //检测存在脉冲  
        DelayXus(240);              //等待设备释放数据线  
        DelayXus(180);  
    }  
}  
  
  
/************************************** 
从DS18B20读1字节数据 
**************************************/  
byte DS18B20_ReadByte()  
{  
    byte i;  
    byte dat = 0;  
  
    for (i=0; i<8; i++)             //8位计数器  
    {  
        dat >>= 1;  
        DQ = 0;                     //开始时间片  
        DelayXus(1);                //延时等待  
        DQ = 1;                     //准备接收  
        DelayXus(4);                //接收延时  
        if (DQ) dat |= 0x80;        //读取数据  
        DelayXus(56);               //等待时间片结束  
    }  
  
    return dat;  
}  
  
/************************************** 
向DS18B20写1字节数据 
**************************************/  
void DS18B20_WriteByte(byte dat)  
{  
    char i;  
  
    for (i=0; i<8; i++)             //8位计数器  
    {  
        DQ = 0;                     //开始时间片  
        DelayXus(1);                //延时等待  
        dat >>= 1;                  //送出数据  
        DQ = CY;  
        DelayXus(60);               //等待时间片结束  
        DQ = 1;                     //恢复数据线  
        DelayXus(1);                //恢复延时  
    }  
}  
  
uint DS18B20_GetTemp()  
{  
    DS18B20_Reset();                //设备复位  
    DS18B20_WriteByte(0xCC);        //跳过ROM命令  
    DS18B20_WriteByte(0x44);        //开始转换命令  
    while (!DQ);                    //等待转换完成  
  
    DS18B20_Reset();                //设备复位  
    DS18B20_WriteByte(0xCC);        //跳过ROM命令  
    DS18B20_WriteByte(0xBE);        //读暂存存储器命令  
    TPL = DS18B20_ReadByte();       //读温度低字节  
    TPH = DS18B20_ReadByte();       //读温度高字节  
    temp = TPH;    
    temp <<= 8; temp = temp | TPL;    
    f_temp = temp * 0.0625;       
    f_temp = f_temp + 0.5;            
    if(f_temp > 4000.0) f_temp -= 4096.437;  
    temp = f_temp + 0.05;         
    return temp;   
}  
  
                                    
  
  
  
/*   e   e   p   r   o   m   */  
  
/* Declare SFR associated with the IAP */  
sfr IAP_DATA  = 0xC2;  //Flash data register  
sfr IAP_ADDRH = 0xC3;  //Flash address HIGH  
sfr IAP_ADDRL = 0xC4;  //Flash address LOW  
sfr IAP_CMD   = 0xC5;  //Flash command register  
sfr IAP_TRIG  = 0xC6;  //Flash command trigger  
sfr IAP_CONTR = 0xC7;  //Flash control register  
  
/* Define ISP/IAP/EEPROM command */  
#define CMD_IDLE 0     //Stand-By  
#define CMD_READ 1     //Byte-Read  
#define CMD_PROGRAM 2  //Byte-Program  
#define CMD_ERASE 3    //Sector-Erase  
  
/* Define ISP/IAP/EEPROM operation const for IAP_CONTR */  
//#define ENABLE_IAP 0x80    //if SYSCLK < 30MHz  
//#define ENABLE_IAP 0x81    //if SYSCLK < 24MHz  
//#define ENABLE_IAP 0x82    //if SYSCLK < 20MHz  
//#define ENABLE_IAP 0x83    //if SYSCLK < 12MHz  
//#define ENABLE_IAP 0x84    //if SYSCLK < 6MHz  
//#define ENABLE_IAP 0x85    //if SYSCLK < 3MHz  
//#define ENABLE_IAP 0x86    //if SYSCLK < 2MHz  
#define ENABLE_IAP 0x87  //if SYSCLK < 1MHz  
  
//Start address for STC12C5201AD series EEPROM  
#define IAP_ADDRESS 0x0000  
  
  
void IapIdle()  
{  
     IAP_CONTR = 0;        //close IAP function  
     IAP_CMD = 0;          //clear command to standby  
     IAP_TRIG = 0;         //clear tirgger register  
     IAP_ADDRH = 0x80;     //data ptr point to non EEPROM area  
     IAP_ADDRL = 0;        //clear IAP address to prevent mususe  
}  
  
/* read one byte from isp/iap/eeprom area input:addr(isp iap eeprom address) output:flash data */  
byte IapReadByte(word addr)  
{  
    byte dat;  
  
    IAP_CONTR = ENABLE_IAP; //Open IAP function and set wait time  
    IAP_CMD = CMD_READ;     //Set ISAP READ command  
    IAP_ADDRL = addr;       //Set ISP address low  
    IAP_ADDRH = addr >> 8;  //Set IAP address high  
    IAP_TRIG = 0x5a;        //Send trigger command1(0x5a)  
    IAP_TRIG = 0xa5;        //Send trigger command2(0xa5)  
    _nop_();                //MCU will hold here until IAP operation complete  
  
    dat = IAP_DATA;         //Read IAP EEPROM data  
    IapIdle();              //Close ISP function  
  
    return dat;             //Return Flash data  
}  
  
/* Program one byte to ISP area   Input:addr (address)  dat(data)  Output:- */  
void IapProgramByte(word addr, byte dat)  
{  
    IAP_CONTR = ENABLE_IAP;     //Open IAP function, and set wait time  
    IAP_CMD   = CMD_PROGRAM;    //Set EEPROM PROGRAM command  
    IAP_ADDRL = addr;  
    IAP_ADDRH = addr >> 8;  
    IAP_DATA = dat;  
    IAP_TRIG = 0x5a;  
    IAP_TRIG = 0xa5;  
    _nop_();  
  
    IapIdle();  
}  
  
/* Erase one sector area Input:addr */  
void IapEraseSector(word addr)  
{  
    IAP_CONTR = ENABLE_IAP;  
    IAP_CMD = CMD_ERASE;  
    IAP_ADDRL = addr;  
    IAP_ADDRH = addr >> 8;  
    IAP_TRIG = 0x5a;  
    IAP_TRIG = 0xa5;  
    _nop_();  
  
    IapIdle();  
}  
  
unsigned char ReadE2Prom()  
{  
    if(IapReadByte(IAP_ADDRESS) == 0xff)  
    {  
        IapEraseSector(IAP_ADDRESS);  
        IapProgramByte(IAP_ADDRESS, 0x01);  
        return 1;  
    }  
    if(IapReadByte(IAP_ADDRESS) == 0x01)  
    {  
        return 1;  
    }  
    return 0;  
}  
  
  
/*  g  s  m  */  
void MsgRemindInit()  //GSM模块来信提醒  
{  
    unsigned char i;  
      
    for(i = 0; i < 13; ++i)  
    {  
        putChar( ICMD1[i] );  
        delay(10);  
    }  
    delay(100);  
    for(i = 0; i < 11; ++i)  
    {  
        putChar( ICMD2[i] );  
        delay(10);  
    }  
    delay(100);  
    delay(100);  
}  
  
unsigned char CheckMSG()  
{  
    unsigned char i, Yctr = 0, Nctr = 0;  
    for(i = 0; i < 7; ++i)  
    {  
        if(MsgContent[i] == Yes[i]) Yctr++;  
        if(MsgContent[i] == No[i]) Nctr++;  
    }  
  
    if(Yctr >= 7)  
    {  
        EFlag = 1;  
        while(ReadE2Prom() != 1)  
        {  
            IapEraseSector(IAP_ADDRESS);  
            IapProgramByte(IAP_ADDRESS, 0x01);  
            delay(300);  
        }  
        return 1;  
    }  
    else if(Nctr >= 7)  
    {  
        EFlag = 0;  
        while(ReadE2Prom() != 0)  
        {  
            IapEraseSector(IAP_ADDRESS);  
            IapProgramByte(IAP_ADDRESS, 0x00);  
            delay(300);  
        }  
        return 0;   
    }  
    else  
    {  
        return 0;  
    }    
}  
unsigned char ReadMSG()  
{  
    unsigned char i;  
  
    if (MsgAddEnd == 0)   
    {  
        delay(100); return 0;  
    }  
  
    for(i = 0; i < 5; ++i)  
    {  
        RCMD2[i] = MsgAdd[i];  
        if(MsgAdd[i] == 0xff) break;  
    }  
         
    MsgAddEnd = 0;  
    for(i = 0; i < 5; ++i) MsgAdd[i] = 0xff;  
      
    /*tx*/  
      
    for(i = 0; i < 8; ++i)  
    {  
        putChar( RCMD1[i] );  
        delay(10);  
    }  
      
    for(i = 0; i < 5; ++i)  
    {  
        if(RCMD2[i] != 0xff)  
        {  
            if(RCMD2[i] == 0x00) break;  
            putChar( RCMD2[i] );  
            delay(10);  
        }  
        else break;  
    }  
      
    for(i = 0; i < 2; ++i)  
    {  
         putChar( RCMD3[i] );  
         delay(10);  
    }  
  
    /*waiting for msg content*/  
    while(MsgContentEnd == 0) delay(10);  
    delay(100);  
    MsgContentEnd = 0;  
  
    /*删除短信*/  
    for(i = 0; i < 13; ++i)  
    {  
        putChar( DCMD[i] );  
        delay(10);  
    }  
  
    return  CheckMSG();  
//    if(MsgContent[0] == '1')  
//    {  
//      EFlag = 1;  
//      while(ReadE2Prom() != 1)  
//        {  
//          IapEraseSector(IAP_ADDRESS);  
//          IapProgramByte(IAP_ADDRESS, 0x01);  
//          delay(300);  
//      }  
//      return 1;  
//    }  
//    else if(MsgContent[0] == '0')  
//    {  
//        EFlag = 0;  
//      while(ReadE2Prom() != 0)  
//        {  
//          IapEraseSector(IAP_ADDRESS);  
//          IapProgramByte(IAP_ADDRESS, 0x00);  
//          delay(300);  
//      }  
//      return 0;   
//    }  
//  else  
//  {  
//      return 0;  
//  }    
}  
    
  
  
void ser() interrupt 4      //串口中断  
{        
      
    if( RI )        
    {        
        RI = 0;        
        RxData = SBUF;  
        if(MsgAddBegin == 1)  
        {  
            if(RxData == 0x0D)  
            {  
                MsgAddEnd = 1;  
                MsgAddBegin = 0;  
                HeadCur = 0;  
                AddHeadCur = 0;  
                MsgAddSvCur = 0;  
                return;  
            }  
            MsgAdd[MsgAddSvCur] = RxData;  
            MsgAddSvCur++;  
            return;  
        }  
        if(MsgContentBegin == 1)  
        {  
            if(RxData == 0x0D)  
            {  
                MsgContentEnd = 1;  
                MsgContentBegin = 0;  
                HeadCur = 0;  
                ContentHeadCur = 0;  
                MsgContentSvCur = 0;  
                QuotationMarkCnt = 0;  
                return;  
            }  
            MsgContent[MsgContentSvCur] = RxData;  
            MsgContentSvCur++;  
            return;              
        }  
          
        if(RxData == Head[HeadCur]) HeadCur++;  
        else  
        {  
            if(HeadCur == HeadCnt)  
            {     
                if(RxData == AddHead[AddHeadCur]) AddHeadCur++;  
                if(RxData == ContentHead[ContentHeadCur]) ContentHeadCur++;   
                  
                if(ContentHeadCur == ContentHeadCnt)  
                {                   
                    if(RxData == 0x22) QuotationMarkCnt++ ;  
                    if(QuotationMarkCnt == 8)  
                    {   
                        if(RxData == 0x0A)  
                        {  
                            MsgContentBegin = 1;  
                            MsgContentSvCur = 0;  
                        }  
                    }  
                    return;  
                }                 
                else if(AddHeadCur == AddHeadCnt)  
                {  
                    MsgAddBegin = 1;  
                    MsgAddSvCur = 0;  
                    return ;  
                }  
            }  
            else HeadCur = 0;  
        }        
    }        
    else if( TI )        
    {        
        TI = 0;         
    }  
            
    return ;        
}  
  
void GSMCtrl()  
{     
    if(ReadMSG() == 1 || EFlag == 1)   
    {  
        //putStr("\r\n GSM = 1");  
        GsmPin = 1;  
    }
    else   
    {  
        GsmPin = 0;  
    }  
}  
  
  
  
/*    A     D     */  
  
sfr ADC_CONTR   =   0xBC;           //ADC control register  
sfr ADC_RES     =   0xBD;           //ADC high 8-bit result register  
sfr ADC_LOW2    =   0xBE;           //ADC low 2-bit result register  
sfr P1ASF       =   0x9D;           //P1 secondary function control register  
  
/* Define ADC operation const for ADC_CONTER */  
#define ADC_POWER   0x80            //ADC power control bit  
#define ADC_FLAG    0x10            //ADC complete flag  
#define ADC_START   0x08            //ADC start control bit  
#define ADC_SPEEDLL 0x00            //420 clocks  
#define ADC_SPEEDL  0x20            //280 clocks  
#define ADC_SPEEDH  0x40            //140 clocks  
#define ADC_SPEEDHH 0x60            //70 clocks  
  
#define VEFF 6  
#define VREF 5  
  
unsigned char ADC_ch = 5;  
volatile int Veff, Vref;  
  
  
void Ddelay(word n)  
{  
    word x;  
  
    while (n--)  
    {  
        x = 5000;  
        while (x--);  
    }  
}  
  
void initADC()  
{  
    P1ASF = 0x00 + (1 << VEFF) + (1 << VREF); //Set All P1 as analog input port  
    ADC_RES = 0;  //Clear previous result  
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL;  
    Ddelay(2);   
}  
  
  
byte GetADCResult(byte ch)  
{  
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;  
    _nop_();                        //Must wait before inquiry  
    _nop_();  
    _nop_();  
    _nop_();  
    while (!(ADC_CONTR & ADC_FLAG));//Wait complete flag  
    ADC_CONTR &= ~ADC_FLAG;         //Close ADC  
  
    return ADC_RES;                 //Return ADC result  
}  
  
//void ShowResult(byte ch)  
//{  
//    putChar(ch);                   //Show Channel NO.  
//    putChar(GetADCResult(ch));     //Show ADC high 8-bit result  
//}  
  
  
/*   C o n t r o l  P r o g r a m*/  
  
/* Contral Val */  
sbit CHARGE = P1^0;  
sbit DISCHARGE =  P1^1;  
  
volatile int Voltage = 0;  
volatile int Temperature = 0;  
  
volatile int UnderV = 116, OverV = 144;  
int T_20 = -20, T_10 = -10, T45 = 50, T60 = 60;  
  
void GetPara()  
{  
    Vref = GetADCResult(5);  
    Veff = GetADCResult(6);  
    Voltage = Veff; Voltage *= 25; Voltage /= Vref;  
    Voltage = Voltage * 4;  
  
//  putStr("\r\n VVV5 = ");  
//  sprintf(buff,"%d",Vref);  
//  putStr(buff);  
//  
//  putStr("\r\n VVV6 = ");  
//  sprintf(buff,"%d",Veff);  
//  putStr(buff);  
  
    DS18B20_GetTemp();  
    Temperature = f_temp + 0.05;     
//    putStr("\r\nTemp = ");    
//    sprintf(buff,"%d",Temperature);                  
//    putStr(buff);        
    return;  
}  
  
void ChargeDischarge(unsigned char Charge, unsigned char Discharge)  
{  
    CHARGE = Charge;    DISCHARGE = Discharge;  
//  putStr("\r\n Charge = ");  
//  putChar(Charge + '0');  
//  putStr("   Disharge = ");  
//  putChar(Discharge + '0');  
    //cout << (Charge ? "充电   " : "不充电   ") << (Discharge ? "放电" : "不放电") << endl;   
}  
  
void Changemode()  
{  
    int V = Voltage;  
  
//  putStr("\r\nVoltage = ");  
//  sprintf(buff,"%d",V);  
//  putStr(buff);  
//  
//  putStr("\r\nTemperature = ");  
//  sprintf(buff,"%d",Temperature);  
//  putStr(buff);  
  
    if(V < UnderV)  
    {  
        UnderV = 124;  
        //UnderV = UnderV + 2;  
        if(Temperature > T_10 && Temperature < T45) ChargeDischarge(1, 0);  
        else ChargeDischarge(0, 0);  
    }  
    else if(V >= UnderV && V < OverV)  
    {  
        UnderV = 116; OverV = 144;  
        //cout << "电压" << V << "温度" << Temperature << endl;   
        if(Temperature < T_20)     ChargeDischarge(0, 0);  
        else if(Temperature > T_20 && Temperature < T_10) ChargeDischarge(0, 1);  
        else if(Temperature >= T_10 && Temperature < T45)  ChargeDischarge(1, 1);  
        else if(Temperature >= T45  && Temperature < T60)  ChargeDischarge(0, 1);  
        else if(Temperature >= T60) ChargeDischarge(0, 0);  
    }  
    else if(V >= OverV)  
    {  
        UnderV = 116; OverV = 136;  
        if(Temperature > T_20 && Temperature < T60) ChargeDischarge(0, 1);  
        else ChargeDischarge(0, 0);  
    }  
}  
  
  
  
  
  
                      
void main()    
{     
    unsigned char i;              
    initSCI();  //串口初始化  
    for(i = 0; i < 100; ++i) delay(1000);  
//  for(i = 0; i < 100; ++i) delay(1000);  
    MsgRemindInit(); //GSM初始化     
    initADC();           // AD转换初始化   
    P0 = 0x00;  
    while(EFlag == -1) EFlag = ReadE2Prom();  
    while (1)  
    {  
      delay(500);           
      GetPara();     // 更新电压 及 温度参数  
      Changemode();  // 模式转换  
      GSMCtrl();     // GSM P1.7控制  
    }                
}   
  
   
void delay(uint xms)   //  延时函数    
{    
    uint i,j;    
    for(i=xms;i>0;i--)    
      for(j=110;j>0;j--);    
}  


你可能感兴趣的:(Solar V5.0 Source)