/*********************************************************
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 //外触发1----->PG2
#define DI2 PTED_PTED5 //外触发2----->PE5
#define DI3 PTED_PTED4 //外触发3----->PE4
#define DI4 PTED_PTED3 //外触发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发送标识符
//#define ID_RX 0x0002 //自定义的CAN接收标识符
//Bool can_send_enable = FALSE; //CAN发送标志位,暂定RTC0.5秒发送一次
#define Baud 19200 //串口波特率9600
#define N 51
#define T 1800 //运算电量的时间单位1800是半个小时(1800秒)
extern byte time_buf1[8]; //1302时钟寄存器
byte ReadTimeFlag = 0; //定时器每0.5秒读1302时间的标志位
byte ADSET = 0; //发送电流电压功率等数值到显示屏标志位
/*********************变量和函数定义****************************/
word ADCbuffer1[N] = 0; //AD转换缓冲
word ADC1,ADC2,ADC3,ADC4; //AD转换缓冲
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内容缓冲区数组
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; //进入设置时间页面和电量页面设置计数;
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];
}
//===================================
//函数名:MCU_INIT
//作用: 初始化MCU时钟 晶振16M总线频率8M
//====================================
void MCU_INIT(void)
{
MCGC1=0x04; //选择内部时钟
MCGC2=0x40; //时钟源二分频
MCGTRM=0xa8;//内部时钟微调
}
//===================================
//函数名: IO_INIT
//作用: 初始化IO 输入输出
//====================================
void IO_INIT(void)
{
PTADD = 0xe6; //数据方向 1为输出,0为输入
PTBDD = 0x76;
PTCDD = 0xb0;
//PTDDD = 0xff;
PTEDD = 0x45;
PTFDD = 0xff;
PTGDD = 0x38;
PTAD = 0 ; //初始状态IO全为0
PTBD = 0;
PTCD = 0;
PTDD = 0;
PTED = 0;
PTFD = 0;
PTGD = 0;
}
//===================================
//函数名: ADC_INIT
//作用: 初始化ADC 总线时钟8M
//===================================
void ADC_INIT(void)
{
ADCCFG = 0xf9; //低功耗模式,10位精度,ADCK=总线频率/8/2=500K
ADCSC2 = 0x00; //0x00:软件触发,比较功能禁止
APCTL1 = 0x14; //通道引脚使能: 使用通道为AD19 AD11 AD3 AD4
APCTL2 = 0x08;
APCTL3 = 0x08;
ADch_s = 19; //选择19通道开始
ADCSC1 = 0x73; //0x53:中断使能,单次转换,选择19通道启动转换.
}
//===================================
//函数名:SCI_INIT
//作用: 初始化SCI1
//====================================
void SCI_INIT(void)
{
SCI1BD = 8000000/16/Baud;
SCI1C1 = 0x00;
SCI1C2 = 0x2c; //使能接受中断
}
//===================================
//串口发送
//===================================
void SCI1send (byte x)
{
while(SCI1S1_TDRE==0);
SCI1D = x;
}
//===================================
//定时器1初始化
//===================================
void TPM1_Init(void) //定时器1初始化
{
TPM1MODH=0x3d; //
TPM1MODL=0x09; //250MS
TPM1SC=0x4F; //TPM1时钟源为总线时钟;分频系数为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;
}
/*********************主函数************************************/
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转换标志
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发送使能;
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; //设置FLASH分频 8M总线时钟分频数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(); //喂内部看门狗
if(!DI1)
{ //充电
Pchange = 0x01;
} //放电
if(!DI2)
{
Pchange = 0x02;
}
if(DI1&&DI2)
{
Pchange = 0; //停机状态
}
if(Pchange==0x02)
{
if((time_buf1[2] != MonthF3)|| (time_buf1[3] != DateF3)) //只要是 时间不等,就要把当前记录写入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); //如果时间变了,原缓存存入前一天的内存
*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]; //当前时间送入缓存
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]; //当前时间送入缓存
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; //保证切换到发射
Delay(200);
SCI1send (0x01); //站号
SCI1send (0x57); //写命令
SCI1send (0x12); //18号地址跳转页面指令,跳转到1界面
SCI1send (0x01); //1个长度
SCI1send (0x00); //18号地址
SCI1send (0x01);
SCI1send (0x6c);
Delay(100); //需加一段长延时
SCI1send (0x01); //站号
SCI1send (0x57); //写命令
SCI1send (0x12); //18号地址跳转页面指令,跳转到2界面
SCI1send (0x01); //1个长度
SCI1send (0x00); //18号地址
SCI1send (0x02);
SCI1send (0x6d);
Delay(200); //必须加段延时确保数据发送出去
RR = 1; //1分钟内ENT没有按下,转回正常模式
asm(nop);
}
if(ADSET) //处理AD;
{
ADSET = 0;
if(ADcount == 1)
{
filter();
ADC1= (sum/(N-2));
if(ADC1<7){ ADC1 = 0; //屏蔽掉待机状态时的不干净的初值
}
if (ADC1>163)
{
Failure = Failure|0x01; //置过压标志
}
else Failure = Failure&0xfe; //清过压标志
//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; //置过流标志
}
else Failure = Failure&0xfd; //清过流标志
//a= 400*50;
//a= a/255;
a = (long)4000*ADC2;
//ADC2 = a*ADC2; //转换成电压值 ,取小数点后一位,所以先扩大50倍
//ADC2 = ADC2/5; //10倍电流送显示,用于显示小数点
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)) //当前时间等于缓存时间,继续写入缓存
{
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)) //当前时间等于缓存时间,继续写入缓存
{
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(); //如果相等则认为是当前时间,继续
}
}
}
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键状态
SCI1send (0x01); //1个地址
SCI1send (0x68);
Delay(1); //必须加段延时确保数据发送出去
DE485 = 0; //485切换到接收状态
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); //必须加段延时确保数据发送出去
DE485 = 0; //485切换到接收状态
//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 当前充电电量(一天累计)
SCI1send (MW5L);
SCI1send (MW6H); //MW6
SCI1send (MW6L);
SCI1send (MW7H); //MW7 当前放电电量(一次累计)
SCI1send (MW7L);
SCI1send (MW8H); //MW8 当前放电电量(一次累计)
SCI1send (MW8L);
SCI1send (MW9H); //MW9 当前放电电量(一次累计)
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); //必须加段延时确保数据发送出去
DE485 = 0; //485切换到接收状态
asm(nop);
}
}
}
}
//==========================================
//定时器1中断函数 中断向量号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; //转判断ENT键是否按下程序
PAGE8 = 0;
}
}
if(!TENT)
{
k = 0;
}
else
{
k++;
if(k>TENT)
{
k = 0;
T20 = 1; //如果ENT键1分钟内没有按下则跳转到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) //串口接收中断标志位
{ //清标志位
SCI1S1_RDRF = 0; //接收数据送缓存
Rcv = SCI1D;
//*********************读页面数值*****************************
if(RR == 1)
{
if(Rcv == 0x13)
{
j = 1;
Buffer[0]=Rcv;
}
else
{
if(j < 5) //5个字节
{
Buffer[j] = Rcv;
j++;
}
}
if((Buffer[3]==0x08)&&(Buffer[4]==0x1d)) //如果检测到是第8页面则处理数据
{
PAGE8 =20; //如果停在8页面设置一个计数器,5秒时间内如果还在则认为在修改时间
TENT = 240; //2分钟内ENT键没有按下,则跳转到2页面;
}
if(Buffer[3]!=0x08) //如果跳转到别的界面,马上清零
{
PAGE8 = 0;
TENT = 0;
RR = 1; //回到正常状态
}
}
//****************判断ENT键按下与否******************************* ENT键按下的话20站号变成1
if(RR ==2)
{
if(Rcv == 0x14)
{
j = 1;
Buffer[0]=Rcv;
}
else
{
if(j < 5) //5个字节
{
Buffer[j] = Rcv;
j++;
}
}
if((Buffer[3]==0x01)&&(Buffer[4]==0x17)) //ENT键已经按下
{
RR = 3;
}
}
//******************************读取要修改的时间*******************************
if(RR ==4) //此时ENT已经清零
{
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转换完成中断服务程序 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); //在此设置一个断点,观测ad_h和ad_l的变化
}