📄 czx167-145-v2.2.c
字号:
/********************************************************************************************/
/*
/* Copyright (c) 2005,许继仪表股份有限公司
/*
/* All Rights Reserved
/*
/*
/*
/* 文件名称:CZX165-145.C
/*
/* 文件标识:存档
/*
/* 摘 要:1、红外和载波通过485转发抄表控制程序
/* 2、该项目包括文件:CZX167-145.c ; pl3105.h
/* 3、CPU :PL3105
/* 4、该程序仅适用于符合标准645协议485电能表或多功能表的抄读
/* 5、载波信道CRC校验
/*
/* 功 能:0. 终端保存16个电表表号。
/* 1. 接收到红外通讯后转RS485抄表。
/* 2. 接收到载波通讯后转RS485抄表。
/* 3. 自动查表,抄读电表时,若该电表是终端所管理的电表,则该终端能够将表号自动保存
/* 4. 自动冻结功能,该终端能够根据设定的冻结时间将累计用电电量冻结
/*
/* 串口速率:1200BPS 偶校验
/*
/* 当前版本:2.02(发布)
/* 作 者:王振举
/* 完成日期:2006年07月04日
/*
/********************************************************************************************/
#include "PL3105.h"
#define uchar unsigned char
#define uint unsigned int
//#include <INTRINS.H>
#define WR_24_COM 0xA2 /*24c04 读写命令字*/
#define RD_24_COM 0xA3
//写24XX不同空间的地址指令
#define WR_2402 0xA0 // 24空间0-2K 不受保护的低半部分
#define WR_2404 0xA2 // 24空间2-4K 受保护的高半部分
#define add_password 0x10 // 24空间0-2K
#define add_password_bak 0x28 // 24空间0-2K
#define add_terminal 0x00 // 24空间0-2K
#define add_terminal_bak 0x18 // 24空间0-2K
#define add_frozenday 0x08 // 24空间0-2K
#define add_frozenday_bak 0x20 // 24空间0-2K
#define first_Son_addr 0x00 // 24空间2-4K
#define first_Son_addr_bak 0x80 // 24空间2-4K
/****** I/O 口设置 ********/
//sbit led = P1^1; // 24保存指示灯
sbit myled = P0^4; //调试灯
sbit wp24 = P2^0;
/////////////////////////////-----------------------------------
sbit key = P0^3;
sbit RXD_TXD = P3^7; // 载波数据输入、输出口
/////////////////////////////------------------------------------
sbit S_Clk = P2^1; // FM24C04的时钟口
sbit S_Dat = P1^5; // FM24C04的数据口
//sbit psk_out = P1^7;
// 位变量
uchar bdata pl_data; //发送载波数据移位使用
sbit pl_h = pl_data^7;
uchar bdata BIT_BIT; //
sbit r_x = BIT_BIT^1;
sbit r_d = BIT_BIT^2;
uchar bdata Flag_Byte; // 位变量字节
sbit FM24_Bit=Flag_Byte^0; // FM24C04 的数据位(SDA)
//***载波通讯使用变量*****
uchar data pl_8; //发送位数计数器
uchar data plret_l; //载波发送复位计数器
uint data x_09af; //接收同步头
uchar data r_data; //接收载波数据移位使用
uchar data r_8; //接收位数计数器
uchar data r_len; //载波接收字节计数器
uchar data r_len1; //载波要接收的数据长度(字节数)
/******* 全局变量设置 ******/
uchar data Watchdog_Reset; // 复位看门狗标志:为0x9A时,可以复位看门狗.
uchar data Timer_RS_Answer; // RS485应答时间
uchar data Timer_HW; // 红外发射/接收定时器
uchar data Timer_RS; // 485发射/接收定时器
uchar data Timer_Disp; // 显示时间间隔定时器(nx1S定时)
uchar data Timer_Disp_Temp; // 显示时间间隔定时器(1S定时)
uchar data Disp_Pointer; // 显示内容指针
uchar data ZJ_SEND; // 中继下发标志
uchar data space_judge1;
uchar data space_judge2;
uchar data space_judge3;
uchar data HW_Re_OK; // 红外接收状态标志: "OK"=接收正确, "End"=接收数据处理完毕
uchar data ZB_Re_OK; // 载波接收状态标志: "OK"=接收正确, "ERR"=接收数据处理完毕
uchar data RS_Re_OK; // 485接收状态标志: "OK"=接收正确, "ERR"=接收数据处理完毕
uchar data HW_ZB; // 红外/载波状态标志:"HW"=红外接收 ;"ZB"=载波接收
uchar data RS485_Txd_OK; // RS485发送状态标志: "OK"=数据准备好, "End"=数据发送结束
uchar data HW_State; // 红外接收过程标志
uchar data ZB_Read_Time; // 载波读时间标志:
uchar data RS485_Send_Sign;
uchar data HW_Pointer; // 红外BUF数据指针
uchar data HW_Data_Len; // 红外规约中数据部分的长度
uchar data HW_Data_CRC; // 红外规约中的校验和
uchar data RS485_Pointer; // RS485 BUF数据指针
uchar data RS485_Data_Len; // RS485 规约中数据部分的长度
uchar data ZB_Txd_Len; // 载波发送数据长度
uchar data ZB_Glob_Len; // 载波全局发送数据长度
uchar xdata Infrared_buf[30]; // Com0中断所接收的数据(红外数据)
uchar xdata Carrier_buf[50]; // 载波中断所接收的数据(载波数据)
uchar xdata RS485_buf[40]; // Com1中断所接收的数据(RS485数据)
uchar xdata Infrared_buf_bak[30]; // Com0中断所接收的数据(红外数据)备份
uchar xdata Carrier_buf_bak[50]; // 载波中断所接收的数据(载波数据)备份
uchar xdata RS485_buf_bak[30]; // Com1中断所接收的数据(RS485数据)备份
uchar xdata Send_Infrared_buf[30]; // Com0中断所发射的数据(红外数据)
uchar xdata Send_Carrier_buf[50]; // 载波中断所发射的数据(载波数据)
uchar xdata Send_RS485_buf[30]; // Com1中断所发射的数据(RS485数据)
uchar xdata Send_RS485_buf0[30]; // 读写电表所发射的数据(RS485数据)
uchar xdata Add_buf[7]; // 当前电表地址(通讯用)
uchar xdata Read_buf[8]; // 读取FM24时用的中间缓冲区
uchar xdata Write_buf[8]; // 写入FM24时用的中间缓冲区
uchar xdata terminal_add[7]; // 终端表号
uchar xdata addr_checked[7]; // 自动寻表时组帧用地址
uchar xdata new_addr_checked[6]; // 载波接收到的新表地址
uchar xdata new_meter_Txd;
uchar xdata new_meter_flag; // 载波通讯中发现新表的标志
uchar xdata flag_byte_No; // 自动寻表时按地址的低位到高位的顺序依次查询,flag_byte_No是正在查询的字节次序
uchar xdata Var_byte; // 自动寻表时,正在查询的字节的16进制数值
uchar xdata on_frame_flag; // 启动自动寻表或判拆表组帧标志
uchar data Meter_NO; // 判断查表过程数据指针
uchar data no_ans_times; // 判拆表或自动找表数据帧发送后未接到应答的次数
uchar data ans_times; // 查表数据帧下发后正确接收到应答的次数
uchar data flag_no_RXD; // 启动485发送无应答处理标志
uchar data j_f_meter_flag; // 正在判拆表或自动找表标志
uchar xdata find_meter_on; // 启动自动寻表标志
uchar xdata judge_find_Txd; // 判拆表或自动找表数据发送标志
uchar xdata HW_auto; // 红外修改表号不启动自动寻表
uchar xdata ZJ_Add_buf[7]; // 中继上传地址
uchar xdata Son_Add_buf[16][7]; // 子表号的电表地址 //前16块表号为终端所管理的16块表,最后一块为终端地址
uchar xdata Send_RS485_buf1[14]; // 自动查表或判拆表数据组帧缓冲区
uchar xdata Send_RS485_buf2[14]; // 载波通讯中发现新表查寻时数据组帧缓冲区
uchar xdata ans_Add_buf[3][6]; // 自动寻表数据帧下发后接收到正确数据帧时电表地址暂存缓冲区
uchar xdata Asc_buf[10]={0xED, 0x28, 0xB5, 0xB9, 0x78, 0xD9, 0xDD, 0xA8, 0xFD, 0xF9};
// 0x45, 0x7C, 0xF4, 0xD5, 0xD4, 0xFC};
// 0 1 2 3 4 5 6 7 8 9
// L H P E F R
void Infrared_Data_Send(uchar Send_Len);
void HW_Answer_Success();
void HW_Answer_MeterNO(uchar MeterNO);
uchar Check_ZB_ZJ_ADD(uchar Pos);
uchar Compare_HW_ADD();
void Write_FM24_nByte(uchar WR_24,uchar byte_len,uchar Add_FM24);
uchar Read_FM24_7Byte(uchar WR_24, uchar Add_FM24);
uint cal_crc(uchar *ptr, uchar len);
void read_son_addr(uchar son_add_NO);
void frame_judge_meter(void);
void frame_find_meter(void);
void Rxd1_prog(void);
void RXD_judge_prog(void);
void Rxd_find_prog(void);
void write_addr_son(uchar k);
void no_ans_process(void);
void judge_next_byte(void);
void GB_Design_Prog(void);
void start_j_f_meter(void);
uchar safe_where(void);
void frame_new_meter(void);
/**************************************************************************************
*
* FUNCTION: timeint0
*
* DESCRIPTION: 定时器0中断程序,5ms 发生一次中断,
* 对延时变量进行减1处理
*
* PARAMETERS: none
*
* RETURNED: none
*
*************************************************************************************/
void timeint0(void) interrupt 1
{
if(Timer_Disp_Temp>0)
Timer_Disp_Temp--;
else
{
Timer_Disp_Temp=100;
if(Timer_Disp>0)
Timer_Disp--;
else
Timer_Disp=0;
}
if(RS485_Send_Sign=='O')
{
if(Timer_RS_Answer>0)
Timer_RS_Answer--;
else if(RS485_Pointer==0)
{
RS485_Send_Sign=0;
if(judge_find_Txd=='E')
{
no_ans_times++;
flag_no_RXD='O';
}
}
}
if(Timer_HW>0)
Timer_HW--;
else
Timer_HW=0;
if(Timer_RS>0)
Timer_RS--;
else
Timer_RS=0;
if(j_f_meter_flag!='O')
{
if(space_judge1>0)
{
if(space_judge2>0)
{
if(space_judge3>0)
space_judge3--;
else
{
space_judge2--;
space_judge3=250;
}
}
else
{
space_judge1--;
space_judge2=250;
}
}
else
start_j_f_meter();//启动判拆表及自动寻表
}
if(Watchdog_Reset==0x9a)
{
WDT_RST=0xa1; // 清看门狗
Watchdog_Reset=0;
}
TH0=0xF8; // 置定时器计数 5ms 中断一次( 9.6/2 )
TL0=0x30;
}
/**************************************************************************************
*
* FUNCTION: Com0_int
*
* DESCRIPTION: COM0中断程序: COM0(红外)中断产生时,按照顺序接收规约数据
*
*
* PARAMETERS: none
*
* RETURNED: none
*
*************************************************************************************/
void Com0_int(void) interrupt 4 using 3
{
uchar i;
if(RI!=0)
{
ES=0; // 串口0中断禁止
ET0=1;
REN=1;
// 500mS未接收到下一字节则退出接收状态(恢复原始态)
Timer_HW=100;
if(HW_State==0) // 初始状态接收
{
HW_Pointer=0;
HW_Data_CRC=0;
HW_Data_Len=0;
Infrared_buf[HW_Pointer]=SBUF;
HW_Data_CRC+=Infrared_buf[HW_Pointer];
if(Infrared_buf[HW_Pointer]==0x68)
{
HW_State=1;
HW_Pointer++;
}
else
{
HW_State=0;
HW_Pointer=0;
HW_Data_CRC=0;
}
}
else if(HW_State==1) // 已经接收到第一个0x68,开始接收地址部分
{
Infrared_buf[HW_Pointer]=SBUF;
HW_Data_CRC+=Infrared_buf[HW_Pointer];
if(HW_Pointer==6)
HW_State=2;
HW_Pointer++;
}
else if(HW_State==2) // 已经接收完地址,开始接收第二个0x68
{
Infrared_buf[HW_Pointer]=SBUF;
HW_Data_CRC+=Infrared_buf[HW_Pointer];
if(Infrared_buf[HW_Pointer]==0x68)
{
HW_State=3;
HW_Pointer++;
}
else
{
HW_State=0;
HW_Pointer=0;
HW_Data_CRC=0;
}
}
else if(HW_State==3) // 已经接收到第二个0x68,开始接收控制码
{
Infrared_buf[HW_Pointer]=SBUF;
HW_Data_CRC+=Infrared_buf[HW_Pointer];
HW_State=4;
HW_Pointer++;
}
else if(HW_State==4) // 已经接收到控制码,开始接收数据长度
{
Infrared_buf[HW_Pointer]=SBUF;
HW_Data_Len=Infrared_buf[HW_Pointer];
HW_Data_CRC+=Infrared_buf[HW_Pointer];
if(HW_Data_Len>30)
{
HW_State=0;
HW_Pointer=0;
HW_Data_CRC=0;
}
else
{
HW_State=5;
HW_Pointer++;
}
}
else if(HW_State==5) // 已经接收到数据长度字节,开始接收数据部分
{
Infrared_buf[HW_Pointer]=SBUF;
HW_Data_CRC+=Infrared_buf[HW_Pointer];
HW_Data_Len--;
if(HW_Data_Len==0)
HW_State=6;
HW_Pointer++;
}
else if(HW_State==6) // 已经接收完数据部分字节,开始接收校验和
{
Infrared_buf[HW_Pointer]=SBUF;
if(Infrared_buf[HW_Pointer]==HW_Data_CRC)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -