?? main.c
字號:
// Copyright (c)2005 - 2006 by Laser Electronics, All Rights Reserved.
/*----------------------------------------------------------------------------+
| File Name: Main.c, v1.0.1 |
| Author: |
| Date: |
+-----------------------------------------------------------------------------+
| Description: 聯網型智能樓宇對講系統 -- 管理中心機主程序文件 |
| 器件選擇 -- STC89C58RD+, PQFP-44 |
| 時鐘頻率 -- 24.000 MHz |
+-----------------------------------------------------------------------------+
| Release Notes: |
| | |
+----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------+
| Include files |
+----------------------------------------------------------------------------*/
#include "Main.h"
#include "LCD.h"
#include "UART.h"
#include "Timer.h"
#include "KeyProcess.h"
#include "RouteTable.h"
/*----------------------------------------------------------------------------+
| Type Definition & Macro |
+----------------------------------------------------------------------------*/
// I2C存儲器的配置:使用24C512,64K字節空間, 0x0000 ~ 0xFFFF, 這里只用到16K字節
/*----------------------------------------------------------------------------+
| 0x0000(2字節): 系統標志
| 0x0002(1字節): 雙擊間隔時間
| 0x0003(1字節): 管理機輪檢門口機的時間間隔
| 0x0004(2字節): 小區的路由信息I2C起始地址
| 0x0006(2字節): 小區的路由信息長度
| 0x0008(2字節): 射頻卡信息起始地址
| 0x000A(2字節): 射頻卡信息長度
| 0x000C(2字節): 報警信息起始地址
| 0x000E(2字節): 報警信息長度
| 0x0010(2字節): 報警記錄第一條記錄的地址
| 0x0012(2字節): 報警記錄最后一條記錄的地址
| 0x0020 - 0x002F (16字節): 系統密碼+密碼長度
| 0x0030 - 0x003F (16字節): 管理機LOGO,在管理機空閑模式下LCD屏的第一行顯示的字符
| 0x0400 - 0x07FF (1K字節):
| 0x0800 - 0x0FFF (2K字節): 存放小區的路由信息,每個單元占用8個字節,所以可以存放256個單元的路由信息
| 0x1000 - 0x1FFF (4K字節): 存放卡號,每張卡號占用16個字節,所以可以存放256張卡號
| 0x2000 - 0x3FFF (8K字節): 存放報警記錄,每條報警記錄占用16個字節,所以可以存放512條報警記錄
+----------------------------------------------------------------------------*/
#define DEFAULT_ROUTE_INFO_START_ADDR 0x0800 // 從0x0800地址處開始
#define DEFAULT_ROUTE_INFO_LENGTH 0x0800 // 用2K字節來存放小區路由信息,每個單元需要8字節,可以存放256個單元的路由信息
#define DEFAULT_RFCARDTAB_START_ADDR 0x1000 // 從0x1000地址處開始
#define DEFAULT_RFCARDTAB_LENGTH 0x1000 // 用4K字節來存放臨時射頻卡號,每張卡需16字節,可以存放256張臨時卡
#define DEFAULT_ALARM_RECORD_START_ADDR 0x2000 // 從0x2000地址處開始
#define DEFAULT_ALARM_RECORD_LENGTH 0x2000 // 用8K字節來存放分機報警記錄,每條記錄需16字節,可以存放512條報警記錄
/*----------------------------------------------------------------------------+
| Extern Variables |
+----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------+
| Global Variables |
+----------------------------------------------------------------------------*/
bit bHandleUp; // 指示手柄是否提起,TRUE為提起狀態,FALSE為壓下狀態
bit LineIdle; // 當前線路上是否有數據,如果沒有才可以發數據
bit TxOK; // 當前字節是否已經發送完成
data t_SystemStatus SystemStatus; // 當前選擇的命令,是監視、查詢還是呼叫等等
data UINT RS485SendWaitTimer; // RS485總線超時重發計數器,當這個數減計數到MAX_RS485_WAIT_TIMES的倍數的時候重發,減到0的時候表示放棄這一次發送
data UINT MessageShowTimer; // 消息顯示的時間長短計數器,當這個數減到0的時候清除顯示的消息并回到之前的狀態
data UINT BeepTimer; // 蜂鳴器發聲定時器
idata BYTE WDT_Counter; // 看門狗狗糧
idata UINT LineIdleWaitTime; // 等待485總線空閑需要等待的時間, 根據地址而各不相同
idata UINT RingTimeCounter; // 振鈴信號持續時間,超過這個時間就會停止振鈴
idata UINT AlarmTimeCounter; // 報警持續時間,超過這個時間就會停止報警
idata UINT ViewTimeCounter; // 監視定時器,當這個計數器減計數到0的時候向門口機發送取消監視請求的命令
xdata BYTE ConnectingAddr[4]; // 管理機正在監視的門口機地址
xdata BYTE KeyBuffer[KEY_BUF_LENGTH+1]; // 按鍵緩沖
xdata BYTE CardBuffer[Card_BUF_LENGTH+1]; // 卡號緩沖
xdata t_RouteInfo RouteInfo; // 路由信息緩沖區
idata BYTE DoubleKeyPressTimer; // 設定雙擊按鍵的時間間隔,以10ms為單位
idata BYTE CheckDoorIntervalTimer; // 設定管理機輪檢門口機的時間間隔
idata UINT RouteInfoStartAddr; // 用于存放各個用戶的路由信息的表格在I2C存儲器中的起始地址
idata UINT RouteInfoLength; // 用于存放各個用戶的路由信息的表格的長度
idata UINT RFCardTabStartAddr; // 用于存放各個單元所有卡號對應的I2C地址的表格的頭地址,即表格的地址
idata UINT RFCardTabLength; // 用于存放各個單元所有卡號對應的I2C地址的表格的長度的地址
idata UINT AlarmRecordStartAddr; // 存放的報警記錄的首地址
idata UINT AlarmRecordLength; // 存放的報警記錄的長度
xdata BYTE SystemPassword[MAX_SYSTEM_PASSWORD_LENGTH+1]; // 存放系統管理員密碼,第一個字節為密碼長度
xdata t_AlarmRecord AlarmRecord; // 報警記錄緩沖區
idata t_AlarmRecord *pAlarmRecord; // 指向報警記錄的指針
xdata t_RFCardUser RFCardUser; // 定義記錄刷卡用戶的結構體,包括卡號,用戶名
idata t_RFCardUser *p_RFCardUser;
xdata BYTE I2CBuffer[I2C_PAGE_SIZE] _at_ 0x0000; // 讀寫I2C存儲器的內存緩沖
xdata BYTE CheckDoorIntervalArray[MAX_DOOR_NUM] _at_ I2C_PAGE_SIZE;// 管理機輪檢各個門口機所用到的數據緩存,每一個門口機對應一個字節
data UINT DoorNumber; // 在I2C存儲器中設置的單元的數量,根據這個數量管理機決定需要對多少個門口機進行輪檢
code UINT SystemPasswordAddress = 0x20; // 用于存放系統管理員密碼的I2C地址,長度為16個字節,用一頁來存放
code BYTE NullString[NULL_STRING_LENGTH] = {0x00}; // 常量空字符串
code BYTE Logo[DISP_BUF_LENGTH] = " 雷森電子 ";
/*----------------------------------------------------------------------------+
| Internal Variables |
+----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------+
| Type Definition & Macro |
+----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------+
| System Initialization Routines |
+----------------------------------------------------------------------------*/
//
// 初始化定時器0, 定時1.1ms作為檢測線路是否沖突的時間界限
void InitTimer0(void)
{
// initial timer0 interrupt
TMOD &= 0xF0; // zero low nibble
TMOD |= 0x01; // 設置 Timer 0 為16位計數器工作方式
// Init Timer0 counter
TH0 = LineIdleWaitTime >> 8;
TL0 = LineIdleWaitTime & 0xFF;
TF0 = 0; // clear timer 0 overflow flag
ET0 = 1; // enable timer 0 interrupt
}
//
// 初始化定時器2, Auto Reload方式定時10ms作為系統心跳信號
void InitTimer2(void)
{
// initial timer2
// T2CON __ ___
// TF2 EXF2 RCLK TCLK EXEN2 TR2 C/T2 CP/RL2
// 0 0 0 0 0 0 0 0
// T2CON = 0x00; // Mode 0, 16Bit Auto-Reload Mode
TR2 = 0; // Clear Interrupt Flag
EXF2 = 0; // reset flag
TCLK = 0; RCLK = 0; // disable baud rate generator
EXEN2 = 0; // ignore events on T2EX
C_T2 = 0; // timer mode
CP_RL2 = 0; // reload mode
T2MOD &= 0xFC; // T2OE(Timer 2 Output Enable bit)=0; DCEN(up/down counter)=0;
// initial timer2 reload value (1.1ms) @ fosc=24MHz
RCAP2H = TIMER2_H; // 自動裝載寄存器, 高8位
RCAP2L = TIMER2_L; // 自動裝載寄存器, 低8位
// Init timer2 counter
TH2 = TIMER2_H;
TL2 = TIMER2_L;
ET2 = ENABLE; // enable timer2 interrupt
TR2 = ENABLE; // timer2 run
}
// 初始化
void CopyDefaultSettings(void)
{
EA = DISABLE; // 關閉總中斷
AUXR = 0x01; // 禁止ALE信號輸出,提升系統的EMI性能,STC單片機專用
// 修改中斷優先級,讓Timer2中斷有最高優先級,其次是INT0
IP = 0x00;
XICON = 0x00; ////////////////////////////////////////////////////
PT2 = 0;
PT2H = 1; // 設置Timer2具有優先級2
IT2 = 1; //INT2邊沿觸發
PX2H = 1;
PX2 = 1; // 設置INT2具最高優先級
EX2 = 1;
P_VIDEO = P_OFF; // 電源關閉
P_AUDIO = P_OFF; // 電源關閉
BeepTimer = 0;
ViewTimeCounter = 0x0000; // 監視定時器,當這個計數器減計數到0的時候向門口機發送取消監視請求的命令
MessageShowTimer = 0x0000;
RS485SendWaitTimer = 0x0000; // RS485總線超時重發計數器,當這個數減計數到MAX_RS485_WAIT_TIMES的倍數的時候重發,減到0的時候表示放棄這一次發送
KeyBuffer[0] = 0x00;
LineIdleWaitTime = 0xF6A0; // (65536-1200*2), 如果有地址,則在后面減去與地址相關的數
InitTimer0();
InitTimer2();
InitMessagePool();
}
/*----------------------------------------------------------------------------+
| Main Routine |
+----------------------------------------------------------------------------*/
void main(void)
{
bit bTemp;
UINT i;
BYTE temp;
MSG msg;
GREEN_LED = P_OFF; // 綠色LED亮
RED_LED = P_ON; // 紅色LED滅
CopyDefaultSettings(); // 初始化系統變量
RESET_WDT;
Delayms(20);
RESET_WDT;
Delayms(20);
RESET_WDT;
Delayms(20);
RESET_WDT;
Delayms(20);
RESET_WDT;
InitLCD();
Delayms(1); // LCD初始化之后要等待1ms才能正常顯示
RESET_WDT;
SystemStatus.PreStatus = Status_Idle;
SystemStatus.Status = Status_Init;
InitDispBuffer(TRUE);
UpdateDisp(TRUE);
InitKey();
InitUART(); // 初始化串口和模擬串口
RESET_WDT;
// i = 0x55AA;
// I2CWriteString(0x00, 0x0000, (BYTE *)(&i), 2); // 先寫高字節,然后寫低字節,說明高字節放在低地址處,低字節放在高地址處
// 掃描按鍵并判斷'*'鍵的狀態,如果是按下的狀態,則進入設置模式
KEY_ROW1 = 0; // 掃描第1行(1 2 3 監視)
i <<= 4;
i |= (P0 & 0x0F); // 得到第1行按鍵的電平 "1, 2, 3, 13"
KEY_ROW1 = 1;
KEY_ROW2 = 0; // 掃描第2行(4 5 6 呼叫)
i <<= 4;
i |= (P0 & 0x0F); // 得到第2行按鍵的電平 "4, 5, 6, 14"
KEY_ROW2 = 1;
KEY_ROW3 = 0; // 掃描第3行(7 8 9 開鎖)
i <<= 4;
i |= (P0 & 0x0F); // 得到第3行按鍵的電平 "7, 8, 9, 15"
KEY_ROW3 = 1;
KEY_ROW4 = 0; // 掃描第4行(* 0 # 查詢)
i <<= 4;
i |= (P0 & 0x0F); // 得到第4行按鍵的電平 "11, 0, 12, 16"
KEY_ROW4 = 1;
if (i == 0xFFF7) // 0000,0000,0000,1000,即所有按鍵中只有'*'鍵是按下的
{
memcpy(&DispBuffer[0][1], "系統正在初始化 ", DISP_BUF_LENGTH);
memcpy(&DispBuffer[1][1], "請稍候! ", DISP_BUF_LENGTH);
UpdateDisp(TRUE);
// 向I2C存儲器中寫入默認的配置
// 清空前面2K字節空間
for (i=0x0000; i<DEFAULT_ROUTE_INFO_START_ADDR; i+=NULL_STRING_LENGTH)
{
RESET_WDT;
I2CWriteString(0x00, i, NullString, NULL_STRING_LENGTH);
}
// 清空小區路由信息所占用的2K字節空間
for (i=DEFAULT_ROUTE_INFO_START_ADDR; i<(DEFAULT_ROUTE_INFO_START_ADDR+DEFAULT_ROUTE_INFO_LENGTH); i+=NULL_STRING_LENGTH)
{
RESET_WDT;
I2CWriteString(0x00, i, NullString, NULL_STRING_LENGTH);
}
// 清空卡號所占用的4K字節空間
for (i=DEFAULT_RFCARDTAB_START_ADDR; i<(DEFAULT_RFCARDTAB_START_ADDR+DEFAULT_RFCARDTAB_LENGTH); i+=NULL_STRING_LENGTH)
{
RESET_WDT;
I2CWriteString(0x00, i, NullString, NULL_STRING_LENGTH);
}
// 清空報警記錄所占用的8K字節空間
for (i=DEFAULT_ALARM_RECORD_START_ADDR; i<(DEFAULT_ALARM_RECORD_START_ADDR+DEFAULT_ALARM_RECORD_LENGTH); i+=NULL_STRING_LENGTH)
{
RESET_WDT;
I2CWriteString(0x00, i, NullString, NULL_STRING_LENGTH);
}
// 寫入標志
I2CWriteString(0x00, 0x0000, "\x55\xAA", 2);
RESET_WDT;
// 初始化系統變量
RouteInfoStartAddr = DEFAULT_ROUTE_INFO_START_ADDR;
RouteInfoLength = sizeof(RouteInfoTable);//小區路由長度
RFCardTabStartAddr = DEFAULT_RFCARDTAB_START_ADDR;
RFCardTabLength = DEFAULT_RFCARDTAB_LENGTH;
AlarmRecordStartAddr = DEFAULT_ALARM_RECORD_START_ADDR;
AlarmRecordLength = DEFAULT_ALARM_RECORD_LENGTH;
DoubleKeyPressTimer = 25; // 設置按鍵雙擊間隔時間為25*10=250ms
CheckDoorIntervalTimer = 0; // 設置管理機輪檢門口機的時間間隔: 60*10=600秒
I2CBuffer[0] = DoubleKeyPressTimer;
I2CWriteString(0x00, 0x0002, I2CBuffer, 1); // 按鍵雙擊間隔時間
RESET_WDT;
I2CBuffer[0] = CheckDoorIntervalTimer;
I2CWriteString(0x00, 0x0003, I2CBuffer, 1); // 管理機輪檢門口機時間間隔
RESET_WDT;
I2CBuffer[0] = RouteInfoStartAddr>>8;
I2CBuffer[1] = RouteInfoStartAddr&0xFF;
I2CWriteString(0x00, 0x0004, I2CBuffer, 2); // 小區的路由信息I2C起始地址
RESET_WDT;
I2CBuffer[0] = RouteInfoLength>>8;
I2CBuffer[1] = RouteInfoLength&0xFF;
I2CWriteString(0x00, 0x0006, I2CBuffer, 2); // 小區的路由信息長度
RESET_WDT;
I2CBuffer[0] = RFCardTabStartAddr>>8;
I2CBuffer[1] = RFCardTabStartAddr&0xFF;
I2CWriteString(0x00, 0x0008, I2CBuffer, 2); // 射頻卡信息起始地址
RESET_WDT;
I2CBuffer[0] = RFCardTabLength>>8;
I2CBuffer[1] = RFCardTabLength&0xFF;
I2CWriteString(0x00, 0x000A, I2CBuffer, 2); // 射頻卡信息長度
RESET_WDT;
I2CBuffer[0] = AlarmRecordStartAddr>>8;
I2CBuffer[1] = AlarmRecordStartAddr&0xFF;
I2CWriteString(0x00, 0x000C, I2CBuffer, 2); // 報警信息起始地址
RESET_WDT;
I2CBuffer[0] = AlarmRecordLength>>8;
I2CBuffer[1] = AlarmRecordLength&0xFF;
I2CWriteString(0x00, 0x000E, I2CBuffer, 2); // 報警信息長度
RESET_WDT;
// 初始化管理機LOGO
I2CWriteString(0x00, 0x0030, Logo, 16); // 管理機LOGO
RESET_WDT;
memcpy(MainLogo, Logo, DISP_BUF_LENGTH);
// 初始化報警記錄存儲空間
AlarmRecord.Index = 0x00; // 報警記錄的長度
AlarmRecord.PreRecord = AlarmRecordStartAddr; // 報警記錄最后一條記錄的地址
AlarmRecord.NextRecord = AlarmRecordStartAddr; // 報警記錄第一條記錄的地址
I2CWriteString(0x00, AlarmRecordStartAddr, (BYTE *)(&AlarmRecord), sizeof(t_AlarmRecord));
RESET_WDT;
// 寫入小區的路由信息
for (i=0; i<sizeof(RouteInfoTable); )
{
if ((sizeof(RouteInfoTable) - i) > I2C_PAGE_SIZE) // 一頁寫不完這些數據,需要轉到下一頁
temp = I2C_PAGE_SIZE;
else
temp = (sizeof(RouteInfoTable) - i);
I2CWriteString(0x00, RouteInfoStartAddr+i, (BYTE *)(RouteInfoTable)+i, temp);//
RESET_WDT;
i += temp;
}
}
else
{
bTemp = FALSE;
if (I2CReadString(0x00, 0x0000, I2CBuffer, 64)) // 第一次讀16各字節,包括一些系統變量的值
{
if ((I2CBuffer[0] == 0x55) && (I2CBuffer[1] == 0xAA))
{
// 初始化系統變量
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -