学生考勤系统由硬件和软件两个部分构成。硬件部分主要是能够实现读取卡号,显示相关学生信息,以及能够传输和接收相关信息。软件部分包括操作界面和数据库处理两个内容,操作界面主要是相关内容的显示,包括登录和操作两个内容。操作页面由显示学生信息,显示课程信息,学生考勤信息页面,考勤操作页面,教师信息页,开课设置页面等六个页面组成。数据库处理是用来处理对老师,学生,课程管理以及上课考勤等相关信息的处理。
系统的硬件部分,根据调查市场上现有的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();