📄 run.c
字号:
#include "defs.h"
#include "44b0x.h"
#include <avt.h>
#include <string.h>
// 空闲故障节点
TRB *TrbFree;
// 已发生故障头节点
TRB *TrbActive;
// 空闲故障节点池
static TRB Trbs[TRB_MAX];
// 报警位标志
USHORT AlarmBits;
// 开关量
UCHAR Switch[16];
// 交采数据
USHORT JC[24];
UINT toggle;
extern const char *TRB_MSG[];
void bspInitSio(void);
//
// 接收到一个故障数据报
//
static void
MakeTrb(const UCHAR *pkt) {
ULONG Num;
ULONG tm;
TRB *t;
int psw;
UCHAR Code;
UCHAR r, reco;
UCHAR xxx[8];
Code = pkt[7];
// 125故障是一个特殊号。所有需要保存SOE的开关量共用125号故障来保存。
if(Code == 125)
goto skip;
// 实际的故障编号。
r = (Code & 0x7F) + 1;
// 故障撤销如果故障号的高八位为1。
reco = Code & 0x80;
// 根据故障类型确定故障显示的区域。
switch((int)TRB_MSG[2 * r]) {
#define CASE(type, field) \
case (int)type: \
if(reco) { \
if(LcdTrbs.field == r) \
LcdTrbs.field = 0; \
} \
else { \
LcdTrbs.field = r; \
} \
break;
// 走车故障
CASE(ZC, ZouChe)
// 主断电路故障
case (int)ZD:
// 劈相机电路故障
CASE(PX, PiXian)
// 保护电路故障
CASE(BH, BaoHu)
// 电子柜输入指令
CASE(DZG, DianZiGui)
// 辅助电路漏电故障
CASE(FZ, FuZhu)
// 牵引电机漏电故障
CASE(QY, QianYin)
}
//
// **故障撤销也存储**
//
//if(Code & 0x80) // 故障撤销, 不存储
// return;
skip:
// 每个故障至少会发送五次,所以只在第一次接收到时保存它。
Num = pkt[9] | (pkt[10] << 8) | (pkt[11] << 16) | (pkt[12] << 24);
for(t = TrbActive; t != NULL; t = t->Next) {
if(t->Number == Num) {
t->RcvCnt++;
return;
}
}
// 在链表中没有找到它,说明它是第一次接收到的,将它插入链表中并且写入FLASH。
psw = interrupts_disable();
if(TrbFree == NULL) {
TRB **pp = &TrbActive;
// 空闲链表空,则释放一个接收5次以上的节点。
while((t = *pp) != NULL) {
if(t->RcvCnt >= 5) {
*pp = t->Next;
break;
}
pp = &t->Next;
}
}
else {
// 否则直接摘取一个。
t = TrbFree;
TrbFree = t->Next;
}
t->RcvCnt = 1;
t->Number = Num;
t->Year = pkt[1];
t->Month = pkt[2];
t->Day = pkt[3];
t->Hour = pkt[4];
t->Min = pkt[5];
t->Sec = pkt[6];
t->Code = Code + 1;
t->SubCode = pkt[8];
// 插入已发生故障节点
t->Next = TrbActive;
TrbActive = t;
interrupts_enable(psw);
// 将数据加上时标并写入FLASH
tm = mktime(t->Year, t->Month, t->Day, t->Hour, t->Min, t->Sec);
tm |= 0x80000000;
xxx[0] = (tm >> 24) & 255;
xxx[1] = (tm >> 16) & 255;
xxx[2] = (tm >> 8) & 255;
xxx[3] = tm & 255;
xxx[4] = t->Code;
xxx[5] = t->SubCode;
NfWriteFile(xxx, Code == 125 ? 6 : 5);
}
// 数据接收任务,负责从主模块接收数据
void
RcvMain(void *args) {
UINT i;
UCHAR len;
UCHAR lpc;
UCHAR c;
UCHAR pkt[128];
for(i = 0; i < TRB_MAX - 1; i++)
Trbs[i].Next = &Trbs[i + 1];
Trbs[TRB_MAX - 1].Next = 0;
TrbFree = Trbs;
TrbActive = NULL;
toggle = 0;
//pkterr = 0;
// 初始化串口
bspInitSio();
// 允许串口接收中断
rINTMSK &= ~(BIT_URXD0);
// 开始接收数据报
//
// EB 90 `Len` `Lpc` `Data`
//
while(1) {
// 等待数据头
c = ReadByte();
if(c != 0xEB) continue;
lpc = c;
c = ReadByte();
if(c != 0x90) continue;
lpc += c;
// 数据长度字段
len = ReadByte();
if(len == 0 || len > 127)
continue;
lpc += len;
// 校验和字段
c = ReadByte();
lpc += c;
// 数据字段
for(i = 0; i < len; i++) {
c = ReadByte();
lpc += c;
pkt[i] = c;
}
// 判断校验和
if(lpc != 0)
continue;
if(pkt[0] == 8) { // TYPE: 故障信息
MakeTrb(pkt);
}
else if(pkt[0] == 13) { // TYPE: 交采数据
toggle += 1;
AlarmBits = MKWORD(pkt[1], pkt[2]);
for(i = 0; i < 24; i++)
JC[i] = pkt[3 + i*2] | (pkt[4 + i*2] << 8);
// 网压(25.nkV)
LcdTrbs.JC[14] = JC[0] / 10;
// 原边电流(xxxA)
LcdTrbs.JC[15] = JC[1] / 10;
// 辅压
LcdTrbs.JC[11] = JC[2] / 10;
// 发电相U
LcdTrbs.JC[10] = JC[3]/ 10;
// 牵引I1
LcdTrbs.JC[0] = JC[4] / 10;
// 牵引I2
LcdTrbs.JC[1] = JC[5] / 10;
// 牵引I3
LcdTrbs.JC[2] = JC[6] / 10;
// 牵引I4
LcdTrbs.JC[3] = JC[7] / 10;
// 牵引I5
LcdTrbs.JC[4] = JC[8] / 10;
// 牵引I6
LcdTrbs.JC[5] = JC[9] / 10;
// 牵引1U
LcdTrbs.JC[6] = JC[10];
// 牵引2U
LcdTrbs.JC[7] = JC[11];
// 励磁电流
LcdTrbs.JC[9] = JC[12] / 10;
// 110V
LcdTrbs.JC[12] = JC[13] / 100;
// +24.nV
LcdTrbs.JC[13] = JC[14] / 100;
// 15.nV
// +15V-1
//+15V-2
LcdTrbs.JC[8] = (JC[15] > JC[16] ? JC[15] : JC[16]) / 10;
JC[15] = LcdTrbs.JC[8];
// 功率kW
{
UINT p1, p2;
p1 = (LcdTrbs.JC[0] + LcdTrbs.JC[1] + LcdTrbs.JC[2]) * LcdTrbs.JC[6];
p2 = (LcdTrbs.JC[3] + LcdTrbs.JC[4] + LcdTrbs.JC[5]) * LcdTrbs.JC[7];
LcdTrbs.JC[16] = (p1 + p2) / 1000;
}
}
else if(pkt[0] == 22) { // TYPE: 开关量
Memcpy(Switch, pkt + 1, 13);
}
else if(pkt[0] == 88) { // TYPE: 工况信息
LcdTrbs.ShouBing = pkt[1];
LcdTrbs.QianHou = pkt[2];
LcdTrbs.ZhiQian = pkt[3];
LcdTrbs.GongKuang = pkt[4];
}
else if(pkt[0] == 99) { // TYPE: 对时
struct tm t;
t.tm_year = 2000 + pkt[1];
t.tm_mon = pkt[2];
t.tm_mday = pkt[3];
t.tm_hour = pkt[4];
t.tm_min = pkt[5];
t.tm_sec = pkt[6];
SetTime(&t);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -