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--);
}