FM1701调试手记

做完刷卡版充电插座这个项目遇到的问题做一些笔记

首先是硬件电路如下:

从 TX 发射出去的是调制过的 13.56MHz 载波信号,软件发送命令,6脚产生13.56MHZ的正弦波的载波信号,然后天线刷卡得到信号跟载波信号叠加传输到RX脚。


在使用SPI的时候配要根据FM1701的时序图,由下图可以判断出用的SPI模式(参考博客

批量生产的时候测试的时候可以输出卡,后来到现场都不行,偶尔能刷出来,就是因为SPI模式配错。

软件部分

技术支持给的驱动是裸机的,我做项目的时候是用RT_Thread系统需要更换SPI的发送、接收接口函数。

初始化函数、SPI读写函数如下:

unsigned char Fm1701_init(void)
{
	u8 temp = 0x55;
	RFID_RST_H;
	rt_thread_delay(10);
	RFID_RST_L;
	rt_thread_delay(50);
	spi_fm1701 = (struct rt_spi_device *)rt_device_find("FM1701");
	if(spi_fm1701 == RT_NULL)
	{
		return RT_ERROR;
	}
	/* config spi */
	{
		struct rt_spi_configuration cfg;
		cfg.data_width = 8;
		cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB;
		cfg.max_hz = 5000;//50000000
		if(rt_spi_configure(spi_fm1701, &cfg) != RT_EOK)
		{
			return RT_ERROR;
		}
	}
	if(FM1702_Bus_Sel())		 	//总线选择
	{
//		rt_kprintf("FM1701 总线选择成功! \r\n");
		temp = Fm1701_read(0x05);
		if(temp == 0x60)
		{ 
			Fm1701_write(TxControl,0x5b);	
			return RT_EOK;
		}
		else
		{
			return RT_ERROR;
		}			 
	}
	else
	{
		rt_kprintf("FM1701 总线选择失败!\r\n");
		return RT_ERROR;
	}	
}
/******************************************************************************
*
* 描述:   
* 输入:
* 输出:
* 返回:
*
******************************************************************************/
static void Fm1701_write(uchar address,uchar data )
{
	u8	status;  
	address = address << 1;
	address = address & 0x7f;
	status = rt_spi_send_then_send(spi_fm1701, &address, 1, &data, 1);  

//	address = address << 1;
//	address = address & 0x7f;
//    send_buf[0]=address;
//    send_buf[1]=data&0xff;

//    rt_spi_send(spi_fm1701,  send_buf, 2);
}
/******************************************************************************
*
* 描述:   
* 输入:
* 输出:
* 返回:
*
******************************************************************************/
static u8 Fm1701_read(uchar address)
{
	u8	status;  
	u8	result;
	address=address<<1;
	address=address | 0x80;
	status = rt_spi_send_then_recv(spi_fm1701,&address,1,&result, 1);
	return result;
//    u8 send_buf[2];
//	address=address<<1;
//	address=address | 0x80;
//	send_buf[0]=address;

//    rt_spi_recv(spi_fm1701, send_buf, 2);
//    return (send_buf[1]);
}

在项目中出现死机情况是在检测到卡冲突之后进入循环,刷卡这个线程应该有比较高的优先级,才不会在在读卡到一半被打断程序应该改成:

/****************************************************************/
/*名称: AntiColl                                                */
/*功能: 该函数实现对放入FM1702操作范围之内的卡片的防冲突检测     */
/*输入: N/A                                                     */
/*输出: FM1702_NOTAGERR: 无卡                                   */
/* FM1702_BYTECOUNTERR: 接收字节错误                            */
/* FM1702_SERNRERR: 卡片序列号应答错误                          */
/* FM1702_OK: 卡片应答正确                                      */
/****************************************************************/
uchar AntiColl(void)
{
	uchar	temp;
	uchar	i;
	uchar	row, col;
	uchar	pre_row;
	uchar	fail_cnt=0;
	row = 0;
	col = 0;
	pre_row = 0;
	
	while(1)
	{
		Fm1701_write(CRCPresetLSB,0x63);
		Fm1701_write(CWConductance,0x3f);
		Fm1701_write(ModConductance,0x3f);
		buf[0] = RF_CMD_ANTICOL;
		buf[1] = 0x20;
		Fm1701_write(ChannelRedundancy,0x03);	                   // 关闭CRC,打开奇偶校验
		temp = Command_Send(2, buf, Transceive);
		if(temp == FALSE)
		{
			return(FM1702_NOTAGERR);
		}

		temp = Fm1701_read(FIFO_Length);
		if(temp == 0)
		{
			return FM1702_BYTECOUNTERR;
		}

		Read_FIFO(buf);
		Save_UID(row, col, temp);			        // 将收到的UID放入UID数组中
	
		temp = Fm1701_read(ErrorFlag);			    // 判断接収数据是否出错
		temp = temp & 0x01;
		if(temp == 0x00)
		{
			temp = Check_UID();			            // 校验收到的UID 卡ID前面4个字节是ID号最后一个字节是校验码
			if(temp == FALSE)
			{
				return(FM1702_SERNRERR);
			}
			return(FM1702_OK);
		}
		else
		{   /*查询位置,对应错误的位置清除*/
			temp = Fm1701_read(CollPos);             // 读取冲突检测寄存器 
			row = temp / 8;
			col = temp % 8;								
			buf[0] = RF_CMD_ANTICOL;
			Set_BitFraming(row + pre_row, col);	//     设置待发送数据的字节数 
			pre_row = pre_row + row;
			for(i = 0; i < pre_row + 1; i++)
			{
				buf[i + 2] = UID[i];
			}

			if(col != 0x00)
			{
				row = pre_row + 1;
			}
			else
			{
				row = pre_row;
			}
			temp = Command_Send(row + 2, buf, Transceive);	
		}
		fail_cnt++;
		if(fail_cnt>=5)
		{
			return(FM1702_NOTAGERR);//  add by suguolin
		}
		APP_IWDGClr();
	}
}

猜你喜欢

转载自blog.csdn.net/SuGuolin/article/details/85009060