標題:
單片機單相電能表源碼
[打印本頁]
作者:
niuzhihong
時間:
2016-4-3 08:04
標題:
單片機單相電能表源碼
單相飛控智能電表源碼,單相多功能電能表源碼。電能計量,485通訊,總線通訊,液晶顯示等功能
0.png
(43.89 KB, 下載次數(shù): 140)
下載附件
2016-4-6 15:25 上傳
全部源碼下載:
單相多功能電能表源碼.rar
(80.05 KB, 下載次數(shù): 48)
2016-4-6 15:25 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
主程序預(yù)覽:
///
/// @file main.c
/// 系統(tǒng)主程序
///
///
///=====================================================================================
///
#define MAIN
#define AUTOCAL
#include "Liger.h"
#include "typemeter.h"
/**
* 系統(tǒng)默認校表參數(shù)
*
* Detailed description starts here.
* 該表記錄的電能表的默認校準參數(shù),但系統(tǒng)發(fā)生恢復(fù)參數(shù)失敗或是第一次上電等
* 情況時,會從該表中恢復(fù)參數(shù)
*/
unsigned long code meterprm_table[]=
{ 0x00000000, //有功門限高1
0x5A55D125, //有功門限低1
0x00000000, //有功門限高2
0xA3E30760, //有功門限低2
0x0000001a, //有效值門限高1
0x67F16719, //有效值門限低1
0x0018F380, //啟動門限1
0x0018F380, //啟動門限2
0x022EA846, //有功功率比差1
0x022EA846, //有功功率比差2
0xFE75A15D, //U比差
0x10000000, //I1比差
0x10000000, //I2比差
0x00000000, //補償1
0x00000000, //補償2
0x05, //A通道角差校正
0x05, //B通道角差校正
0x00000000, //有功啟動門限高位
0xB4ABA24A, //有功啟動門限低位
0x00000001, //無功啟動門限高位
0x47C60EC0 //無功啟動門限低位
};
/**
* 根據(jù)所給的ID號從外部存儲器中恢復(fù)數(shù)據(jù)項,恢復(fù)的數(shù)據(jù)會放在wr_buff中
* @param chk_id 數(shù)據(jù)項ID
* @return 1 成功
* 0 失敗
//limin 修改 返回值恒定為0
*/
unsigned char recover_item(unsigned int chk_id)
{
unsigned char i,j,num,value,datanum;
value=0;
num=addr_from_coreID(1,chk_id);
for(i=0;i<num;i++)
{ if((*ID_coretalbpoint[i]).stortype==EEPROM)
{ data_addr.word[1]=(*ID_coretalbpoint[i]).dataaddr;
datanum=(*ID_coretalbpoint[i]).datalong;
Read_data(EEPROM,datanum);
wr_buff[datanum]=0;
for(j=0;j<datanum-1;j++) //校驗和判斷
{ wr_buff[datanum]+=wr_buff[j];
}
if(wr_buff[datanum]==(wr_buff[datanum-1]-0x33)) //如果校驗和正確
{
if((*ID_coretalbpoint[i]).datatype==BCD)
{
if(check_X_bcd((datanum-1),wr_buff)==1) //BCD嘛校驗
{
value=1; //檢測到合法數(shù)據(jù),放在wr_buff中
break;
}
}
else
{
value=1; //檢測到合法數(shù)據(jù),放在wr_buff中
break;
}
}
}
}
return value;
}
//===================================================================================
//函數(shù)功能:恢復(fù)第一個脈沖的門限
//
//=====================================================================================
void Recover_pd01(void)
{ unsigned char i,value;
Word32 read_buff;
//40 bit
for(i=0;i<2;i++) //門限值恢復(fù)
{
if(recover_item(0x8500+i)==1) //恢復(fù)參數(shù)正確
{ read_buff.lword=Longdate_from_xbcd(&wr_buff[1],4);
u8PMdatah=wr_buff[0];
u32PMdatal= read_buff.lword;
u8PMdatah=u8PMdatah<<1;
if((u32PMdatal&0x80000000)==0x80000000)
u8PMdatah|=0x01;
u32PMdatal=u32PMdatal<<1;
SetMeterCfg(0x10f4+i*6);
}
else //恢復(fù)參數(shù)失敗
{ u8PMdatah=(uint8)meterprm_table[2*i];
u32PMdatal=meterprm_table[1+2*i];
u8PMdatah=u8PMdatah<<1;
if((u32PMdatal&0x80000000)==0x80000000)
u8PMdatah|=0x01;
u32PMdatal=u32PMdatal<<1;
SetMeterCfg(0x10f4+i*6);
}
}
for(i=0;i<2;i++)
{value=0;
ReadMeterPara(0x10f5+i*6);
if(recover_item(0x8503+i)==1) //防潛門限值設(shè)定
{ read_buff.lword=Longdate_from_xbcd(&wr_buff[0],4);
if(u32PMdatal!= read_buff.lword)
{ u32PMdatal= read_buff.lword;
value=1;
}
}
else //恢復(fù)參數(shù)失敗
{ if(u32PMdatal!=meterprm_table[6+i])
{ u32PMdatal=meterprm_table[6+i];
value=1;
}
}
if(value==1)
{
u32PMdatal <<= 1;
SetMeterCfg(0x10f5+i*6);
}
}
}
//===================================================================
//函數(shù)功能:恢復(fù)第一個CF之后的門限值
//===================================================================
void Recover_pd(void)
{ unsigned char i,value;
Word32 read_buff;
for(i=0;i<2;i++) //門限值恢復(fù)
{ value=0;
ReadMeterPara(0x10f4+i*6);
if(recover_item(0x8500+i)==1) //恢復(fù)參數(shù)正確
{ read_buff.lword=Longdate_from_xbcd(&wr_buff[1],4);
if(u8PMdatah!=wr_buff[0])
{ u8PMdatah=wr_buff[0];
value=1;
}
if(u32PMdatal!=read_buff.lword)
{ u32PMdatal= read_buff.lword;
value=1;
}
}
else //恢復(fù)參數(shù)失敗
{ if(u8PMdatah!=(uint8)meterprm_table[2*i])
{ u8PMdatah=(uint8)meterprm_table[2*i];
value=1;
}
if(u32PMdatal!=meterprm_table[1+2*i])
{ u32PMdatal=meterprm_table[1+2*i];
value=1;
}
}
if(value==1)
SetMeterCfg(0x10f4+i*6);
}
for(i=0;i<2;i++)
{ value=0;
ReadMeterPara(0x10f5+i*6);
if(recover_item(0x8503+i)==1) //防潛門限值設(shè)定
{ read_buff.lword=Longdate_from_xbcd(&wr_buff[0],4);
if(u32PMdatal!= read_buff.lword)
{ u32PMdatal= read_buff.lword;
value=1;
}
}
else //恢復(fù)參數(shù)失敗
{ if(u32PMdatal!=meterprm_table[6+i])
{ u32PMdatal=meterprm_table[6+i];
value=1;
}
}
if(value==1)
{
SetMeterCfg(0x10f5+i*6);
}
}
}
//===============================================================================
//函數(shù)功能:恢復(fù)除門限值之外的參數(shù)
//================================================================================
void Recover_metprim(void)
{ uint8 i,value;
unsigned char xdata *point;
Word32 read_buff;
for(i=0;i<7;i++) //參數(shù)恢復(fù)
{ value=0;
ReadMeterPara(0x10dd+i*6);
if(recover_item(0x8505+i)==1) //恢復(fù)參數(shù)正確
{ read_buff.lword=Longdate_from_xbcd(&wr_buff[0],4);
if(u32PMdatal!=read_buff.lword)
{ u32PMdatal= read_buff.lword;
value=1;
}
}
else //恢復(fù)參數(shù)失敗
{ if(u32PMdatal!=meterprm_table[8+i])
{ u32PMdatal=meterprm_table[8+i];
value=1;
}
}
if(value==1)
SetMeterCfg(0x10dd+i);
}
point=&PHCCtrl1;
for(i=0;i<2;i++) //角差值設(shè)定
{ if(recover_item(0x850e+i)==1)
{ if(*(point+i)!=wr_buff[0])
*(point+i)=wr_buff[0];
}
else //恢復(fù)參數(shù)失敗
{ if(*(point+i)!=meterprm_table[15+i])
*(point+i)=meterprm_table[15+i];
}
}
}
/**
* 回復(fù)校表參數(shù)
* @param void
* @return void
*/
void Recover_meter(void)
{
Recover_pd01(); //恢復(fù)門限
Recover_metprim(); //恢復(fù)比差等其他參數(shù)
}
/**
* 初始化IO口
* @param void
* @return void
*/
void port_init(void)
{
P0OE = DISABLE_PORT_OUTPUT_ALL;
P1OE = DISABLE_PORT_OUTPUT_ALL;
P2OE = DISABLE_PORT_OUTPUT_ALL;
P3OE = DISABLE_PORT_OUTPUT_ALL;
P4OE = DISABLE_PORT_OUTPUT_ALL;
P5OE = DISABLE_PORT_OUTPUT_ALL;
P6OE = DISABLE_PORT_OUTPUT_ALL;
P7OE = DISABLE_PORT_OUTPUT_ALL;
P8OE = DISABLE_PORT_OUTPUT_ALL;
P0IE = DISABLE_PORT_INPUT_ALL;
P1IE = DISABLE_PORT_INPUT_ALL;
P2IE = DISABLE_PORT_INPUT_ALL;
P3IE = DISABLE_PORT_INPUT_ALL;
P4IE = DISABLE_PORT_INPUT_ALL;
P5IE = DISABLE_PORT_INPUT_ALL;
P6IE = DISABLE_PORT_INPUT_ALL;
P7IE = DISABLE_PORT_INPUT_ALL;
P8IE = DISABLE_PORT_INPUT_ALL;
P2OE&=(~BIT5); //輸出使能
P2OD|=BIT5; //輸出高電平
}
void IO_Sleep()
{
P0OE = DISABLE_PORT_OUTPUT_ALL;
P1OE = DISABLE_PORT_OUTPUT_ALL;
P2OE = DISABLE_PORT_OUTPUT_ALL;
P3OE = DISABLE_PORT_OUTPUT_ALL;
P4OE = DISABLE_PORT_OUTPUT_ALL;
P5OE = DISABLE_PORT_OUTPUT_ALL;
P6OE = DISABLE_PORT_OUTPUT_ALL;
P7OE = DISABLE_PORT_OUTPUT_ALL;
P8OE = DISABLE_PORT_OUTPUT_ALL;
P0IE = DISABLE_PORT_INPUT_ALL;
P1IE = DISABLE_PORT_INPUT_ALL;
P2IE = DISABLE_PORT_INPUT_ALL;
P3IE = DISABLE_PORT_INPUT_ALL;
P4IE = DISABLE_PORT_INPUT_ALL;
P5IE = DISABLE_PORT_INPUT_ALL;
P6IE = DISABLE_PORT_INPUT_ALL;
P7IE = DISABLE_PORT_INPUT_ALL;
P8IE = DISABLE_PORT_INPUT_ALL;
}
/**
* 初始化TIMER0,10ms中斷一次
* @param void
* @return void
*/
void Init_Timer0(void)
{
TMOD = 0x01; // 工作在模式1
CKCON|=0x08; // clk
TL0 = 0xff; //10ms
TH0 = 0x7f;
TR0 = 1; // 開定時器0
SetInterrupt(1); //打開中斷
}
/**
* 初始化ADC,設(shè)定當(dāng)前的測量頻率
* @param void
* @return void
*/
void Inti_anlmode(void)
{
InitAnalog(); //初始化模擬模塊
SetADC(SETADC_IA,SETADC_CLOSE); //A通道電流關(guān)閉
SetADC(SETADC_IB,SETADC_IT16); //B通道電流,采用16倍增益
SetADC(SETADC_U,SETADC_IT1); //電壓通道,采用1倍增益
SetMChannel(SETM_TEMP,SETM_T1); //開m通道,1倍增益,測量溫度測量模式
Alt_50_60Hz(ALT_50HZ); //50hz
PowerDown=0;
}
/**
* 初始化計量系統(tǒng)
* @param void
* @return void
*/
void Inti_metermode(void)
{
SysCtrl&=0xef; //開啟計量電路時鐘
PMCtrl4=0x00;
PMCtrl1&=(~0xe0);
Inti_anlmode(); // AD增益
PMCtrl1=0x70; //選擇B通道劑量
InitMeter(); //初始化計量電路
u32PMdatal=0x01;
SetMeterCfg(0x10f5); //潛動門限1
SetMeterCfg(0x10fb);
Recover_meter(); //恢復(fù)校表參數(shù)
PMCtrl1=0x7b; //使能U,B,UM通路,選擇B路計量,使能角差校準
PMCtrl3=0x20; //一路有功計量,一路無功計量,開啟次諧波濾波
PMCtrl4=0x20; //??????
CFCtrl=0x00; //用正反有功產(chǎn)生CF1
CFNumber=0;
CF1Number=0;
ULowFlag=0;
CF1Flag=0;
CFFlag=0xd5;
count_opencftime=100; //CF延時1妙打開
F_PmIdle = 0;
pmIdleCnt = 0;
}
/**
* 系統(tǒng)初始化,初始化模擬部分和數(shù)字部分寄存器
* @param void
* @return void
*/
void Init_System(void)
{
port_init(); //初始化io口
SetXRam(1); //開啟對XRAM的寫保護
Init_Timer0();
Inti_metermode();
}
/**
* 復(fù)位計量模塊,當(dāng)檢測到計量有問題是會調(diào)用該函數(shù)
* @param void
* @return void
*/
void reset_primjiaobiao(void)
{
Inti_metermode(); //初始化計量模塊
}
/**
* 檢測CF脈沖是否有異常,通過將1s內(nèi)產(chǎn)生的CF脈沖個數(shù)與門限CF脈沖個數(shù)比較,決定是否需要復(fù)位計量模塊
* @param data_cf CF脈沖個數(shù)
* @return 0 脈沖個數(shù)異常
* data_cf 正常脈沖個數(shù)
*/
unsigned long check_jump(unsigned char data_cf)
{
unsigned long value;
if(data_cf>max_CF)
{
value=0; //停止能量計量
if(count_errenergmode<10)
{
count_errenergmode++;
reset_primjiaobiao(); //重新初始化計量模塊
}
}
else
{
count_errenergmode=0;
value=data_cf;
}
return value;
}
/**
* 讀取CF active energy 脈沖個數(shù),累加脈沖
* @param void
* @return void
*/
/*
void read_encount(void)
{
unsigned char temp_CF1,temp_CF2,temp_data;
unsigned int Temp_CFNumber;
temp_data=PMCtrl4;
temp_CF1=0;
ReadMeterPara(0x10f2);
buffer_energ[0]=u32PMdatal;
ReadMeterPara(0x10f3); //讀有功脈沖數(shù)
buffer_energ[2]=u32PMdatal;
if(buffer_energ[0]>buffer_energ[1]) //如果脈沖數(shù)有增加
{ temp_CF1=buffer_energ[0]-buffer_energ[1]; //計算增加的脈沖數(shù)
temp_CF1=check_jump(temp_CF1); //防飛走
}
if(buffer_energ[2]>buffer_energ[3])
{
temp_CF2=buffer_energ[2]-buffer_energ[3];
// temp_CF2=check_jump(temp_CF2); //防飛走
}
if(CFFlag==0x55)
{
if((temp_CF1!=0)||(temp_CF2!=0))
{
sumCF_Z=sumCF_Z+temp_CF1+temp_CF2; //能量脈沖累加
}
}
if(CFFlag==0xd5)
{
if((temp_CF1==1)||(temp_CF2==1))
{
sumCF_Z=sumCF_Z+temp_CF1+temp_CF2+1;
CFFlag=0x55;
}
}
buffer_energ[1]=buffer_energ[0];
buffer_energ[3]=buffer_energ[2];
ReadMeterPara(0x10f2);
Temp_CFNumber=u32PMdatal;
if(Temp_CFNumber>0xf000)
{
buffer_energ[1]=0;
u32PMdatal=0;
SetMeterCfg(0x10f2);
}
ReadMeterPara(0x10f3);
Temp_CFNumber=u32PMdatal;
if(Temp_CFNumber>0xf000)
{
buffer_energ[3]=0;
u32PMdatal=0;
SetMeterCfg(0x10f3);
}
}
*/
/**
* 恢復(fù)電量整數(shù)部分,3字節(jié)
* @param rec_id 電量整數(shù)部分的ID
* @return void
*/
void Recover_int(unsigned int rec_id)
{
check_engint(rec_id);
}
/**
* 恢復(fù)電量小數(shù)部分,在存放小數(shù)的時候,每走1萬度存放的位置向后移動一個字節(jié)
* @param void
* @return void
*/
void Recover_dot(unsigned int dotaddress,unsigned int ID)
{
unsigned int temp_addr;
addr_baseonIDandtype(RAM,ID);
temp_addr=(*ID_coretalbpoint[0]).dataaddr;
temp_addr=(ram[temp_addr]&0x0f);
data_addr.lword=dotaddress+temp_addr;
Read_data(EEPROM,1);
if(checkone_bcd(wr_buff[0])==0)
{
Read_data(EEPROM,1);
if(checkone_bcd(wr_buff[0])==0)
wr_buff[0]=0;
}
addr_baseonIDandtype(RAM,ID);
data_addr.word[1]=(*ID_coretalbpoint[0]).dataaddr+3;
Write_data(RAM,1);
}
//=========================================================
//函數(shù)功能:恢復(fù)電量數(shù)據(jù)
//=========================================================
void Recover_eng(void)
{
Recover_int(ID_POSENGSUM); //恢復(fù)組合電量整數(shù)部分
Recover_dot(EEP_Save_engdot,ID_POSENGSUM); //恢復(fù)組合電量小數(shù)部分
Recover_int(0x0200); //正向
Recover_dot(EEP_Save_engdotZ,0x0200);
Recover_int(0x0300); //反向
Recover_dot(EEP_Save_engdotF,0x0300);
}
/**
* 恢復(fù)電能表的參數(shù),如果讀取外部存儲器失敗,將默認的參數(shù)寫入存儲器
* @param void
* @return void
*/
void Recover_prim(void)
{
unsigned char i,len;
wr_buff[0]=0;
wr_buff[1]=0x12; //默認為1200
wr_buff[2]=0;
addr_baseonIDandtype(RAM,ID_CHANGSHU);
data_addr.word[1]=(*ID_coretalbpoint[0]).dataaddr;
Write_data(RAM,(*ID_coretalbpoint[0]).datalong);
if(recover_item(ID_BANTRATA)==0) //如果恢復(fù)波特率出錯
{
wr_buff[0]=0x08; //默認參數(shù)2400
}
addr_baseonIDandtype(RAM,ID_BANTRATA);
data_addr.word[1]=(*ID_coretalbpoint[0]).dataaddr;
Write_data(RAM,(*ID_coretalbpoint[0]).datalong);
if(recover_item(ID_COMADDR)==0) //恢復(fù)表地址錯誤
{
for(i=0;i<6;i++)
wr_buff[i]=0x11;
}
addr_baseonIDandtype(RAM,ID_COMADDR);
data_addr.word[1]=(*ID_coretalbpoint[0]).dataaddr;
len=(*ID_coretalbpoint[0]).datalong;
Write_data(RAM,len);
if(recover_item(0x8400)==0) //恢復(fù)表號錯誤0000001
{ for(i=0;i<5;i++)
wr_buff[i]=0;
wr_buff[5]=0x01;
}
addr_baseonIDandtype(RAM,0x8400);
data_addr.word[1]=(*ID_coretalbpoint[0]).dataaddr;
len=(*ID_coretalbpoint[0]).datalong;
Write_data(RAM,len);
}
/**
* 恢復(fù)CF脈沖余量
* @param void
* @return void
*/
void Recover_tindiandata(void)
{
data_addr.word[1]=EEP_Save_cf; //CF 恢復(fù)
Read_data(EEPROM,2);
if(wr_buff[1]==(wr_buff[0]+0x33))
{ if(wr_buff[0]>128)
wr_buff[0]=0;
}
else
wr_buff[0]=0;
sumCF=wr_buff[0];
}
/*
void RTCIOOff()
{
CfgPort(4,0);
P1ID&=~(BIT0);
P1OE|=BIT0;
P1IE&=~(BIT0);
}
*/
//==================================================
//函數(shù)功能:恢復(fù)數(shù)據(jù)
//備注:
//===================================================
void Recover_data(void)
{
Recover_eng(); //恢復(fù)電量
Recover_tindiandata(); //恢復(fù)停電時保存的數(shù)據(jù)
Recover_prim(); //恢復(fù)參數(shù)
}
/**
* 檢測當(dāng)前的供電模式
* @param void
* @return 1 市電供電
* 0 電池供電
*/
unsigned char check_powertype(void)
{
unsigned char value;
if((Systate&0x01)==0x01)
value=1; //正常供電
else
{
if((Systate&0x01)==0x01)
value=1;
else
value=0;
}
return value;
}
/**
* 初始化系統(tǒng)各個模塊
* @param void
* @return void
*/
void Init_modul(void)
{
Init_disp(); //初始化顯示模塊
init_RTCmode(); //初始化RTC模塊
int_energeadd(); //初始化能量計量模塊
Init_checkmode(); //初始化check模塊
init_485comm(); //初始化485模塊
InitInfrComm(); //初始化紅外模塊
Initcommu(); //初始化通訊驅(qū)動
Init_Mchannel(); //初始化M通道
SysInitAutoCal(); //初始化自動校
}
/**
* 初始化停電模塊
* @param void
* @return void
*/
void ini_sleepmode(void)
{ CfgInterrupt(0); //關(guān)所有中斷
EA=0; //關(guān)總中斷
// time_jihuo=0;
// time_lostiv=0;
// CfgPort(4,0); //秒脈沖輸出打開
port_init(); //禁止IO口輸入輸出
}
/**
* 停電初始化
* @param void
* @return void
*/
//void Init_jihuo(void)
//{
// Init_disp(); //初始化顯示模塊
// sta_meterrun=5; //激活模式
// time_jihuo=0;
//}
/**
* 停電保存各類數(shù)據(jù),備注:包括:電量小數(shù),CF脈沖位數(shù),當(dāng)月平均功率因數(shù)、停電時間
* @param void
* @return void
*/
void savedata_tingdian(void)
{
//======================================================================CF
wr_buff[0]=sumCF;
wr_buff[1]=wr_buff[0]+0x33;
data_addr.word[1]=EEP_Save_cf;
Write_data(EEPROM,2);
}
/**
* 開啟CF脈沖輸出
* @param void
* @return void
*/
void Open_CF(void)
{
unsigned char i;
if(count_opencftime==0)
{ i=PMCtrl4;
if((i&0x18)!=0x18) //如果cf沒有開
{
i=PMCtrl4;
if((i&0x18)!=0x18)
{ i|=0x18; //開CF
PMCtrl4=i;
SetInterrupt(14); //開CF1中斷
}
}
}
if(ULowFlag==0)
{ if(CFNumber>=1)
{ ULowFlag=1;
Recover_pd(); //第一個脈沖之后,恢復(fù)正常門限值
}
}
}
//計量防潛動 判斷
void pm_Idle(void)
{
unsigned int temp_int;
unsigned long xdata temp;
//if((PMCtrl4&0x18)==0)
// return;
//--------------------------獲取脈沖常數(shù)
addr_baseonIDandtype(RAM,ID_CHANGSHU); //獲取脈沖常數(shù)指針
data_addr.word[1]=(*ID_coretalbpoint[0]).dataaddr;
Read_data((*ID_coretalbpoint[0]).stortype,(*ID_coretalbpoint[0]).datalong);
temp_int=value_hex_from_2bcd(&wr_buff[1]);
if((temp_int>12800)||(temp_int<200)) //脈沖常數(shù)是否異常
temp_int=1200;
///計算0.4%IB啟動電流時的功率
temp=meterprm_table[1];
temp >>= 11;
temp |= (meterprm_table[0]<<21);
temp *= type_Ib;
temp /= 2250;
temp *= temp_int;
temp *= type_volit; //220V x 10A /100
temp /= 312500;
ReadMeterPara(DATAP);
if(u32PMdatal&0x80000000)
u32PMdatal = (~u32PMdatal) +1;
if(u32PMdatal>=((temp*6)/10) ) //加啟動電流時的功率的 60%
{
if(F_PmIdle)
{
if(pmIdleCnt<5)
pmIdleCnt++;
else
{
F_PmIdle = 0;
pmIdleCnt = 0;
PMCtrl4 &= ~BIT5; //關(guān)閉防潛功能, 復(fù)位防潛能量桶
PMCtrl4 |= BIT5; //開啟防潛,重新進行防潛計算
}
}
else
pmIdleCnt = 0;
}
else if(u32PMdatal<= ((temp*3)/10) ) //加啟動電流時的功率的 30%
{
if(!F_PmIdle)
{
if(pmIdleCnt<5)
pmIdleCnt++;
else
{
F_PmIdle = 1;
pmIdleCnt = 0;
}
}
else
pmIdleCnt = 0;
}
}
/**
* 流程描述
*
* 主程序根據(jù)系統(tǒng)狀態(tài)寄存器的狀態(tài)來判斷當(dāng)前是執(zhí)行哪類操作
* RTC 喚醒 (BIT2) 快速休眠(注意快速休眠必須配合PLL快速流程,不然無法休眠)
* 看門狗復(fù)位(BIT4) 恢復(fù)系統(tǒng)狀態(tài)
* IO口復(fù)位(BIT3) 更新顯示
* 正常上電(BIT0) 正常上電流程
*/
void main(void)
{ uint8 dispflashtime,waketime;
jumpsta:
F0=1;
CLKFRQ=1;
SPCFNC=0x01;
XBYTE [0x8002] = 0x86;
SPCFNC=0x00;
SetMeterFunc(0); //關(guān)CF輸出
if(Systate & BIT2) // rtc reset
{ CtrlMEAS = 0x80; //關(guān)LDO33
if(sta_meterrun==run_sleepdisp) //程序在停電顯示模式
{ waketime=0;
dispflashtime++;
if(dispflashtime==5)
{ Disp_close();
}
else if(dispflashtime==10)
{ if(BatteryInfo==1)
Disp_err1(); //顯示err1
else
Disp_oninsleep(); //顯示電量
}
else if(dispflashtime==15)
{ Disp_close();
}
else if(dispflashtime>19)
{ dispflashtime=0;
Disp_oninsleep(); //顯示電量
}
if(save_lastday!=RTCHC)
{ save_lastday=RTCHC;
times_cutpower++;
if(times_cutpower>TIMDISOCUTP) //顯示7天,超過7點則進入休眠模式
{ times_cutpower=0;
CloseLCD();
sta_meterrun=run_sleep; //進入睡眠模式
waketime=3; //一天喚醒一次
}
}
}
else
waketime=3;
CfgRTC(0,waketime); //32768,定時喚醒
if(check_powertype()==1)
{ ClearWDT();
goto jumprun;
}
Sleep();
if(check_powertype()==1)
{ ClearWDT();
goto jumprun;
}
}
#ifdef DEBUG
#else
else if(Systate & BIT4)
{ SetPLL(SETPLL_3_2M); //開啟pll
Init_System();
Recover_data(); //恢復(fù)數(shù)據(jù) re
Init_modul();
EA = 1; //開總中斷
ClearWDT();
}
#endif
else if(Systate & BIT3) // io reset
{if(check_powertype()==1)
{ ClearWDT();
goto jumprun;
}
Sleep();
}
else // 正常上電復(fù)位
{
jumprun:
SetPLL(SETPLL_3_2M); //開啟pll
Init_System();
Recover_data(); //恢復(fù)數(shù)據(jù)
Init_modul();
EA = 1; //開總中斷
ClearWDT();
}
/**
* 正常運行部分,該部分中,系統(tǒng)反復(fù)執(zhí)行以下流程
* RTC時鐘刷新模塊
* 計量模塊CF打開
*
*/
run_zhengchang:
while(check_powertype()==1) //市電供電
{
PowerDown=0;
ClearWDT(); //喂狗
if(check_powertype()==0)
break;
Rtc_refreshmode(); //時鐘刷新
if(check_powertype()==0)
break;
commu_mode(); //通訊模塊
if(check_powertype()==0)
break;
Open_CF();
if(check_powertype()==0)
break;
display_mode(); //顯示模塊
if(check_powertype()==0)
break;
energ_addmode(); //能量計量模塊
if(check_powertype()==0)
break;
check_mode(); //自檢模塊
if(check_powertype()==0)
break;
Mchannelmode(); //M通道測量
}
//==============================================================================================停電處理部分
if(check_powertype()== 0) //電池供電
{ while(1)
{ if(check_powertype()==1)
{ ClearWDT();
PowerDown=0;
goto run_zhengchang;
}
else
{ PowerDown++;
delay_1ms();
ClearWDT();
if(PowerDown>3)
goto xiumian;
}
}
xiumian:
savedata_tingdian(); //停電保存數(shù)據(jù)
ClearWDT();
CfgRTC(0,0); //32768,1秒喚醒
ini_sleepmode(); //初始化停電模式
IO_Sleep();
times_cutpower=0; //停電計時器
dispflashtime=0; //閃爍時間
Ini_sleepdisp();
if(check_powertype()==1)
{ ClearWDT();
goto jumpsta;
}
sta_meterrun=run_sleepdisp; //程序進入停電顯示模式
Sleep();
}
else
goto run_zhengchang;
}
//=========================================================================================停電激活
#undef AUTOCAL
#undef MAIN
復(fù)制代碼
作者:
從頭再來1
時間:
2016-4-3 10:40
你好,能夠把源碼發(fā)給我學(xué)習(xí)一下,可以嗎?謝謝。!
作者:
admin
時間:
2016-4-3 13:08
賣源碼,請到供求信息發(fā)布去
作者:
小小號
時間:
2017-7-1 10:51
樓主,有沒有更詳細的電能表設(shè)計方案
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1