1.1 概述
本模块属 RFID 超小型 IC(Mifare1/TypeA/14443A)卡读卡模块,可单独使用,也可二次开发。可选接口有(miniUSB 接口,RS232 串口,TTL串口),用户无须了解任何 RC523 等射频芯片的复杂控制命令,也无需了解 14443A 协议,只需将卡片靠近读卡模块感应范围即可马上读取到唯一卡片物理序列号,也可通过指令读取卡片指定扇区内容,适合门禁、停车场、多卡应用、智能终端等卡片身份识别产品的开发。
1.2 特点
模块体积小,安装简易,用途灵活,集成天线,使用及二次开发简单。自带 CPU 控制无需用户二次编辑程序,有卡靠近天线范围时即可自动读取物理卡号并于 PC 端输出(串口接收卡号 或键盘模式输出) 能与任何系统无缝对接,无需另外安装驱动程序,只需要接通 VCC、TX、RX、GND 四根线或插上 USB 即可通讯。 电压范围(3.3~5V) 人性化设计,蜂鸣器作为提醒动作,板载电源 LED 灯/读卡 LED 指示灯,方便查看上电状态以及读卡响应状态。功能齐全,开发简单,天线互补干扰可重叠在一起。
1.3串口通讯
模块通过 2.0*4Pin USB 插座(J2)于 PC 端连接。连接前注意 U6 处是否贴片,如无则模块须通过 RS232
转 TTL 模块才能与 PC 连接,如有则模块通过标配串口线与 PC(COM1/COM2)直连(注意 V 口电压必须为
+5V)
成功连接后 需使用串口助手等 PC 串口工具来接收卡号
如二次开发,只需给模块提供正确电源,刷卡时 卡号既可通过 TX 向外部发送出去。默认卡号字节顺
序:正向 卡号数字格式:十六进制
注意事项:
打开对应端口号(如果是 PC 主板上的串口则端口号为 COM1 或 COM2,如使用 RS232 转 TTL 模块需
于计算机硬件出查询端口号)
输出方式(十六进制),
波特率:9600
校验位:None
数据位:8
停止位:1
如无法接收卡号 检查:
1:线序是否正确, 电压是否正常(5V)
2:端口是否选择正确,端口是否被其余应用占用(占用要关掉)
3:串口工具 参数设置 是否正确
废话不多说直接上代码!
2.1在设备树中配好所需的读写uart 口
//n7v1.dts files
uart0: uart@04003000 {
compatible = "lombo,n7v1-uart";
device_type = "uart0";
reg = <0x04003000 0x800>;
interrupts = ;
clocks = <&apb0_gate 4>, <&apb0_reset 4>, <&uart0_clk>, <&osc24m>, <&perh0_pll_div8>;
uart_port = <0>;
uart_type = <2>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart0_1>;
status = "okay";
};
//n7v1-pinctrl.dtsi file
pinctrl_uart0_0: uart0-grp0 {
lombo,pins = "gpe-5", "gpe-6";
lombo,pin-function = <7>;
lombo,pin-pud = ;
lombo,pin-drv = ;
lombo,pin-pud-reg = ;
};
2.2应用代码
2.2.1初始化一个线程去执行读卡的初始化动作
int card_parse_init(void)
{
pthread_t card_parse_thread;
if (pthread_create(&card_parse_thread, NULL, card_parse_start, NULL)) {
ALOGE("pthread_create card_parse_thread thread failed!!\n");
return -1;
}
pthread_detach(card_parse_thread);
return 0;
}
2.2.2初始化 读写卡数据的UART口
int UART0_Open(int fd, char *port)
{
fd = open(port, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd < 0) {
perror("Can't Open Serial Port");
return(FALSE);
}
if (fcntl(fd, F_SETFL, 0) < 0) {
printf("fcntl failed!\n");
return(FALSE);
} else {
printf("fcntl=%d\n",fcntl(fd, F_SETFL,0));
}
/*
* if (0 == isatty(STDIN_FILENO)) {
* printf("standard input is not a terminal device\n");
* return(FALSE);
* } else
* printf("isatty success!\n");
*
*/
printf("fd->open=%d\n", fd);
return fd;
}
void UART0_Close(int fd)
{
close(fd);
}
int UART0_Set(int fd,int speed,int flow_ctrl,int databits,int stopbits,int parity)
{
int i;
int status;
int speed_arr[] = { B115200, B19200, B9600, B4800, B2400, B1200, B300};
int name_arr[] = {115200, 19200, 9600, 4800, 2400, 1200, 300};
struct termios options;
if (tcgetattr(fd, &options) != 0) {
perror("SetupSerial 1");
return (FALSE);
}
for (i= 0; i < sizeof(speed_arr) / sizeof(int); i++) {
if (speed == name_arr[i]) {
cfsetispeed(&options, speed_arr[i]);
cfsetospeed(&options, speed_arr[i]);
}
}
options.c_cflag |= CLOCAL;
options.c_cflag |= CREAD;
switch (flow_ctrl) {
case 0:
options.c_cflag &= ~CRTSCTS;
break;
case 1:
options.c_cflag |= CRTSCTS;
break;
case 2:
options.c_cflag |= IXON | IXOFF | IXANY;
break;
}
options.c_cflag &= ~CSIZE;
switch (databits) {
case 5:
options.c_cflag |= CS5;
break;
case 6:
options.c_cflag |= CS6;
break;
case 7:
options.c_cflag |= CS7;
break;
case 8:
options.c_cflag |= CS8;
break;
default:
fprintf(stderr,"Unsupported data size\n");
return (FALSE);
}
switch (parity) {
case 'n':
case 'N':
options.c_cflag &= ~PARENB;
options.c_iflag &= ~INPCK;
break;
case 'o':
case 'O':
options.c_cflag |= (PARODD | PARENB);
options.c_iflag |= INPCK;
break;
case 'e':
case 'E':
options.c_cflag |= PARENB;
options.c_cflag &= ~PARODD;
options.c_iflag |= INPCK;
break;
case 's':
case 'S':
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
break;
default:
fprintf(stderr,"Unsupported parity\n");
return (FALSE);
}
switch (stopbits) {
case 1:
options.c_cflag &= ~CSTOPB;
break;
case 2:
options.c_cflag |= CSTOPB;
break;
default:
fprintf(stderr,"Unsupported stop bits\n");
return (FALSE);
}
options.c_oflag &= ~OPOST;
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
options.c_cc[VTIME] = 1;
options.c_cc[VMIN] = 0;
tcflush(fd, TCIFLUSH);
if (tcsetattr(fd, TCSANOW, &options) != 0) {
perror("com set error!\n");
return (FALSE);
}
return (TRUE);
}
int UART0_Init(int fd, int speed,int flow_ctrl,int databits,int stopbits,int parity)
{
int err;
if (UART0_Set(fd, speed, 0, 8, 1, 'N') == FALSE) {
return FALSE;
} else {
return TRUE;
}
}
int UART0_Recv(int fd, char *rcv_buf,int data_len, Boolean no_wait)
{
int len, fs_sel;
fd_set fs_read;
struct timeval time;
FD_ZERO(&fs_read);
FD_SET(fd, &fs_read);
time.tv_sec = 20;
time.tv_usec = 0;
if (no_wait) {
fs_sel = 1;
} else {
fs_sel = select(fd+1, &fs_read, NULL, NULL, &time);
if (fs_sel) {
usleep(100*1000);
}
}
if (fs_sel) {
len = read(fd, rcv_buf, data_len);
if (len > 0) {
printf("read len= %d\n", len);
}
return len;
} else {
return FALSE;
}
}
int UART0_Send(int fd, char *send_buf,int data_len)
{
int len = 0;
int total_len = 0;
is_uart_sending = TRUE;
while (total_len < data_len) {
len = write(fd, send_buf, data_len);
total_len += len;
printf("UART write len= %d,total_len= %d,\n", len, total_len);
sleep(1);
if (len <= 0) {
printf("write len <= 0\n");
break;
}
}
is_uart_sending = FALSE;
if (len == data_len ){
printf("send data is %s\n", send_buf);
return len;
}else{
tcflush(fd, TCOFLUSH);
return FALSE;
}
}
2.2.3 读卡号
void *card_parse_start(void *args)
{
int fd = -1;
int err;
int len;
int total_len;
int i, pos = 0;
char rcv_buf[32];
sleep(5);
do {
sleep(3);
fd = UART0_Open(fd, "/dev/ttySLB3");
err = UART0_Init(fd, 9600, 0, 8, 1, 'N');
if(FALSE == err)
UART0_Close(fd);
printf("Set Port Exactly! err:%d, fd:%d\n",err,fd);
} while (FALSE == err || FALSE == fd);
while (1) {
total_len = 0;
memset(rcv_buf, 0, sizeof(rcv_buf));
for ( ; ;) {
len = UART0_Recv(fd, &rcv_buf[total_len],
sizeof(rcv_buf) - total_len, total_len > 0);
if (len > 0) {
total_len += len;
} else {
break;
}
}
if (total_len > 0) {
ALOGD("data len: %d,card_no is: ", total_len);
for (i = 0; i < total_len; i++) {
if (rcv_buf[i] != 0x30) {
pos = i;
break;
}
}
for (i = 0; i < total_len - pos; i++) {
ALOGD("card_data:oX%02X ",rcv_buf[i]);
if (rcv_buf[i] == 0x0a || rcv_buf[i + pos] == 0x0a)
rcv_buf[i] = '\0';
else
rcv_buf[i] = rcv_buf[i + pos];
}
UART0_Close(fd);
}
读出来的卡号为十六进制数
读出来的0x33 0x31 .... 是十六进制0x33 转换成十进制为51 ,对应的ASCII 码 为 3
card_no = atoll(rcv_buf);
(0x0a为回车换行)
注意这里我碰到的一个问题:
atoi: 返回值超过了int 的最大值导致转的卡号一直对不上;
atol:由于 设备是 arm 32 位系统,返回的值超过了long值的范围;
最后用atoll才能正确的返回卡号的值;
可以得知卡号为:3191570528