精选文章 莱卡TG0020-M8读卡器单片机开发

莱卡TG0020-M8读卡器单片机开发

作者:请叫我阿进 时间: 2020-08-05 04:34:37
请叫我阿进 2020-08-05 04:34:37

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);
}

读出来的卡号为十六进制数

莱卡TG0020-M8读卡器单片机开发1

读出来的0x33 0x31 .... 是十六进制0x33 转换成十进制为51 ,对应的ASCII 码 为 3

card_no = atoll(rcv_buf);

(0x0a为回车换行)

注意这里我碰到的一个问题:

atoi: 返回值超过了int 的最大值导致转的卡号一直对不上;

atol:由于 设备是 arm 32 位系统,返回的值超过了long值的范围; 

最后用atoll才能正确的返回卡号的值;

可以得知卡号为:3191570528

 

 

 

 

 

 

 

 

勿删,copyright占位
分享文章到微博
分享文章到朋友圈

上一篇:计蒜客----训练联盟赛ICPC Yokohama, 2018(Domestic)

下一篇:LeetCode-015三数之和

您可能感兴趣

  • 一文读懂人脸识别技术

    2019-08-27 17:06:26 本文内容涵盖人脸识别发展历程、市场研究、核心技术、商业应用以及产业落地、个人看法等干货研究。注意,本文干货满满,约有2万7千字,强烈建议大家先收藏后学习! 01 发展史 1. 人脸识别的理解 人脸识别(Face Recognition)是一种依据人的面部特征(如统计或几何特征等),自动进行身份识别的一种生物识别技术,又称为面像识别、人像识别、相貌识别、...

  • Go 语言创建者,大佬们的有趣的对话访谈

    卡门(Carmen)和乔恩(Jon)与罗布·派克(Rob Pike)和罗伯特·格里塞梅尔(Robert Griesemer)(Go的创造者)讨论了它的起源,增长,影响力和未来。这是一部史诗般的剧集,深入探讨了Go语言的历史和细节,以及Go语言的方式和原因,以及他们在创建这种出色的编程语言过程中所做的选择。 卡门·安多(CARMEN ANDOH) 欢迎大家,去时间!今天我们为您举办一场非常特别...

  • 鲲鹏性能优化十板斧(三)——网络子系统性能调优

    1 网络子系统性能调优 3.1 调优简介 3.2 常用性能监测工具 3.3 优化方法 1.1 调优简介 调优思路 本章主要是围绕优化网卡性能和利用网卡的能力分担CPU的压力来提升性能。在高并发的业务场景下,推荐使用两块网卡,减少跨片内存访问的次数。即将两块网卡分别绑定在服务器的不同CPU上,每个CPU只处理对应的网卡数据。高并发场景还可以为网卡选择x16的PCIE卡。 高并发场景是指:在同时...

  • 非常详细的sklearn介绍

    0 引言 Sklearn (全称 Scikit-Learn) 是基于 Python 语言的机器学习工具。它建立在 NumPy, SciPy, Pandas 和 Matplotlib 之上,里面的 API 的设计非常好,所有对象的接口简单,很适合新手上路。 在 Sklearn 里面有六大任务模块:分别是分类、回归、聚类、降维、模型选择和预处理,如下图从其官网的截屏。 要使用上述六大模块的方法,...

  • 任正非:华为5G是瞎猫碰死老鼠

    喜欢话糙理不糙的任正非,又飙金句。 11月6日,在和彭博社记者对话时,谈到华为5G,他说: “回顾这个过程,我们也没有什么必胜的信心,有时候也是瞎猫碰上了死老鼠,刚好碰上世界是这个需求。 我们这三十年运气比较好,每个点都踩在时代的鼓点上。 ” 在对话中,任正非表示,十年前,土耳其的教授Erdal Arikan(通信技术专家,Polar码之父Arikan)曾发表过一篇数学论文。 华为捕捉到这篇...

  • 花了三个月终于把所有的Python库全部整理了!祝你早日拿到高薪!

    链接:https://www.jianshu.com/p/2642f9d28f34 库名称简介 Chardet字符编码探测器,可以自动检测文本、网页、xml的编码。 colorama主要用来给文本添加各种颜色,并且非常简单易用。 Prettytable主要用于在终端或浏览器端构建格式化的输出。 difflib,[Python]标准库,计算文本差异 Levenshtein,快速计算字符串相似度...

  • 这项技术厉害了!让旅行者 2 号从星际空间发首批数据!

    立即购票:https://dwz.cn/z1jHouwE 物联网作为信息系统向物理世界的延伸,极大地拓展了人类认知和控制物理世界的能力,被称为继计算机和互联网之后的世界信息产业的第三次浪潮,正在深刻地改变着人类的生存环境和生活方式。 据最新报道称, 从去年进入星际空间的旅行者 2 号探测器,返回极为珍贵的首批数据,利于科学家研究外太空。在探测器探测的过程中,涉及数据感知、数据传输与处理等物联...

  • 美通企业日报 | 全球金融科技50强榜中企居首;施乐退出与富士胶片合资企业...

    今日看点 11月4日,KPMG(毕马威)和金融科技投资公司H2 Ventures联合发布了2019年全球金融科技100强榜单 (Fintech100)。入选 Fintech100的公司,既有全球首屈一指的50家金融科技公司,也包括引人注目的50家“明日之星”;前者以创新能力、资金筹集、企业规模和影响范围为标准,后者则普遍处于创新技术前沿,并致力追求全新的业务模式。蚂蚁金服、Grab和京东数字...

华为云40多款云服务产品0元试用活动

免费套餐,马上领取!
CSDN

CSDN

中国开发者社区CSDN (Chinese Software Developer Network) 创立于1999年,致力为中国开发者提供知识传播、在线学习、职业发展等全生命周期服务。