// 以下代码基于 RFID 硬件,主要实现功能
获取当前刷卡的卡号(比如公交卡,饭卡等等)
#include <stdio.h>
#include <assert.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/select.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <stdbool.h>
#include <string.h>
#include <termios.h>
#define UART1 "/dev/ttySAC1"
#define UART2 "/dev/ttySAC2"
/*****************************************************/
/*************封装主机发送命令的串口属性****************/
/***************该处使用的是RFID模块*******************/
/*****************************************************/
void init_tty(int fd)
{
// 1、准备串口属性设置结构体
struct termios new_termios;
bzero(&new_termios, sizeof (new_termios));
// 2、将串口属性设置为默认属性
//cfmakeraw(&termios_new);
// 2、设置串口属性为只收发数据
new_termios.c_cflag |= CLOCAL | CREAD;
// 3、比特率设置
cfsetispeed(&new_termios, B9600); // 接收波特率
cfsetospeed(&new_termios, B9600); // 发送波特率
// 4、设置数据位
new_termios.c_cflag &= ~CSIZE;
new_termios.c_cflag |= CS8;
// 5、设置奇偶校验 这里不需要奇偶校验
new_termios.c_cflag &= ~PARENB;
// 5、设置奇校验
// new_termios.c_cflag |= (PARODD | PARENB);
// new_termios.c_iflag |= INPCK;
//5、设置偶校验
// new_termios.c_cflag |= PARENB;
// new_termios.c_cflag &= ~PARODD;
// new_termios.c_iflag |= INPCK;
// 6、设置停止位
new_termios.c_cflag &= ~CSTOPB;
// 7、设置等待时间以及最小接收数据量
new_termios.c_cc[VTIME] = 0;
new_termios.c_cc[VMIN] = 1;
// 8、设置接收刷新缓冲,立即刷新输入输出缓冲
tcflush (fd, TCIFLUSH);
// 9、配置串口属性立即生效
if(tcsetattr(fd, TCSANOW, &new_termios))
printf("Setting the serial1 failed!\n");
}
// 计算校验和
unsigned char CalBCC(unsigned char *buf, int n)
{
int i;
unsigned char bcc=0;
for(i = 0; i < n; i++)
{
bcc ^= buf[i];
}
return (~bcc);
}
// 考虑到以后卡片的读取可能是多线程操作,故写成标准线程处理函数
void uart_send_cmd(void *arg)
{
int fd = *((int *)arg); // 获取串口描述符
char send_cmd[8];
char recv_msg[12];
char ID[4];
int flag = 1;
int count = 0;
// 1、设置发送 ISO14443 A 类命令
bzero(send_cmd, sizeof(send_cmd));
send_cmd[0] = 0x07; // 帧长为7
send_cmd[1] = 0x02; // ISO14443 A类命令
send_cmd[2] = 0x41; // 命令模式为 'A'
send_cmd[3] = 0X01; // 信息长度为 1
send_cmd[4] = 0x52; // 接受所有卡片
send_cmd[5] = CalBCC(send_cmd, send_cmd[0] - 2);
send_cmd[6] = 0x03; // 命令结束位
// 2、发送命令给RDFI
while (1)
{
tcflush (fd, TCIFLUSH);
bzero(recv_msg, sizeof (recv_msg));
write(fd, send_cmd, send_cmd[0]);
read(fd, recv_msg, sizeof (recv_msg));
// 3、收到正确回复
if (recv_msg[2] == 0x00)
{
fprintf(stderr, "刷卡成功\n");
break;
}
else
{
if (flag == 1)
{
fprintf(stderr, "等待刷卡");
flag++;
}
if (count == 10)
{
fprintf(stderr, ".");
count = 0;
}
usleep(50*1000);
count++;
}
}
// 1、设置发送 ISO14443 B 类命令
bzero(send_cmd, sizeof(send_cmd));
send_cmd[0] = 0x08; // 帧长为8
send_cmd[1] = 0x02; // ISO14443A类命令
send_cmd[2] = 0x42; // 命令模式为 'B'
send_cmd[3] = 0X02; // 信息长度为 2
send_cmd[4] = 0x93; // 设置第一级防碰撞
send_cmd[5] = 0x00; // 位计数 0 不懂,不懂
send_cmd[6] = CalBCC(send_cmd, send_cmd[0] - 2);
send_cmd[7] = 0x03; // 命令结束位
// 2、发送命令给RDFI
tcflush (fd, TCIFLUSH);
bzero(recv_msg, sizeof (recv_msg));
write(fd, send_cmd, send_cmd[0]);
read(fd, recv_msg, sizeof (recv_msg));
// 3、收到正确回复
if (recv_msg[2] == 0x00)
{
strncpy(ID, recv_msg+4, 4);
fprintf(stderr, "卡号是:");
for (int i = 0; i < 4; i++)
printf("%d\n", ID[i]);
printf("\n");
}
else
{
fprintf(stderr, "获取卡号失败\n");
}
}
int main(int argc, char **argv)
{
int fd = open(UART1, O_RDWR | O_NOCTTY);
init_tty(fd);
uart_send_cmd(&fd);
return 0;
}