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

📄 relay.c

📁 此源码为商用的电力抄表系统的从机端源程序。通过电力载波模块
💻 C
字号:
/*=============================================================================*/
// relay.c  - source file for lme2200 API
// 
// Copyright 2005, Leaguer MicroElectronics Co., Ltd
// www.leaguerme.com
/*=============================================================================*/

#include <REG922.H>

#include "amr_config.h"
#include "amr_cctr.h"
#include "wr_flash.h"
#include "relay.h"
#include "timer.h"
#include "plc.h"
#include "sart.h"
#include "stdio.h"

#define uint unsigned int
#define uchar unsigned char

#define PLC_TIMEOUT 	10000     // x basic timer 
idata uchar plc_frame[18];
extern idata uchar amr_frame[];  // AMR frame buffer
uchar code auto_frame[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x06,0x43,0xC3,0xcc,0xcc,0xcc,0xcc,0x8d,0x16};//9999.99

extern code uchar  METER_ADDR[6];
uchar   RELAY_PATH[6];	// hold the last successful relay path to cctr
idata  uchar   relay_level;	    // the last relay levels to cctr
uchar code ADDR_flash[6]; 
idata uchar cur_pos;
uchar L_amr;
uchar check_sum;//自动返回校验和
bit tmout_t1;
extern bit open_com_data;
extern bit NO_METER;
extern bit delay_tx;
/*=============================================================================*/

/* time-out functions */
/*
void plc_tmout(void)
{
  plc_timeout = 1;
  disable_t1();
}

*/

/*=============================================================================*/

void accept_frame(uchar frame[])
{  
  uchar R, L, i;
 // uchar addr[6];
  bit  D7; 

  R = (frame[0] & 0x30) >> 4;	  //中继级数 
		 
  D7 = (bit)(frame[0] & 0x80);
  L = frame[2*R + 4]; //数据长度
   // save relay path
  relay_level = R;
  for (i = 0; i < R; i++) {
    RELAY_PATH[2*i] = frame[2*i+3];
	RELAY_PATH[2*i+1] = frame[2*i+4];
  }
 
/*-----------------------仿真校验和----------------------------*/
  check_sum = 0xd0;
  for (i = 0; i < 6; i++)
   check_sum +=  METER_ADDR[i];
/*--------------------------------------------------------------*/

  clr_wdt();
  // pass the frame to meter
  if(D7){	  	   
      send_to_cctr(frame,0);	 //集中器回抄后续帧
  }  

   else {
           if(NO_METER)amr_send_frame(METER_ADDR, &frame[2*R+4-AMR_OS_L]);	//D7=0发入表端
           else send_to_cctr(auto_frame,1);	  //自动返回

   }
}

/*=============================================================================*/
/*							中继转发处理		    			               */
/*=============================================================================*/

void relay_frame(uchar frame[], bit uplink)
{
  uchar k;


  k = frame[0] & 0x03;	//中继次数
  frame[0] &= 0xfc;

  if (!uplink) {//<-------下传减一
	frame[0] |= (k-1);
  }
  else {    	//<-------上传加一
	frame[0] |= (k+1);
  }
  clr_wdt();
  while(delay_tx)clr_wdt();  
   plc_send(frame);	//<----中继载波发送
   if(open_com_data)tx_com_data(frame,0);               //从串口发出数据  

}
/*=============================================================================*/
/*						           将信号发入电力网线  				           */
/*=============================================================================*/

void send_to_cctr(uchar frame[],bit IL)
{
  idata uchar buf[16];
  uchar i, pos, max_bytes;
  uchar come,R;
  bit TX;
 
  TX = 0;
  R = 0;

  if(IL)frame[14] =  check_sum; //自动返回校验和
	
  if(IL){
	    L_amr = frame[7] + 4;come = 6;cur_pos = 0;TX = 1;	/*<-----------------------------表数据*/
	  } 
   else {	
		    
		  switch(plc_frame[2*relay_level + 3]){	 //CMD0
	      
	        case 0x01: {cur_pos = plc_frame[2*relay_level + 4];come = 2*relay_level +6;R = 0;TX = 1;R = 1;} break;  //<--------来自后续W数
	
			case 0x02: {cur_pos =0x02;come = 2*relay_level +4;R = 1;TX = 1;R = 0; L_amr = 14;}break;		
		
            default:{TX = 0;}break;
          }
	  }	
	
	  max_bytes = 18 - (2*relay_level + 4);//4
	
	  buf[0] = 0x40 | (relay_level << 4); //D6=1 uplink message, R, K  = 0
	 
	  if ((uchar)(L_amr - cur_pos) > max_bytes)   buf[0] |= 0x04;		  //设D2为1
	  else	buf[0] &= 0xfb;	
	
	  buf[1] = METER_ADDR[0];
	  buf[2] = METER_ADDR[1];
	
	  pos = 3;
	
	  if (relay_level > 0) {
	      for (i = 0; i < relay_level; i++) {
		    buf[2*i+3] = RELAY_PATH[2*i];
		    buf[2*i+4] = RELAY_PATH[2*i+1];
		  }	
		  pos = 2*relay_level + 3;
	  }

  buf[pos++] = cur_pos;

  for (i = 0; i < max_bytes; i++) {	//  buf[pos+i] = frame[come +cur_pos++];   

	if(IL){
        buf[pos+i] = frame[come++];//*   表端数据
	  cur_pos++;
	}	
	else{
	  if(R){
		buf[pos+i] = frame[6+cur_pos++];//**是01h时有W
	  }
      else buf[pos+i] = plc_frame[come++];  //02h---AA
	}	
	if (cur_pos >= L_amr) {
	  buf[pos+i] = 0x00; //剩下的值清零
	  if(cur_pos == max_bytes) cur_pos = 255;  		  
	}
  }

  clr_wdt();
/*-------------------------------------------------------------------------*/
  while(delay_tx)clr_wdt(); /*-延迟返回------*/
  if(TX)plc_send(buf);
  if(open_com_data) tx_com_data(buf,0);;//从串口发出数据
 
}

/*=============================================================================*/
/*						         	取表地址	    				           */
/*=============================================================================*/

// Get meter address from received amr frame from meter
void get_meter_addr(uchar frame[],bit err)
{
  uchar i;
  Rxok  = 0;
//  uchar buf[16]
//frame --->99 99 99 99 99 99 8A 00 33 33 33 33 33 33 A8 16 
   for(i = 0;i < 6; i++ )
      frame[i] =  frame[8 +i];

   for(i = 0;i < 10; i++ )
      frame[7 +i] =  0;

   eviscerate(frame,6);//-33
   if(err){
   EA = 0; 
   FLASH_WriteNByte((int code *)METER_ADDR, frame, 6);
   EA = 1;
//   EA = 0; 
 //  FLASH_ReadNByte ((int code *)&ADDR_flash, METER_ADDR, 6);
//   EA = 1; 
   }
   for(i = 0;i < 6; i++ )
      frame[i] =  METER_ADDR[i];

   frame[8] = amr_check_cs(frame,0);//校验和

}

/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$<<<<<软件说明>>>>>$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$* /
                        软件修改说明在main.c,敬请留意

!!!!!!重复特别注意:写表的地址必须从串口写入才有效!!!!!
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$<<<<<软件说明>>>>>$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/


⌨️ 快捷键说明

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