📄 armspi.c
字号:
/*************************************************************************
SPI通信方式下读卡器驱动程序
************************************************************************/
#include "config.h"
///////////////////////////////////////////////////////////////////////////////
// **底层函数**
///////////////////////////////////////////////////////////////////////////////
#define FM1702_NSS 1<<24 // P0.24 为片选线
#define FM1702_RESET 1<<23
#define BEEPCON 1<<7
///////////////////////////////////////////////////////////////////////////////
// **基本的写函数**
///////////////////////////////////////////////////////////////////////////////
void WriteIO(uint8 Address, uint8 value)
{
uint8 a;
OS_ENTER_CRITICAL();
IO0CLR=FM1702_NSS;
S1PDR=(Address&0x3f)<<1;
while(0==(S1PSR&0x80));
a=S1PDR;
S1PDR=value;
while(0==(S1PSR&0x80));
a=S1PDR;
IO0SET=FM1702_NSS;
OS_EXIT_CRITICAL();
}
void WriteIOint(uint8 Address, uint8 value)
{
uint8 a;
// OS_ENTER_CRITICAL();
IO0CLR=FM1702_NSS;
S1PDR=(Address&0x3f)<<1;
while(0==(S1PSR&0x80));
a=S1PDR;
S1PDR=value;
while(0==(S1PSR&0x80));
a=S1PDR;
IO0SET=FM1702_NSS;
// OS_EXIT_CRITICAL();
}
///////////////////////////////////////////////////////////////////////////////
// **基本的读函数**
///////////////////////////////////////////////////////////////////////////////
uint8 ReadIO(uint8 Address)
{
uint8 a;
OS_ENTER_CRITICAL();
IO0CLR=FM1702_NSS; // 选通
S1PDR=((Address&0x3f)<<1)|0x80;
while(0==(S1PSR&0x80));
a=S1PDR;
S1PDR=0;
while(0==(S1PSR&0x80));
a=S1PDR;
IO0SET=FM1702_NSS;
OS_EXIT_CRITICAL();
return a;
}
uint8 ReadIOint(uint8 Address)
{
uint8 a;
// OS_ENTER_CRITICAL();
IO0CLR=FM1702_NSS;
S1PDR=((Address&0x3f)<<1)|0x80;
while(0==(S1PSR&0x80));
a=S1PDR;
S1PDR=0;
while(0==(S1PSR&0x80));
a=S1PDR;
IO0SET=FM1702_NSS;
// OS_EXIT_CRITICAL();
return a;
}
///////////////memcpy1函数/////////////////////////////////////////
void memcpy1(uint8 *des,uint8 *source,uint8 len)
{
uint8 i;
for(i=0;i<len;i++)
{*des=*source;
des++;
source++;
}
}
//////////////初始化SPI接口以及1702引脚函数///////////////////////
void FM1702SpiInit(void)
{
T1PR=0; //不分频
PINSEL0 =(PINSEL0&~0x0000C000);
IO0DIR|= BEEPCON;
IO0SET=BEEPCON;
PINSEL1 = ((PINSEL1 & ~0x3C3FF) | 0x2A9);
EXTMODE|=0x01;
EXTPOLAR&=0x0E;
IO0DIR|=0x01800000;
IO0SET=FM1702_NSS;
S1PCCR = 0x08;
S1PCR = (0 << 3) |
(0 << 4) |
(1 << 5) |
(0 << 6) |
(0 << 7);
}
/********************************************************************************
*********************************************************************************
********************************************************************************/
// M O D U L E D E F I N I T I O N
////////////////////////////////////////////////////////////////////////////////
//为了复位 函数和ISR间的通信渠道,定义了如下结构(复位信息初始值)
#define ResetInfo(info) \
info.cmd = 0; \
info.status = MI_OK;\
info.irqSource = 0; \
info.nBytesSent = 0; \
info.nBytesToSend = 0; \
info.nBytesReceived = 0; \
info.nBitsReceived = 0; \
info.collPos = 0;
// struct definition for a communication channel between function and ISR
typedef struct
{
uint8 cmd;
int8 status;
uint8 nBytesSent;
uint8 nBytesToSend;
uint8 nBytesReceived;
uint16 nBitsReceived;
uint8 irqSource;
uint8 collPos;
} MfCmdInfo;
// ----------读卡模块使用的变量------------------
static volatile uint8 MFIFOLength = DEF_FIFO_LENGTH; // 实际的FIFO的长度
//定义50us延时
#define DELAY50 Fpclk/20000
static volatile uint8 MSndBuffer[SND_BUF_LEN];// 发送缓冲区
static volatile uint8 MRcvBuffer[RCV_BUF_LEN]; // 接收缓冲区
static volatile MfCmdInfo MInfo;
//--------------------中断服务程序------------------------------
static volatile MfCmdInfo *MpIsrInfo = 0;
static volatile uint8 *MpIsrOut = 0;
static volatile uint8 *MpIsrIn = 0;
uint8 MLastSelectedSnr[5];
uint8 volatile Timer1out_flag = 0; // 定时器1溢出标志位
///////////////////////////////////////////////////////////////////////////////
// Prototypes for local functions
///////////////////////////////////////////////////////////////////////////////
void delay_50us(uint32 _50us);
void start_timeout(uint32 _50us);
void stop_timeout(void);
// _____________________________________________________________________________
// FUNCTION: FM1702PcdSetTmo
void FM1702PcdSetTmo(uint8 tmoLength);
// _____________________________________________________________________________
//
// FUNCTION: FM1702PcdCmd
int8 FM1702PcdCmd(uint8 cmd, volatile uint8* send, volatile uint8* rcv, volatile MfCmdInfo *info);
// _____________________________________________________________________________
//
// FUNCTION: SetBitMask
int8 SetBitMask(uint8 reg,uint8 mask);
// _____________________________________________________________________________
// FUNCTION: ClearBitMask
int8 ClearBitMask(uint8 reg,uint8 mask);
// _____________________________________________________________________________
void FlushFIFO(void);
// _____________________________________________________________________________
// FUNCTION: FM1702PiccAuthState
int8 FM1702PiccAuthState(uint8 auth_mode,uint8 *snr,uint8 block);
///////////////////////////////////////////////////////////////////////////////
// FM1702中断服务程序
///////////////////////////////////////////////////////////////////////////////
void EXINT0_Exception (void)
{
static uint8 irqBits;
static uint8 irqMask;
static uint8 nbytes;
static uint8 cnt,a;
if (MpIsrInfo && MpIsrOut && MpIsrIn)// transfer pointers have to be set correctly
{OS_ENTER_CRITICAL();
while( ReadIOint(RegPrimaryStatus) & 0x08)// loop while IRQ pending--IRQ
// Attention: IRQ bit is inverted when used with low activ IRQ
{
irqMask = ReadIOint(RegInterruptEn); // read enabled interrupts
// read pending interrupts
irqBits = ReadIOint(RegInterruptRq) & irqMask;
MpIsrInfo->irqSource |= irqBits; // save pending interrupts
//************ LoAlertIRQ ******************
if (irqBits & 0x01) //LoAlert
{
nbytes = MFIFOLength - ReadIOint(RegFIFOLength);
// less bytes to send, than space in FIFO
if ((MpIsrInfo->nBytesToSend - MpIsrInfo->nBytesSent) <= nbytes)
{
nbytes = MpIsrInfo->nBytesToSend - MpIsrInfo->nBytesSent;
WriteIOint(RegInterruptEn,0x01); // LoAlert IRQ
}
IO0CLR=FM1702_NSS; // Enable the /CS for RC500选通
S1PDR=((RegFIFOData&0x3f)<<1);
while((S1PSR&0x80)==0);
a=S1PDR;
for ( cnt = 0;cnt < nbytes;cnt++)
{
S1PDR=MpIsrOut[MpIsrInfo->nBytesSent];
MpIsrInfo->nBytesSent++;
while((S1PSR&0x80)==0);
a=S1PDR;
}
IO0SET=FM1702_NSS; // disable the /CS for RC500
WriteIOint(RegInterruptRq,0x01); // LoAlertIRQ bit
}
//************* TxIRQ Handling **************
if (irqBits & 0x10)
{
WriteIOint(RegInterruptRq,0x10); // TxIRQ bit
WriteIOint(RegInterruptEn,0x82); // enable HiAlert Irq for response
if (((MpIsrInfo->cmd & 0xF0) == 0x90)&& (MpIsrInfo->nBitsReceived == 7))
// if cmd is anticollision switch off parity generation
WriteIOint(RegChannelRedundancy,0x02); // RXCRC and TXCRC disable, parity disable
}
//************* HiAlertIRQ or RxIRQ Handling ******************
if (irqBits & 0x0E)
{
// read some bytes ( length of FIFO queue) into the receive buffer
nbytes = ReadIOint(RegFIFOLength);
// read date from the FIFO and store them in the receive buffer
for ( cnt = 0; cnt < nbytes; cnt++)
{
MpIsrIn[MpIsrInfo->nBytesReceived] = ReadIOint(RegFIFOData);
MpIsrInfo->nBytesReceived++;
}
WriteIOint(RegInterruptRq,0x0A & irqBits);
// reset IRQ bit - idle irq will be deleted in a seperate section
}
//************** IdleIRQ Handling ***********
if (irqBits & 0x04)
{
WriteIOint(RegInterruptEn,0x20);
WriteIOint(RegInterruptRq,0x20);
irqBits &= ~0x20; // clear Timer IRQ in local var
MpIsrInfo->irqSource &= ~0x20; // clear Timer IRQ in info var
// when idle received, then cancel timeout
WriteIOint(RegInterruptRq,0x04); // reset IRQ bit
// status should still be MI_OK
// no error - only used for wake up
}
//************* TimerIRQ Handling ***********
if (irqBits & 0x20) // timer IRQ
{
WriteIOint(RegInterruptRq,0x20); // reset IRQ bit
MpIsrInfo->status = MI_NOTAGERR; // timeout erro----保存错误原因
// otherwise ignore the interrupt
}
}
OS_EXIT_CRITICAL();
}
EXTINT|=1;
VICVectAddr=0;
}
///////////////////////////////////////////////////////////////////////
// S e t T i m e o u t L E N G T H
//设置FM1702内部定时器的定时时间
///////////////////////////////////////////////////////////////////////
void FM1702PcdSetTmo(uint8 tmoLength)
{
switch(tmoLength)
{ // timer clock frequency 13,56 MHz
//TimerClock
//TimerReload
case 1: // short timeout (1,0 ms)
WriteIO(RegTimerClock,0x07); // TAutoRestart=0,TPrescale=128-
WriteIO(RegTimerReload,0x6a);// TReloadVal = 'h6a =106(dec)
break;
case 2: // medium timeout (1,5 ms)
WriteIO(RegTimerClock,0x07); // TAutoRestart=0,TPrescale=128
WriteIO(RegTimerReload,0xa0);// TReloadVal = 'ha0 =160(dec)
break;
case 3: // medium timeout (6 ms)
WriteIO(RegTimerClock,0x09); // TAutoRestart=0,TPrescale=4*128
WriteIO(RegTimerReload,0xa0);// TReloadVal = 'ha0 =160(dec)
break;
case 4: // long timeout (9.6 ms)
WriteIO(RegTimerClock,0x09); // TAutoRestart=0,TPrescale=4*128
WriteIO(RegTimerReload,0xff);// TReloadVal = 'hff =255(dec)
break;
case 5: // long timeout (38.5 ms)
WriteIO(RegTimerClock,0x0b); // TAutoRestart=0,TPrescale=16*128
WriteIO(RegTimerReload,0xff);// TReloadVal = 'hff =255(dec)
break;
case 6: // long timeout (154 ms)
WriteIO(RegTimerClock,0x0d); // TAutoRestart=0,TPrescale=64*128
WriteIO(RegTimerReload,0xff);// TReloadVal = 'hff =255(dec)
break;
case 7: // long timeout (616.2 ms)
WriteIO(RegTimerClock,0x0f); // TAutoRestart=0,TPrescale=256*128
WriteIO(RegTimerReload,0xff);// TReloadVal = 'hff =255(dec)
break;
default: //
WriteIO(RegTimerClock,0x07); // TAutoRestart=0,TPrescale=128
WriteIO(RegTimerReload,tmoLength);// TReloadVal = 'h6a =tmoLength(dec)
break;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -