文章目录
一、简易刷卡式打卡考勤系统
(一)功能简介
1、材料:STM32F103C8T6、MFR522、O.96寸OLED、4个按键
2、功能:
①初始化管理员卡片,请放入管理员卡片
②进入管理界面,按键可以选择录入新员工、删除员工、更换管理员卡片、设置时间、设置上下班时间、查看考勤信息、恢复出厂设置等功能
③管理界面可以查看考勤信息
④退出管理界面后到正常界面,正常界面显示时间,有员工刷卡显示"员工X 早上好\中午好\下午好\晚上好\辛苦了"等字样
原理图设计
采用最普遍的STM32F103C8T6便宜好用又稳定
下载接口用排针
这次用TYPEC来供电5V,一看充电器9V12V不要慌,接上没带协议的设备是通通都5V。只要能接就不会爆炸。
5V转3.3降压采用降压芯片AMS1117C33电流大稳定可靠
用RFID射频卡来刷卡打卡
采用7针SPI OLED显示 ,屏幕是单色128*64分辨率
按键用来设置信息
蜂鸣器用来提示打卡成功或者失败
程序设计
这段代码是主程序,包含了初始化和主循环部分。在初始化部分,
程序设置了延时函数、NVIC中断分组、串口、OLED显示屏、蜂鸣器和实时时钟(RTC)。
主循环中,程序根据系统标志位sysFlag.DisMain
的值来执行不同的任务,如锁定界面、
管理员界面和解锁界面的任务。
c
#include "main.h" // 包含主程序的头文件
#include <string.h> // 包含字符串处理函数
// 系统参数结构体
SysTemPat sys;
// 系统标志位定义
SysflagTypedef sysFlag;
// 函数声明
void Display_Data(void); // 显示时间的函数
void starting(void); // 开机界面信息的函数
u8 MFRC522_lock(void); // 刷卡功能的函数
u8 Add_Rfid(void); // 录入RFID的函数
u8 Delt_Rfid(void); // 删除RFID的函数
void Set_Time(void); // 设置时间的函数
void Massige(void); // 信息提示的函数
void SysPartInit(void); // 系统参数初始化的函数
// 主函数
int main(void)
{
//初始化延时函数
delay_init();
// 设置NVIC中断分组为2:2位抢占优先级,2位响应优先级
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
// 初始化串口,波特率为115200
uart_init(115200); printf("串口功能正常\r\n");
// 初始化按键
KEY_Init();
// 初始化OLED显示屏
OLED_Init();
// 清除OLED显示屏
OLED_Clear();
// 初始化蜂鸣器
BEEP_Init();
// 显示开机信息
starting();
// 初始化RTC(实时时钟)
RTC_Init();
// 初始化系统参数
SysPartInit();
// 主循环
while(1)
{
// 根据系统标志位sysFlag.DisMain的值执行不同的任务
switch(sysFlag.DisMain)
{
case DIS_MAIN: main_task(); break; // 执行锁定界面任务
case DIS_MANAGE: manage_task(); break; // 执行管理员界面任务
case DIS_INFO: info_task(); break; // 执行解锁界面任务
}
}
}
使用删除数组并前移的方式来删除指定的员工
c
// 删除数组中的指定元素,并将后续元素前移
void deleteAndShift_card(int indexToDelete) {
int i, j;
if (indexToDelete >= 0 && indexToDelete <= sys.userNum) {
// 从要删除的元素开始,将后续元素前移
for ( i = indexToDelete; i < sys.userNum; i++) {
memcpy(sys.cardid[i],sys.cardid[i+1],5);
}
} else {
printf("索引无效。\n");
}
}
// 删除数组中的指定元素,并将后续元素前移
void deleteAndShift_user(int indexToDelete) {
int i, j;
if (indexToDelete >= 0 && indexToDelete <= sys.userNum) {
// 从要删除的元素开始,将后续元素前移
for ( i = indexToDelete; i < sys.userNum; i++) {
memcpy(&sys.user[i],&sys.user[i+1],sizeof(sys.user[0]));
}
} else {
printf("索引无效。\n");
}
}
主界面显示任务
c
void main_task(void)
{
#define DATA_TIME 100
#define KEY_TIME 10
#define RC522_TIME 300
static u32 scan_time = 0;
u8 key_num;
scan_time++; //扫描计数
if(scan_time % DATA_TIME == 1) {
Display_Data();//时间显示:每1000ms更新一次显示数据
if(sysFlag.DisFlag == 1)
{
sysFlag.DisFlag = 0;
OLED_Refresh_Gram();//更新显示
}
}
//MFRC522解锁
if(scan_time % RC522_TIME == 1) {
u8 ret = MFRC522_lock();
if(ret == 0)//MFRC522解锁
{
sysFlag.DisMain = DIS_MANAGE; //跳到管理界面
}
}
key_num = KEY_Scan(0);
if(key_num)
{
dis_info((u8*)"请刷卡打卡!",3000);
}
delay_ms(1);
}
管理员模式任务
c
void manage_task(void)
{
static char arrow = 0; //箭头位子
static u32 scan_time = 0;
static u8 dis_first = 1;
u8 key_num = 0;
if(dis_first)
{
dis_first = 0;
OLED_Clear_NOupdate();
Dis_SysSetup(arrow);
}
//超时
scan_time++;
//功能选项选择
key_num = KEY_Scan(0);
if(scan_time > 30000 | key_num == KEY2_PRES) {
scan_time = 0;
sysFlag.DisMain = DIS_MAIN; //跳到锁定界面
dis_first = 1;
}
if(key_num)
{
scan_time = 0;
if(key_num == KEY0_PRES) {
if(arrow > 0)arrow--;
}
if(key_num == KEY1_PRES) {
if(arrow < MAX_SYS_PARA_NUM - 1)arrow++;
}
Dis_SysSetup(arrow);
if(key_num == KEY3_PRES) {
switch(arrow)
{
case ADD_RFID:
Add_Rfid();
break;//录入新员工
case DEL_RFID:
Delt_Rfid();
break;//删除员工
case MOD_MANG_PSWD:
SetManage();
break;//更换管理员卡片
case MOD_TIMES:
Set_Time();
break;//设置时
case MOD_WORK_TIMES:
Set_WorkTime();
break; //设置上下班时间
case READ_SYS_INFO:
//查看考勤信息
Read_ColokinInfo();
break;
case FACTORY_RESET:
//恢复出厂设置
set_facory_reset();
break;
}
dis_first = 1;
}
}
delay_ms(1);
}
系统参数结构体
c
typedef struct
{
u32 HZCFlag;
u8 cardid[MAXRFIDNUM][CARID_LENGTH];
u8 errCnt;//错误计数
u8 errTime;//等待错误时间
u16 userNum;//员工人数
_time_obj sb_time; //上班时间
_time_obj xb_time; //下班时间
_user_obj user[MAXRFIDNUM];
}SysTemPat;