IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 技能梳理4@NODEMCU+NFC+串口屏+获取在线时间+排序 -> 正文阅读

[嵌入式]技能梳理4@NODEMCU+NFC+串口屏+获取在线时间+排序

学生使用NFC打卡,显示在屏幕上,显示前十名的名字,每天显示两次;有个按键,一按就可以显示每个人一周前十名的总次数

1、项目简介

在这里插入图片描述

2、实现逻辑

#NFC检测到id卡,将卡号通过串口传送给mcu
#mcu获取卡号的最后一位做为识别人的标志,列一个数组将卡号最后一位和真人对应起来
#nodemcu正常联网成功会进行指示灯闪烁
#nodemcu一段时间连不上网会重启
#人员刷卡时间为上午和下午某个时间段,超出这个时间认为迟到,超出时间的或者不在打卡前十名的不显示在屏幕上
#串口屏上有10个位置,正常情况为空,在时间段内有人打卡就显示人名,超出时间段,会在屏幕右下角显示这个人迟到,屏幕人名会在上午和下午统计前清除上一次状态
#有一个按键,按键按下显示周排名前十的人名,并进行次数多少排序以及将进前十的次数显示出来,在周日的某个时间清零
#再次按显示周排名按键,重新显示当日某时间段进前十的人名

3、应用场景

#学生打卡
#nfc签到

4、核心代码梳理

uint8_t *data_nfc = (uint8_t *) malloc(50);

uint8_t stu_nums_t[STU_SUB] = {
    0xF0, 0x05, 0x21, 0x20, 0xBB, 0x4F, 0x70, 0xE9, 0x25,
    0xEF, 0x64, 0xD4, 0xDF, 0x0F, 0xFC, 0xED, 0x23, 0x98,
    0x68, 0x0A, 0x4B, 0x3B, 0x1B, 0xCC, 0x47, 0xE8, 0x77,
    0x71, 0xC1, 0xE3, 0x9F, 0xF2, 0x7A, 0x1A, 0x8E, 0x10,
    0x2E, 0xDE, 0x7B, 0x63, 0xB2, 0xE7, 0xC7, 0xE2, 0xAD,
    0x09, 0xF8, 0x8D, 0x08, 0x1E, 0x33, 0xBC, 0x4D, 0x61,
    0x3C, 0x86, 0x2A
};
/wifi&time///
const char *ssid = "fei";//WIFI   
const char *password = "0123456789";//WIFI密码  0123456789

const char* ntpServer = "pool.ntp.org";
const long  gmtOffset_sec = 8*3600;//这里采用UTC计时,中国为东八区,就是 8*60*60
const int   daylightOffset_sec = 0;//同上 

void printLocalTime()
{
  struct tm timeinfo;
  if(!getLocalTime(&timeinfo)){
    Serial.println("Failed to obtain time");
    return;
  }
  Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
}

void setup(void)
{

    //USART
    Serial.begin(115200);
    Serial2.begin(9600);  //io16 rx - tx;  io17 tx - rx;  Serial1 rx fail
   
    pinMode(LED_BUILTIN, OUTPUT);

    pinMode(KEY1, INPUT);
    pinMode(KEY1, INPUT_PULLUP);
    

    Serial.print("START");
    Serial2.print("START");

    WiFi.begin(ssid, password);//连接到网络
 
    while (WiFi.status() != WL_CONNECTED) {//等待网络连接成功
        delay(500);
        Serial.print(".");
        if(rst_num++ > 20)//10s没连上就重启
        {
          esp_restart();
        }
    }
 
    Serial.println("");
    Serial.println("WiFi connected");
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());//打印模块IP

    //init and get the time
    configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
    printLocalTime();

    for(uint8_t i=0; i<10; i++)
    {
        stus_early_day[i] = 0xff;
    }

}

void loop(void)
{
    //led///
    digitalWrite(LED_BUILTIN, HIGH);
    delay(100);
    digitalWrite(LED_BUILTIN, LOW);
    delay(100);

    

    
  //check///  
    check = digitalRead(KEY1);
    if(check == 0)
    {
        delay(100);
        check = digitalRead(KEY1);
        while(!check) //wait 
        {
            check = digitalRead(KEY1);
            delay(100);
        }

        check_flag = !check_flag; 
        //Serial.printf("KEY: %d\r\n",check_flag);

        if(check_flag) //查看周排名  
        {
            uint8_t b[STU_SUB];
            for(uint8_t i=0; i<STU_SUB; i++)    //变量i代表比较的趟数
            {
                b[i] = i;
            }
            //前十次数排序   57个数中找到最大的10个数对应的下标
            for(uint8_t i=1; i<STU_SUB; i++)    //变量i代表比较的趟数
            {
                for(uint8_t j=0; j<STU_SUB-i; j++)    //变最j代表每趟两两比较的次数
                {
                    if(stus_sub_num[b[j]] < stus_sub_num[b[j+1]])
                    {
                        uint8_t t = b[j];    //利用中间变量实现两值互换
                        b[j] = b[j+1];
                        b[j+1] = t;
                    }
                }  
            }

            for(uint8_t i=0; i<10; i++)   //获取周排名前十的学生序号,一次没进过就不显示了 
            {
              if(stus_sub_num[b[i]] == 0)
              {
                  break;
              }
              stus_early_wek[i] = b[i];
            }
            
              
            //显示前十及前十对应的次数
            for(uint8_t i=0; i<10; i++)
            {
                //stus_early_wek[i]
                //stus_sub_num[stus_early_wek[i]]
                delay(50);
                tx_data[5] = i+1;
                tx_data[7] = stus_early_day[i];
                for(uint8_t j=0; j<8; j++)   //显示人名
                {  
                    Serial.printf("%c", tx_data[j]);
                } 

                delay(50);
                tx_data[5] = i+16;
                if(tx_data[7] == 58)
                 tx_data[7] = 0;
                else  tx_data[7] = stus_sub_num[stus_early_wek[i]];
               
                for(uint8_t j=0; j<8; j++)   //显示排名
                {  
                    Serial.printf("%c", tx_data[j]);
                } 
                //Serial.printf("studen %d weed nums is :%d\r\n", stus_early_wek[i], stus_sub_num[stus_early_wek[i]]);
            }
        }
        else//恢复日常显示
        {
            for(uint8_t i=0; i<10; i++)
            {
                //显示前十
                delay(50);
                tx_data[5] = i+1;
                tx_data[7] = stus_early_day[i];
                for(uint8_t j=0; j<8; j++)   //显示人名
                {  
                    Serial.printf("%c", tx_data[j]);
                } 

                delay(50);
                tx_data[5] = i+16;
                tx_data[7] = 0;
               
                for(uint8_t j=0; j<8; j++)   //显示排名
                {  
                    Serial.printf("%c", tx_data[j]);
                } 

            }
        }
    }


//receive nfc///    
    int len = Serial2.readBytes(data_nfc, 50);  //04 0C 02 20 00 04 00 31    04 0C 02 20 00 04 00 01 


    //get time/// 
    struct tm timeinfo;
    if(!getLocalTime(&timeinfo)){
    Serial.println("Failed to obtain time");
    }

    if((timeinfo.tm_hour == 21) && (timeinfo.tm_min >= 0) && (timeinfo.tm_min <= 39)) //6:35- 6:41
    {
        //check_flag = 0;
        //显示前十名 并记录
        if(len > 0)
        {
            if((data_nfc[0] == 0x04) && (data_nfc[1] == 0x0C))
            {
                //判断是否已经刷过卡  stus_early_day[10]
                uint8_t card_d = 0;
                uint8_t stu_num = STU_SUB + 1;
                for(uint8_t i=0; i<STU_SUB; i++)
                {
                    if(stu_nums_t[i] == data_nfc[11])
                    {
                        stu_num = i;
                        break;
                    }
                }

                for(uint8_t i=0; i<10; i++)
                {
                  if(stus_early_day[i] == stu_num)
                      card_d = 1;
                }
                
                //记录
                if(!card_d)
                {
                    if(name_add < 10)
                    {
                        stus_early_day[name_add++] = stu_num;
                        stus_sub_num[stu_num] ++;//周前十次数加一

                        //Serial.printf("studen`s weed num is :%d\r\n", stus_sub_num[stu_num]);
                    }
                }
                //显示
                for(uint8_t i=0; i<10; i++)
                {
                    delay(50);
                    //显示前十
                    //Serial.printf("studen`s name is :%d\r\n", stus_early_day[i]); 
                    tx_data[5] = i+1;
                    tx_data[7] = stus_early_day[i];
                    for(uint8_t j=0; j<8; j++)   //显示人名
                    {  
                        Serial.printf("%c", tx_data[j]);
                    }    
                }
            }
        }
    }
    else if((timeinfo.tm_hour == 21) && (timeinfo.tm_min >= 40) && (timeinfo.tm_min <= 58)) //13:30- 13:38
    {
        //check_flag = 0;
        //显示前十名 并记录
        if(len > 0)
        {
            if((data_nfc[0] == 0x04) && (data_nfc[1] == 0x0C))
            {
                //判断是否已经刷过卡  stus_early_day[10]
                uint8_t card_d = 0;
                uint8_t stu_num = STU_SUB + 1;
                for(uint8_t i=0; i<STU_SUB; i++)
                {
                    if(stu_nums_t[i] == data_nfc[11])
                    {
                        stu_num = i;
                        break;
                    }
                }
                for(uint8_t i=0; i<10; i++)
                {
                  if(stus_early_day[i] == stu_num)
                      card_d = 1;
                }
                
                //记录
                if(!card_d)
                {
                    if(name_add < 10)
                    {
                        stus_early_day[name_add++] = stu_num;
                       
                    }
                }

                stus_sub_num[stu_num] ++;//周前十次数加一
                //Serial.printf("studen`s weed num is :%d\r\n", stus_sub_num[stu_num]);
                
                //显示
                for(uint8_t i=0; i<10; i++)
                {
                    delay(50);
                    //Serial.printf("studen`s name is :%d\r\n", stus_early_day[i]); 
                    tx_data[5] = i+1;
                    tx_data[7] = stus_early_day[i];
                    for(uint8_t j=0; j<8; j++)   //显示人名
                    {  
                        Serial.printf("%c", tx_data[j]);
                    }    
                }
            }
        }

    }
    else if((timeinfo.tm_hour == 22) && (timeinfo.tm_min == 00))
    {
        for(uint8_t i=0; i<10; i++)
        {
            delay(50);
            stus_early_day[i] = 58;
            if(!check_flag)//不是查看周排名模式  就前10显示屏全清
            {
                tx_data[5] = i+1;
                tx_data[7] = stus_early_day[i];
                for(uint8_t j=0; j<8; j++)   //显示人名
                {  
                    Serial.printf("%c", tx_data[j]);
                }  
            }
        }

        name_add = 0;

        
    }
    else  //显示迟到
    {
      if(len > 0)
      {
          if((data_nfc[0] == 0x04) && (data_nfc[1] == 0x0C))
          {
                uint8_t stu_num = STU_SUB + 1;
                for(uint8_t i=0; i<STU_SUB; i++)
                {
                    if(stu_nums_t[i] == data_nfc[11])
                    {
                        stu_num = i;
                        break;
                    }
                }
                delay(50);
                tx_data[5] = 11;
                tx_data[7] = stu_num;
                for(uint8_t j=0; j<8; j++)   //显示人名
                {  
                    Serial.printf("%c", tx_data[j]);
                } 

                delay(1000);

                tx_data[5] = 11;
                tx_data[7] = STU_SUB;
                for(uint8_t j=0; j<8; j++)   //显示迟到
                {  
                    Serial.printf("%c", tx_data[j]);
                }

                delay(1000);

                tx_data[5] = 11;
                tx_data[7] = 58;
                for(uint8_t j=0; j<8; j++)   //清除迟到
                {  
                    Serial.printf("%c", tx_data[j]);
                }
          }
      }
    }

    if((timeinfo.tm_hour == 22) && (timeinfo.tm_wday == 7)) //周日晚上10点清空这周排名
    {
        for(uint8_t i=0; i<STU_SUB; i++)
        {
            stus_sub_num[i] = 0;
        }

         for(uint8_t i=0; i<10; i++)
            {
                stus_early_wek[i] = 58;

                delay(50);
                tx_data[5] = i+1;
                tx_data[7] = stus_early_day[i];
                for(uint8_t j=0; j<8; j++)   //显示人名
                {  
                    Serial.printf("%c", tx_data[j]);
                } 

                delay(50);
                tx_data[5] = i+16;
                tx_data[7] = 0;
                for(uint8_t j=0; j<8; j++)   //显示排名
                {  
                    Serial.printf("%c", tx_data[j]);
                } 
                //Serial.printf("studen %d weed nums is :%d\r\n", stus_early_wek[i], stus_sub_num[stus_early_wek[i]]);
            }
    }
    


    while (WiFi.status() != WL_CONNECTED) {//等待网络连接成功
        delay(500);
        Serial.print(".");
        if(rst_num++ > 20)//10s没连上就重启
        {
          esp_restart();
        }
    }
}

5、部分参考资料

#修改卡号使用HF高频读写测试软件V1.0.4.exe
#串口屏使用sd卡烧录固件,因为屏太大使用外部供电
#需要在资料包中看一下esp32接线和串口屏通信接口相关的内容

6、注意事项

#显示屏使用外部12v供电,nodemcu是5v,中间加了一个电压转换
在这里插入图片描述
#按键识别使用的算法不需要加外部电容滤波,但需要长按一会,在弹起的那一刻识别
#现程序中在打卡时间外打卡没显示迟到字样,只显示一下刷卡的人名然后消失,可以取消那部分注释进行显示

完整可运行项目地址

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-05-07 11:20:04  更:2022-05-07 11:20:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 3:27:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码