/********************************************************* Hardware : EVB9S08DZ60 Board Author : WBR Version : V1.0 Begin Time: 2011.5.30 **********************************************************/ #include <hidef.h> /* for EnableInterrupts macro */ #include "derivative.h" /* include peripheral declarations */ #include "1302.h" //#include "lcd.h" //#include "mscan.h" //#include "KEY.h" /****************************************************** IO說明: 1:四路AD輸入通道 ADP19(AD1) ADP11(AD2) ADP3(AD3) ADP4(AD4) 2:485通信 DE (PTE2) TXD1(PTE0) RXD1(PTE1) 3:四路光耦輸入 DI1(PTG2) DI2 (PTE5) DI3 (PTE4) DI4(PTE3) 4:DS1302 SCL(PTF2) SDA (PTF3) RST (PTG4) 5:繼電器控制 PTA6 PTB5 PTA5 PTC4 PTB6 6:按鍵(輸入) PTC0 PTB0 PTC1 PTA0 PTC2(SW1~SW5) 7:CAN TX(PTE6) RX(PTE7) 8:LCD RW(PTG3) RS(PTF0) E(PTF1) RST(PTF7) 背光(PTG5) DATA(PTD0~PTD7) ************************************************************/ #define DI1 PTGD_PTGD2 //外觸發(fā)1----->PG2 #define DI2 PTED_PTED5 //外觸發(fā)2----->PE5 #define DI3 PTED_PTED4 //外觸發(fā)3----->PE4 #define DI4 PTED_PTED3 //外觸發(fā)4----->PE3 //********以上為輸入IO********// #define JDQ1 PTCD_PTCD4 //繼電器1----->PC4 #define JDQ2 PTAD_PTAD5 //繼電器2----->PA5 #define JDQ3 PTBD_PTBD5 //繼電器3----->PB5 #define JDQ4 PTAD_PTAD6 //繼電器4----->PA6 #define JDQ5 PTBD_PTBD6 //繼電器5----->PB6 #define DE485 PTED_PTED2 //485 T R切換----->PE2 //#define ID_TX 0x0001 //自定義的CAN發(fā)送標(biāo)識符 //#define ID_RX 0x0002 //自定義的CAN接收標(biāo)識符 //Bool can_send_enable = FALSE; //CAN發(fā)送標(biāo)志位,暫定RTC0.5秒發(fā)送一次 #define Baud 19200 //串口波特率9600 #define N 51 #define T 1800 //運(yùn)算電量的時間單位1800是半個小時(1800秒) extern byte time_buf1[8]; //1302時鐘寄存器 byte ReadTimeFlag = 0; //定時器每0.5秒讀1302時間的標(biāo)志位 byte ADSET = 0; //發(fā)送電流電壓功率等數(shù)值到顯示屏標(biāo)志位 /*********************變量和函數(shù)定義****************************/ word ADCbuffer1[N] = 0; //AD轉(zhuǎn)換緩沖 word ADC1,ADC2,ADC3,ADC4; //AD轉(zhuǎn)換緩沖 byte ADC1L,ADC1H,ADC2L,ADC2H,ADC3L,ADC3H,ADC4L,ADC4H; byte MW4L,MW4H,MW5L,MW5H,MW6L,MW6H,MW7L,MW7H,MW8L,MW8H,MW9L,MW9H; byte MW21L,MW21H,MW22L,MW22H,MW25L,MW25H,MW26L,MW26H; //歷史充電電量記錄 byte MW29L,MW29H,MW30L,MW30H,MW33L,MW33H,MW34L,MW34H; //歷史放電電量記錄 byte Buffer[15]; //串口接收緩沖 byte ADch_s; //AD通道選擇 byte ADcount; //byte Key_value=0; //按鍵 //byte CANbuffer[8]; //接收到的CAN內(nèi)容緩沖區(qū)數(shù)組 word sum=0; long P,P1,P2,P3,Premain,Pup,Pdown,Psum; //實時充電功率,實時放電功率,歷史充電功率,歷史放電記錄 word PL,PH; //拆分P byte P0L,P0H,P1L,P1H; //拆分PH,PL byte RR = 1; //RR = 1;讀屏的19號地址;RR = 2讀屏的20號地址開始的時間; byte PAGE8; //進(jìn)入設(shè)置時間頁面和電量頁面設(shè)置計數(shù); byte T20 =0; word TENT; byte *p; //================================ //中值濾波程序 //================================ void filter() { static byte count,i,j; word value_buf[N]; word temp; sum=0; for(count=0;count<N;count++) { value_buf[count] = ADCbuffer1[count];; } for (j=0;j<N-1;j++) { for (i=0;i<N-j;i++) { if ( value_buf[i]>value_buf[i+1] ) { temp = value_buf[i]; value_buf[i] = value_buf[i+1]; value_buf[i+1] = temp; } } } for(count=1;count<N-1;count++) sum += value_buf[count]; } //=================================== //函數(shù)名:MCU_INIT //作用: 初始化MCU時鐘 晶振16M總線頻率8M //==================================== void MCU_INIT(void) { MCGC1=0x04; //選擇內(nèi)部時鐘 MCGC2=0x40; //時鐘源二分頻 MCGTRM=0xa8;//內(nèi)部時鐘微調(diào) } //=================================== //函數(shù)名: IO_INIT //作用: 初始化IO 輸入輸出 //==================================== void IO_INIT(void) { PTADD = 0xe6; //數(shù)據(jù)方向 1為輸出,0為輸入 PTBDD = 0x76; PTCDD = 0xb0; //PTDDD = 0xff; PTEDD = 0x45; PTFDD = 0xff; PTGDD = 0x38; PTAD = 0 ; //初始狀態(tài)IO全為0 PTBD = 0; PTCD = 0; PTDD = 0; PTED = 0; PTFD = 0; PTGD = 0; } //=================================== //函數(shù)名: ADC_INIT //作用: 初始化ADC 總線時鐘8M //=================================== void ADC_INIT(void) { ADCCFG = 0xf9; //低功耗模式,10位精度,ADCK=總線頻率/8/2=500K ADCSC2 = 0x00; //0x00:軟件觸發(fā),比較功能禁止 APCTL1 = 0x14; //通道引腳使能: 使用通道為AD19 AD11 AD3 AD4 APCTL2 = 0x08; APCTL3 = 0x08; ADch_s = 19; //選擇19通道開始 ADCSC1 = 0x73; //0x53:中斷使能,單次轉(zhuǎn)換,選擇19通道啟動轉(zhuǎn)換. } //=================================== //函數(shù)名:SCI_INIT //作用: 初始化SCI1 //==================================== void SCI_INIT(void) { SCI1BD = 8000000/16/Baud; SCI1C1 = 0x00; SCI1C2 = 0x2c; //使能接受中斷 } //=================================== //串口發(fā)送 //=================================== void SCI1send (byte x) { while(SCI1S1_TDRE==0); SCI1D = x; } //=================================== //定時器1初始化 //=================================== void TPM1_Init(void) //定時器1初始化 { TPM1MODH=0x3d; // TPM1MODL=0x09; //250MS TPM1SC=0x4F; //TPM1時鐘源為總線時鐘;分頻系數(shù)為128;溢出中斷使能 } //=================================== //延時 //=================================== void Delay(Word time) { Word i,j; for(i=0;i<time;i++) { __RESET_WATCHDOG(); for(j=0;j<500;j++); } } void WEEP() { FCMD=0x20; FSTAT_FCBEF=1; asm{ NOP NOP NOP NOP } while(FSTAT_FCCF==0); if(FSTAT_FACCERR==1) FSTAT_FACCERR=1; } /*********************主函數(shù)************************************/ void main(void) { static byte MonthF1,DateF1,MonthF2,DateF2,MonthF3,DateF3,MonthC1,DateC1,MonthC2,DateC2,MonthC3,DateC3; //充電放電歷史記錄的兩次時間變量及緩存變量 static byte FBETW0L,FBETW0H,FBETW1L,FBETW1H,CBETW0L,CBETW0H,CBETW1L,CBETW1H; static word PupCount,PdownCount; byte Pchange = 0 ; //充電0XFF 放電0X00轉(zhuǎn)換標(biāo)志 byte Failure; //故障信息指示MW17.0 = 1過壓 MW17.1 = 1過流 word BetweenH,BetweenL; long a,b; byte SendSum; MCU_INIT(); IO_INIT(); Ds1302_Init(); ADC_INIT(); TPM1_Init(); SCI_INIT(); DE485 = 1; //485發(fā)送使能; PTED_PTED6 = 1; Ds1302_Read_Time(); //先讀取一次時間用于判斷歷史時間 if(!DI1) //DI1 = 0 { Pchange = 0x01; //充電 } if(!DI2) //DI2 = 0 { //放電 Pchange = 0x02; } if(DI1&&DI2) //DI1,DI2都 為高電平 { Pchange = 0; } FCDIV = 39; //設(shè)置FLASH分頻 8M總線時鐘分頻數(shù)39;FLASH讀寫200KH asm(nop); //**************讀取記錄的充電的歷史記錄************************ //************前1次的前1次得充電記錄 p=(byte *)(0x1401); // MonthC1= *p; p=(byte *)(0x1402); //時間 DateC1= *p; p=(byte *)(0x1403); //電量的最低位 MW21L= *p; p=(byte *)(0x1404); // MW21H= *p; p=(byte *)(0x1405); // MW22L= *p; p=(byte *)(0x1406); // MW22H= *p; if(MonthC1>12) { MonthC1 = 0; DateC1= 0; MW21L = 0; MW21H = 0; MW22L = 0; MW22H = 0; } //*************前1次的充電記錄********************************* p=(byte *)(0x1411); // MonthC2= *p; p=(byte *)(0x1412); //時間 DateC2= *p; p=(byte *)(0x1413); //電量的最低位 MW25L= *p; p=(byte *)(0x1414); // MW25H= *p; p=(byte *)(0x1415); // MW26L= *p; p=(byte *)(0x1416); // MW26H= *p; // if(MonthC2>12) //如果日期錯誤,清零 { MonthC2 = 0; DateC2= 0; MW25L = 0; MW25H = 0; MW26L = 0; MW26H = 0; } //***************緩存的充電記錄,用于比較計算****************** p=(byte *)(0x1421); // MonthC3= *p; p=(byte *)(0x1422); //時間 DateC3= *p; p=(byte *)(0x1423); //電量的最低位 CBETW0L= *p; p=(byte *)(0x1424); // CBETW0H= *p; p=(byte *)(0x1425); // CBETW1L= *p; p=(byte *)(0x1426); // CBETW1H= *p; if(MonthC3>12) // { MonthC3 = 0; DateC3= 0; CBETW0L = 0; CBETW0H = 0; CBETW1L = 0; CBETW1H = 0; } //**************讀取記錄的放電的歷史記錄************************** //************前1次的前1次的放電記錄 p=(byte *)(0x1501); // MonthF1= *p; p=(byte *)(0x1502); //時間 DateF1= *p; p=(byte *)(0x1503); //電量的最低位 MW29L= *p; p=(byte *)(0x1504); // MW29H= *p; p=(byte *)(0x1505); // MW30L= *p; p=(byte *)(0x1506); // MW30H= *p; if(MonthF1>12) { MonthF1 = 0; DateF1= 0; MW29L = 0; MW29H = 0; MW30L = 0; MW30H = 0; } //*************前1次的放電記錄********************************* p=(byte *)(0x1511); // MonthF2= *p; p=(byte *)(0x1512); //時間 DateF2= *p; p=(byte *)(0x1513); //電量的最低位 MW33L= *p; p=(byte *)(0x1514); // MW33H= *p; p=(byte *)(0x1515); // MW34L= *p; p=(byte *)(0x1516); // MW34H= *p; if(MonthF2>12) // { MonthF2 = 0; DateF2= 0; MW33L = 0; MW33H = 0; MW34L = 0; MW34H = 0; } //***************緩存的放電記錄,用于比較計算****************** p=(byte *)(0x1521); // MonthF3= *p; p=(byte *)(0x1522); //時間 DateF3= *p; p=(byte *)(0x1523); //電量的最低位 FBETW0L= *p; p=(byte *)(0x1524); // FBETW0H= *p; p=(byte *)(0x1525); // FBETW1L= *p; p=(byte *)(0x1526); // FBETW1H= *p; if(MonthF3>12) // { MonthF3 = 0; DateF3= 0; FBETW0L = 0; FBETW0H = 0; FBETW1L = 0; FBETW1H = 0; } p=(byte *)(0x1601); // MW8L= *p; p=(byte *)(0x1602); //時間 MW8H= *p; p=(byte *)(0x1603); //電量的最低位 MW9L= *p; p=(byte *)(0x1604); // MW9H= *p; if((MW8L==0xff)&&(MW8H==0xff)&&(MW9L==0xff)&&(MW9H==0xff)) //第一次上電 { MW8L = 0; MW8H = 0; MW9L = 0; MW9H = 0; P2 = 0; } else{ Premain = MW9L+(MW9H<<8); P2= (Premain<<16)+ (MW8L+(MW8H<<8)); P2 = P2*3600*1000; } if(Pchange==0x01) //充電時比較 { if((time_buf1[2] == MonthC3)&& (time_buf1[3] == DateC3)) { MW4L = CBETW0L; MW4H = CBETW0H; MW5L = CBETW1L; MW5H = CBETW1H; Premain = MW5L+(MW5H<<8); P3= (Premain<<16)+ (MW4L+(MW4H<<8)); P3 = P3*3600; } else { MW4L = 0; MW4H = 0; MW5L = 0; MW5H = 0; P3 = 0; } } if(Pchange==0x02) //放電時比較 { if((time_buf1[2] == MonthF3)&& (time_buf1[3] == DateF3)) { MW6L = FBETW0L; MW6H = FBETW0H; MW7L = FBETW1L; MW7H = FBETW1H; Premain = MW7L+(MW7H<<8); P1= (Premain<<16)+ (MW6L+(MW6H<<8)); P1 = P1*3600; } else { MW6L = 0; MW6H = 0; MW7L = 0; MW7H = 0; P1 = 0; } } EnableInterrupts; //開中斷 for(;;) { __RESET_WATCHDOG(); //喂內(nèi)部看門狗 if(!DI1) { //充電 Pchange = 0x01; } //放電 if(!DI2) { Pchange = 0x02; } if(DI1&&DI2) { Pchange = 0; //停機(jī)狀態(tài) } if(Pchange==0x02) { if((time_buf1[2] != MonthF3)|| (time_buf1[3] != DateF3)) //只要是 時間不等,就要把當(dāng)前記錄寫入EEPROM,開始新的計算 { p=( unsigned char *)(0x1500); //指定地址 緩存的時間寫入前1天,前一天的時間寫入前1天前1天 *p=0x01; FCMD=0x40; //擦除命令 FSTAT_FCBEF=1; //啟動命令 Delay(1); while(FSTAT_FCCF==0); //等待完成 if(FSTAT_FACCERR==1) FSTAT_FACCERR=1; p=(byte *)(0x1500); //指定地址 *p = 0x01; WEEP(); p=(byte *)(0x1501); *p = MonthF2; WEEP(); p=(byte *)(0x1502); *p = DateF2; WEEP(); p=(byte *)(0x1503); *p = MW33L; WEEP(); p=(byte *)(0x1504); *p = MW33H; WEEP(); p=(byte *)(0x1505); *p = MW34L; WEEP(); p=(byte *)(0x1506); *p = MW34H; WEEP(); p=( unsigned char *)(0x1510); //指定地址 //緩存的時間寫入前1天,前一天的時間寫入前1天前1天 *p=0x01; FCMD=0x40; //擦除命令 FSTAT_FCBEF=1; //啟動命令 Delay(1); while(FSTAT_FCCF==0); //等待完成 if(FSTAT_FACCERR==1) FSTAT_FACCERR=1; p=(byte *)(0x1510); //指定地址 *p = 0x01; WEEP(); p=(byte *)(0x1511); //如果時間變了,原緩存存入前一天的內(nèi)存 *p = MonthF3; WEEP(); p=(byte *)(0x1512); *p = DateF3; WEEP(); p=(byte *)(0x1513); *p = FBETW0L; WEEP(); p=(byte *)(0x1514); *p = FBETW0H; WEEP(); p=(byte *)(0x1515); *p = FBETW1L; WEEP(); p=(byte *)(0x1516); *p = FBETW1H; WEEP(); P1 = 0; MW29L = MW33L; MW29H = MW33H; MW30L = MW34L; MW30H = MW34H; MonthF1 = MonthF2; DateF1 = DateF2; MW33L = FBETW0L; MW33H = FBETW0H; MW34L = FBETW1L; MW34H = FBETW1H; MonthF2 = MonthF3; DateF2 = DateF3; asm(nop); MonthF3 =time_buf1[2]; //當(dāng)前時間送入緩存 DateF3= time_buf1[3]; //MonthF3 = time_buf1[2]; //DateF3 = time_buf1[3]; FBETW0L = MW6L; FBETW0H = MW6H; FBETW1L = MW7L; FBETW1H = MW7H; p=( unsigned char *)(0x1520); //指定地址 *p=0x01; FCMD=0x40; //擦除命令 FSTAT_FCBEF=1; //啟動命令 Delay(1); while(FSTAT_FCCF==0); //等待完成 if(FSTAT_FACCERR==1) FSTAT_FACCERR=1; p=(byte *)(0x1520); //指定地址 *p = 0x01; WEEP(); p=(byte *)(0x1521); *p = time_buf1[2]; WEEP(); p=(byte *)(0x1522); *p = time_buf1[3]; WEEP(); p=(byte *)(0x1523); *p = MW6L; WEEP(); p=(byte *)(0x1524); *p = MW6H; WEEP(); p=(byte *)(0x1525); *p = MW7L; WEEP(); p=(byte *)(0x1526); *p = MW7H; WEEP(); } } if(Pchange == 0x01) //充電的時候 { if((time_buf1[2] != MonthC3)|| (time_buf1[3] != DateC3)) //只要時間不等,開始新的計算 { p=( unsigned char *)(0x1400); //指定地址 緩存的時間寫入前1天,前一天的時間寫入前1天前1天 *p=0x01; FCMD=0x40; //擦除命令 FSTAT_FCBEF=1; //啟動命令 Delay(1); while(FSTAT_FCCF==0); //等待完成 if(FSTAT_FACCERR==1) FSTAT_FACCERR=1; p=(byte *)(0x1400); //指定地址 *p = 0x01; WEEP(); p=(byte *)(0x1401); *p = MonthC2; WEEP(); p=(byte *)(0x1402); *p = DateC2; WEEP(); p=(byte *)(0x1403); *p = MW25L; WEEP(); p=(byte *)(0x1404); *p = MW25H; WEEP(); p=(byte *)(0x1405); *p = MW26L; WEEP(); p=(byte *)(0x1406); *p = MW26H; WEEP(); p=( unsigned char *)(0x1410); //指定地址 緩存的時間寫入前1天,前一天的時間寫入前1天前1天 *p=0x01; FCMD=0x40; //擦除命令 FSTAT_FCBEF=1; //啟動命令 Delay(1); while(FSTAT_FCCF==0); //等待完成 if(FSTAT_FACCERR==1) FSTAT_FACCERR=1; p=(byte *)(0x1410); //指定地址 *p = 0x01; WEEP(); p=(byte *)(0x1411); *p = MonthC3; WEEP(); p=(byte *)(0x1412); *p = DateC3; WEEP(); p=(byte *)(0x1413); *p = CBETW0L; WEEP(); p=(byte *)(0x1414); *p = CBETW0H; WEEP(); p=(byte *)(0x1415); *p = CBETW1L; WEEP(); p=(byte *)(0x1416); *p = CBETW1H; WEEP(); MW21L = MW25L; MW21H = MW25H; MW22L = MW26L; MW22H = MW26H; MonthC1 = MonthC2; DateC1 = DateC2; MW25L = CBETW0L; MW25H = CBETW0H; MW26L = CBETW1L; MW26H = CBETW1H; MonthC2 = MonthC3; DateC2 = DateC3; P3 = 0; MonthC3 =time_buf1[2]; //當(dāng)前時間送入緩存 DateC3= time_buf1[3]; //MonthC3 = time_buf1[2]; //DateC3 = time_buf1[3]; CBETW0L = MW4L; CBETW0H = MW4H; CBETW1L = MW5L; CBETW1H = MW5H; p=( unsigned char *)(0x1420); //指定地址 *p=0x01; FCMD=0x40; //擦除命令 FSTAT_FCBEF=1; //啟動命令 Delay(1); while(FSTAT_FCCF==0); //等待完成 if(FSTAT_FACCERR==1) FSTAT_FACCERR=1; p=(byte *)(0x1420); //指定地址 *p = 0x01; WEEP(); p=(byte *)(0x1421); *p = time_buf1[2]; WEEP(); p=(byte *)(0x1422); *p = time_buf1[3]; WEEP(); p=(byte *)(0x1423); *p = MW4L; WEEP(); p=(byte *)(0x1424); *p = MW4H; WEEP(); p=(byte *)(0x1425); *p = MW5L; WEEP(); p=(byte *)(0x1426); *p = MW5H; WEEP(); } } if(!RR) { Ds1302_Write_Time(); Delay(10); T20 = 1; } if(T20) //切換到2界面 { T20 = 0; TENT = 0; DE485 = 1; //保證切換到發(fā)射 Delay(200); SCI1send (0x01); //站號 SCI1send (0x57); //寫命令 SCI1send (0x12); //18號地址跳轉(zhuǎn)頁面指令,跳轉(zhuǎn)到1界面 SCI1send (0x01); //1個長度 SCI1send (0x00); //18號地址 SCI1send (0x01); SCI1send (0x6c); Delay(100); //需加一段長延時 SCI1send (0x01); //站號 SCI1send (0x57); //寫命令 SCI1send (0x12); //18號地址跳轉(zhuǎn)頁面指令,跳轉(zhuǎn)到2界面 SCI1send (0x01); //1個長度 SCI1send (0x00); //18號地址 SCI1send (0x02); SCI1send (0x6d); Delay(200); //必須加段延時確保數(shù)據(jù)發(fā)送出去 RR = 1; //1分鐘內(nèi)ENT沒有按下,轉(zhuǎn)回正常模式 asm(nop); } if(ADSET) //處理AD; { ADSET = 0; if(ADcount == 1) { filter(); ADC1= (sum/(N-2)); if(ADC1<7){ ADC1 = 0; //屏蔽掉待機(jī)狀態(tài)時的不干凈的初值 } if (ADC1>163) { Failure = Failure|0x01; //置過壓標(biāo)志 } else Failure = Failure&0xfe; //清過壓標(biāo)志 //b = 750*50; //b = b/255; b = (long)7500*ADC1; //放大10倍,為了送顯示 //ADC1 = b*ADC1; //ADC1 = ADC1/5; ADC1 = b>>10; //除以1024 ADC1H = ADC1>>8; ADC1L = ADC1&255; ADch_s = 11; ADCSC1=0x6b; } if(ADcount == 2) { filter(); ADC2= (sum/(N-2)); if(ADC2<7) { ADC2 = 0; } if (ADC2>191) //過流 { Failure = Failure|0x02; //置過流標(biāo)志 } else Failure = Failure&0xfd; //清過流標(biāo)志 //a= 400*50; //a= a/255; a = (long)4000*ADC2; //ADC2 = a*ADC2; //轉(zhuǎn)換成電壓值 ,取小數(shù)點后一位,所以先擴(kuò)大50倍 //ADC2 = ADC2/5; //10倍電流送顯示,用于顯示小數(shù)點 ADC2 = a>>10; ADC2H = ADC2>>8; ADC2L = ADC2&255; ADC1 = ADC1/10; ADC2 = ADC2/10; P =(long)ADC1*ADC2; PH = P>>16; PL = P&0xffff; P1H = PH>>8; P1L = PH&255; P0H = PL>>8; P0L = PL&255; if(Pchange==0x02) //如果放電 { PdownCount++; //秒累加 P2 = P2+P; //一直累積的放電電量 Psum=(long)(P2/3600/1000); BetweenH = Psum>>16; BetweenL = Psum&0xffff; MW9H = BetweenH>>8; MW9L = BetweenH&255; MW8H = BetweenL>>8; MW8L = BetweenL&255; P1 = P1+P; //秒功率累加 Pdown = (long)P1/3600; //實際放電功率,按小時計算 BetweenH = Pdown>>16; BetweenL = Pdown&0xffff; MW7H = BetweenH>>8; MW7L = BetweenH&255; MW6H = BetweenL>>8; MW6L = BetweenL&255; if(PdownCount > T) //超過半個小時開始寫入EEPROM { PdownCount = 0; p=( unsigned char *)(0x1600); //指定地址 *p=0x01; FCMD=0x40; //擦除命令 FSTAT_FCBEF=1; //啟動命令 Delay(1); while(FSTAT_FCCF==0); //等待完成 if(FSTAT_FACCERR==1) FSTAT_FACCERR=1; p=(byte *)(0x1600); //指定地址 *p = 0x01; WEEP(); p=(byte *)(0x1601); //總放電量寫入EEPROM *p = MW8L; WEEP(); p=(byte *)(0x1602); *p = MW8H; WEEP(); p=(byte *)(0x1603); *p = MW9L; WEEP(); p=(byte *)(0x1604); *p = MW9H; WEEP(); asm(nop); if((time_buf1[2] == MonthF3)&& (time_buf1[3] == DateF3)) //當(dāng)前時間等于緩存時間,繼續(xù)寫入緩存 { MonthF3 = time_buf1[2]; DateF3 = time_buf1[3]; FBETW0L = MW6L; FBETW0H = MW6H; FBETW1L = MW7L; FBETW1H = MW7H; p=( unsigned char *)(0x1520); //指定地址 *p=0x01; FCMD=0x40; //擦除命令 FSTAT_FCBEF=1; //啟動命令 Delay(1); while(FSTAT_FCCF==0); //等待完成 if(FSTAT_FACCERR==1) FSTAT_FACCERR=1; p=(byte *)(0x1520); //指定地址 *p = 0x01; WEEP(); p=(byte *)(0x1521); *p = time_buf1[2]; WEEP(); p=(byte *)(0x1522); *p = time_buf1[3]; WEEP(); p=(byte *)(0x1523); *p = MW6L; WEEP(); p=(byte *)(0x1524); *p = MW6H; WEEP(); p=(byte *)(0x1525); *p = MW7L; WEEP(); p=(byte *)(0x1526); *p = MW7H; WEEP(); } } } if(Pchange == 0x01) //如果充電 { PupCount++; //秒累加 P3 =P3+P; //秒功率累加 Pup = (long)P3/3600; //實際放電功率,按小時計算 BetweenH = Pup>>16; BetweenL = Pup&0xffff; MW5H = BetweenH>>8; MW5L = BetweenH&255; MW4H = BetweenL>>8; MW4L = BetweenL&255; if(PupCount >T) { PupCount = 0; //超過半個小時開始寫入EEPROM if((time_buf1[2] == MonthC3)&& (time_buf1[3] == DateC3)) //當(dāng)前時間等于緩存時間,繼續(xù)寫入緩存 { MonthC3 = time_buf1[2]; DateC3 = time_buf1[3]; CBETW0L = MW4L; CBETW0H = MW4H; CBETW1L = MW5L; CBETW1H = MW5H; p=( unsigned char *)(0x1420); //指定地址 *p=0x01; FCMD=0x40; //擦除命令 FSTAT_FCBEF=1; //啟動命令 Delay(1); while(FSTAT_FCCF==0); //等待完成 if(FSTAT_FACCERR==1) FSTAT_FACCERR=1; p=(byte *)(0x1420); //指定地址 *p = 0x01; WEEP(); p=(byte *)(0x1421); *p = time_buf1[2]; WEEP(); p=(byte *)(0x1422); *p = time_buf1[3]; WEEP(); p=(byte *)(0x1423); *p = MW4L; WEEP(); p=(byte *)(0x1424); *p = MW4H; WEEP(); p=(byte *)(0x1425); *p = MW5L; WEEP(); p=(byte *)(0x1426); *p = MW5H; WEEP(); //如果相等則認(rèn)為是當(dāng)前時間,繼續(xù) } } } asm(nop); ADch_s = 3; ADCSC1=0x63; } if(ADcount == 3) { filter(); ADC3= (sum/(N-2)); ADC3H = (sum/(N-2))>>8; ADC3L = (sum/(N-2))&255; ADch_s = 4; ADCSC1=0x64; } if(ADcount == 4) { filter(); ADC4= (sum/(N-2)); ADC4H = (sum/(N-2))>>8; ADC4L = (sum/(N-2))&255; ADch_s = 19; ADCSC1=0x73; } if(RR ==2) { DE485 = 1; Delay(2); SCI1send (0x01); //站號 SCI1send (0x52); //讀命令 SCI1send (0x14); //20號地址判斷ENT鍵狀態(tài) SCI1send (0x01); //1個地址 SCI1send (0x68); Delay(1); //必須加段延時確保數(shù)據(jù)發(fā)送出去 DE485 = 0; //485切換到接收狀態(tài) asm(nop); } if(RR ==3) { DE485 = 1; Delay(2); SCI1send (0x01); //站號 SCI1send (0x57); //寫命令 SCI1send (0x14); //20號地址清零 SCI1send (0x01); //1個長度 SCI1send (0x00); //18號地址 SCI1send (0x00); SCI1send (0x6D); Delay(50); RR =4; } if(RR ==4) //讀時間 { DE485 = 1; Delay(5); SCI1send (0x01); //站號 SCI1send (0x52); //讀命令 SCI1send (0x0B); //11號地址 SCI1send (0x06); //6個地址 SCI1send (0x64); Delay(1); //必須加段延時確保數(shù)據(jù)發(fā)送出去 DE485 = 0; //485切換到接收狀態(tài) //asm(nop); } } if(ReadTimeFlag) { ReadTimeFlag = 0; if(RR ==1) { Delay(10); DE485 = 1; Ds1302_Read_Time(); asm(nop); SendSum = (0x6a+Pchange+Failure+ADC1L+ADC1H+ADC2L+ADC2H+P0H+P0L+P1H+P1L+ time_buf1[1]+time_buf1[2]+time_buf1[3]+time_buf1[4]+time_buf1[5]+time_buf1[6]+ MW4L+MW4H+MW5L+MW5H+MW6L+MW6H+MW7L+MW7H+MW8L+MW8H+MW9L+MW9H); //累加和 SCI1send (0x01); //站號 SCI1send (0x57); //寫命令 SCI1send (0x00); //首地址 SCI1send (0x12); //18個地址 SCI1send (ADC1H); //MW0高位 電壓 SCI1send (ADC1L); //MW0低位 SCI1send (ADC2H); //MW1 電流 SCI1send (ADC2L); SCI1send (P0H); //MW2 實時功率 SCI1send (P0L); SCI1send (P1H); //MW3 SCI1send (P1L); SCI1send (MW4H); //MW4 SCI1send (MW4L); SCI1send (MW5H); //MW5 當(dāng)前充電電量(一天累計) SCI1send (MW5L); SCI1send (MW6H); //MW6 SCI1send (MW6L); SCI1send (MW7H); //MW7 當(dāng)前放電電量(一次累計) SCI1send (MW7L); SCI1send (MW8H); //MW8 當(dāng)前放電電量(一次累計) SCI1send (MW8L); SCI1send (MW9H); //MW9 當(dāng)前放電電量(一次累計) SCI1send (MW9L); SCI1send (0x00); //MW10 充放電指示00:放電;FF:充電 SCI1send (Pchange); SCI1send (0x00); //MW11開始為時間 SCI1send (time_buf1[1]); SCI1send (0x00); SCI1send (time_buf1[2]); SCI1send (0x00); SCI1send (time_buf1[3]); SCI1send (0x00); SCI1send (time_buf1[4]); SCI1send (0x00); SCI1send (time_buf1[5]); SCI1send (0x00); SCI1send (time_buf1[6]); SCI1send (0x00); //MW17 過壓過流指示 SCI1send (Failure); SCI1send (SendSum); asm(nop); Delay(100); SendSum = 0x7d+MW21H+MW21L+MW22H+MW22L+MonthC1+DateC1+MW25H+MW25L+MW26L+MW26H+MonthC2+DateC2 +MW29H+MW29L+MW30H+MW30L+MonthF1+DateF1+MW33L+MW33H+MW34H+MW34L+MonthF2+DateF2; SCI1send (0x01); //站號 SCI1send (0x57); //寫命令 SCI1send (0x15); //21號地址 SCI1send (0x10); //16個地址 SCI1send (MW21H); //MW21高位 SCI1send (MW21L); //MW21低位 SCI1send (MW22H); //MW22 SCI1send (MW22L); SCI1send (0x00); //月 MW23 SCI1send (MonthC1); SCI1send (0x00); //日 MW24 SCI1send (DateC1); SCI1send (MW25H); //MW25 SCI1send (MW25L); SCI1send (MW26H); //MW26 SCI1send (MW26L); SCI1send (0x00); //MW27 SCI1send (MonthC2); SCI1send (0x00); //MW28 SCI1send (DateC2); SCI1send (MW29H); //MW29 SCI1send (MW29L); SCI1send (MW30H); //MW30 SCI1send (MW30L); SCI1send (0x00); //MW31 SCI1send (MonthF1); SCI1send (0x00); //MW32 SCI1send (DateF1); SCI1send (MW33H); //MW33 SCI1send (MW33L); SCI1send (MW34H); //MW34 SCI1send (MW34L); SCI1send (0x00); //MW35 SCI1send (MonthF2); SCI1send (0x00); //MW36 SCI1send (DateF2); SCI1send (SendSum); //累加和 asm(nop); Delay(10); SCI1send (0x01); //站號 SCI1send (0x52); //讀命令 SCI1send (0x13); //19號地址判斷在哪個頁面 SCI1send (0x01); //1個地址 SCI1send (0x67); Delay(1); //必須加段延時確保數(shù)據(jù)發(fā)送出去 DE485 = 0; //485切換到接收狀態(tài) asm(nop); } } } } //========================================== //定時器1中斷函數(shù) 中斷向量號11 250毫秒定時 //========================================== void interrupt 11 TPM1_ISR(void) { static byte i,j,k; if((TPM1SC & 0x80)==0x80) { TPM1SC_TOF=0; ADSET = 1; } i++; if(!PAGE8) // { j = 0; } else { j++; if(j>PAGE8) //大于5秒 { j = 0; RR = 2; //轉(zhuǎn)判斷ENT鍵是否按下程序 PAGE8 = 0; } } if(!TENT) { k = 0; } else { k++; if(k>TENT) { k = 0; T20 = 1; //如果ENT鍵1分鐘內(nèi)沒有按下則跳轉(zhuǎn)到2界面(顯示電壓,電流) TENT = 0; } } if(i>3) { i = 0; ReadTimeFlag = 1; } } //========================================== //串口接收中斷 VectorNumber_Vsci1rx 中斷向量號17 //========================================== interrupt VectorNumber_Vsci1rx void SCI_RE(void) { static byte j; static byte i; byte Rcv; if(SCI1S1_RDRF) //串口接收中斷標(biāo)志位 { //清標(biāo)志位 SCI1S1_RDRF = 0; //接收數(shù)據(jù)送緩存 Rcv = SCI1D; //*********************讀頁面數(shù)值***************************** if(RR == 1) { if(Rcv == 0x13) { j = 1; Buffer[0]=Rcv; } else { if(j < 5) //5個字節(jié) { Buffer[j] = Rcv; j++; } } if((Buffer[3]==0x08)&&(Buffer[4]==0x1d)) //如果檢測到是第8頁面則處理數(shù)據(jù) { PAGE8 =20; //如果停在8頁面設(shè)置一個計數(shù)器,5秒時間內(nèi)如果還在則認(rèn)為在修改時間 TENT = 240; //2分鐘內(nèi)ENT鍵沒有按下,則跳轉(zhuǎn)到2頁面; } if(Buffer[3]!=0x08) //如果跳轉(zhuǎn)到別的界面,馬上清零 { PAGE8 = 0; TENT = 0; RR = 1; //回到正常狀態(tài) } } //****************判斷ENT鍵按下與否******************************* ENT鍵按下的話20站號變成1 if(RR ==2) { if(Rcv == 0x14) { j = 1; Buffer[0]=Rcv; } else { if(j < 5) //5個字節(jié) { Buffer[j] = Rcv; j++; } } if((Buffer[3]==0x01)&&(Buffer[4]==0x17)) //ENT鍵已經(jīng)按下 { RR = 3; } } //******************************讀取要修改的時間******************************* if(RR ==4) //此時ENT已經(jīng)清零 { Buffer[j]=Rcv; if(!i) { if(Buffer[j]== 0x0b) //接收到11 { Buffer[0] =0x0b; j=1; //才開始類加 } if(Buffer[1]== 0x06) { i = 1; } } if(i) { if(j< 15) { Buffer[j] = Rcv; j++; } } if(j==15) { i = 0; } if(Buffer[14]==(Buffer[3]+Buffer[5]+Buffer[7]+Buffer[9]+Buffer[11]+Buffer[13]+0x12)) { RR = 0; time_buf1[1] = Buffer[3] ; //年 time_buf1[2] = Buffer[5] ; //月 time_buf1[3] = Buffer[7] ; //日 time_buf1[4] = Buffer[9] ; //時 time_buf1[5] = Buffer[11]; //分 time_buf1[6] = Buffer[13]; //秒 } } } } //========================================== //ADC轉(zhuǎn)換完成中斷服務(wù)程序 VectorNumber_Vadc中斷向量號23 //========================================== interrupt VectorNumber_Vadc void ADC_ISR(void) { static byte count; switch(ADch_s) { case 19: ADCbuffer1[count]=ADCR; count++; if (count > N-1){ count = 0; ADCSC1=0x00; ADcount = 1; } break; case 11: ADCbuffer1[count]=ADCR; count++; if (count > N-1){ count = 0; ADCSC1=0x00; ADcount = 2; } break; case 3: ADCbuffer1[count]=ADCR; count++; if (count > N-1){ count = 0; ADCSC1=0x00; ADcount = 3; } break; case 4: ADCbuffer1[count]=ADCR; count++; if (count > N-1){ count = 0; ADCSC1=0x00; ADcount = 4; } break; default:break; } asm(nop); //在此設(shè)置一個斷點,觀測ad_h和ad_l的變化 }