(二)串口通信实例

// 以下代码基于 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;
}

猜你喜欢

转载自blog.csdn.net/qq_41985711/article/details/82986805