📄 pdemo_df.c
字号:
// 单、复费率载波DEMO收发板程序
// 适用费率规约: 不加跳线端子,适用于复费率
// 4、5脚加跳线端子,适用于单费率
// CPU :PL3105
// 功能:1. 接收PC机串口下发的抄表命令并通过载波转发
// 2. 接收载波返回的抄表应答命令并通过串口转发给PC机
// 串口波特率: 2400BPS 无校验
// 复费率接收最长有效字节数:247
// 单费率接收最长字节数:14
// 程序完成日期: 2004年2月27日
//
#include "PL3105.h"
#define uchar unsigned char
#define uint unsigned int
//I/O 口设置
sbit RXD_TXD = P3^7; // 载波数据输入、输出口
sbit txd = P3^1; // 向上发
sbit rxd = P3^0; // 串口收
sbit rlamp = P1^2; // 接收指示灯
sbit tlamp = P1^3; // 发送指示灯
sbit d_f = P1^1; // 单——复费率转换
// 全局变量设置
uchar bdata pl_data; // 发送字节缓冲
sbit pl_h=pl_data^7;
uchar data pl_len,ti_len; // 发送字节计数
uchar data d_f_x; // 单——复费率标识
uchar data pl_8; // 发送位计数
uchar data x,n,plret_l;
uchar xdata r[250];
uchar data ystxd;//, ysrxd;
uint data x_09af;
uchar data r_data,r_8;
uchar data wdi;
uchar data r_len,r_len1;
// 位变量
bit bdata r_x,r_d;
bit bdata plmrxd;
bit bdata plmtxd;
uchar xdata pl_buf[250];
/////////////////////////////////////
// 定时器0中断程序
// 功能: 对延时变量进行减1处理
/////////////////////////////////////
void timeint0(void) interrupt 1 // 定时中断程序 50 ms 发生一次中断
{ if (ystxd!=0)
{ ystxd--;
}
TH0=0x63; // 置定时器计数 50ms 中断一次( 12MHz )
TL0=0xcc;
if(wdi==0x9a)
{ WDT_RST=0xa1; // 清看门狗
wdi=0;
}
}
////////////////////////////////////
// 载波中断收、发程序
// 入口:PLM_RS
// PLM_RS=0 载波接收; PLM_RS=1 载波发送
// 返回: plmrxd=1 载波接收成功
// pl_buf[] 载波接收成功的数据
////////////////////////////////////
void pl_pro(void) interrupt 7
{ uchar data i;
if(d_f_x=='D') goto d_zb;
// 复费率载波处理
if(PLM_RS)
{ // 载波发送
if(pl_8<8)
{ RXD_TXD=pl_h;
pl_8++;
pl_data=pl_data<<1;
if(pl_8==8) goto pl_ret;
}
else
{ pl_ret:
pl_8=0; // 位计数清0
pl_len++; // 发送长度加1
plret_l++;
pl_data=r[pl_len]; // 下一个字节
if(plret_l==20) { PLM_RST=0xa2; plret_l=0; }
if((pl_len>=ti_len)||(pl_len>240))
{ //发送完成
PLM_RS=0; // 置成收态
ti_len=0; pl_data=0; pl_8=0;
for(pl_len=0;pl_len<20;pl_len++)
r[pl_len]=0;
pl_len=0; RXD_TXD=1;
tlamp=1; // 发送指示灯灭
plmtxd=0; // 清正在发送标志
}
}
}
else
{ // 载波接收
RXD_TXD=1;
if (r_x==0)
{ if (RXD_TXD==1)
{ x_09af=x_09af|1; }
if (x_09af==0x09af)
{ r_x=1; r_8=0; r_d=0; x_09af=0; r_data=0;
rlamp=0; // 接收指示灯亮
}
else { x_09af=x_09af<<1; }
}
else { if (r_d==0)
{ if (RXD_TXD==1)
r_data=r_data|1;
r_8++;
if (r_8!=8)
r_data=r_data<<1;
else { pl_buf[0]=r_data; r_8=0; r_d=1;
r_len=1; r_data=0; r_len1=240;
}
}
else { if (RXD_TXD==1)
r_data=r_data|1;
r_8++; r_d=1;
if (r_8!=8)
r_data=r_data<<1;
else { pl_buf[r_len]=r_data; r_8=0;
if(r_len==4) { r_len1=r_data+7; }
r_len++; r_data=0;
if (r_len>=r_len1)
{ r_x=0; r_d=0; plmrxd=1;
rlamp=1; // 接收指示灯灭
}
}
}
}
}
goto zb_end;
d_zb: // 单费率载波处理
if(PLM_RS)
{ // 载波发送
if(pl_8<8)
{ RXD_TXD=pl_h;
pl_8++;
pl_data=pl_data<<1;
if(pl_8==8) goto pl_ret_d;
}
else
{ pl_ret_d:
pl_8=0; // 位计数清0
pl_len++; // 发送长度加1
pl_data=r[pl_len]; // 下一个字节
if(pl_len==20) PLM_RST=0xa2; // 复位发送计数器
if((pl_len>=ti_len)||(pl_len>40))
{ //发送完成
PLM_RS=0; // 置成收态
ti_len=0; pl_data=0; pl_8=0;
for(pl_len=0;pl_len<20;pl_len++)
r[pl_len]=0;
pl_len=0; RXD_TXD=1;
tlamp=1; // 发送指示灯灭
plmtxd=0; // 清正在发送标志
}
}
}
else
{ // 载波接收
RXD_TXD=1;
if (r_x==0)
{ if (RXD_TXD==1)
{ x_09af=x_09af|1; }
if (x_09af==0x09af)
{ r_x=1; r_8=0; r_d=0; x_09af=0; r_data=0;
rlamp=0; // 接收指示灯亮
}
else { x_09af=x_09af<<1; }
}
else { if (r_d==0)
{ if (RXD_TXD==1)
r_data=r_data|1;
r_8++;
if (r_8!=8)
r_data=r_data<<1;
else { i=r_data; i=i&0x20;
if(i==0x20) r_len1=14; // 上行
else // 下行
{ i=r_data; i=i&0x18;
if((i==0x18)||(i==0x10))
{ i=r_data; i=i&0x07;
r_len1=8+(2*i);
}
else
if(i==0x08) r_len1=8;
else r_len1=14;
}
pl_buf[0]=r_data; r_8=0; r_d=1;
r_len=1; r_data=0;
}
}
else { if (RXD_TXD==1)
r_data=r_data|1;
r_8++;
if (r_8!=8)
r_data=r_data<<1;
else { pl_buf[r_len]=r_data; r_8=0;
r_len++; r_data=0;
if (r_len>=r_len1)
{ r_x=0; r_d=0; plmrxd=1;
rlamp=1; // 接收指示灯灭
}
}
}
}
}
zb_end:;
}
///////////////////////////////////
// 初始化设置函数
// 功能:进行系统初始化设置
///////////////////////////////////
void initsys(void)
{ // 控制看门狗喂狗时间长度
CKCON=0X3F;
// 8位/16位运算模式选择位设置
ALU_MOD=0; // 设置成8位运算模式
//载波通讯配置
PLM_SSC=1; // (D8H)使能载波通讯PLM_SSC(EXT_CFG.0)=1
EIE=0X01; // (A9H 使能INT2中断(EX2=1)
IT2=1; // (C8H) 为边沿触发方式(IT2=1)。
PLM_RS=0; // PLM_RS(EXT_CTRL.0)=1 为0时,载波处于接收状态
//串口通讯配置
TMOD = 0x21 ; // 设 T/C1 为定时方式2 设置为8位自装载计数器 T/C0 为定时方式 14
SCON=0x50; // 工作方式1
PCON=0X80; // 波特率加倍
TH1=0xf6;
TL1=0xf6; // 加倍设定波特率 9.6MHz(PL3105按4800计算) 下数 F6H
TR1=1; // 启动定时器1
// 不显示使能
LED_LCD=0;
// 定时器0中断配置
TH0=0x63; TL0=0xcc; // 定时 50 ms 一个定时中断
TR0 = 1; // 启动 T0 定时器
// 中断级别设置
IP=0x02; // 定时器 T0 中断为高级中断
EIP=1; // 外部中断2 为高级中断
// 中断允许设置
IE=0x82; // 允许ET0=1定时器 T0 中断; 开放中断
}
///////////////////////////////////
// 初始化重置函数
// 功能:进行系统初始化重置
///////////////////////////////////
void initsys_ref(void)
{ // 载波设置重置
uchar data i;
if (PLM_SSC!=1) PLM_SSC=1; // (D8H)使能载波通讯PLM_SSC(EXT_CFG.0)=1
if (EIE!=1) EIE=0X01; // (A9H 使能INT2中断(EX2=1)
if (IT2!=1) IT2=1; // (C8H) 为边沿触发方式(IT2=1)
// 串口设置重置
if (TMOD!=0x21) TMOD = 0x21 ; // 设 T/C1 为定时方式2 设置为8位自装载计数器 T/C0 为定时方式 14
if (PCON!=0x80) PCON=0X80; // 波特率加倍
i=SCON;
i=i&0xf0;
if(i!=0x50) initsys();
if (TH1!=0xf6) TH1=0xf6;
if (TR1!=1) TR1=1; // 启动定时器1
// 中断设置重置
if (IE!=0x82) IE=0x82;
if (IP!=2) IP=2;
if (EIP!=1) EIP=1; // 外部中断2 为高级中断
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -