📄 fm1715.c
字号:
#pragma small
#include <REG52.h>
#include "INTRINS.H"
//#include <string.h>
#include "FM1715.H"
extern void delay_1ms (uchar _1ms);
extern void delay_50us (uchar _50us);
//uchar idata readdata[16] _at_ 0x0040; //读写数据缓冲区
//第 17 页 共 52 页
//uchar idata value[4] _at_ 0x0050; //增减的数值
//uchar idata KeySet; //密码类型
//uchar idata tagtype[2];// _at_ 0x0096; //卡片标识字符
//******************* FM1715 变量定义********************
//uchar idata PRO_SendBuf[16] _at_ 0x0080; //发送处理缓冲区 16 BYTE
//uchar idata PRO_RecvBuf[16] _at_ 0x0080; //接收处理缓冲区 16 BYTE
//uchar idata buffer[7];//[24];// _at_ 0x0060; //FM1715 命令发送接收缓冲区
//uchar idata UID[5];// _at_ 0x007a; //序列号
//uchar idata Secnr;// _at_ 0x0090; //扇区号
//uchar idata keybuffer[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF} ; //密钥存放区
#ifdef FM_Serial
void SPI_W(uchar W_Byte);//向SPI串行总线发送数据
void WRITE_FM(uchar Adr,uchar BD);//向FM系列读写卡芯片发送数据
uchar READ_FM(uchar Adr);//从FM系列读写卡芯片读取数据
//FM1715 管脚定义
sbit FM_SPICS=P3^4; //片选脚
#define FM_SPICS_L FM_SPICS=0;
#define FM_SPICS_H FM_SPICS=1;
sbit FM_SPISI=P2^1; //串行数据输入脚
sbit FM_SPISO=P2^2; //串行数据输出脚
sbit FM_SPISCK=P2^0;//串行时钟输入脚
//注意:FM芯片的SPI接口可以对同一地址连续写入不同的数据,只需发送一次地址
// 而读数据就必须是发一个地址读一个数据。
/****************************************************************/
/*名称: WRITE_FM */
/*功能: 该函数实现把数据写入FM系列芯片的寄存器中 */
/*输入: Adr:FM芯片的寄存器地址
/* BD:要写入的数据*/
/*输出: N/A */
/****************************************************************/
void WRITE_FM(uchar Adr,uchar BD)
{
Adr=(Adr<<1)&0x7E; //要发送的命令是写命令
// FM_SPICS=0; //片选FM读写卡芯片
FM_SPICS_L;
SPI_W(Adr); //发送写命令和地址
SPI_W(BD); //发送数据
// FM_SPICS=1; //关闭片选
FM_SPICS_H;
}
/****************************************************************/
/*名称: READ_FM */
/*功能: 该函数实现读取FM系列芯片的寄存器中的内容 */
/*输入: Adr:要读取的FM芯片的寄存器地址
/*输出: 返回读出的内容 */
/****************************************************************/
uchar READ_FM(uchar Adr)
{
uchar i;
uchar R_Byte;
// FM_SPICS=0; //片选FM读写卡芯片
FM_SPICS_L;
Adr=(Adr<<1)&0x7E|0x80; //要发送的命令是读命令
SPI_W(Adr); //发送读命令和地址
for(i=8;i>0;i--)
{
FM_SPISO=1;
_nop_();
FM_SPISCK = 1;
// Delay_10_uS();
_nop_(); _nop_(); _nop_();
_movcb_(FM_SPISO);//或用CY = FM_SPISO
_rlca_();
FM_SPISCK = 0;
// Delay_10_uS();
_nop_();
}
_movra_(R_Byte);//或用R_Byte = ACC;
// FM_SPICS=1; //关闭片选
FM_SPICS_H;
/*
R_Byte=0;
for(i=0; i<8; i++)
{
FM_SPISO=1;
FM_SPISCK = 0;
_nop_();_nop_(); _nop_(); _nop_();
R_Byte *= 2;
FM_SPISCK = 1;
FM_SPISO=1;
_nop_(); _nop_(); _nop_(); _nop_();
if (FM_SPISO) R_Byte++;
} // for i
*/
return R_Byte;
}
/****************************************************************/
/*名称: SPI_W */
/*功能: 该函数实现把送据传送给FM系列芯片 */
/*输入: W_Byte:要传送的内容
/*输出: N/A */
/****************************************************************/
void SPI_W(uchar W_Byte)
{
uchar i;
_movar_(W_Byte);//或用ACC = W_Byte
for(i = 8; i >0; i--)
{
_rlca_();
_movbc_(FM_SPISI);//或用FM_SPISI = CY;
FM_SPISCK = 1;
// Delay_10_uS();
_nop_(); _nop_(); _nop_();
FM_SPISCK = 0;
// Delay_10_uS();
_nop_();
}
/*
for(i=0;i<8;i++)
{
FM_SPISCK = 0; //准备改变数据线的数据
_nop_(); _nop_(); _nop_(); _nop_();
FM_SPISI = (bit)(W_Byte & 0x80);
W_Byte= W_Byte << 1; // RLC 左移1位
_nop_(); _nop_(); _nop_(); _nop_(); //delay_1us(8);
FM_SPISCK = 1; //写入一位
_nop_(); _nop_(); _nop_(); _nop_();
} // for i
*/
}
#endif
/*
void DELAY_20us()
{
uchar i;
for(i=8;i>0;i--){};
}
*/
//5.2.1 接收到的卡片UID 号的判别
//****************************************************************
//*名称: Check_UID
//*功能: 该函数实现对收到的卡片的序列号的判断
//*输入: N/A */
//*输出: TRUE: 序列号正确
//* FALSE: 序列号错误
//****************************************************************
uchar Check_UID(uchar *CardID)
{
uchar temp;
uchar i;
temp = 0x00;
for(i = 0;i < 5; i++)
{
temp = temp ^ CardID[i];
}
if(temp == 0)
{
return TRUE;
}
return FALSE;
}
/*
//第 19 页 共 52 页
//5.2.2 保存卡片的UID 号
//****************************************************************
//*名称: Save_UID
//*功能: 该函数实现保存卡片收到的序列号
//*输入: row: 产生冲突的行
//* col: 产生冲突的列
//* length: 接収到的UID 数据长度
//*输出: N/A
//****************************************************************
void Save_UID(uchar row,uchar col,uchar length)
{
uchar i;
uchar temp;
uchar temp1;
if ((row == 0x00) && (col == 0x00))
{
for(i = 0; i < length; i++)
{
UID[i] = buffer[i];
}
}
else
{
temp = buffer[0];
temp1 = UID[row - 1];
switch (col)
{
case 0:
temp1 = 0x00;
row = row + 1;
break;
case 1:
temp = temp & 0xFE;
temp1 = temp1 & 0x01;
break;
case 2:
temp = temp & 0xFC;
temp1 = temp1 & 0x03;
break;
case 3:
temp = temp & 0xF8;
// 第 20 页 共 52 页
temp1 = temp1 & 0x07;
break;
case 4:
temp = temp & 0xF0;
temp1 = temp1 & 0x0F;
break;
case 5:
temp = temp & 0xE0;
temp1 = temp1 & 0x1F;
break;
case 6:
temp = temp & 0xC0;
temp1 = temp1 & 0x3F;
break;
case 7:
temp = temp & 0x80;
temp1 = temp1 & 0x7F;
break;
default:
break;
}
buffer[0] = temp;
UID[row - 1] = temp1 | temp;
for(i = 1; i < length; i++)
{
UID[row - 1 + i] = buffer[i];
}
}
}
*/
//第 21 页 共 52 页
//5.2.3 设置待发送数据的字节数
//****************************************************************
//*名称: Set_BitFraming
//*功能: 该函数设置待发送数据的字节数
//*输入: row: 产生冲突的行
//* col: 产生冲突的列
//*输出: N/A
//****************************************************************
/*
void Set_BitFraming(uchar row,uchar col)
{
switch (row)
{
case 0:
buffer[1] = 0x20;
break;
case 1:
buffer[1] = 0x30;
break;
case 2:
buffer[1] = 0x40;
break;
case 3:
buffer[1] = 0x50;
break;
case 4:
buffer[1] = 0x60;
break;
default:
break;
}
switch(col)
{
case 0:
Bit_FrameW(0x00);
break;
case 1:
Bit_FrameW(0x11);
buffer[1] = (buffer[1] | 0x01);
break;
case 2:
Bit_FrameW(0x22);
//第 22 页 共 52 页
buffer[1] = (buffer[1] | 0x02);
break;
case 3:
Bit_FrameW(0x33);
buffer[1] = (buffer[1] | 0x03);
break;
case 4:
Bit_FrameW(0x44);
buffer[1] = (buffer[1] | 0x04);
break;
case 5:
Bit_FrameW(0x55);
buffer[1] = (buffer[1] | 0x05);
break;
case 6:
Bit_FrameW(0x66);
buffer[1] = (buffer[1] | 0x06);
break;
case 7:
Bit_FrameW(0x77);
buffer[1] = (buffer[1] | 0x07);
break;
default:
break;
}
}
*/
//第 23 页 共 52 页
//5.3 FM1715 基本函数
//5.3.1 总线选择
//****************************************************************
//*名称: FM1715_Bus_Sel
//*功能: 该函数实现对FM1715 操作的总线方式(并行总线,SPI)选择
//*输入: N/A
//*输出: TRUE, 总线选择成功
//* FALSE, 总线选择失败
//****************************************************************
uchar FM1715_Bus_Sel(void)
{
uchar i;
Page_SelW(0x80); //表示PageSelect的值做为寄存器地址A5,A4 和A3,低
//三位寄存器地址A2-A0 由//外部地址线A2-A0 决定
for(i = 0; i < RF_TimeOut; i++) //延时
{
if(CommandR == 0x00) //读命令执行结果, bit7为0表示接口检测结束
{
Page_SelW(0x00);
return TRUE;
}
}
return FALSE;
}
//第 24 页 共 52 页
//5.3.2 FM1715 初始化
//****************************************************************
//*名称: Init_FM1715
//*功能: 该函数实现对FM1715 初始化操作
//*输入: mode:工作模式, 0:TYPEA 模式
//* 1:TYPEB模式
//* 2:上海模式
//*输出: N/A
//****************************************************************
uchar Init_FM1715(void)
{
uchar idata temp;
// uchar idata rbt[8];
int i;
/*
FM1715RST_H;
for (i = 0; i < 0x1fff; i++)
{
_nop_();
}
for (i = 0; i < 0x1fff; i++)
{
_nop_();
}
FM1715RST_L;
for (i = 0; i < 0x1fff; i++)
{
_nop_();
}
for (i = 0; i < 0x1fff; i++)
{
_nop_();
}
while(CommandR != 0) //等待Command = 0,FM1715 复位成功
{
_nop_();
}
*/
// FM1715RST_L;
// delay_1ms(25);//25ms
FM1715RST_H;
delay_50us(50);//2.5ms
FM1715RST_L;
delay_1ms(25);//25ms
i=2100;
while(i>0) //等待Command = 0,FM1715 复位成功
{
if((CommandR&0x3F) == 0)
break;
delay_1ms (1);
i--;
}
if(i<=0)
{
return FALSE;
}
if(FM1715_Bus_Sel()) //FM1715总线选择
{
TimerClockW(0x0b); //151us/per
TimerControlW(0x02); //发送结束开定时器,接收开始关定时器
TimerReloadW(0x42); //10ms 定时
InterruptEnW(0x7f); //关所有中断
temp = InterruptEnR;
Int_ReqW(0x7f);
MFOUTSelectW(0x02); //调试用
TxControlW(0x5b); //开启TX1、TX2
TypeSHW(0x00);
// i=Read_E2(8,0,4,rbt);//该函数实现从FM1715的EE中读出数据,现在是把芯片的4字节ID号读出来
//MfInOutSlaveConfig();//重新初始化FM1702的内部寄存器值
return TRUE;
}
return FALSE;
}
//第 26 页 共 52 页
//5.3.3 命令传输
//****************************************************************
//*名称: Command_Send
//*功能: 该函数实现向FM1715 发送命令集的功能
//*输入: count, 待发送命令集的长度
//* buff, 指向待发送数据的指针
//* Comm_Set, 命令码
//*输出: TRUE, 命令被正确执行
//* FALSE, 命令执行错误
//****************************************************************
uchar Command_Send(uchar count, uchar idata * buff, uchar Comm_Set)
{
// uint j;
uchar j;
uchar temp,temp1;
CommandW(0x00);
Clear_FIFO();
Int_ReqW(0);
Write_FIFO(count, buff);
temp = MFOUTSelectR;
CommandW(Comm_Set); //命令执行
for(j = 0; j< RF_TimeOut; j++) //检查命令执行否
{
delay_1ms(5);//5ms
// temp = MFOUTSelectR;
temp = CommandR;
/*
temp1 = Int_ReqR & 0x80;
if((temp == 0x00) || (temp1 == 0x80))
{
//Rxcontrol2=0x41;
return TRUE;
}
*/
temp1 = Int_ReqR ;
temp1 = temp1 & 0x10;
// temp1 = Int_ReqR & 0x10;
if((temp == 0x00) || (temp1 == 0x10))
{
return TRUE;
}
}
return FALSE;
}
//第 27 页 共 52 页
//5.3.4 清除FM1715 的FIFO 中的数据
//****************************************************************
//*名称: Clear_FIFO
//*功能: 该函数实现清空FM1715 中FIFO 的数据
//*输入: N/A
//*输出: TRUE, FIFO 被清空
//* FALSE, FIFO 未被清空
//****************************************************************
uchar Clear_FIFO(void)
{
uchar temp;
uint i;
ControlW(ControlR|0x01); //清空FIFO
for(i = 0; i < RF_TimeOut; i++) //检查FIFO 是否被清空
{
temp = FIFO_LengthR;
if(temp == 0)
{
return TRUE;
}
}
return FALSE;
}
//第 28 页 共 52 页
//5.3.5 向FM1715 的FIFO 中写入x 字节数据
//****************************************************************
//*名称: Write_FIFO
//*功能: 该函数实现向FM1715 的FIFO 中写入x bytes 数据
//*输入: count, 待写入字节的长度
//* buff, 指向待写入数据的指针
//*输出: N/A
//****************************************************************
void Write_FIFO(uchar count,uchar idata *buff)
{
uchar i;
#ifdef FM_Serial
// FM_SPICS=0; //片选FM读写卡芯片
FM_SPICS_L;
SPI_W(4); //发送写命令和地址
for(i = 0; i < count; i++)
{
SPI_W(*(buff + i));//发送数据
}
// FM_SPICS=1; //关闭片选
FM_SPICS_H;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -