⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fm1702.c

📁 ARM_CORTEX-M3应用实例开发详解光盘
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************* (C) Embest ***********************************
* File Name          : fm1702.c
* Author             : tary
* Date               : 2009-06-25
* Version            : 0.4u
* Description        : fm1702 device low level operations 
******************************************************************************/

/* Includes ------------------------------------------------------------------*/
#include "fm1702_inf.h"
#include "fm1702.h"
#include "iso14443.h"
#include <stdio.h>
#include <string.h>

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#if FM1702_CW_DEBUG
int CW_VAL = 0x3F;
int MOD_W_VAL = 0x13;
#endif
unsigned long stm;

/* Private macro -------------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
//FM1702的FIFO操作
__inline int fifo_len(void);
static int clear_fifo(void);
static int write_fifo(char* buf, int len);
static int read_fifo(char* buf);

int err_chk(const char* file, int lineno);

static int trans_uid(int collision, char* uid, char* buf, int len);

/* Private functions ---------------------------------------------------------*/
//该函数实现对fm1702接口的初始化
int fm1702_init(void) {
	char dummy = 0xFF;
	//char rsvbyte;
	
	fm1702_inf_init();

	FM1702_RST_HIGH();
	sleep(10);
	FM1702_RST_LOW();
	sleep(10);

	//选择SPI接口方式,必不可少,
	//否则会有ErrorFlag初始状态错误
	FM1702_SET_REG(Page_Reg, 0x80);	
	//等待复位完成
	fm1702_timeout(&stm, 0);
	do {
		if ((dummy = FM1702_GET_REG(Command_Reg)) == 0) {
			FM1702_SET_REG(Page_Reg, 0x00);
			break;
		}
	} while (!fm1702_timeout(&stm, 100));
	if (dummy != 0) {
		return FM1702_ERR_INIT;
	}
#if 0
	printf("\r\n");
	err_chk(__FUNCTION__, __LINE__);
#endif

	FM1702_SET_REG(TimerClock_Reg, 0x0B);		//151us/per
	FM1702_SET_REG(TimerControl_Reg, 0x02);	//发送结束开定时器,接收开始关定时器
	FM1702_SET_REG(TimerReload_Reg, 0x42);		// 10ms定时
	FM1702_SET_REG(InterruptEn_Reg, 0x7F);		//禁用所有中断
	FM1702_SET_REG(InterruptRq_Reg, 0x7F);		//打开所有中断标志
	//0
	//10	Modulator Source, 使用内部编码器
	//1
	//1	TX2Inv, TX2脚输出反相能量载波
	//0	TX2Cw, TX2脚输出持续的13.56MHz调制能量载波
	//1	TX2RFEn, TX2脚输出13.56MHz经发送数据调制后的能量载波
	//1	TX1RFEn, TX1脚输出13.56MHz经发送数据调制后的能量载波
	FM1702_SET_REG(TxControl_Reg, 0x5B);
	//0	RcvClkSelI, 0表示使用Q-clock(I-clock和Q-clock有90度相位差).
	//0	RxAutoPD, 0总是接收
	//0000	
	//01	DecoderSource, 使用内部解码器
	//FM1702_SET_REG(RxControl2_Reg, 0x41);
	
	//00000111 数据传输后, 在7个等待位时钟后激活接收器
	FM1702_SET_REG(RxWait_Reg, 0x07);

	//设置脉冲调制宽度
	FM1702_SET_REG(ModWidth_Reg, MOD_W_VAL);

	//设置接收信号强度阈值
	//FM1702_SET_REG(RxThreshold_Reg, 0xFF);
	return FM1702_OK;
}


int err_chk(const char* file, int lineno) {
	char dummy;

	if ((dummy = FM1702_GET_REG(ErrorFlag_Reg)) == 0)
		return FM1702_OK;
#if FM1702_DEBUG
	printf("\r\n%s():%d errs: ", file, lineno);
	if (dummy & 0x01) {
		printf("Colli ");
	}
	if (dummy & 0x02) {
		printf("Parity ");
	}
	if (dummy & 0x04) {
		printf("Frame ");
	}
	if (dummy & 0x08) {
		printf("CRC ");
	}
	if (dummy & 0x10) {
		printf("FIFOOvfl ");
	}
	if (dummy & 0x20) {
		printf("Access ");
	}
	if (dummy & 0x40) {
		printf("Key ");
	}
#endif	// FM1702_DEBUG
	return dummy + FM1702_E_BASE;
}


//FM1702 EEPROM 0x10-0x2F信息必须正确,
//否则FM1702寄存器会不正常地工作
int fm1702_reg_initial(int fix) {
	static const char reg_inits[] = {
		0x00, 0x58, 0x3F, 0x3F,
		0x19, 0x13, 0x00, 0x00,
		0x00, 0x73, 0x08, 0xAD,
		0xFF, 0x00, 0x41, 0x00,
		0x00, 0x06, 0x03, 0x63,
		0x63, 0x00, 0x00, 0x00,
		0x00, 0x08, 0x07, 0x06,
		0x0A, 0x02, 0x00, 0x00
	};
	char reg_buf[40];
	int rlen;

	rlen = fm1702_read_e2p(0x10, reg_buf, 0x10);
	if (rlen != 0x10) {
		return rlen;
	}
	rlen = fm1702_read_e2p(0x20, reg_buf + 0x10, 0x10);
	if (rlen != 0x10) {
		return rlen;
	}

	if (memcmp(reg_buf, reg_inits, 32) == 0) {
		return FM1702_OK;
	}

	if (fix == 0) {
		return FM1702_ERR_REG;
	}
	
	rlen = fm1702_write_e2p(0x10, (char*)reg_inits, 0x10);
	if (rlen != FM1702_OK) {
		return rlen;
	}
	rlen = fm1702_write_e2p(0x20, (char*)reg_inits + 0x10, 0x10);
	if (rlen != FM1702_OK) {
		return rlen;
	}
	return FM1702_OK;
}

//取得FIFO长度
__inline static int fifo_len(void) {
	return FM1702_GET_REG(FIFOLength_Reg);
}

//清空FM1715中FIFO的数据
static int clear_fifo(void) {
	char dummy, i;
	
	// bit0, Flush FIFO
	FM1702_SET_REG(Control_Reg, FM1702_GET_REG(Control_Reg) | 0x01);

	for (i = 10; i != 0; i--) {
		if ((dummy = FM1702_GET_REG(FIFOLength_Reg)) == 0)
			break;
		//sleep_us(500);
	}
	if (dummy != 0) {
		err_chk(__FUNCTION__, __LINE__);
		return FM1702_ERR_FIFO;
	}
	return FM1702_OK;
}

//从FM1715的FIFO中读出数据
//返回读取字节数 >= 0
static int read_fifo(char* buf) {
	int len = 0;
	
	if ((len = fifo_len()) < 0) {
		err_chk(__FUNCTION__, __LINE__);
		return FM1702_ERR_FIFO;
	} else if (len == 0) {
		return FM1702_OK;
	} else if (len >= 24) {
		len = 24;
	}

	//printf("\r\n%s(): ", __FUNCTION__);
	//printf("fifo len = %d", len);
	//sleep_us(1000);
	
	fm1702_inf_read(FIFOData_Reg, buf, len);
	return len;
}

//FM1715的FIFO中写入len字节数据
static int write_fifo(char* buf, int len) {
	fm1702_inf_write(FIFOData_Reg, buf, len);
	return FM1702_OK;
}

//向FM1715发送命令集
static int cmd_send(int cmd, char* buf, int len) {
	int rlen;
	char dummy;

	FM1702_SET_REG(Command_Reg, 0x00);

	if (clear_fifo() != FM1702_OK) {
		err_chk(__FUNCTION__, __LINE__);
		return FM1702_ERR_FIFO;
	}

	if (write_fifo(buf, len) != FM1702_OK) {
		err_chk(__FUNCTION__, __LINE__);
		return FM1702_ERR_FIFO;
	}

	FM1702_SET_REG(Command_Reg, cmd);

	fm1702_timeout(&stm, 0);
	while (!fm1702_timeout(&stm, 20)) {
		if ((dummy = FM1702_GET_REG(Command_Reg)) == 0x00) {
			//printf("%02X", dummy);
			return FM1702_OK;
		}		
		dummy = FM1702_GET_REG(InterruptRq_Reg);
		if ((dummy & 0x80) == 0x80) {
			//printf("%02X", dummy);
			return FM1702_OK;
		}
	}
#if 1
	if ((rlen = err_chk(__FUNCTION__, __LINE__)) != 0) {
		return rlen;
	} 
	return FM1702_ERR_CMD;
#endif
	//return FM1702_OK;
}

//从FM1715的EEPROM中读出数据
//addr	读取地址
//len	待读出数据的字节数
//buf	指向待读出数据的指针
int fm1702_read_e2p(int addr, char* buf, int len) {
	char bsnd[3];
	
	// 可读取域为0x0 - 0x7F
	bsnd[0] = (addr & 0x7F);
	bsnd[1] = 0;
	bsnd[2] = (char)len;
	//debug_buf("R ADDR", bsnd, 3);
	if (cmd_send(ReadE2, bsnd, 3) != FM1702_OK) {
		return err_chk(__FUNCTION__, __LINE__);
	}
	return read_fifo(buf);
}

//向FM1715的EEPROM中写入数据
//addr	写入地址
//len	待写入数据的字节数
//buf	指向待写入数据的指针
int fm1702_write_e2p(int addr, char* buf, int len) {
	char bsnd[2 + 18];
	char dummy;
	//int rlen;

	if (addr < 0x10) {
		return FM1702_ERR_E2P; 
	}
	bsnd[0] = (addr & 0xFF);
	bsnd[1] = (addr & 0x0100) >> 8;
	len = (len > 16)? 16: len;
	memcpy(bsnd + 2, buf, len);

	//debug_buf("W ADDR", bsnd, len + 2);
	if ((//rlen = 
	cmd_send(WriteE2, bsnd, len + 2)) != FM1702_OK) {
		//return rlen;
	}
	fm1702_timeout(&stm, 0);
	do {
		dummy = FM1702_GET_REG(SecondaryStatus_Reg);
		if ((dummy & 0x40) == 0x40)
			break;
		//bit6, E2Ready, 1 = EEPROM操作结束
	} while (!fm1702_timeout(&stm, 10));
#if 0
	//检测Command_Reg为0
	fm1702_timeout(&stm, 0);
	do {
		FM1702_SET_REG(Command_Reg, 0x00);
		if (FM1702_GET_REG(Command_Reg) == 0)
			break;
	} while (!fm1702_timeout(&stm, 10));
#endif
	if ((dummy & 0x40) == 0x40) {
	//fm1702_read_e2p(addr, bsnd, len);
	//if (memcmp(bsnd, buf, len) == 0) {
		return FM1702_OK;
	}
	//printf("\r\n%s():", __FUNCTION__);
	//printf("line = %d", __LINE__);
	return FM1702_ERR_E2P;
}

// 卡片复位应答的判断
int detect_req(char* buf) {
	if (buf[1] == 0) {
		//上海标准1KB卡
		if (buf[0] == 0x53) {
			return 1;
		}

		//上海标准TOKEN卡
		if (buf[0] == 0x03) {
			return 1;
		}

		//MIFARE标准TOKEN卡
		if (buf[0] == 0x05) {
			return 1;
		}

		//MIFARE ULTRALIGHT
		if (buf[0] == 0x44) {
			return 1;
		}

		//MIFARE 1K
		if (buf[0] == 0x04) {
			return 1;
		}

		//MIFARE 4K
		if (buf[0] == 0x02) {
			return 1;
		}
	}
	
	if (buf[1] == 0x03) {
		//MIFARE DESFire
		if (buf[0] == 0x04) {
			return 1;
		}
	}
	
	if ((buf[1] & 0xF8) == 0) {
		//MIFARE ProX或SmartMX xD(T)
		if (
		  buf[0] == 0x08 ||
		  buf[0] == 0x04 ||
		  buf[0] == 0x02 ||
		  buf[0] == 0x48 ||
		  buf[0] == 0x44 ||
		  buf[0] == 0x42
		) {
			return 1;
		}
	}
	return 0;
}

// 判断卡片收到的序列号
int check_uid(char* buf) {
	char chk = 0;
	int i;

	for (i = 0; i < 5; i++) {
		chk ^= buf[i];
	}
	return chk == 0x00;
}

// 保存卡片收到的序列号
static int trans_uid(int collision, char* uid, char* buf, int len) {
	char row, col, chbuf, chid;

	//debug_buf(__FUNCTION__, buf, len);
	if ((collision & 0xFFFF) == 0) {
		memcpy(uid, buf, len);
		return 0;
	}

	row = (collision & 0xFF00) >> 8;
	col = collision;
	chbuf = buf[0];
	chid = uid[row - 1];
	if (col == 0x00) {
		chid = 0x00;
		row++;
	} else if (col <= 7){
		chbuf &= (0xFF << col);
		chid &= ~(0xFF << col);
	}
	buf[0] = chbuf;
	uid[row - 1] = chbuf | chid;
	memcpy(&uid[row], &buf[1], len - 1);
	return 1;
}

//设置待发送数据的字节数
int set_bitframe(int collision, char* buf) {
	int bf = 0;
	char row, col;

	row = (collision & 0xFF00) >> 8;
	col = collision;
	if (row <= 4) {
		buf[1] = (2 + col) * 0x10;
	}

	if (col != 0x00 && col <= 7) {
		bf = col * 0x11;
		buf[1] |= col;
	}
	FM1702_SET_REG(BitFraming_Reg, bf);
	return bf;	
}

// 加载key到FM1702的KEY BUFFER中
int fm1702_mif_key(int mif_sec, char* key) {
	if (cmd_send(LoadKey, key, 12) != FM1702_OK) {
		return err_chk(__FUNCTION__, __LINE__);
	}
	return FM1702_OK;
}

// 将E2PROM密码存入FM1702的KEY BUFFER中
int fm1702_mif_key_e2p(int mif_sec) {
	int addr;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -