学生考勤系统由硬件和软件两个部分构成。硬件部分主要是能够实现读取卡号,显示相关学生信息,以及能够传输和接收相关信息。软件部分包括操作界面和数据库处理两个内容,操作界面主要是相关内容的显示,包括登录和操作两个内容。操作页面由显示学生信息,显示课程信息,学生考勤信息页面,考勤操作页面,教师信息页,开课设置页面等六个页面组成。数据库处理是用来处理对老师,学生,课程管理以及上课考勤等相关信息的处理。
系统的硬件部分,根据调查市场上现有的RFID考勤系统,需要读卡器和PC直接连接,造成使用非常不方便。为了解决这一问题,本设计打算采用无线通信技取代传统的有线通信。读卡器端直接放置在教室门口,学生在班级门口时,就能刷卡进入班级。因此本设计硬件的相关模块包括:电源模块,刷卡提示模块,显示模块,无线通信模块,射频卡识别模块以及控制模块。电源模块用来给系统供电,因为系统中各部分工作电压不同,电压模块能解决相关问题。刷卡提示模块是利用蜂鸣器或发光二极管等提示,当刷卡成功时能发出提示声音或指示灯发光。显示部分是利用相关液晶屏显示学生的相关信息以及系统工作情况。无线通信模块,系统能够将读取的射频卡号发送给上位机,也能接收上位机发出的信息。射频卡识别模块能够读取相关卡号,并能传送至主控制芯片。控制模块,利用相关芯片对给部分进行控制处理,完成系统硬件功能。
软件部分能够实现对老师的添加,老师可以对学生进行添加,删除,修改,查看。同时也能添加和删除相关课程,查询每门课学生人数,出勤情况,同时也能及时查看学生刷卡情况,能够看到学生照片用以对比学生信息。
系统模型设计过程如下,老师可以通过对上位机的操作,完成相关课程的开课,以及选择相关学生,学生通过刷卡完成上课考勤,老师通过对相关信息的筛选完成学生上课信息的查看,相关模型图如图1所示。
图1 系统模型图
系统采用STC公司IAP15W4K58S4单片机作为主控制芯片、采用ESP8266作为WIFI通信模块、RFID-RC522为读卡器的标签、1602液晶显示模块,此外还需解决电源供电模块间工作电压不一致等问题,USB转TTL串口以及按键,LED提示等电路设计,系统的结构如图2所示。
图2 系统硬件结构图
初始化包括初始化单片机,液晶屏以及RFID,过程中系统液晶屏会显示“RFID System”在完成初始化后则显示“connect server..”。初始化程序如下:
init_system(); //初始化系统单片机
init_lcd(); //初始化液晶屏,并清屏
fill_screen();
sprintf(lcd_line1,"RFID System");
write_string(lcd_line1,1,1);
sprintf(lcd_line2,"connect server..");
write_string(lcd_line2,2,1);
init_rfid_system(); //初始化RFID
WDT_CONTR = 0x37; //开启看门狗
看门狗的功能是为了防止程序非正常工作时,从新回到系统上电状态,在程序调试和运行过程都有着很重要的意义。
完成相关初始化后,即调用加入wifi程序,需要对此进行判断,是否加入成功,若加入成功,即可继续操作,若没有成功,则继续加入wifi的程序。相关代码如下:
if (setup_wifi_dev()) {
Serial_println("wifi device ok!");
wifi_dev_ok= 1;
LED1= 0; //网络连接成功,LED1亮
fill_screen();
sprintf(lcd_line1,"RFID System");
write_string(lcd_line1,1,1);
sprintf(lcd_line2,"Ready!");
write_string(lcd_line2,2,1);
}else {
Serial_println("wifi device error!");
while(1) {
DelayMS(5000); //延时5秒,重启设备
return;
}
}
成功加入WIFI后,进行清屏等相关操作,然后进入死循环,执行读卡,向服务器发送数据等操作,为了防止长时间不用而产生的掉线,做了一个网络心跳操作,即定期向服务器发送不相干的操作保证网络连接相关程序如下:
while (1) {
WDT_CONTR = 0x37; //开启看门狗
process_rfid_event(); //RFID系统扫描卡片
if (time0_flag == 1) {
fill_screen();
sprintf(lcd_line1,"RFID System");
write_string(lcd_line1,1,1);
sprintf(lcd_line2,"Ready!");
write_string(lcd_line2,2,1);
time0_flag = 0;
LED2 = ~LED2; //状态指示灯 闪烁
if (send_heartbeat_time_interval_action--<= 0) { //定期发送网络心跳包给服务器
send_heartbeat_time_interval_action= send_heartbeat_time_interval; //设置计数初值
if(send_heartbeat_data_to_server() == 0) { //发送数据异常,重启系统
goto START;
}
}
}
if(recv_valid_data) { //判断标志位 是否接收到网络数据
if (g_i < 32) //判断wifi是否有 有效数据
continue;
recv_valid_data = 0;
Serial_println(g_Rec_Buf);
if (Hand("+IPD,")) { //接收到有效数据
parse_buf(); //处理接收到的网络数据
}
if (Hand("CLOSED")) { //接收到客户端断开信息
CLR_Buf();
LED2 = 1; //灭 第2个指示灯
g_connect_online= 0;
Serial_println("devdisconnect");
gotoSTART;
}
}
本设计是针对高校学生考勤,所以它的数据量不是特别的大,在设计时考虑到低成本、高性能的特点决定使用MYSQL数据库,同时针对系统的工作原理,对数据库进行了优化设计。
在数据库的概念设计中,我们通常用E-R图来表示实体与实体属性和实体之间的关系,通过E-R图来描述现实世界的实体,这样即使不了解系统设计的人也能理解数据库设计。
本系统的数据库一共设计了6张数据库表,数据库名为rfidsys。
1.teacher(教师表):该表用于存储系统教师的信息以及登录账号和密码。内容如下面信息表4-1所示。
表4-1 teacher
序号 | 名称 | 别名 | 类型 | 长度 | 主外键 |
1 | idteacher | 教师编号 | INT | 11 | Primary key |
2 | name | 教师姓名 | Varchar | 45 |
|
3 | sex | 教师性别 | Varchar | 2 |
|
4 | username | 登录名 | Varchar | 45 |
|
5 | passwd | 密码 | Varchar | 45 |
|
6 | age | 年龄 | INT | 11 |
|
2.studentinfo(学生信息表):该表用于存储系统的学生信息,内容如下面信息表4-2所示。
表4-2 studentinfo
序号 | 名称 | 别名 | 类型 | 长度 | 主外键 |
1 | idstudentinfo | 学生编号 | Int | 11 | Primar key |
2 | name | 姓名 | Varchar | 45 |
|
3 | no | 学号 | Int | 45 |
|
4 | rfidno | 校园卡号 | Varchar | 45 |
|
5 | sex | 性别 | Varchar | 2 |
|
6 | ago | 年龄 | Varchar | 11 |
|
7 | class | 班级 | Varchar | 45 |
|
8 | py | 姓名拼音 | Varchar | 45 |
|
3.classinfo(班级信息表):该表用于存班级信息,如表4-3所示。
表4-3 classinfo
序号 | 名称 | 别名 | 类型 | 长度 | 主外键 |
1 | idclassinfo | 班级编号 | int | 11 | Primar key |
2 | name | 班级名 | Varchar | 45 |
|
3 | classnum | 教室号 | int | 11 |
|
4.teacherlesson (老师上课表):用于存储老师上课情况,如表4-4所示。
表4-4 teacherlesson
序号 | 名称 | 别名 | 类型 | 长度 | 主外键 |
1 | id teacherlesson | id号 | Int | 11 | Primar key |
2 | teacherid | 教师编号 | Int | 11 | Foreign key |
3 | classid | 班级号 | INT | 11 |
|
4 | lessonnum | 课时 | INT | 11 |
|
5 | isover | 出勤 | Int | 11 |
|
6 | readydt | 准备上课 | DATATIME |
|
|
7 | begindt | 开始上课 | DATATIME |
|
|
8 | enddt | 结束上课 | DATATIME |
|
|
5.classsetup(设置上课表):该表用于存储班级设置的信息,如表4-5下面的信息所示。
表4-5 classsetup
序号 | 名称 | 别名 | 类型 | 长度 | 主外键 |
1 | idclasssetup | 设置id | Int | 11 | Primary key |
2 | teacherid | 教师id | INT | 11 |
|
3 | studentid | 学生id | INT | 11 | Foreign key |
4 | classindex | 课时 | Int | 11 |
|
5 | studentrecord | 出勤记录 | INT | 11 |
|
6 | recorddt | 记录时间 | DATATIME |
|
|
7 | lessonindex | 课时 | INT | 11 |
|
6.addclass(添加班级表):该表用于存储班级信息,如表4-6所示。
表4-6 addclass
序号 | 名称 | 别名 | 类型 | 长度 | 主外键 |
1 | idaddclass | id | Int | 11 | Primary key |
2 | classname | 班级名 | Varchar | 45 |
|
初始化数据库包括设置数据库的用户名,登录密码连接成功后打开数据库,相关代码如下:
public void init_db_system()
{
string connStr ="server=localhost;user=root;database=rfidsys;port=3306;password=123456;";
conn = new MySqlConnection(connStr);
try {
conn.Open();
connected_db = true;
}catch(Exception e) {
connected_db = false;
}
}
查询数据库使用MySqlCommand来查询,关闭数据库使用相关函数 conn.Close();来关闭数据库,登录界面判断用户名代码如下:
string strSQL = "select count(*) fromteacher where name = '" + strName + "' and passwd = '" +strPasswd + "'";
if (publicClass.query_sql_scalar(strSQL) != 1)
{
MessageBox.Show("错误的用户名或者密码?");
return;
}
publicClass.uninit_db_system();
MainForm mainForm = new MainForm();
mainForm.strTeacherUserName = strName;
mainForm.Show();
Hide();