当前位置:   article > 正文

基于gec6818RFID的办公室系统

6818rfid

目录

前言

一、高频RFID卡的读取

1.    模块引脚说明:

2、接线方式:

3.    mifare522模块的数据帧格式:

​编辑4.不同命令的数据帧格式

5、串口1初始化

6、读卡id代码如下

二、LCD使用及原理

1、lcd介绍

 2、LCD初始化,对文件进行映射

 3、LCD画点,清屏,显示字符串函数

 4显示图片

5、读触摸点坐标

 三、使用文件保存信息

1、读文件里信息

 2、从文件里删除信息

四、蓝牙通信与灯光

总结


前言

经过几个星期对RFID的学习,完成了一个关于RFID的项目,本项目用到的模块有gec6818开发板,一个高频RFID,一个高频RFID读卡器,一个蓝牙模块。根据RFID实现用户注册功能,记录一些用户的基本信息,如姓名、部门单位、工牌号等,信息存储在一个文件中。每次运行程序都会读取之前保存的信息。打卡功能:用户进入和离开办公室需要刷卡,LCD显示打开房间门。刷卡时会显示基本信息,记录上下班打卡时间,语音播报,显示用户基本信息,并通过蓝牙模块通知手机。家电管理功能:第一个员工进入办公室,会使用驱动程序打开gec6816的led灯;最后一个员工离开办公室时,会使用驱动程序关闭所有灯光。

一、高频RFID卡的读取

1.    模块引脚说明:

1    GND    地
2    VCC    +5v
3    TXD    串口输出
4    TRD    串口输入
 

2、接线方式:

6818串口con2     低频RFID阅读器
        VCC------------------------VCC
        GND-----------------------GND
        RX    ------------------------- TX
        TX—————————RX

3.    mifare522模块的数据帧格式:



4.不同命令的数据帧格式


1、    请求(CMD=A)
命令类型:0x02
命令:‘A‘
数据长度:1
数据信息:0x26—IDLE,0x52—ALL

代码如下

  1. int PiccRequest(int fd)
  2. {
  3. int ret;
  4. unsigned char tx_buf[7];//存放要发送的数据
  5. tx_buf[0]=0x07;//命令长度
  6. tx_buf[1]=0x02;//命令类型
  7. tx_buf[2]='A';//命令
  8. tx_buf[3]=0x01;//数据长度
  9. tx_buf[4]=0x52;//请求模式
  10. tx_buf[5]=CalBCC(tx_buf,tx_buf[0]-2);//校验
  11. tx_buf[6]=0x03;//结束
  12. write(fd,tx_buf,7);//发送数据给从机
  13. usleep(50000);//延时
  14. ret=read(fd,rt_buf,8);//接收从机应答消息
  15. if(ret<0)//接收返回值小于0接收失败
  16. {
  17. printf("read err\n");
  18. return 1;
  19. }
  20. if(ret==8)//接收到长度8的数据
  21. {
  22. if(rt_buf[2]==0x00)//判断status位为0表示成功
  23. {
  24. return 0;
  25. }
  26. }
  27. return 1;
  28. }


2、    防碰撞
命令类型:0x02
命令:‘B‘
数据长度:计数位=0,长度=2;计数位!=0,长度=6
数据信息:0x93——一级防碰撞 0x95——二级防碰撞 0x97——三级防碰撞

代码如下

  1. int PiccAnticoll(int fd)
  2. {
  3. int ret;
  4. unsigned char tx_buf[8];//存放要发送的数据
  5. int card_ID=0;
  6. tx_buf[0]=0x08;//命令长度
  7. tx_buf[1]=0x02;//命令类型
  8. tx_buf[2]='B';//命令
  9. tx_buf[3]=0x02;//数据长度
  10. tx_buf[4]=0x93;//碰撞级别选择1
  11. tx_buf[5]=0x00;
  12. tx_buf[6]=CalBCC(tx_buf,tx_buf[0]-2);//校验
  13. tx_buf[7]=0x03;//结束
  14. write(fd,tx_buf,8);//发送数据给从机
  15. usleep(50000);//延时
  16. ret=read(fd,rt_buf,10);//接收从机应答消息
  17. if(ret<0)//接收返回值小于0接收失败
  18. {
  19. printf("read err\n");
  20. return 1;
  21. }
  22. if(ret==10)//接收到长度10的数据
  23. {
  24. if(rt_buf[2]==0x00)//判断status位为0表示成功
  25. {
  26. card_ID=(rt_buf[7]<<24)|(rt_buf[6]<<16)|(rt_buf[5]<<8) |rt_buf[4];//读取buf中数据
  27. printf("ID=%x\n",card_ID);
  28. return 0;
  29. }
  30. }
  31. return 1;
  32. }

5、串口1初始化

  1. int uart1_init()
  2. {
  3. int uart1_fd= open("/dev/ttySAC1", O_RDWR);//打开串口1设备文件
  4. if (uart1_fd == -1)
  5. {
  6. perror("open error:");
  7. return -1;
  8. }
  9. struct termios myserial;
  10. memset(&myserial, 0, sizeof (myserial));//清空结构体
  11. myserial.c_cflag |= (CLOCAL | CREAD);//O_RDWR
  12. //设置控制模式状态,本地连接,接受使能
  13. //设置 数据位
  14. myserial.c_cflag &= ~CSIZE; //清空数据位
  15. myserial.c_cflag &= ~CRTSCTS; //无硬件流控制
  16. myserial.c_cflag |= CS8; //数据位:8
  17. myserial.c_cflag &= ~CSTOPB;// //1位停止位
  18. myserial.c_cflag &= ~PARENB; //不要校验
  19. cfsetospeed(&myserial, B9600); //设置波特率,B9600是定义的宏
  20. cfsetispeed(&myserial, B9600);
  21. tcflush(uart1_fd, TCIFLUSH);/* 刷新输出队列,清楚正接受的数据 */
  22. tcsetattr(uart1_fd, TCSANOW, &myserial);/* 改变配置 */
  23. return uart1_fd;
  24. }

6、读卡id代码如下

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <string.h>
  5. #include <sys/types.h>
  6. #include <sys/stat.h>
  7. #include <fcntl.h>
  8. #include <errno.h>
  9. #include <termios.h>
  10. unsigned char rt_buf[10];//存放接收数据
  11. //串口初始化
  12. int uart1_init()
  13. {
  14. int uart1_fd= open("/dev/ttySAC1", O_RDWR);//打开串口1设备文件
  15. if (uart1_fd == -1)
  16. {
  17. perror("open error:");
  18. return -1;
  19. }
  20. struct termios myserial;
  21. memset(&myserial, 0, sizeof (myserial));//清空结构体
  22. myserial.c_cflag |= (CLOCAL | CREAD);//O_RDWR
  23. //设置控制模式状态,本地连接,接受使能
  24. //设置 数据位
  25. myserial.c_cflag &= ~CSIZE; //清空数据位
  26. myserial.c_cflag &= ~CRTSCTS; //无硬件流控制
  27. myserial.c_cflag |= CS8; //数据位:8
  28. myserial.c_cflag &= ~CSTOPB;// //1位停止位
  29. myserial.c_cflag &= ~PARENB; //不要校验
  30. cfsetospeed(&myserial, B9600); //设置波特率,B9600是定义的宏
  31. cfsetispeed(&myserial, B9600);
  32. tcflush(uart1_fd, TCIFLUSH);/* 刷新输出队列,清楚正接受的数据 */
  33. tcsetattr(uart1_fd, TCSANOW, &myserial);/* 改变配置 */
  34. return uart1_fd;
  35. }
  36. //校验
  37. unsigned char CalBCC(unsigned char *buf,int n)
  38. {
  39. int i;
  40. unsigned char bcc=0;
  41. for(i=0;i<n;i++)
  42. {
  43. bcc^=*(buf+i);
  44. }
  45. return (~bcc);
  46. }
  47. //申请请求
  48. int PiccRequest(int fd)
  49. {
  50. int ret;
  51. unsigned char tx_buf[7];//存放要发送的数据
  52. tx_buf[0]=0x07;//命令长度
  53. tx_buf[1]=0x02;//命令类型
  54. tx_buf[2]='A';//命令
  55. tx_buf[3]=0x01;//数据长度
  56. tx_buf[4]=0x52;//请求模式
  57. tx_buf[5]=CalBCC(tx_buf,tx_buf[0]-2);//校验
  58. tx_buf[6]=0x03;//结束
  59. write(fd,tx_buf,7);//发送数据给从机
  60. usleep(50000);//延时
  61. ret=read(fd,rt_buf,8);//接收从机应答消息
  62. if(ret<0)//接收返回值小于0接收失败
  63. {
  64. printf("read err\n");
  65. return 1;
  66. }
  67. if(ret==8)//接收到长度8的数据
  68. {
  69. if(rt_buf[2]==0x00)//判断status位为0表示成功
  70. {
  71. return 0;
  72. }
  73. }
  74. return 1;
  75. }
  76. //防碰撞
  77. int PiccAnticoll(int fd)
  78. {
  79. int ret;
  80. unsigned char tx_buf[8];//存放要发送的数据
  81. int card_ID=0;
  82. tx_buf[0]=0x08;//命令长度
  83. tx_buf[1]=0x02;//命令类型
  84. tx_buf[2]='B';//命令
  85. tx_buf[3]=0x02;//数据长度
  86. tx_buf[4]=0x93;//碰撞级别选择1
  87. tx_buf[5]=0x00;
  88. tx_buf[6]=CalBCC(tx_buf,tx_buf[0]-2);//校验
  89. tx_buf[7]=0x03;//结束
  90. write(fd,tx_buf,8);//发送数据给从机
  91. usleep(50000);//延时
  92. ret=read(fd,rt_buf,10);//接收从机应答消息
  93. if(ret<0)//接收返回值小于0接收失败
  94. {
  95. printf("read err\n");
  96. return 1;
  97. }
  98. if(ret==10)//接收到长度10的数据
  99. {
  100. if(rt_buf[2]==0x00)//判断status位为0表示成功
  101. {
  102. card_ID=(rt_buf[7]<<24)|(rt_buf[6]<<16)|(rt_buf[5]<<8) |rt_buf[4];//读取buf中数据
  103. printf("ID=%x\n",card_ID);
  104. return 0;
  105. }
  106. }
  107. return 1;
  108. }
  109. int main()
  110. {
  111. int fd=uart1_init();//串口初始化
  112. while(1)
  113. {
  114. if(PiccRequest(fd))//请求
  115. {
  116. continue;
  117. }
  118. if(PiccAnticoll(fd))//防碰撞
  119. {
  120. continue;
  121. }
  122. }
  123. colse(fd);//关闭文件
  124. return 0;
  125. }

二、LCD使用及原理

1、lcd介绍


 由宽x=800,高y=480个像素点组成
在Linux中一切皆文件
LCD屏同样是一个文件:    /dev/fb0
fb:Frame Buffer 帧缓存,也叫做显存
帧缓存的每一个存储单元对应一个像素,整个帧缓存就对应一副图像
像素:描述组成图像的每一个点的颜色值
颜色:在计算机系统中,颜色常见的是由RGB三基色组成的24位整数值表示
用符号描述为:0x00RRGGBB    
即:
        bit16  ~ bit23 这8个bit位表示红色分量
        bit8   ~ bit15  这8个bit位表示绿色分量
        bit0   ~ bit7    这8个bit位表示蓝色分量
相关函数1、void *mmap(void *addr, size_t length, int prot, int flags,
                  int fd, off_t offset);//地址映射
2、int munmap(void *addr, size_t length); //地址释放映射
映射后,mmap的返回值(plcd)就是映射空间的首地址,对于映射屏幕来说,指针plcd指向的就是第一个像素点,给该地址存入数据,就是给对于的像素点显示颜色。因此  *plcd  =  0x00ff00;  就是给第一个像素点显示了绿色

 

 2、LCD初始化,对文件进行映射

  1. int *plcd=NULL;
  2. int lcd_fd;
  3. int lcd_init()
  4. {
  5. lcd_fd=open("/dev/fb0",O_RDWR);//打开lcd控制文件
  6. if(lcd_fd==-1)
  7. {
  8. perror("open lcd err\n");
  9. return -1;
  10. }
  11. plcd=mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcd_fd,0);//地址映射
  12. if(MAP_FAILED==plcd)
  13. {
  14. perror("mmap erro\n");
  15. return -1;
  16. }
  17. return 0;
  18. }

 3、LCD画点,清屏,显示字符串函数

  1. //lcd画点
  2. void lcd_draw_point(int x,int y,int color)
  3. {
  4. *(plcd+y*800+x)=color;
  5. }
  6. //清屏
  7. void lcd_clear(int color)
  8. {
  9. int x,y;
  10. for(y=0;y<480;y++)
  11. {
  12. for(x=0;x<800;x++)
  13. lcd_draw_point(x,y,color);
  14. }
  15. }
  16. //显示单个字符
  17. void show_word(unsigned char word[],int width,int length,int x0,int y0,unsigned int color)
  18. {
  19. int i,j,k;
  20. int x;
  21. for(i=0;i<length;i++)
  22. {
  23. x=word[i];
  24. //printf("%x\n",x);
  25. for(k=7;k>=0;k--)
  26. {
  27. if(x&0x01<<k)
  28. lcd_draw_point(x0+(7-k)+(i%(width/8)*8),y0+(i/(width/8)),color);
  29. }
  30. }
  31. }

 4显示图片

  1. //显示图片
  2. void lcd_show_bmp(int x,int y,char *bmpname)
  3. {
  4. unsigned char buf[4];
  5. int fd=open(bmpname,O_RDWR);
  6. if(fd==-1){
  7. perror("open bmp file err\n");
  8. return ;
  9. }
  10. //读魔数
  11. lseek(fd,0,SEEK_SET);
  12. read(fd, buf, 2);
  13. if(buf[0]!=0x42 || buf[1]!=0x4D)
  14. {
  15. printf("this picture is not bmo!\n");
  16. return ;
  17. }
  18. //读位图宽度
  19. int bmp_w=0;
  20. lseek(fd, 0x12, SEEK_SET);
  21. read(fd,&bmp_w,4);
  22. //读位图高度
  23. int bmp_h=0;
  24. lseek(fd,0x16,SEEK_SET);
  25. read(fd,&bmp_h,4);
  26. //读图片色深
  27. int bmp_colordepath=0;
  28. lseek(fd, 0x1c, SEEK_SET);
  29. read(fd,&bmp_colordepath,2);
  30. printf("bmp:%d*%d*%d\n",bmp_w,bmp_h,bmp_colordepath);
  31. //读像素数组
  32. lseek(fd,54, SEEK_SET);
  33. int i,j;
  34. for(i=0;i<bmp_h;i++)
  35. {
  36. for(j=0;j<bmp_w;j++)
  37. {
  38. int color=0;
  39. read(fd, &color, bmp_colordepath/8);
  40. lcd_draw_point(x+j,y+(bmp_h>0?(bmp_h-i-1):i),color);
  41. }
  42. lseek(fd, (4-bmp_colordepath/8*bmp_w%4)%4,SEEK_CUR);
  43. }
  44. //printf("i=%d,j=%d\n",x+j,y+(bmp_h>0?(bmp_h-i-1):i));
  45. close(fd);
  46. }

5、读触摸点坐标

  1. int get_coordinate(int *x,int *y)
  2. {
  3. struct input_event et;
  4. int fd=open("/dev/input/event0",O_RDONLY);
  5. if(fd==-1)
  6. {
  7. perror("open event0 failed");
  8. return -1;
  9. }
  10. while (1)
  11. {
  12. int r=read(fd, &et, sizeof(et));
  13. if(r==sizeof(et))
  14. {
  15. if(et.type==EV_ABS && et.code==ABS_X)//保存x
  16. {
  17. *x=et.value;
  18. }
  19. if(et.type==EV_ABS && et.code==ABS_Y)//保存y
  20. {
  21. *y=et.value;
  22. }
  23. if(et.type==EV_KEY && et.code==BTN_TOUCH && et.value==0)//手指离开
  24. {
  25. close(fd);
  26. return 0;
  27. }
  28. }
  29. }
  30. }

 三、使用文件保存信息

1、读文件里信息

  1. void write_user_to_file(FILE *fp)
  2. {
  3. int class=0;
  4. int number=0;
  5. char name[25];
  6. char str[124];
  7. printf("请输入class,number,name:\n");
  8. scanf("%d %d %s",&class,&number,name);
  9. sprintf(str,"%u %d %d %s\n",card_ID,class,number,name);//无符号整型写入
  10. fputs(str, fp);
  11. //更新用户信息
  12. users[num].card_id=card_ID;
  13. users[num].class=class;
  14. users[num].number=number;
  15. users[num].time_num=5;
  16. strcpy(users[num].name, name);
  17. num++;
  18. }

 2、从文件里删除信息

  1. FILE *delete_line(FILE *fp,unsigned int id)
  2. {
  3. FILE *ff;
  4. unsigned int id_bk=0;
  5. ff=fopen("./users_message_bk","at+");
  6. system("chmod 777 users_message_bk");//防止权限问题
  7. fseek(fp,0,SEEK_SET);
  8. while(fgets(data_buf,sizeof(data_buf),fp)!=NULL)
  9. {
  10. sscanf(data_buf,"%u",&id_bk);
  11. if(id_bk!=id)
  12. {
  13. fputs(data_buf,ff);
  14. //printf("id=%u,id_bk=%u\n",id,id_bk);//取值取无符号整型
  15. }
  16. }
  17. fclose(fp);
  18. remove("./users_message");
  19. fp=fopen("./users_message","at+");
  20. system("chmod 777 users_message");//防止权限问题
  21. fseek(ff,0,SEEK_SET);
  22. while(fgets(data_buf,sizeof(data_buf),ff)!=NULL)
  23. {
  24. fputs(data_buf,fp);
  25. }
  26. fclose(ff);
  27. remove("./users_message_bk");
  28. //更新用户信息
  29. num=0;
  30. fseek(fp,0,SEEK_SET);
  31. get_file_users_message();
  32. return fp;
  33. }

四、蓝牙通信与灯光

使用串口2

首先对串口2进行初始化

使用手机蓝牙助手与gec6818进行通信

效果如下

我使用的是gec6818驱动开发,对led的gpio进行高低电平的输出来控制led灯的亮灭

led测试代码如下

  1. #include <sys/types.h>
  2. #include <sys/stat.h>
  3. #include <fcntl.h>
  4. #include <unistd.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <stdlib.h>
  8. #include <sys/ioctl.h>
  9. /* ioctl: ./step_motor_test /dev/xxx type frequency
  10. */
  11. //定义LED的魔幻数
  12. #define MOTOR_forward _IO('x', 0)//正转
  13. #define MOTOR_backward _IO('x', 1)//逆转
  14. static int Power_10(int num)
  15. {
  16. int i,temp=1;
  17. for( i=0;i<num;i++)
  18. temp=temp*10;
  19. return temp;
  20. }
  21. int main(int argc, char **argv)
  22. {
  23. int fd,i=100;
  24. int len;
  25. unsigned int com,freq,num=0;
  26. char buf[5];
  27. if (argc < 4)
  28. {
  29. printf("Usage: \n");
  30. printf("%s <dev> type frequency\n", argv[0]);
  31. return -1;
  32. }
  33. // open
  34. fd = open(argv[1], O_RDWR);
  35. if (fd < 0)
  36. {
  37. printf("can not open file %s\n", argv[1]);
  38. return -1;
  39. }
  40. com=strtol(argv[2],NULL,0);
  41. freq=strtol(argv[3], NULL, 0);
  42. printf("com=%d,freq=%d\n",com,freq);
  43. if(com!=0 && com!=1)
  44. {
  45. printf("type=0 or 1\n");
  46. close(fd);
  47. return -1;
  48. }
  49. while(i--)
  50. {
  51. switch (com) {
  52. case 0:
  53. ioctl(fd,MOTOR_backward,freq);
  54. break;
  55. case 1:
  56. ioctl(fd,MOTOR_forward,freq);
  57. break;
  58. }
  59. //sleep(1);
  60. }
  61. // close
  62. close(fd);
  63. return 0;
  64. }

 使用mplayer进行语音播报

总结

经过这个小项目我获得了很多收获,对linux操作系统和RFID有了更加深刻的理解。 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/神奇cpp/article/detail/750006
推荐阅读
相关标签
  

闽ICP备14008679号