994|1

330

帖子

5

TA的资源

纯净的硅(中级)

楼主
 

【米尔-TI AM62x开发板-试用评测】危险品设备NFC标签数据读取 [复制链接]

在 【米尔-TI AM62x开发板-试用评测】485通讯测试 中,分享了485通讯的测试,这篇分享,则是实际的应用。

 

一、硬件准备

之前做过一套危险品设备溯源的系统,手头还有开发测试时使用的读卡器和NFC标签,具体如下:

 这个设备,供电是5V,通讯是485接口的。

 

在开发板上,正好有5V供电的位置:

 

 

因此,使用GPMC的5V供电,然后连接到485接口的A2、B2:

 

二、命令行查看数据

在linux的命令行下,能够通过系统自带的工具,查看串口数据的数据。

连接后以后,可以试用如下的命令进行查看:

stty -F /dev/ttyS0 raw speed 9600

cat /dev/ttyS0 | stdbuf -oL hexdump -C

具体结果如下:

 

读卡器返回的数据为HEX格式,当数据以AA DD 00 0B开头的时候,返回的就是读卡的数据;当数据以AA DD 00 04开头的时候,返回的就是NFC标签离开的状态。

 

三、代码编写

 

系统提供支持后,RS485的操作,和普通的串口操作类似了。

根据以上读卡器输出数据的情况,以及linux下面串口编程的经验,编写代码如下:

#include <stdlib.h>
#include <fcntl.h>
#include "stdio.h"
#include "termios.h"
#include "unistd.h"
#include "limits.h"
#include <stdint.h>
#include "time.h"
#include <string.h>
//===================
#include <sys/select.h>
#include <sys/time.h>
//===================

#define UART_DEV "/dev/ttyS0" // 根据电脑插入的串口号定义

#define CARD_1 "AADD000B00000053DE738C30000143"
#define CARD_2 "AADD000B00000053E1648C3000016B"

const char hex_table[] = {
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
void to_hex(char *s, int l, char *d)
{
    while (l--)
    {
        *(d++) = hex_table[*s >> 4];
        *(d++) = hex_table[*(s++) & 0x0f];
    }
}

void main()
{
    int fd = 0;
    int rx_len = 0;
    int step = 0;
    uint8_t rx_buff[128] = {0};
    uint8_t rx_buff_hex[257] = {0};

    //==========打开串口============//
    fd = open(UART_DEV, O_RDWR | O_NOCTTY);
    if (fd < 0)
    {
        printf("Serial Port (%s) Open Fail! \n", UART_DEV);
        return;
    }

    printf("Serial Port (%s) Open Success!\n\n", UART_DEV);

    //==========配置串口============//
    struct termios opt;  // 配置串口的属性定义在结构体struct termios中
    tcgetattr(fd, &opt); // 获取终端控制属性

    cfsetispeed(&opt, B9600); // 指定输入波特率(读卡器的波特率默认9600bps)
    cfsetospeed(&opt, B9600); // 指定输出波特率(读卡器的波特率默认9600bps)

    /* c_lflag 本地模式 */
    opt.c_cflag &= ~INPCK;           // 不启用输入奇偶检测
    opt.c_cflag |= (CLOCAL | CREAD); // CLOCAL忽略 modem 控制线,CREAD打开接受者

    /* c_lflag 本地模式 */
    opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // ICANON启用标准模式;ECHO回显输入字符;ECHOE如果同时设置了 ICANON,字符 ERASE 擦除前一个输入字符,WERASE 擦除前一个词;ISIG当接受到字符 INTR, QUIT, SUSP, 或 DSUSP 时,产生相应的信号

    /* c_oflag 输出模式 */
    opt.c_oflag &= ~OPOST;           // OPOST启用具体实现自行定义的输出处理
    opt.c_oflag &= ~(ONLCR | OCRNL); // ONLCR将输出中的新行符映射为回车-换行,OCRNL将输出中的回车映射为新行符

    /* c_iflag 输入模式 */
    opt.c_iflag &= ~(ICRNL | INLCR);        // ICRNL将输入中的回车翻译为新行 (除非设置了 IGNCR),INLCR将输入中的 NL 翻译为 CR
    opt.c_iflag &= ~(IXON | IXOFF | IXANY); // IXON启用输出的 XON/XOFF流控制,IXOFF启用输入的 XON/XOFF流控制,IXANY(不属于 POSIX.1;XSI) 允许任何字符来重新开始输出

    /* c_cflag 控制模式 */
    opt.c_cflag &= ~CSIZE;  // 字符长度掩码,取值为 CS5, CS6, CS7, 或 CS8,加~就是无
    opt.c_cflag |= CS8;     // 数据宽度是8bit
    opt.c_cflag &= ~CSTOPB; // CSTOPB设置两个停止位,而不是一个,加~就是设置一个停止位
    opt.c_cflag &= ~PARENB; // PARENB允许输出产生奇偶信息以及输入的奇偶校验,加~就是无校验

    /* c_cc[NCCS] 控制字符 */
    opt.c_cc[VTIME] = 0; // 等待数据时间(10秒的倍数),每个单位是0.1秒  若20就是2秒
    opt.c_cc[VMIN] = 0;  // 最少可读数据,非规范模式读取时的最小字符数,设为0则为非阻塞,如果设为其它值则阻塞,直到读到到对应的数据,就像一个阀值一样,比如设为8,如果只接收到3个数据,那么它是不会返回的,只有凑齐8个数据后一齐才READ返回,阻塞在那儿
    /* new_cfg.c_cc[VMIN]   =   8;//DATA_LEN;
       new_cfg.c_cc[VTIME]  =   20;//每个单位是0.1秒  20就是2秒
       如果这样设置,就完全阻塞了,只有串口收到至少8个数据才会对READ立即返回,或才少于8个数据时,超时2秒也会有返回
       另外特别注意的是当设置VTIME后,如果read第三个参数小于VMIN ,将会将VMIN 修改为read的第三个参数*/

    /*TCIFLUSH  刷清输入队列
      TCOFLUSH  刷清输出队列
      TCIOFLUSH 刷清输入、输出队列*/
    tcflush(fd, TCIOFLUSH);       // 刷串口清缓存
    tcsetattr(fd, TCSANOW, &opt); // 设置终端控制属性,TCSANOW:不等数据传输完毕就立即改变属性

    while (1)
    {
        //==========串口接收(字符串)============//
        while (((rx_len = read(fd, rx_buff, sizeof(rx_buff))) > 0))
        {
            rx_buff[rx_len] = 0;
            rx_buff_hex[rx_len * 2] = '\0';
            to_hex(rx_buff, rx_len, rx_buff_hex);
            printf("recv[%d]: %s\n", rx_len, rx_buff_hex);

            // 数据头部检查
            if (rx_len > 4 && rx_buff[0] == 0xAA && rx_buff[1] == 0xDD)
            {
                // 数据类型检查
                if (rx_buff[3] == 0x0B)
                {
                    // 卡片读取
                    if (strcmp(CARD_1, rx_buff_hex) == 0)
                    {
                        printf("CARD1: %s\n", rx_buff_hex);
                    }
                    else if (strcmp(CARD_2, rx_buff_hex) == 0)
                    {
                        printf("CARD2: %s\n", rx_buff_hex);
                    }
                    else
                    {
                        printf("CARDX: %s\n", rx_buff_hex);
                    }
                    step = 1;
                }
                else if (rx_buff[3] == 0x04)
                {
                    // 卡片离开
                    if (step == 1)
                    {
                        printf("CARD: removed\n");
                        step = 2;
                    }
                }
                else
                {
                    printf("data error\n");
                }
            }
        }
    }
}

编写后,保存为nfc_reader.c,然后,在交叉编译环境中,编译上述代码,并将编译后生成的文件,上传到开发板。

 

在开发板上运行 nfc_reader,再将NFC标签拿到读卡器上方,一会再拿开,具体结果如下:

 

 

现在,已经能够成功读取到了NFC标签的数据了。

 

四、简单界面编写

这个板子是AM6231,没有GPU,所以就没有专门研究图形界面了。

结合以前的经验,在BASH环境中,写了个简单的界面:

#!/bin/bash

screen_width=$(stty size |awk '{print $2}')
let screen_height=$(stty size |awk '{print $2}')
let screen_height=screen_height+1
stdbuf -oL ./nfc_reader | stdbuf -oL cat | stdbuf -oL grep -E 'CARD' | dialog --title "RS485 NFC Card Reader System v1.0" --programbox $screen_height $screen_width

 

然后,通过手机,连接到开发板的ssh环境,做为屏幕显示,最终效果如下:

 

 

实际读卡离卡的效果如下:

6296_1708655025

 

五、总结

上面只是演示了通过485接口,与NFC读卡器的基本操作。

在实际项目使用中,还会根据读取到的卡号,进行信息的显示,以及根据状态进行报警。

大家如果有类似的设备,可以进一步完善功能。

 

六、参考资料

最新回复

通过485接口和NFC读卡器的基本操作效果还行   详情 回复 发表于 2024-2-24 07:49
点赞 关注(1)
 

回复
举报

6828

帖子

0

TA的资源

五彩晶圆(高级)

沙发
 

通过485接口和NFC读卡器的基本操作效果还行

 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表