⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 run.c

📁 基于ARM7的直流电机的驱动,还有FLASH驱动,LCD驱动等
💻 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 + -