📄 work.c
字号:
FMSet(a_24Consume1+c_OneSize*serial, 0, c_24ConLen);
}
}
else if(tempBuff1[1] == tempBuff[0])
{
tempBuff1[0] = timerBuff[dd]; //当前日写入另一区域
addr = a_24Consume0; //写另一个缓冲区
for(serial=0; serial<c_MaxMeterAmount; serial++)
{
v_ExtRunFlag = c_FMSet;
FMSet(a_24Consume0+c_OneSize*serial, 0, c_24ConLen);
}
}
else
{
tempBuff1[0] = timerBuff[dd];
tempBuff1[1] = tempBuff[0];
addr = a_24Consume0;
for(serial=0; serial<c_MaxMeterAmount; serial++)
{
v_ExtRunFlag = c_FMSet;
FMSet(a_24Consume0+c_OneSize*serial, 0, c_24ConLen*2);
}
}
v_ExtRunFlag = c_putStrFM;
putStrFM(a_24ConMark, tempBuff1, 2);
}
//转存小时电量
for(serial=0; serial<c_MaxMeterAmount; serial++)
{
//判断该序号表号是否有效
if(_FALSE == getMeterID(tempBuff, serial)) continue; //无效判断下一只电表
//判断当前电量有效性
getStrFM(tempBuff, a_FalseNO+c_OneSize*serial, 1);
temp = tempBuff[0];
if(temp != 0)
{
//数据无效
highmemset(tempBuff+2, 0, 4); //tempBuff+2开始是电量
v_ExtRunFlag = c_putStrFM;
putStrFM(a_FzConsume+c_OneSize*serial, tempBuff+2, 1);//冻结数据无效标志
continue;
}
else
{
//数据有效
getStrFM(tempBuff+1, a_Consume+c_OneSize*serial, 21);//获取当前电量,tempBuff+2,电量
//判断冻结任务
if(v_FreezeTask != 0)
{
//保存冻结电量
tempBuff[0] = v_FreezeTask; //冻结日
temp = tempBuff[1] + 2; //写入数据长度+长度和冻结日
v_ExtRunFlag = c_putStrFM;
putStrFM(a_FzConsume+c_OneSize*serial, tempBuff, temp);
}
}
//写入小时电量
v_ExtRunFlag = c_putStrFM;
putStrFM((addr+c_OneSize*serial)+(4*v_hhTask), tempBuff+2, 4);
}
v_hhTask = 0xff;
v_FreezeTask = 0;
}
//*********定时任务开始条件判断
//程序入口:分钟每次加1时调用
//自动抄表启动,冻结电量的存储,小时电量,月电量。。。
//*************************************
void minTaskSet(void)
{
unsigned char temp;
//获取当前时间
getStrRTC(timerBuff, 0, 7); //ss,mm,hh,WW,dd,MM,YY
highmemcpy(timerBuff+3, timerBuff+4, 3); //调整为s,m,h,w,d,m,y
//修正时间偏差
temp = timerBuff[ss]; //因为所有间接寻址都在高bank,需要导入低两bank
v_ssCont = bytebcdtohex(temp);
temp = timerBuff[min];
v_mmCont = bytebcdtohex(temp);
//获取抄表间隔,抄表间隔取值10,15,20, 30,60
getStrFM(tempBuff, a_AmrSpace, 1);
v_AmrSpace = tempBuff[0];
temp = v_AmrSpace;
if(v_AmrSpace == 0xff)
{
temp = 30;
}
if((v_mmCont%temp) != 0) return; //没有定时任务
//*** 到达定时抄表时间
//启动定时抄表任务
if(c_TaskAllStart != AmrTask.start) //如果已经启动,不需重新起动
{
AmrTask.start = c_TaskAllStart; //启动条件
AmrTask.Sta = c_TaskFree;
AmrTask.serial = 0; //开始序号
}
//判断整点
if(v_mmCont != 0) return; //不是整点没有任务
//整点,开始小时重点用户电量转存
temp = timerBuff[hh]; //小时, BCD码
v_hhTask = bytebcdtohex(temp); //开始小时任务
//判断小时是否和冻结时一致
getStrFM(tempBuff, a_FreezeTime, 1);
v_FreezeTask = tempBuff[0]; //冻结时相等,开始冻结任务
if(v_FreezeTask != temp)
{
v_FreezeTask = 0; //取消冻结任务
}
else
{
v_FreezeTask = timerBuff[dd];
}
}
//组织645帧,485缓冲区
//需要传递表号地址
//只能固定使用Buff485!!!!
void FrameSet485(bank2 unsigned char *ID)
{
unsigned char len, cs;
Buff485[c_Offset68_1] = 0x68;
Buff485[c_Offset68_2] = 0x68;
Buff485[c_OffsetC] = v_FrameC485;
Buff485[c_OffsetL] = v_FrameL485;
Buff485[c_OffsetDI0] = v_DI0485;
Buff485[c_OffsetDI1] = v_DI1485;
Buff485Mark.len = v_FrameL485 + 12; //数据域为0时帧长12,包括CS 16
//填充表号
highmemcpy(Buff485+1, ID, 6);
#ifdef DEBUG
for(len=6; len>0; len--)
{
if((*(ID+len)) == 0xff)
{
NOP();
}
}
#endif
//数据域+33
p_Buff485 = Buff485 + c_OffsetDI0;
len = v_FrameL485;
while(len--)
{
*p_Buff485 += 0x33;
p_Buff485++;
}
//计算CS
len = v_FrameL485 + 10; //需要计算CS的个数
p_Buff485 = Buff485;
cs = 0;
while(len--)
{
cs += *p_Buff485;
p_Buff485++;
}
*p_Buff485++ = cs;
*p_Buff485 = 0x16;
//设置返回参数
Buff485Mark.ptr = Buff485;
Buff485Mark.Sta = c_Send;
}
//自动抄表,数据有效性判断
//数据都在Buff485中
unsigned char amrFrameCheck(void)
{
if(_FALSE == frame645Check(Buff485)) return _FALSE; //帧格式
if(0x81 != Buff485[c_OffsetC]) return _FALSE; //控制字,因为都是抄读类
if(Buff485[c_OffsetDI0] != AmrTask.DI0) return _FALSE;
if(Buff485[c_OffsetDI1] != AmrTask.DI1) return _FALSE;
if(Buff485[c_OffsetL] < 0x06) return _FALSE; //抄读数据不能少于4字节 + 2
if(highmemcmp(Buff485+1, AmrMeterID, 6) != 0) return _FALSE; //表号不一致
return _TRUE;
}
//测试表类型,数据有效性判断
//数据都在Buff485中
unsigned char testFrameCheck(void)
{
if(_FALSE == frame645Check(Buff485)) return _FALSE; //帧格式
if(0x81 != Buff485[c_OffsetC]) return _FALSE; //控制字,因为都是抄读类
if(Buff485[c_OffsetDI0] != TestTask.DI0) return _FALSE;
if(Buff485[c_OffsetDI1] != TestTask.DI1) return _FALSE;
if(Buff485[c_OffsetL] < 0x06) return _FALSE; //抄读数据不能少于4字节 + 2
return _TRUE;
}
//************** 根据DI0设置抄读项相应位
void bsfMarkbit(unsigned char *p_mark, unsigned char DI0)
{
switch (DI0) {
case 0x1f:
*p_mark |= bsf_901f;
break;
case 0x10:
*p_mark |= bsf_9010;
break;
case 0x11:
*p_mark |= bsf_9011;
break;
case 0x12:
*p_mark |= bsf_9012;
break;
case 0x13:
*p_mark |= bsf_9013;
break;
case 0x14:
*p_mark |= bsf_9014;
}
}
void bcfMarkbit(unsigned char *p_mark, unsigned char DI0)
{
switch (DI0) {
case 0x1f:
*p_mark &= bcf_901f;
break;
case 0x10:
*p_mark &= bcf_9010;
break;
case 0x11:
*p_mark &= bcf_9011;
break;
case 0x12:
*p_mark &= bcf_9012;
break;
case 0x13:
*p_mark &= bcf_9013;
break;
case 0x14:
*p_mark &= bcf_9014;
break;
}
}
/*******************************************/
// 查找空表号位置
/*******************************************/
unsigned char getFreeMeter(void)
{
unsigned char loop1;
unsigned char loop2 = 0; //8次读取=32只表
unsigned char serial = 0; //表序号
bank2 unsigned char *p_data;
while(loop2 < 8)
{
//获取所有电表表号
getStrFM(tempBuff, a_MeterID+loop2*24, 24);//一次4只表
p_data = tempBuff;
loop1 = 4;
while(loop1--)
{
if(_FALSE == MeterIDCheck(p_data)) //无效表号就可以作为空表号地址
{
return(serial); //返回地址序号
}
serial++;
p_data += 6;
}
loop2++;
}
return c_MaxMeterAmount+10; //随便返回一个大于表数量的数
}
//************** 添加新表号到采集器内
// 添新表到第一个空位
// 返回加入序号,序号大于数量,没有加成功
//*************************************
unsigned char addOneMeter(bank2 unsigned char *ID)
{
unsigned char sr; //保存序号
sr = getFreeMeter();
if(sr < c_MaxMeterAmount)
{
//有空位可以添加电表
//保存表号
v_ExtRunFlag = c_putStrFM;
putStrFM(a_MeterID+6*sr, ID, 6u); //表号连续存放,不同于数据
//初始化失败次数为1, 0代表成功
v_ExtRunFlag = c_FMSet;
FMSet(a_FalseNO+c_OneSize*sr, 0x01u, 1u);
//冻结标志初始化
v_ExtRunFlag = c_FMSet;
FMSet(a_FzConsume+c_OneSize*sr, 0x00, 0x01);//首字节为零数据无效
//初始化电表特征字
v_ExtRunFlag = c_FMSet;
FMSet(a_MeterMark+c_OneSize*sr, 0x00, 0x01);
}
return sr;
}
/***********************************
* delOneMeter:按序号删除一只电表
***********************************/
void delOneMeter(unsigned char sr)
{
//删除电表
v_ExtRunFlag = c_FMSet;
FMSet(a_MeterID + 6*sr, 0xff, 6);
}
/**************************************
* 按序号获取电表表号,并判断是否有效
**************************************/
unsigned char getMeterID(bank2 unsigned char *ID, unsigned char sr)
{
if(sr > c_MaxMeterAmount) return(_FALSE);
getStrFM(ID, a_MeterID + 6*sr, 6); //读取表号
return (MeterIDCheck(ID)); //判断表号有效性
}
/*******************************************/
//按表号查找表序号,返回电表在存储器中的序号
//从 0 开始
// 返回值大于表最大数量时失败
/*******************************************/
unsigned char getMeterSr(bank2 unsigned char *p_ID)
{
unsigned char loop1;
unsigned char loop2 = 0; //8次读取=32只表
unsigned char serial = 0; //表序号
bank2 unsigned char *p_data;
while(loop2 < 8)
{
//获取所有电表表号
getStrFM(tempBuff, a_MeterID+loop2*24, 24);//一次4只表
p_data = tempBuff;
loop1 = 4;
while(loop1--)
{
if(0 == highmemcmp(p_data, p_ID, 6))
{
return(serial); //返回地址序号
}
serial++;
p_data += 6;
}
loop2++;
}
return c_MaxMeterAmount+10; //随便返回一个大于表数量的数
}
// 按抄读项设置,抄读标示
// 输入: 抄读项或者特征字屏蔽表数量
void setDataMark485(unsigned char mark)
{
v_DI1485 = 0x90;
if(mark & bsf_901f)
{
v_DI0485 = 0x1f;
}
else if(mark & bsf_9010)
{
v_DI0485 = 0x10;
}
else if(mark & bsf_9011)
{
v_DI0485 = 0x11;
}
else if(mark & bsf_9012)
{
v_DI0485 = 0x12;
}
else if(mark & bsf_9013)
{
v_DI0485 = 0x13;
}
else if(mark & bsf_9014)
{
v_DI0485 = 0x14;
}
}
/*************************************
* 电表特征字有效性判断
* _TRUE 有效
* _FALSE 无效
**************************************/
unsigned char MeterMarkCheck(unsigned char Mark)
{
if(Mark & 0x80)
{
if(Mark & 0b01111100) return _FALSE; //支持901F,分项必须是零
}
else
{
if((Mark & 0b01000000) == 0x00) return _FALSE; //不支持901F,也不支持9010有问题
}
if((Mark & 0b00000011) == 0x03) return _FALSE; //前导符个数最大2
return _TRUE;
}
/**************************************
* 检测开盖
* 输入:RA4
**************************************/
void OnOffCheck(void)
{
static unsigned char OnOffCont = 128; //计数器
if(_OnOff == 0) //低电平开箱
{
OnOffCont++;
}
else
{
OnOffCont--;
}
if(OnOffCont < 8)
{
OnOffCont = 128;
v_OnOffSta = c_OffSta;
}
else if(OnOffCont > 218) //开箱
{
OnOffCont = 128;
if(c_OffSta == v_OnOffSta)
{
v_OnOffSta = c_OnSta; //开箱状态
tempBuff[0] = v_OnOffSta;
v_ExtRunFlag = c_putStrFM;
putStrFM(a_OnOffSta, &tempBuff[0], 1);
//保存开箱时间
putStrFM(a_OnOffSta+1, timerBuff, 6);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -