?? main.c
字號:
DoubleKeyPressTimer = I2CBuffer[2];
CheckDoorIntervalTimer = I2CBuffer[3];
RouteInfoStartAddr = *(UINT *)(&I2CBuffer[4]);
RouteInfoLength = *(UINT *)(&I2CBuffer[6]);
RFCardTabStartAddr = *(UINT *)(&I2CBuffer[8]);
RFCardTabLength = *(UINT *)(&I2CBuffer[10]);
AlarmRecordStartAddr = *(UINT *)(&I2CBuffer[12]);
AlarmRecordLength = *(UINT *)(&I2CBuffer[14]);
DoorNumber = RouteInfoLength / sizeof(t_RouteInfo); // DoorNumber決定了管理機需要輪檢的門口機的數量,也就決定了數組的大小
if (DoorNumber > MAX_DOOR_NUM)
{
DoorNumber = MAX_DOOR_NUM;
}
memcpy(MainLogo, &I2CBuffer[0x30], DISP_BUF_LENGTH);
bTemp = TRUE; // 初始化成功
// 開機畫面延時
RESET_WDT;
Delayms(20);
RESET_WDT;
Delayms(20);
RESET_WDT;
Delayms(20);
}
}
if (bTemp == FALSE) // 如果初始化失敗,即讀I2C不成功或者I2C沒有被初始化
{
memcpy(&DispBuffer[0][1], "嚴重錯誤: ", DISP_BUF_LENGTH);
memcpy(&DispBuffer[1][1], "系統初始化失敗!", DISP_BUF_LENGTH);
UpdateDisp(TRUE);
BEEP = P_ON;
while (1) // 出現嚴重錯誤后系統將停留在初始化狀態,不再繼續工作
{
RESET_WDT;
PCON |= IDL_;
_nop_();
_nop_();
}
}
}
RESET_WDT;
// 初始化CheckDoorIntervalArray[]為默認值
for (i=0; i<DoorNumber; i++)
{
if (CheckDoorIntervalTimer == 0)
{
CheckDoorIntervalArray[i] = 0;
}
else
{
CheckDoorIntervalArray[i] = CheckDoorIntervalTimer;
}
}
InitRealTimer();
RESET_WDT;
SystemStatus.Status = Status_Idle;
InitDispBuffer(TRUE);
UpdateDisp(FALSE);
RED_LED = P_OFF;
ENABLE_WDT;
EA = ENABLE; // Enable global interrupt
while ( 1 )
{
RED_LED = P_ON;
WDT_Counter = 0x00; // 給狗糧
if (GetMessage(&msg))
{
switch (msg.Msg)
{
case MSG_TIMER_OVER: // 10ms系統心跳
{
if (BeepTimer > 0)
{
BEEP = P_ON;
BeepTimer --;
if (BeepTimer == 0)
{
BEEP = P_OFF;
}
}
if (SystemStatus.Status == Status_Idle) //多余(除開鎖)
{
ClosePower( ); //空閑狀態關閉音視頻
}
if (MessageShowTimer > 0)
{
if (SystemStatus.Status == Status_ShowingMessage) // 如果當前正在顯示消息
{
if ((--MessageShowTimer) == 0) // 如果顯示的時間到,則退回到顯示消息之前的狀態
{
SystemStatus.Status = SystemStatus.PreStatus;
SystemStatus.PreStatus = Status_Idle;
InitDispBuffer(TRUE);
UpdateDisp(TRUE);
}
}
else
{
MessageShowTimer = 0;
}
}
if (RingTimeCounter > 0)
{
if ((SystemStatus.Status == Status_Calling) // 管理機正在呼叫室內分機
|| (SystemStatus.Status == Status_bCallingIn_F) // 管理機正在振鈴
|| (SystemStatus.Status == Status_bCallingIn_M))
{
if ((--RingTimeCounter) == 0)
{
// 發送斷開連接的命令
RS485SendCancelCommand();
// 關閉音頻、視頻電源
ClosePower();
SystemStatus.Status = Status_Idle;
}
}
else
{
RingTimeCounter = 0;
}
}
if (AlarmTimeCounter > 0)
{
if ((SystemStatus.Status == Status_Alarming_F) // 管理機正在報警
|| (SystemStatus.Status == Status_Alarming_M))
{
if ((--AlarmTimeCounter) == 0)
{
ClosePower();
SystemStatus.Status = Status_Idle;
}
}
else
{
AlarmTimeCounter = 0;
}
}
if (ViewTimeCounter > 0) // 監視定時器減計數
{
if (SystemStatus.Status == Status_Viewing)
{
if ((--ViewTimeCounter) == 0)
{
// 發送取消命令
RS485SendCancelCommand();
SystemStatus.Status = Status_Idle;//多余,防止返回出錯
}
}
else
{
ViewTimeCounter = 0;
}
}
// 超時重發定時器減計數
if (RS485SendWaitTimer > 0) // 正在等待應答
{
if ((--RS485SendWaitTimer) == 0) // 超過重發次數,放棄發送
{
memcpy(&DispBuffer[1][1], "對方沒有應答! ", DISP_BUF_LENGTH);
DispBuffer[1][0] = 0x01;
if ((SystemStatus.Status == Status_Viewing)
|| (SystemStatus.Status == Status_Talking)
|| (SystemStatus.Status == Status_Calling)
|| (SystemStatus.Status == Status_Alarming_F)
|| (SystemStatus.Status == Status_Alarming_M)
|| (SystemStatus.Status == Status_bCallingIn_F)
|| (SystemStatus.Status == Status_bCallingIn_M))
{
ClosePower();
}
MessageShowTimer = 200;
SystemStatus.PreStatus = Status_Idle;
SystemStatus.Status = Status_ShowingMessage;
UpdateDisp(FALSE);
}
else if ((RS485SendWaitTimer%MAX_RS485_WAIT_TIMES) == 0) // 超時,重發
{
RS485SendTxFrame();
}
}
if (LastKeyTimer < 0xFF)// 給兩次按鍵之間的時間間隔計數,最大為2550ms
LastKeyTimer ++;
TickCountAdd(); // 更新時間顯示
break;
}
case MSG_TIMER_TEN_SECOND: // 1秒鐘定時時間到,檢查整個路由表中的每一個門口機發來的數據包的時間間隔是否超過設定值
{
/*
for (i=0; i<DoorNumber; i++)
{
if (CheckDoorIntervalArray[i] > 0)
{
CheckDoorIntervalArray[i] --;
if (CheckDoorIntervalArray[i] == 0)
{
j = RouteInfoStartAddr + i * sizeof(t_RouteInfo);
I2CReadString(0x00, j, (BYTE *)(&RouteInfo), sizeof(t_RouteInfo));
// 判斷當前門口機是否存在
if (RouteInfo.User != 0)
{
// 以下為保存報警記錄并初始化報警顯示緩沖
SystemStatus.Status = Status_Alarming_M;
InitDispBuffer(TRUE);
AlarmRecord.Addr[0] = 0x00; // 第一個字節
AlarmRecord.Addr[1] = RouteInfo.House; // 樓棟號
DispBuffer[1][7] = (RouteInfo.House >> 4) | 0x30;
DispBuffer[1][8] = (RouteInfo.House&0x0F) | 0x30;
AlarmRecord.Addr[2] = RouteInfo.Door; // 單元號
DispBuffer[1][11] = (RouteInfo.Door >> 4) | 0x30;
DispBuffer[1][12] = (RouteInfo.Door&0x0F) | 0x30;
AlarmRecord.Addr[3] = 0x00; // 第四個字節為0x00表示是從門口機報警而不是從分機報警
// 然后發出報警聲音
AlarmTimeCounter = MAX_ALARM_TIMES/2; // 設定最長報警時間為分機報警時間的一半
OpenAlarmPower(); // 打開報警音頻電路
UpdateDisp(FALSE);
memcpy((BYTE *)(&(AlarmRecord.Time)), (BYTE *)(&Time), sizeof(t_Time));// 保存時間
SaveAlarmRecord(&AlarmRecord); // 將報警記錄AlarmRecord結構體寫入到I2C存儲器中
// 將I2C存儲器中該單元的路由信息更新為該門口機不存在
RouteInfo.User = 0;
I2CWriteString(0x00, j, (BYTE *)(&RouteInfo), sizeof(t_RouteInfo));
// 當這次發現某一個門口機失去聯系的時候,就跳出這次的檢查,等下一個1秒鐘再來檢查其它的門口機,防止管理機不能響應其它的消息
// break;
}
}
}
}
*/
break;
}
case MSG_KEY_ROUTINE:
{
KeyRoutine(&msg);
break;
}
case MSG_KEY_DOWN:
{
KeyPressHandler(&msg);
break;
}
case MSG_TIME_DISPLAY:
{
// 更新顯示
// 如果當前顯示的是時間, 則更新顯示, 否則不更新
if ((KeyBuffer[0] == 0x00) && (SystemStatus.Status == Status_Idle))
{
InitDispBuffer(FALSE);
UpdateDisp(FALSE);
}
break;
}
case MSG_RS485_RX_FRAME:
{
RS485RxFrameHandler(&msg);
break;
}
// case MSG_RS232_RX: // 從模擬串口接收到數據
// {
// RS232RxHandler(&msg);
// break;
// }
case MSG_RX_CARDNUMBER: // 接收到一張卡的卡號
{
KeyBuffer[0] = 0x00;
BEEP = 0;
// 轉換為12位數字
for (i=1; i<=CardBuffer[0]; i++)
{
KeyBuffer[++KeyBuffer[0]] = CardBuffer[i] / 100;
CardBuffer[i] = CardBuffer[i] % 100;
KeyBuffer[++KeyBuffer[0]] = CardBuffer[i] / 10;
CardBuffer[i] = CardBuffer[i] % 10;
KeyBuffer[++KeyBuffer[0]] = CardBuffer[i];
//
}
for(i=0; i<KeyBuffer[0]; i++)
{
DispBuffer[1][DISP_BUF_LENGTH-i] = KeyBuffer[KeyBuffer[0]-i]+0x30;
}
BeepTimer = 20; // 每按一個按鍵,蜂鳴器響100ms
// 更新LCD顯示緩沖
DispBuffer[1][0] = 0x01;
UpdateDisp(FALSE);
break;
}
default:
break;
}
}
else // 隊列中沒有消息
{
RED_LED = P_OFF;
// 進入休眠狀態, 靠中斷來激活
PCON |= IDL_;
_nop_();
_nop_();
}
}
}
/*----------------------------------------------------------------------------+
| General Subroutines |
+----------------------------------------------------------------------------*/
//
// 延時微秒
void Delayus(BYTE timer) reentrant
{
// 每微秒執行2條指令
#if (SYS_CLOCK/N_DIV) == 2000
timer -= 4;
while ( --timer ) ;
// 每微秒執行4條指令
#else
#if (SYS_CLOCK/N_DIV) == 4000
timer -= 2;
_nop_();
do {
_nop_();
_nop_();
}while (--timer);
#endif
#endif
}
//
// 延時毫秒
void Delayms(BYTE timer)
{
do {
Delayus(250);
Delayus(250);
Delayus(250);
Delayus(248);
}while (--timer);
}
//
// 從RS485串口接收到一幀數據
void RS485RxFrameHandler(PMSG msg)
{
BYTE i;
BYTE j;
// BYTE k;
bit bTemp;
UINT temp;
FRAME xdata *pRxFrame;
// t_RouteInfo *p_temp;
pRxFrame = (FRAME *)msg->Param;
RouteInfo.RouteAddr = pRxFrame->Frame.Addr[1];// 由數據幀中的路由地址找到其對應的單元地址
RouteInfo.DoorAddr = pRxFrame->Frame.Addr[2];
RouteInfo.User = pRxFrame->Frame.Addr[3];// 用用戶的房號暫時存放分機地址,在查找對應的單元地址的時候同時把用戶的樓層和房號更新
if (pRxFrame->Frame.Addr[3] == 0x00) // 數據幀是從門口機發來的
{
if (pRxFrame->Frame.aData[0] & Command_Ack) // 應答幀
{
pRxFrame->Frame.aData[0] &= ~Command_Ack;
// 判斷數據類型
switch (pRxFrame->Frame.aData[0])
{
case Command_ViewRequest: // 門口機應答管理機發出的監視請求命令
{
if (SystemStatus.Status == Status_ViewSendingRequest) // 如果管理機正在等待門口機的返回
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -