找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4357|回复: 3
打印 上一主题 下一主题
收起左侧

单片机单相电能表源码

[复制链接]
跳转到指定楼层
楼主
单相飞控智能电表源码,单相多功能电能表源码。电能计量,485通讯,总线通讯,液晶显示等功能

全部源码下载: 单相多功能电能表源码.rar (80.05 KB, 下载次数: 44)

主程序预览:
  1. ///
  2. ///      @file  main.c
  3. ///     系统主程序
  4. ///
  5. ///
  6. ///=====================================================================================
  7. ///

  8. #define        MAIN
  9. #define AUTOCAL

  10. #include "Liger.h"
  11. #include "typemeter.h"

  12. /**
  13. * 系统默认校表参数
  14. *
  15. * Detailed description starts here.
  16. * 该表记录的电能表的默认校准参数,但系统发生恢复参数失败或是第一次上电等
  17. * 情况时,会从该表中恢复参数
  18. */

  19. unsigned long code meterprm_table[]=
  20. {  0x00000000,                                 //有功门限高1
  21.     0x5A55D125,                                 //有功门限低1
  22.     0x00000000,                                 //有功门限高2
  23.     0xA3E30760,                                 //有功门限低2
  24.     0x0000001a,                                 //有效值门限高1
  25.     0x67F16719,                                 //有效值门限低1
  26.     0x0018F380,                                 //启动门限1
  27.     0x0018F380,                                 //启动门限2
  28.     0x022EA846,                                 //有功功率比差1
  29.     0x022EA846,                                 //有功功率比差2
  30.     0xFE75A15D,                                 //U比差
  31.     0x10000000,                                 //I1比差
  32.     0x10000000,                                 //I2比差
  33.     0x00000000,                                 //补偿1
  34.     0x00000000,                                 //补偿2
  35.     0x05,                                         //A通道角差校正
  36.     0x05,                                         //B通道角差校正
  37.     0x00000000,                                                  //有功启动门限高位
  38.     0xB4ABA24A,                                   //有功启动门限低位
  39.     0x00000001,                                   //无功启动门限高位
  40.     0x47C60EC0                                    //无功启动门限低位
  41. };


  42. /**
  43. *  根据所给的ID号从外部存储器中恢复数据项,恢复的数据会放在wr_buff中
  44. * @param  chk_id 数据项ID
  45. * @return 1 成功
  46. *         0 失败
  47. //limin   修改 返回值恒定为0
  48. */
  49. unsigned char recover_item(unsigned int chk_id)
  50. {
  51.         unsigned char i,j,num,value,datanum;
  52.           value=0;
  53.           num=addr_from_coreID(1,chk_id);
  54.           for(i=0;i<num;i++)
  55.              { if((*ID_coretalbpoint[i]).stortype==EEPROM)
  56.               { data_addr.word[1]=(*ID_coretalbpoint[i]).dataaddr;
  57.                     datanum=(*ID_coretalbpoint[i]).datalong;
  58.                     Read_data(EEPROM,datanum);
  59.                         wr_buff[datanum]=0;
  60.                         for(j=0;j<datanum-1;j++)                            //校验和判断
  61.                            { wr_buff[datanum]+=wr_buff[j];
  62.                            }
  63.             if(wr_buff[datanum]==(wr_buff[datanum-1]-0x33))            //如果校验和正确
  64.                         {
  65.                                 if((*ID_coretalbpoint[i]).datatype==BCD)
  66.                                 {
  67.                                         if(check_X_bcd((datanum-1),wr_buff)==1)         //BCD嘛校验
  68.                                         {
  69.                                                 value=1;                                  //检测到合法数据,放在wr_buff中
  70.                                                 break;
  71.                                         }
  72.                                 }
  73.                                      else
  74.                                 {
  75.                                         value=1;                                  //检测到合法数据,放在wr_buff中
  76.                                         break;
  77.                                 }
  78.                         }
  79.                 }
  80.         }

  81.         return value;
  82. }

  83. //===================================================================================
  84. //函数功能:恢复第一个脉冲的门限
  85. //
  86. //=====================================================================================
  87. void Recover_pd01(void)
  88. {         unsigned char i,value;
  89.           Word32 read_buff;
  90.     //40 bit
  91.           for(i=0;i<2;i++)                                                      //门限值恢复
  92.              {
  93.                      if(recover_item(0x8500+i)==1)                                 //恢复参数正确
  94.                    { read_buff.lword=Longdate_from_xbcd(&wr_buff[1],4);
  95.                  u8PMdatah=wr_buff[0];
  96.                  u32PMdatal= read_buff.lword;
  97.                  u8PMdatah=u8PMdatah<<1;
  98.                                  if((u32PMdatal&0x80000000)==0x80000000)
  99.                                     u8PMdatah|=0x01;
  100.                  u32PMdatal=u32PMdatal<<1;
  101.                  SetMeterCfg(0x10f4+i*6);
  102.                }
  103.                        else                                                          //恢复参数失败
  104.                       { u8PMdatah=(uint8)meterprm_table[2*i];
  105.                  u32PMdatal=meterprm_table[1+2*i];
  106.                                  u8PMdatah=u8PMdatah<<1;
  107.                                  if((u32PMdatal&0x80000000)==0x80000000)
  108.                                     u8PMdatah|=0x01;
  109.                  u32PMdatal=u32PMdatal<<1;
  110.                      SetMeterCfg(0x10f4+i*6);
  111.                
  112.                        }
  113.             }

  114.         for(i=0;i<2;i++)
  115.           {value=0;
  116.                    ReadMeterPara(0x10f5+i*6);
  117.                    if(recover_item(0x8503+i)==1)                                   //防潜门限值设定
  118.                  { read_buff.lword=Longdate_from_xbcd(&wr_buff[0],4);
  119.                            if(u32PMdatal!= read_buff.lword)
  120.                  { u32PMdatal= read_buff.lword;
  121.                                    value=1;
  122.                                  }
  123.              }
  124.                       else                                                                 //恢复参数失败
  125.                     { if(u32PMdatal!=meterprm_table[6+i])
  126.                              { u32PMdatal=meterprm_table[6+i];
  127.                                    value=1;
  128.                                  }
  129.                  }
  130.                    if(value==1)
  131.                    {
  132.                      u32PMdatal <<= 1;
  133.                      SetMeterCfg(0x10f5+i*6);
  134.                        }
  135.             }
  136. }

  137. //===================================================================
  138. //函数功能:恢复第一个CF之后的门限值
  139. //===================================================================
  140. void Recover_pd(void)
  141. { unsigned char i,value;
  142.   Word32 read_buff;
  143.   for(i=0;i<2;i++)                                                  //门限值恢复
  144.      { value=0;
  145.            ReadMeterPara(0x10f4+i*6);
  146.            if(recover_item(0x8500+i)==1)                                 //恢复参数正确
  147.            { read_buff.lword=Longdate_from_xbcd(&wr_buff[1],4);
  148.              if(u8PMdatah!=wr_buff[0])
  149.                 { u8PMdatah=wr_buff[0];
  150.                   value=1;
  151.                 }   
  152.              if(u32PMdatal!=read_buff.lword)
  153.                 { u32PMdatal= read_buff.lword;
  154.                   value=1;
  155.                 }
  156.             }
  157.        else                                                          //恢复参数失败
  158.            { if(u8PMdatah!=(uint8)meterprm_table[2*i])
  159.                         { u8PMdatah=(uint8)meterprm_table[2*i];
  160.                                   value=1;
  161.                                  }
  162.                          if(u32PMdatal!=meterprm_table[1+2*i])
  163.                  { u32PMdatal=meterprm_table[1+2*i];
  164.                                    value=1;
  165.                                  }
  166.                }
  167.            if(value==1)
  168.             SetMeterCfg(0x10f4+i*6);
  169.      }

  170.          for(i=0;i<2;i++)
  171.      {     value=0;
  172.                    ReadMeterPara(0x10f5+i*6);
  173.                    if(recover_item(0x8503+i)==1)                                   //防潜门限值设定
  174.                  { read_buff.lword=Longdate_from_xbcd(&wr_buff[0],4);
  175.                            if(u32PMdatal!= read_buff.lword)
  176.                  { u32PMdatal= read_buff.lword;
  177.                                    value=1;
  178.                                  }
  179.              }
  180.                       else                                                                 //恢复参数失败
  181.                     { if(u32PMdatal!=meterprm_table[6+i])
  182.                              { u32PMdatal=meterprm_table[6+i];
  183.                                    value=1;
  184.                                  }
  185.                  }
  186.                    if(value==1)
  187.                    {
  188.                      SetMeterCfg(0x10f5+i*6);
  189.                         }
  190.      }

  191. }
  192. //===============================================================================
  193. //函数功能:恢复除门限值之外的参数
  194. //================================================================================
  195. void Recover_metprim(void)
  196. {         uint8 i,value;
  197.         unsigned char xdata *point;
  198.           Word32 read_buff;
  199.     for(i=0;i<7;i++)                                                      //参数恢复
  200.         { value=0;
  201.               ReadMeterPara(0x10dd+i*6);   
  202.                   if(recover_item(0x8505+i)==1)                                   //恢复参数正确
  203.                 { read_buff.lword=Longdate_from_xbcd(&wr_buff[0],4);
  204.               if(u32PMdatal!=read_buff.lword)
  205.                              { u32PMdatal= read_buff.lword;
  206.                                    value=1;
  207.                                  }
  208.             }
  209.                      else                                                             //恢复参数失败
  210.                    { if(u32PMdatal!=meterprm_table[8+i])
  211.                          { u32PMdatal=meterprm_table[8+i];
  212.                    value=1;
  213.                                  }
  214.                  }
  215.                   if(value==1)
  216.              SetMeterCfg(0x10dd+i);
  217.           }
  218.         point=&PHCCtrl1;
  219.     for(i=0;i<2;i++)                                                        //角差值设定
  220.           { if(recover_item(0x850e+i)==1)                                   
  221.                  { if(*(point+i)!=wr_buff[0])
  222.                               *(point+i)=wr_buff[0];
  223.              }
  224.                       else                                                                 //恢复参数失败
  225.                     { if(*(point+i)!=meterprm_table[15+i])
  226.                               *(point+i)=meterprm_table[15+i];
  227.                      }
  228.           }
  229. }
  230. /**
  231. *  回复校表参数
  232. * @param  void
  233. * @return void
  234. */
  235. void Recover_meter(void)
  236. {
  237.    Recover_pd01();                //恢复门限
  238.    Recover_metprim();             //恢复比差等其他参数
  239. }



  240. /**
  241. *  初始化IO口
  242. * @param  void
  243. * @return void
  244. */
  245. void port_init(void)
  246. {

  247.         P0OE = DISABLE_PORT_OUTPUT_ALL;
  248.         P1OE = DISABLE_PORT_OUTPUT_ALL;
  249.         P2OE = DISABLE_PORT_OUTPUT_ALL;
  250.         P3OE = DISABLE_PORT_OUTPUT_ALL;
  251.         P4OE = DISABLE_PORT_OUTPUT_ALL;
  252.         P5OE = DISABLE_PORT_OUTPUT_ALL;
  253.         P6OE = DISABLE_PORT_OUTPUT_ALL;
  254.         P7OE = DISABLE_PORT_OUTPUT_ALL;
  255.         P8OE = DISABLE_PORT_OUTPUT_ALL;
  256.        
  257.         P0IE = DISABLE_PORT_INPUT_ALL;
  258.         P1IE = DISABLE_PORT_INPUT_ALL;
  259.         P2IE = DISABLE_PORT_INPUT_ALL;
  260.         P3IE = DISABLE_PORT_INPUT_ALL;
  261.         P4IE = DISABLE_PORT_INPUT_ALL;
  262.         P5IE = DISABLE_PORT_INPUT_ALL;
  263.         P6IE = DISABLE_PORT_INPUT_ALL;
  264.         P7IE = DISABLE_PORT_INPUT_ALL;
  265.         P8IE = DISABLE_PORT_INPUT_ALL;
  266.     P2OE&=(~BIT5);                                  //输出使能
  267.         P2OD|=BIT5;                                     //输出高电平
  268. }

  269. void IO_Sleep()
  270. {
  271.     P0OE = DISABLE_PORT_OUTPUT_ALL;
  272.         P1OE = DISABLE_PORT_OUTPUT_ALL;
  273.         P2OE = DISABLE_PORT_OUTPUT_ALL;
  274.         P3OE = DISABLE_PORT_OUTPUT_ALL;
  275.         P4OE = DISABLE_PORT_OUTPUT_ALL;
  276.         P5OE = DISABLE_PORT_OUTPUT_ALL;
  277.         P6OE = DISABLE_PORT_OUTPUT_ALL;
  278.         P7OE = DISABLE_PORT_OUTPUT_ALL;
  279.         P8OE = DISABLE_PORT_OUTPUT_ALL;
  280.        
  281.         P0IE = DISABLE_PORT_INPUT_ALL;
  282.         P1IE = DISABLE_PORT_INPUT_ALL;
  283.         P2IE = DISABLE_PORT_INPUT_ALL;
  284.         P3IE = DISABLE_PORT_INPUT_ALL;
  285.         P4IE = DISABLE_PORT_INPUT_ALL;
  286.         P5IE = DISABLE_PORT_INPUT_ALL;
  287.         P6IE = DISABLE_PORT_INPUT_ALL;
  288.         P7IE = DISABLE_PORT_INPUT_ALL;
  289.         P8IE = DISABLE_PORT_INPUT_ALL;

  290. }
  291. /**
  292. *  初始化TIMER0,10ms中断一次
  293. * @param  void
  294. * @return void
  295. */

  296. void Init_Timer0(void)
  297. {       
  298.         TMOD = 0x01;             // 工作在模式1
  299.         CKCON|=0x08;         // clk
  300.     TL0  = 0xff;         //10ms
  301.            TH0  = 0x7f;
  302.            TR0 = 1;                     // 开定时器0
  303.         SetInterrupt(1);     //打开中断
  304.    
  305. }


  306. /**
  307. *  初始化ADC,设定当前的测量频率
  308. * @param  void
  309. * @return void
  310. */
  311. void Inti_anlmode(void)
  312. {  
  313.         InitAnalog();                          //初始化模拟模块
  314.           SetADC(SETADC_IA,SETADC_CLOSE);                    //A通道电流关闭
  315.            SetADC(SETADC_IB,SETADC_IT16);                         //B通道电流,采用16倍增益
  316.            SetADC(SETADC_U,SETADC_IT1);                //电压通道,采用1倍增益
  317.            SetMChannel(SETM_TEMP,SETM_T1);      //开m通道,1倍增益,测量温度测量模式
  318.            Alt_50_60Hz(ALT_50HZ);                //50hz         
  319.            PowerDown=0;
  320. }


  321. /**
  322. *  初始化计量系统
  323. * @param  void
  324. * @return void
  325. */
  326. void Inti_metermode(void)
  327. {
  328.     SysCtrl&=0xef;                //开启计量电路时钟
  329.     PMCtrl4=0x00;
  330.         PMCtrl1&=(~0xe0);
  331.            Inti_anlmode();                // AD增益
  332.            PMCtrl1=0x70;                  //选择B通道剂量
  333.     InitMeter();                   //初始化计量电路
  334.     u32PMdatal=0x01;
  335.     SetMeterCfg(0x10f5);           //潜动门限1
  336.     SetMeterCfg(0x10fb);
  337.            Recover_meter();               //恢复校表参数
  338.     PMCtrl1=0x7b;                                        //使能U,B,UM通路,选择B路计量,使能角差校准
  339.     PMCtrl3=0x20;                                        //一路有功计量,一路无功计量,开启次谐波滤波
  340.         PMCtrl4=0x20;                                        //??????
  341.     CFCtrl=0x00;                                        //用正反有功产生CF1
  342.     CFNumber=0;
  343.     CF1Number=0;
  344.     ULowFlag=0;
  345.         CF1Flag=0;
  346.     CFFlag=0xd5;
  347.            count_opencftime=100;            //CF延时1妙打开
  348.            F_PmIdle = 0;
  349.         pmIdleCnt = 0;
  350. }


  351. /**
  352. *  系统初始化,初始化模拟部分和数字部分寄存器
  353. * @param   void
  354. * @return void
  355. */
  356. void Init_System(void)
  357. {  
  358.            port_init();                //初始化io口
  359.            SetXRam(1);                 //开启对XRAM的写保护
  360.            Init_Timer0();
  361.            Inti_metermode();
  362.    
  363. }


  364. /**
  365. *  复位计量模块,当检测到计量有问题是会调用该函数
  366. * @param  void
  367. * @return void
  368. */
  369. void reset_primjiaobiao(void)
  370. {
  371.           Inti_metermode();                              //初始化计量模块

  372. }


  373. /**
  374. *  检测CF脉冲是否有异常,通过将1s内产生的CF脉冲个数与门限CF脉冲个数比较,决定是否需要复位计量模块
  375. * @param  data_cf  CF脉冲个数
  376. * @return 0   脉冲个数异常
  377. *          data_cf 正常脉冲个数
  378. */
  379. unsigned long check_jump(unsigned char data_cf)
  380. {
  381.         unsigned long value;
  382.         if(data_cf>max_CF)
  383.       {
  384.                       value=0;                                            //停止能量计量
  385.                     if(count_errenergmode<10)
  386.                 {
  387.                         count_errenergmode++;
  388.                          reset_primjiaobiao();                          //重新初始化计量模块
  389.                }
  390.         }
  391.         else
  392.       {
  393.                       count_errenergmode=0;
  394.                     value=data_cf;
  395.         }
  396.        
  397.         return value;
  398. }


  399. /**
  400. *  读取CF active energy 脉冲个数,累加脉冲
  401. * @param  void
  402. * @return void
  403. */
  404. /*
  405. void read_encount(void)
  406. {
  407.         unsigned char temp_CF1,temp_CF2,temp_data;
  408.         unsigned int Temp_CFNumber;
  409.           temp_data=PMCtrl4;
  410.         temp_CF1=0;
  411.       
  412.     ReadMeterPara(0x10f2);
  413.     buffer_energ[0]=u32PMdatal;
  414.     ReadMeterPara(0x10f3);    //读有功脉冲数
  415.     buffer_energ[2]=u32PMdatal;
  416.           if(buffer_energ[0]>buffer_energ[1])                    //如果脉冲数有增加
  417.             { temp_CF1=buffer_energ[0]-buffer_energ[1];           //计算增加的脉冲数
  418.               temp_CF1=check_jump(temp_CF1);                       //防飞走
  419.               }
  420.         if(buffer_energ[2]>buffer_energ[3])
  421.         {
  422.                   temp_CF2=buffer_energ[2]-buffer_energ[3];  
  423.                  // temp_CF2=check_jump(temp_CF2);                       //防飞走
  424.         }
  425.         if(CFFlag==0x55)
  426.         {
  427.         if((temp_CF1!=0)||(temp_CF2!=0))
  428.                 {
  429.                      
  430.                   sumCF_Z=sumCF_Z+temp_CF1+temp_CF2;                           //能量脉冲累加  
  431.                  
  432.                 }
  433.         }
  434.         if(CFFlag==0xd5)
  435.                 {
  436.         if((temp_CF1==1)||(temp_CF2==1))
  437.           {
  438.            sumCF_Z=sumCF_Z+temp_CF1+temp_CF2+1;
  439.            CFFlag=0x55;
  440.           }
  441.             }
  442.          
  443.                        
  444.           
  445.            

  446.        
  447.           buffer_energ[1]=buffer_energ[0];   
  448.         buffer_energ[3]=buffer_energ[2];
  449.          ReadMeterPara(0x10f2);
  450.                  Temp_CFNumber=u32PMdatal;
  451.          if(Temp_CFNumber>0xf000)
  452.             {
  453.              buffer_energ[1]=0;
  454.              u32PMdatal=0;
  455.              SetMeterCfg(0x10f2);
  456.             }
  457.        ReadMeterPara(0x10f3);
  458.              Temp_CFNumber=u32PMdatal;
  459.             if(Temp_CFNumber>0xf000)
  460.             {
  461.             buffer_energ[3]=0;
  462.              u32PMdatal=0;
  463.              SetMeterCfg(0x10f3);
  464.             }
  465. }

  466. */


  467. /**
  468. *  恢复电量整数部分,3字节
  469. * @param  rec_id  电量整数部分的ID
  470. * @return  void
  471. */
  472. void Recover_int(unsigned int rec_id)
  473. {
  474.         check_engint(rec_id);
  475. }

  476. /**
  477. *  恢复电量小数部分,在存放小数的时候,每走1万度存放的位置向后移动一个字节
  478. * @param  void
  479. * @return void
  480. */
  481. void Recover_dot(unsigned int dotaddress,unsigned int ID)
  482. {  
  483.         unsigned int temp_addr;
  484.         addr_baseonIDandtype(RAM,ID);
  485.     temp_addr=(*ID_coretalbpoint[0]).dataaddr;
  486.            temp_addr=(ram[temp_addr]&0x0f);
  487.            data_addr.lword=dotaddress+temp_addr;
  488.            Read_data(EEPROM,1);
  489.            if(checkone_bcd(wr_buff[0])==0)
  490.            {
  491.                    Read_data(EEPROM,1);
  492.                 if(checkone_bcd(wr_buff[0])==0)
  493.                         wr_buff[0]=0;
  494.            }
  495.                      
  496.            addr_baseonIDandtype(RAM,ID);
  497.            data_addr.word[1]=(*ID_coretalbpoint[0]).dataaddr+3;
  498.            Write_data(RAM,1);
  499. }

  500. //=========================================================
  501. //函数功能:恢复电量数据
  502. //=========================================================
  503. void Recover_eng(void)
  504. {
  505.         Recover_int(ID_POSENGSUM);                           //恢复组合电量整数部分
  506.         Recover_dot(EEP_Save_engdot,ID_POSENGSUM);           //恢复组合电量小数部分
  507.        
  508.         Recover_int(0x0200);                                                                //正向
  509.         Recover_dot(EEP_Save_engdotZ,0x0200);

  510.         Recover_int(0x0300);                                                                //反向
  511.         Recover_dot(EEP_Save_engdotF,0x0300);
  512. }



  513. /**
  514. *  恢复电能表的参数,如果读取外部存储器失败,将默认的参数写入存储器
  515. * @param  void
  516. * @return void
  517. */
  518. void Recover_prim(void)
  519. {
  520.         unsigned char i,len;

  521.     wr_buff[0]=0;
  522.         wr_buff[1]=0x12;                                           //默认为1200
  523.         wr_buff[2]=0;
  524.         addr_baseonIDandtype(RAM,ID_CHANGSHU);
  525.         data_addr.word[1]=(*ID_coretalbpoint[0]).dataaddr;
  526.         Write_data(RAM,(*ID_coretalbpoint[0]).datalong);

  527.         if(recover_item(ID_BANTRATA)==0)                                   //如果恢复波特率出错
  528.            {
  529.                      wr_buff[0]=0x08;                                                   //默认参数2400
  530.            }
  531.         addr_baseonIDandtype(RAM,ID_BANTRATA);
  532.         data_addr.word[1]=(*ID_coretalbpoint[0]).dataaddr;
  533.         Write_data(RAM,(*ID_coretalbpoint[0]).datalong);

  534.         if(recover_item(ID_COMADDR)==0)                                   //恢复表地址错误
  535.            {
  536.                    for(i=0;i<6;i++)
  537.                               wr_buff[i]=0x11;
  538.            }
  539.         addr_baseonIDandtype(RAM,ID_COMADDR);
  540.         data_addr.word[1]=(*ID_coretalbpoint[0]).dataaddr;
  541.         len=(*ID_coretalbpoint[0]).datalong;
  542.         Write_data(RAM,len);

  543.         if(recover_item(0x8400)==0)                                     //恢复表号错误0000001
  544.            { for(i=0;i<5;i++)
  545.         wr_buff[i]=0;
  546.           wr_buff[5]=0x01;
  547.            }
  548.         addr_baseonIDandtype(RAM,0x8400);
  549.         data_addr.word[1]=(*ID_coretalbpoint[0]).dataaddr;
  550.         len=(*ID_coretalbpoint[0]).datalong;
  551.         Write_data(RAM,len);

  552. }


  553. /**
  554. *  恢复CF脉冲余量
  555. * @param  void
  556. * @return void
  557. */
  558. void Recover_tindiandata(void)
  559. {   
  560.           data_addr.word[1]=EEP_Save_cf;                                        //CF 恢复
  561.           Read_data(EEPROM,2);

  562.           if(wr_buff[1]==(wr_buff[0]+0x33))
  563.     { if(wr_buff[0]>128)
  564.            wr_buff[0]=0;
  565.         }
  566.         else
  567.            wr_buff[0]=0;

  568.    sumCF=wr_buff[0];

  569. }

  570. /*
  571. void RTCIOOff()
  572. {
  573.   CfgPort(4,0);
  574.   P1ID&=~(BIT0);
  575.   P1OE|=BIT0;
  576.   P1IE&=~(BIT0);
  577. }
  578. */
  579. //==================================================
  580. //函数功能:恢复数据
  581. //备注:
  582. //===================================================
  583. void Recover_data(void)
  584. {
  585.         Recover_eng();                 //恢复电量
  586.           Recover_tindiandata();         //恢复停电时保存的数据
  587.           Recover_prim();                //恢复参数
  588. }


  589. /**
  590. *  检测当前的供电模式
  591. * @param  void
  592. * @return 1  市电供电
  593. *         0  电池供电
  594. */
  595. unsigned char check_powertype(void)
  596. {
  597.         unsigned char value;
  598.           if((Systate&0x01)==0x01)
  599.                       value=1;                    //正常供电
  600.           else
  601.       {
  602.                       if((Systate&0x01)==0x01)
  603.                              value=1;
  604.                  else
  605.                              value=0;
  606.         }
  607.        
  608.           return  value;
  609. }

  610. /**
  611. *  初始化系统各个模块
  612. * @param  void
  613. * @return void
  614. */
  615. void Init_modul(void)
  616. {
  617.           Init_disp();                             //初始化显示模块
  618.           init_RTCmode();                          //初始化RTC模块
  619.           int_energeadd();                         //初始化能量计量模块
  620.           Init_checkmode();                          //初始化check模块
  621.     init_485comm();                          //初始化485模块
  622.     InitInfrComm();                          //初始化红外模块
  623.         Initcommu();                             //初始化通讯驱动
  624.         Init_Mchannel();                           //初始化M通道
  625.     SysInitAutoCal();                         //初始化自动校
  626. }


  627. /**
  628. *  初始化停电模块
  629. * @param  void
  630. * @return void
  631. */
  632. void ini_sleepmode(void)
  633. { CfgInterrupt(0);                //关所有中断
  634.   EA=0;                           //关总中断
  635. //  time_jihuo=0;
  636. //  time_lostiv=0;
  637. //  CfgPort(4,0);                   //秒脉冲输出打开
  638.   port_init();                    //禁止IO口输入输出
  639. }


  640. /**
  641. *  停电初始化
  642. * @param  void
  643. * @return void
  644. */
  645. //void Init_jihuo(void)
  646. //{
  647. //  Init_disp();                             //初始化显示模块
  648. //  sta_meterrun=5;                          //激活模式
  649. //  time_jihuo=0;
  650. //}





  651. /**
  652. *  停电保存各类数据,备注:包括:电量小数,CF脉冲位数,当月平均功率因数、停电时间
  653. * @param  void
  654. * @return void
  655. */
  656. void savedata_tingdian(void)
  657. {
  658.   //======================================================================CF
  659.   wr_buff[0]=sumCF;
  660.   wr_buff[1]=wr_buff[0]+0x33;
  661.   data_addr.word[1]=EEP_Save_cf;
  662.   Write_data(EEPROM,2);
  663. }

  664. /**
  665. *  开启CF脉冲输出
  666. * @param  void
  667. * @return void
  668. */
  669. void Open_CF(void)
  670. {  
  671.         unsigned char i;
  672.         if(count_opencftime==0)
  673.             { i=PMCtrl4;
  674.                     if((i&0x18)!=0x18)                                  //如果cf没有开
  675.                 {
  676.                         i=PMCtrl4;  
  677.                              if((i&0x18)!=0x18)  
  678.                              { i|=0x18;                                 //开CF
  679.                            PMCtrl4=i;
  680.                    SetInterrupt(14);                        //开CF1中断
  681.                  }
  682.                     }
  683.            }
  684.     if(ULowFlag==0)
  685.        { if(CFNumber>=1)
  686.                 { ULowFlag=1;
  687.                           Recover_pd();                   //第一个脉冲之后,恢复正常门限值
  688.                     }
  689.              
  690.              }
  691.       
  692. }

  693. //计量防潜动 判断
  694. void pm_Idle(void)
  695. {
  696.    unsigned int temp_int;
  697.    unsigned long xdata  temp;

  698.    //if((PMCtrl4&0x18)==0)
  699.    //  return;
  700.    //--------------------------获取脉冲常数
  701.            addr_baseonIDandtype(RAM,ID_CHANGSHU);                                //获取脉冲常数指针
  702.            data_addr.word[1]=(*ID_coretalbpoint[0]).dataaddr;
  703.            Read_data((*ID_coretalbpoint[0]).stortype,(*ID_coretalbpoint[0]).datalong);
  704.            temp_int=value_hex_from_2bcd(&wr_buff[1]);
  705.            if((temp_int>12800)||(temp_int<200))                                  //脉冲常数是否异常
  706.        temp_int=1200;                  
  707. ///计算0.4%IB启动电流时的功率
  708.    temp=meterprm_table[1];
  709.    temp >>= 11;
  710.    temp |= (meterprm_table[0]<<21);
  711.    temp *= type_Ib;
  712.    temp /= 2250;
  713.    temp *= temp_int;
  714.    temp *= type_volit;                  //220V x 10A /100  
  715.    temp /= 312500;
  716.    

  717.    ReadMeterPara(DATAP);
  718.    if(u32PMdatal&0x80000000)
  719.           u32PMdatal = (~u32PMdatal) +1;
  720.    if(u32PMdatal>=((temp*6)/10) )  //加启动电流时的功率的 60%
  721.    {
  722.      if(F_PmIdle)
  723.          {
  724.              if(pmIdleCnt<5)
  725.                            pmIdleCnt++;
  726.                  else
  727.                  {
  728.                     F_PmIdle = 0;
  729.                         pmIdleCnt = 0;
  730.                         PMCtrl4 &= ~BIT5;        //关闭防潜功能,         复位防潜能量桶
  731.                         PMCtrl4 |= BIT5;        //开启防潜,重新进行防潜计算
  732.                  }
  733.          }
  734.          else
  735.              pmIdleCnt = 0;
  736.    }
  737.    else if(u32PMdatal<= ((temp*3)/10) )         //加启动电流时的功率的 30%  
  738.    {
  739.       if(!F_PmIdle)
  740.           {
  741.              if(pmIdleCnt<5)
  742.                            pmIdleCnt++;
  743.                  else
  744.                  {
  745.                     F_PmIdle = 1;
  746.                         pmIdleCnt = 0;
  747.                  }
  748.           }
  749.           else
  750.                 pmIdleCnt = 0;
  751.    }
  752. }
  753. /**
  754.       * 流程描述
  755.       *
  756.       * 主程序根据系统状态寄存器的状态来判断当前是执行哪类操作
  757.       * RTC 唤醒 (BIT2)  快速休眠(注意快速休眠必须配合PLL快速流程,不然无法休眠)
  758.       * 看门狗复位(BIT4)   恢复系统状态
  759.       * IO口复位(BIT3)     更新显示
  760.       * 正常上电(BIT0)     正常上电流程
  761.       */
  762. void main(void)
  763. {   uint8 dispflashtime,waketime;   
  764. jumpsta:
  765.      F0=1;                              
  766.      CLKFRQ=1;                     
  767.      
  768.      SPCFNC=0x01;
  769.      XBYTE [0x8002] = 0x86;
  770.      SPCFNC=0x00;
  771.      SetMeterFunc(0);                                           //关CF输出
  772.      if(Systate & BIT2)                                         // rtc reset
  773.             {  CtrlMEAS = 0x80;                                     //关LDO33
  774.                    if(sta_meterrun==run_sleepdisp)                      //程序在停电显示模式
  775.               { waketime=0;       
  776.                 dispflashtime++;
  777.                                 if(dispflashtime==5)
  778.                                     { Disp_close();
  779.                                         }
  780.                             else if(dispflashtime==10)
  781.                     { if(BatteryInfo==1)
  782.                           Disp_err1();                          //显示err1
  783.                       else
  784.                                             Disp_oninsleep();                      //显示电量
  785.                                        }
  786.                 else if(dispflashtime==15)
  787.                     { Disp_close();
  788.                                         }
  789.                 else if(dispflashtime>19)
  790.                     { dispflashtime=0;
  791.                       Disp_oninsleep();                      //显示电量
  792.                     }
  793.                 if(save_lastday!=RTCHC)               
  794.                     { save_lastday=RTCHC;
  795.                       times_cutpower++;
  796.                       if(times_cutpower>TIMDISOCUTP)            //显示7天,超过7点则进入休眠模式
  797.                          { times_cutpower=0;
  798.                            CloseLCD();
  799.                            sta_meterrun=run_sleep;             //进入睡眠模式
  800.                                                    waketime=3;                         //一天唤醒一次  
  801.                          }
  802.                     }
  803.                        }
  804.           else
  805.                      waketime=3;
  806.          CfgRTC(0,waketime);                                     //32768,定时唤醒
  807.          if(check_powertype()==1)
  808.            { ClearWDT();
  809.              goto jumprun;
  810.                    }
  811.                  Sleep();
  812.                  if(check_powertype()==1)
  813.            { ClearWDT();
  814.              goto jumprun;
  815.                    }
  816.         }
  817.      #ifdef        DEBUG
  818.      #else       
  819.      else if(Systate & BIT4)                    
  820.            { SetPLL(SETPLL_3_2M);                       //开启pll  
  821.          Init_System();
  822.              Recover_data();                            //恢复数据 re
  823.          Init_modul();
  824.          EA = 1;                                    //开总中断
  825.          ClearWDT();
  826.        }
  827.      #endif       
  828.            else if(Systate & BIT3)                    // io reset
  829.            {if(check_powertype()==1)
  830.            { ClearWDT();
  831.              goto jumprun;
  832.                    }
  833.                  Sleep();
  834.         }
  835.          else              // 正常上电复位
  836.            {
  837. jumprun:
  838.          SetPLL(SETPLL_3_2M);                       //开启pll
  839.          Init_System();
  840.          Recover_data();                            //恢复数据
  841.              Init_modul();
  842.              EA = 1;                                    //开总中断
  843.          ClearWDT();  
  844.        }
  845.          
  846.          /**
  847.           * 正常运行部分,该部分中,系统反复执行以下流程
  848.           * RTC时钟刷新模块
  849.           * 计量模块CF打开
  850.           *
  851.           */
  852.          
  853. run_zhengchang:

  854.         while(check_powertype()==1)                               //市电供电
  855.            {             
  856.               PowerDown=0;
  857.           ClearWDT();                                   //喂狗
  858.                   if(check_powertype()==0)
  859.                      break;
  860.                   Rtc_refreshmode();                            //时钟刷新
  861.                   if(check_powertype()==0)
  862.                      break;
  863.                   commu_mode();                                  //通讯模块
  864.               if(check_powertype()==0)
  865.                       break;
  866.                   Open_CF();
  867.               if(check_powertype()==0)
  868.                      break;
  869.                   display_mode();                               //显示模块
  870.                   if(check_powertype()==0)
  871.                      break;
  872.               energ_addmode();                              //能量计量模块
  873.           if(check_powertype()==0)
  874.                      break;
  875.           check_mode();                                   //自检模块
  876.           if(check_powertype()==0)
  877.                      break;
  878.            Mchannelmode();                                   //M通道测量
  879.                          
  880.            }
  881. //==============================================================================================停电处理部分
  882.    if(check_powertype()== 0)                                   //电池供电
  883.       { while(1)
  884.               { if(check_powertype()==1)
  885.                     { ClearWDT();
  886.                       PowerDown=0;
  887.                       goto run_zhengchang;
  888.                            }
  889.                 else
  890.                           { PowerDown++;
  891.                          delay_1ms();
  892.                          ClearWDT();
  893.                             if(PowerDown>3)
  894.                                    goto xiumian;
  895.                           }
  896.           }
  897.       xiumian:          
  898.          savedata_tingdian();                                  //停电保存数据
  899.          ClearWDT();
  900.              CfgRTC(0,0);                                          //32768,1秒唤醒
  901.                  ini_sleepmode();                                      //初始化停电模式
  902.                  IO_Sleep();
  903.                  times_cutpower=0;                                      //停电计时器
  904.                  dispflashtime=0;                                       //闪烁时间
  905.                Ini_sleepdisp();
  906.          if(check_powertype()==1)
  907.            { ClearWDT();
  908.              goto jumpsta;
  909.                    }
  910.                 sta_meterrun=run_sleepdisp;                            //程序进入停电显示模式
  911.                  Sleep();
  912.          }
  913.    else
  914.      goto run_zhengchang;
  915. }
  916.          
  917. //=========================================================================================停电激活
  918. #undef AUTOCAL
  919. #undef        MAIN

复制代码


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:103296 发表于 2016-4-3 10:40 | 只看该作者
你好,能够把源码发给我学习一下,可以吗?谢谢!!!
回复

使用道具 举报

板凳
ID:1 发表于 2016-4-3 13:08 来自手机 | 只看该作者
卖源码,请到供求信息发布去
回复

使用道具 举报

地板
ID:197648 发表于 2017-7-1 10:51 | 只看该作者
楼主,有没有更详细的电能表设计方案
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表