📄 relay.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 + -