⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dds18838104.c

📁 一个电表的程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/***********************************************************************/
/*                                                                     */
/*  FILE        :DDS18838104.c                                         */
/*  DATE        :Wed, Jul 20, 2005                                     */
/*  DESCRIPTION :Main Program                                          */
/*  CPU TYPE    :H8/38104F                                             */
/*                                                                     */
/*  This file is generated by Renesas Project Generator (Ver.3.1).     */
/*                                                                     */
/***********************************************************************/
/* 宁波三星科技有限公司 */
/* 文件名:DDS18838104.C */
/* 说明1: 该程序是根据广东单相电子表(液晶显示)的技术特点而开发	 	*/
/* 说明2: 该程序是基于HD64F38104基础上而设计 							*/ 
/* 作者: 叶孟军 														*/
/* 开始日期:2005年7月22日 												*/
/****************************************************************/
#include <machine.h>
#include <stdio.h>   
#include "data.h"
#include "union.h"               
#include "iodefine.h"
#include "edit.h"

void	Power_Lvi(void);
void 	main(void);
void	Rtc_Judge(void);
/********************************************************************************/
#define		Re_Te			(IO.PDR4.BIT.B0)				//控制RS485发送/接收
#define		Key_Int			(IO.PDRB.BIT.B2)
#define		Power_Io_Data		(IO.PDR5.BIT.B0)
#define		NOP					{nop();nop();}	
#define		Revp_Curr		(IO.PDRB.BIT.B1)
#define		Revp_Led		(IO.PDR9.BIT.B2)
/********************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
void abort(void);
#ifdef __cplusplus
}
#endif
/****************************************************************************/
//以下为38104各寄存器单元置初值
/****************************************************************************/
void 	Tma_Define(void)				//定时器A定义,1s定时
{
  	CKSTPR1.BYTE |= 0x01;
	TMRA.TMA.BYTE = 0x18;
 }		
/****************************************************************************/

void 	Tmf_Define(void)				//定时器F定义,定时器FH定时频率为1/1200,定时器FL定时频率为1/600
{
	CKSTPR1.BYTE   |= 0x04;
	TMRF.TCRF.BYTE  = 0x45;				//定时器FH内部时钟为φ/16,定时器FL内部时钟为φ32
	TMRF.OCRFH 		= 0xFF;
	TMRF.OCRFL		= 0xFF;
	TMRF.TCSRF.BYTE = 0x11;				//采用溢出中断
	TMRF.TCFH 	 	= 0x00;			
	TMRF.TCFL 		= 0x00;
 } 
/****************************************************************************/

void 	Int_Define(void)				//中断定义
{
   	IEGR.BYTE 		&= 0xFC;			//IRQ1 与 IRQ0 采用下降沿触发中断
	IENR1.BYTE 		 = 0xC3;			//定时器A、键盘中断、IRQ1、IRQ0允许中断
	IENR2.BYTE 		 = 0x0C;			//定时器FH、定时器FL中断开启	
 } 

/****************************************************************************/
void  	Sci_Define(void)				//SCI 定义
{
    unsigned 	char	i;
	CKSTPR1.BYTE 	|= 0x20;			//开启SCI
	SCI3.SMR.BYTE 	 = 0x20;			//SCI模式设置为异步、1bit起始位、8bit数据位、1为偶校验位、1位停止位,SCI时钟源采用φ/16
	SCI3.BRR         = 0x7F;			//1200bit/s通讯速率
	SCI3.SCR3.BYTE   = 0x50;			//接收中断使能
	SPCR.BYTE 		 = 0x20;			//TXD32使能
    i = SCI3.SSR.BYTE;

	SCI3.TDR = 0xff;
	SCI3.SSR.BYTE	 = 0x00;
	Re_Te = 1;							//RS485处于接收状态
 } 

/****************************************************************************/

void	Pwm_Define(void)				//PWM定义
{
	PWM1.PWCR.BYTE	 = 0x00;			//PWM选用时钟源为φ/512
	PWM1.PWDRL		 = 0x04;
	PWM1.PWDRU		 = 0xFE;			
	CKSTPR2.BYTE	&= 0xED;			//PWM1、PWM2关闭
 }	

/****************************************************************************/
void	Lcd_Define(void)				//LCD定义
{
	CKSTPR2.BYTE	|= 0x01;			//LCD模块开启
	LCD.LPCR.BYTE	 = 0xC9;			//设定LCD工作方式: DTS1 DTS0 CMX - SGS3 SGS2 SGS1 SGS0
	LCD.LCR.BYTE	 = 0x30;			//LCD模块电源模式设定为外部电源模式
	LCD.LCR2.BYTE	 = 0x00;
 }

/****************************************************************************/

void	WatchDog_Define(void)			//WATCHDOG定义
{
	CKSTPR2.BYTE	|= 0x04;			//WATCHDOG模块开启
	IO.PMR2.BYTE	&= 0xFB;			//WATCHDOG时钟源采用TMW
	WDT.TCSRW.BYTE   = 0x7F;	
	TMW.BYTE     	 = 0xF0;			//watchdog time = 200ms -400ms 
	WDT.TCW          = 0x01;
 }


void	WatchDog_Set(void)				//喂狗
{
	WDT.TCW			 = 0x01;
 }
/****************************************************************************/
void	Ad_Define(void)					//AD模块定义
{
	CKSTPR1.BYTE 	|= 0x10;	
	AD.AMR.BYTE		 = 0x34;			//AN0
//	AD.ADSR.BYTE	 = 0x80;
 }
/****************************************************************************/

void	Io_Define(void)					//I/O定义
{
  	IO.PUCR3.BYTE 	 = 0xC6;			//SCL、SDA、WP、IRTXD需内部上拉
	IO.PCR3     	 = 0xC6;			//SCL、SDA、WP、IRTXD为输出
	IO.PMR3.BYTE	 = 0x00;
	IO.PMR2.BYTE	 = 0x01;			//P43作为IRQ0功能使用
	IO.PCR4			 = 0x05;			//P40、P42作为输出功能
	SPCR.BYTE		 = 0x20;			//P42作为TXD口使用
	IO.PCR5 		 = 0xfE;			//POWER作为输入、WP1、SCL1、SDA1作为输出
    IO.PUCR5.BYTE	 = 0x0E;			//WP1、SCL1、SDA1需内部上拉
	IO.PDR5.BYTE	 = 0xff;
	IO.PMR5.BYTE	 = 0x01;			//打开键盘中断0
	IO.PMR9.BYTE	 = 0x01;			//PWM1使用
	IO.PMRB.BYTE	 = 0x08;			//IRQ1使用
	IO.PDR9.BYTE	 = 0x2e;			//LED1、LED2、CF_TEST置高
		  
 }

/*****************************************************************************/
void 	Io_initial(void)				//I/O置初值
{
   IO.PMR3.BYTE		 = 0x00;
   IO.PMR2.BYTE		 = 0x00;
   IO.PMR5.BYTE		 = 0x00;
   IO.PMR9.BYTE		 = 0x00;
   IO.PMRB.BYTE		 = 0x00;
   IO.PUCR3.BYTE 	 = 0x00;
   IO.PCR3   		 = 0x00;
   IO.PCR4   		 = 0x00;
   IO.PUCR5.BYTE	 = 0x00;
   IO.PCR5  		 = 0x00;
   IO.PMR9.BYTE		 = 0xf8;
   IO.PDR9.BYTE		 = 0x2e;
 }	


void	SubActive_Define(void)
{
  	SYSCR1.BYTE = 0x8f;
	SYSCR2.BYTE = 0xE8;
 }

void	Active_Mode(void)
{
    Tma_Define();
	set_imask_ccr(0);
	IENR1.BYTE = 0x80;
	SYSCR1.BYTE = 0x87;
	SYSCR2.BYTE = 0xE8;
	NOP;
	sleep();
	NOP;
	IENR1.BYTE &= 0x7F;
	set_imask_ccr(1);

}

void	PowerLvi_Define(void)
{
	CKSTPR1.BYTE = 0x00;
	CKSTPR2.BYTE = 0x00;
	IENR1.BYTE	 = 0x00;
	IENR2.BYTE	 = 0x00;
	Tma_Define();
	IENR1.BYTE 	|= 0x80;
	IRR1.BYTE	 = 0x00;
	IRR2.BYTE	 = 0x00;
	Lcd_Define();
    RShftDspTm_Dtr[0] = 0x02;
    RStpDspTm_Dtr[0] = 0x03;
	Io_initial();
	LCD.LCR.BYTE	|= 0x40;			//LCD模块电源模式设定为内部部电源模式
	set_imask_ccr(0);					//开中断

 }


/****************************************************************************/
void	Ram_Define(void)			//ram区定义
{  
   unsigned char i;
   BufferHead_Comm = BufferInOut_Comm;
   BufferTail_Comm = BufferInOut_Comm;	
   Cf_Star=0x00;						//脉冲成立标志清零
//   Led_Cnt = 0x40;						//脉冲指示计数器值 >48
   DlStar_Reg = 0x00;  					//0.01kWh电量产生标志清零
   system_timer_in_13ms=0x00;
   TxRxTime_Comm = system_timer_in_13ms;
   for(i=0;i<BufferInOutMax_Comm;i++) 
    {
      BufferInOut_Comm[i]=0x00;
     } 
   Power_Flg.BYTE = 0x02;					//系统认为上电信号生成
   TimDef_Reg.BYTE = 0x00;
   Flag_Comm.BYTE = 0x00;					//通讯置为接收状态
   Rx_Command_Flg.BYTE = 0x00;
   Txrx_state.BYTE	= 0x00;
   TxData_state.BYTE = 0x00;
   Cf_int_reg.BYTE = 0x00;
   Trig_Byte=0x01;
   Disp_WORD = 0x0000;
   Other_Byte = 0x00;
   AccdntRcd_Byte = 0x00;
   Cf_Flg.BYTE = 0x00;
   Sys_Reg.BYTE = 0x00;
   CoutSign_Len=0x00;
   Key_Cnt=0x00;
   RMtWd_Dtr[0] = 0x00;		//电表信息字清零  
   RttPnter_Disp = 0x10;
   KeyPnter_Disp = 0x00;
   NghtCtDown_Disp = 0x00;
   Progrm_DispCnt = 0x00;
   CtDown_Disp = 0x00;
   TmSctNo_Disp=0x09;
   NewComDisp_Tm = 0;
   CoutSign_Len=0x00;
   DI1DI0_Comm=0x0000;
   DlStar_Reg = 0;		
   DispAllOn_Flg = 0x38;
   Hello_Flg = 0x00;
   End_Flg = 0x00;
   Error_Flg = 0x00;
   Txd_Fe_Cnt = 0;
   Tmfh_Cnt = 0x00;
   CrntRStr_Flg[0] = 0x00;			//反向标志清除
   Cf_Alt_TmCnt = 0;			//脉冲间隔时间计数清零
   for(i=0;i<4;i++)
    {
       REnger_Clr[i] = 0x00;
     }
}
/****************************************************************************/
//Cf_Judge程序完成电量计量、储存功能
void  Cf_Add(unsigned char  *addr)
{
   unsigned char i;
   for(i=0;i<4;i++)
    {
       *(addr+i) += 0x01;
       if((*(addr+i) & 0x0f) > 0x09)
        {
           *(addr+i) +=0x06;
           if(*(addr+i) > 0x99)
            {
               *(addr+i) = 0x00;
             }
           else
            {
               break;
             }
         }
       else
        {
           break;
         }
     } 
 }


void Cf_Judge(void)								//脉冲电量累计
{
   unsigned char EngerSave_Flg = 0x00;
   if(Cf_Star==0x68)
    {
       ++CF_CUNT;
       if(CF_CUNT >= Bcd_hex(RMtCt_Dtr[1]))		//当脉冲计数大于(电表常数/100)
     	{
           CF_CUNT = 0x00;						//清脉冲计数
		   DlStar_Reg = 0x01;					//0.01kWh电量产生
		   EngerSave_Flg  = 0x01;				
           Cf_Add(RPPwrTtl_Dtr);  				////当前有功总电量累加  
           if(Revp_Flg)							//当电表处于反向状态时
            {
               Cf_Add(RNPwrTtl_Dtr);  			////当前有功反向总电量累加  
             }
           if((RPPwrTtl_Dtr[0] == 0x00)	&& (EngerSave_Flg ==0x01))	//当前有功电量产生1kWh,须进行E2P备份
            {
		       EngerSave_Flg = 0x00;
               F_BlckWrt_Eeprm(EPPwrTtl_Dtr,RPPwrTtl_Dtr,0x04);		//当前电量保存到E2P电量数据区中,20bytes
               F_BlckWrt_Eeprm(EPPwrTtl_BKUP,RPPwrTtl_Dtr,0x04);	//当前电量保存到E2P电量备份区中,20bytes         
               F_BlckWrt_Eeprm(ENPwrTtl_Dtr,RNPwrTtl_Dtr,0x04);	//当前反向电量保存到E2P电量数据区中,20bytes
               F_BlckWrt_Eeprm(ENPwrTtl_BKUP,RNPwrTtl_Dtr,0x04);	//当前反向电量保存到E2P电量数据区中,20bytes
               
			 }
          }
       Cf_Star=0x00; 					                    //脉冲标志清除         
     }
 }    

/*****************************************************************************/
void	Dianl_ZcJudge(void)
{
   F_BlckRead_Eeprm(HstryEngy_Pter,Databuf,0x01);				//读取历史电量地址指针
   if(Databuf[0] >0x00) 
    {	
       Databuf[0]--;
	 }
   else
    {
       Databuf[0]= 0x0b;
     }
   F_BlckWrt_Eeprm(HstryEngy_Pter,Databuf,0x01);		//历史电量地址刷新
   F_BlckWrt_Eeprm((ELPPwrTtl_Dtr+Databuf[0]*4),RPPwrTtl_Dtr,0x04);	//本月电量转存到上月电量中
 }


void	AutDate_Judge(void)
{
   F_BlckRead_Eeprm(PowDwn_Reg,Databuf,0x01);			//读取掉电事件完成寄存器
   if((Databuf[0] == 0xe8) && (PowerUp_Flg))				//表示已有一次下电及上电事件生成
    {
       PowerUp_Flg=0;
	   Databuf[0] = 0x00;								//清除掉电事件完成标志
	   F_BlckWrt_Eeprm(PowDwn_Reg,Databuf,0x01);
	   F_BlckRead_Eeprm(PowDwn_Tm,Databuf,0x0a);		//读取停电事件1起始时间、结束时间
 	   if(Databuf[3] != Databuf[8])					//停电时间月不等于上电时间月
 	    {
 	       if(Databuf[8] > Databuf[3])					//上电时间月大于停电时间月
 	        {
 		      if((Bcd_hex(Databuf[8])-Bcd_hex(Databuf[3]))>=2)			//上电时间与掉电时间月差2个月以上
 		       {
 		         Dianl_ZcJudge();
 		        } 
 		      else
 		       {
 		         if(((Databuf[2] < RAUtRdTm_Dtr[1]) || ((Databuf[2] == RAUtRdTm_Dtr[1]) && (Databuf[1] < RAUtRdTm_Dtr[0]))) 		//掉电时间在自动抄表日之前而上电时间在自动抄表日之后
 		  	      || (((Databuf[7] == RAUtRdTm_Dtr[1]) && (Databuf[6] >= RAUtRdTm_Dtr[0])) || (Databuf[7] > RAUtRdTm_Dtr[1])))
 		  	      {	
 		  		    Dianl_ZcJudge();
 		  		   }
 		  	    }
 		     }
 	       else
            {
    	       if((12+(Bcd_hex(Databuf[8])-Bcd_hex(Databuf[3]))) >= 2)
 		        {
     	           Dianl_ZcJudge();
     	         }
 		       else
 		        {
 		           if(((Databuf[2] < RAUtRdTm_Dtr[1]) || ((Databuf[2] == RAUtRdTm_Dtr[1]) && (Databuf[1] < RAUtRdTm_Dtr[0]))) 		//掉电时间在自动抄表日之前而上电时间在自动抄表日之后
 		            || (((Databuf[7] == RAUtRdTm_Dtr[1]) && (Databuf[6] >= RAUtRdTm_Dtr[0])) || (Databuf[7]>RAUtRdTm_Dtr[1])))
 		            {	
 		  	           Dianl_ZcJudge();
 		  	         }
 		         }
  	         }
 	    }
 	   else								//停电时间月等于上电时间月
 	    {
 	       if(((Databuf[2] < RAUtRdTm_Dtr[1]) || ((Databuf[2] == RAUtRdTm_Dtr[1]) && (Databuf[1] < RAUtRdTm_Dtr[0])))				//掉电时间在自动抄表日之前而上电时间在自动抄表日之后
 		    && (((Databuf[7] == RAUtRdTm_Dtr[1]) && (Databuf[6] >= RAUtRdTm_Dtr[0])) || (Databuf[7]>RAUtRdTm_Dtr[1])))
 		    {	
 		       Dianl_ZcJudge();
 		      }
 	      }
 	    }
  
   if((RDtWk_Dtr[1] == RAUtRdTm_Dtr[1]) && (RTm_Dtr[2] == RAUtRdTm_Dtr[0])	&& (RTm_Dtr[1] == 0x00) && (RTm_Dtr[0] == 0x00)) //系统正常情况下过自动抄表日判断
    { 
       if(!Dl_ZcFlg)
        {
 	       Dianl_ZcJudge();
           Dl_ZcFlg=1;					//本次过自动抄表日历史电量已转存标志成立,该标志清除在1分钟后

 	     }
     } 
  }	 

void	Dianl_Day_Judge(void)					//本程序完成前60天电量是否需刷新
{
 	if((RTm_Dtr[2] == 00) && (RTm_Dtr[1] == 0x00) && (RTm_Dtr[0] == 0x00))
	 {
 		 F_BlckWrt_Eeprm(ELDay_PPwrTtl_Dtr,RPPwrTtl_Dtr,0x04);	//当前电量转存到上1天电量中
      }
 }	    


void	Dianl_Save(void)
{
 	if((RTm_Dtr[2] == 0x23) && (RTm_Dtr[1] == 0x00) && (RTm_Dtr[0] == 0x00))	//当前时间等于23:00
	 {
 		 F_BlckWrt_Eeprm2(EPPwrTtl_BKUP1,RPPwrTtl_Dtr,0x04);	//当前电量转存到备份E2P中
 		 F_BlckWrt_Eeprm2(ENPwrTtl_BKUP1,RNPwrTtl_Dtr,0x04);	//当前反向电量转存到备份E2P中
	  }
}	 	    



void 	Dianl_Judge(void)
{
    AutDate_Judge();
	Dianl_Day_Judge();
	Dianl_Save();
 }
/*****************************************************************************/
void	Read_Ad(void)				//电池A/D检测
{
    unsigned char i;
//	if((AD.ADSR.BYTE & 0x80) == 0x80)
	 {
	     AD.ADSR.BYTE |= 0x80;
		 i = AD.ADRRH;
		 if(i< 0x40)
   	      {
             RMtWd_Dtr[0] |= 0x08;
		     LcdBuf_Disp[8] |=0x02;
           }
         else
		  {
		     RMtWd_Dtr[0] &= 0xf7;
		     LcdBuf_Disp[8] &=0xfd; 
           }    
      }
 } 
/****************************************************************************/
void	Key_Judge(void)
{
   if(Time1s_Flg1)
    {
	   Time1s_Flg1 = 0;
	   if(!Key_Int)
	    {
		   ++Key_Cnt;
         }
       else
	    {
	       Key_Cnt = 0x00;
	     }
       if(Key_Cnt > 0x01)					//3s
        {
	       Progrm_Disp = 1;
         }
       if(Progrm_Disp)					//编程状态成立
        {
	       ++Progrm_DispCnt;
         }	
       if(Progrm_DispCnt > 240)				//编程时间大于4分钟,编程状态不成立
        {
	       Progrm_Disp = 0;
	       Progrm_DispCnt = 0x00;

         }
    }
   if(Progrm_Disp )
    {
	    LcdBuf_Disp[8] |=0x08;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -