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

📄 main.c

📁 程序概述: 这是个具体产品程序
💻 C
📖 第 1 页 / 共 4 页
字号:
// 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 + -