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

📄 smartcard.c

📁 基于Arm Developer suite 1.2开发
💻 C
字号:
#include <string.h>
#include "SmartCard.h"

typedef volatile struct {
  vu16 CLKVAL;
  vu16 EMPTY;
  vu16 CLKCON;
} SC_TypeDef;

//以下根据实际硬件接线和硬件电气特征定义
#define ESAM_RST_PIN 0         //ESAM的RST为P0.x
#define IC_RST_PIN 0           //IC的RST为P0.y
#define ESAM_BAUD 1       //ESAM的波特率(32M PCLK  8分频 4M CLK)
#define IC_BAUD 1       //IC的波特率

/*
  vu16 BR;
  vu16 EMPTY1;
  vu16 TxBUFR;
  vu16 EMPTY2;
  vu16 RxBUFR;
  vu16 EMPTY3;
  vu16 CR;
  vu16 EMPTY4;
  vu16 IER;
  vu16 EMPTY5;
  vu16 SR;
  vu16 EMPTY6;
  vu16 GTR;
  vu16 EMPTY7;
  vu16 TOR;
  vu16 EMPTY8;
  vu16 TxRSTR;
  vu16 EMPTY9;
  vu16 RxRSTR;                              UART1占用APB1_BASE + 0x5000至0x5025,即38字节)  
*/
#define SC_BASE		(APB1_BASE + 0x5040)      //SC占用APB1_BASE + 0x5040至0x5045
#define SC			((SC_TypeDef *)SC_BASE)
#define SC_BEGINSEND() (UART1->CR &= ~0x0100)     // Enable Rx
#define SC_ENDSEND() \
do { \
	while(!(UART1->SR & UART_TxEmpty)); \
	UART1->CR |= 0x0100; \
} while(0)        //直至TxBUffer为空
#define SC_SEND(c) \
do { \
	while(UART1->SR & UART_TxFull); \
	UART1->TxBUFR = (c); \
} while(0)      //从UART发送一个字节



static void SC_SendHdr(int CLA, int INS, int P1, int P2, int P3)  //发送PSAM命令头部,不存在Lc,Le都大于0的情况,所以只需一个P3即可
{
	SC_SEND(CLA);
	SC_SEND(INS);
	SC_SEND(P1);
	SC_SEND(P2);
	SC_SEND(P3);
}

static void SC_SendData(const u8 *buf, int len)   //UART发送若干个字节              
{
	while(len > 0)
	{
		SC_SEND(*buf++);
		len--;
	}
}

static int SC_RecvByte(void)               //UART接收一个字节
{
	int retry = 16, sr;
	do {
		UART1->TOR = 0xFF;
		while(!((sr = UART1->SR) & (UART_TimeOutIdle | UART_RxBufFull)));
		if(sr & UART_RxBufFull)
			return UART1->RxBUFR & 255;
	} while(--retry);
	return -1;
}

/*
	ESAM初始化和复位
*/
void rst_ESAM(u8 Data[20])
{
	int i;
	memset(&Data[0], 0xff,20);
	 GPIO_Config(GPIO0, 1 << 10 | 1 << 12, GPIO_AF_PP);  //DATA,CLK
	GPIO_Config(GPIO0, 1 << ESAM_RST_PIN, GPIO_OUT_PP);       //RST
	SC->CLKVAL=0x04;                     // DICV2,Smartcard时钟
	//SC->CLKVAL=0x01;
	UART_Init(UART1);     
	UART_OnOffConfig(UART1, ENABLE);// Enable UART1,开波特率产生器
	UART1->CR |= 0x0200;      //SC_ENABLE,激活SmartCard接口
	UART_FifoConfig(UART1, ENABLE);   //FIFO功能使能
	UART_FifoReset(UART1, UART_RxFIFO);
	UART_FifoReset(UART1, UART_TxFIFO);  //清空发送和接收FIFO,TxRSTR=RxRSTR=0xFFFF
	UART_LoopBackConfig(UART1, DISABLE);  //关Loopback,按标准传输接收模式 
	UART_Config(UART1, ESAM_BAUD, UART_EVEN_PARITY, UART_1_5_StopBits, UARTM_8D_P);   //UART配置
	UART_RxConfig(UART1, ENABLE);         // Enable Rx
    UART_GuardTimeConfig(UART1,2);     //UART报警时间
    
    SC->CLKCON |= 1;             
    //GPIO0->PD &= ~(1 << ESAM_RST_PIN);    //ESAM不工作 
	//for(i = 0; i <0x200; i++);
	GPIO0->PD |= 1 << ESAM_RST_PIN;    //Reset,ESAM工作 
	for(i = 0; i <400; i++);  //等待ESAM复位
  // for(i=0;i<20;i++) 
	//UART_ByteReceive(UART1,&Data[i],0xFF);    //接收复位应答
	return ;   
	/*注释的行在判断ESAM参数时使用,实际应用时不需要,Data[0]=0x3b表示正向约定,0x3F表示反向约定*/
}
/*
	ICC初始化和复位
*/
void rst_IC(u8 Data[20])
{
	int i;
	memset(&Data[0], 0xff, 20);
	GPIO_Config(GPIO0, 1 << 10 | 1 << 12, GPIO_AF_PP);  //DATA,CLK
	GPIO_Config(GPIO0, 1 << IC_RST_PIN | 1<<ESAM_RST_PIN, GPIO_OUT_PP);       //RST
	SC->CLKVAL=0x04;                     // DICV2,Smartcard时钟
	UART_Init(UART1);     
	UART_OnOffConfig(UART1, ENABLE);// Enable UART1,开波特率产生器
	UART1->CR |= 0x0200;      //SC_ENABLE,激活SmartCard接口
	UART_FifoConfig(UART1, ENABLE);   //FIFO功能使能
	UART_FifoReset(UART1, UART_RxFIFO);
	UART_FifoReset(UART1, UART_TxFIFO);  //清空发送和接收FIFO,TxRSTR=RxRSTR=0xFFFF
	UART_LoopBackConfig(UART1, DISABLE);  //关Loopback,按标准传输接收模式 
	UART_Config(UART1, IC_BAUD, UART_EVEN_PARITY, UART_1_5_StopBits, UARTM_8D_P);   //UART配置
	UART_RxConfig(UART1, ENABLE);         // Enable Rx
    UART_GuardTimeConfig(UART1,2);     //UART报警时间
    SC->CLKCON |= 1;              //Enable Smartcard Clock output
   
   
    //SC->CLKCON &=~0x01;        //Disable Smartcard Clock output
    
	//GPIO0->PD &= ~(1 << IC_RST_PIN);    //IC不工作 
	//for(i = 0; i <0x200; i++);
	GPIO0->PD |= 1 << IC_RST_PIN;    //Reset,IC工作 
	for(i = 0; i <400; i++);  //等待IC复位
    //for(i=0;i<20;i++) 
	//UART_ByteReceive(UART1,&Data[i],0x1F);    //接收复位应答
	return ;   
	/*注释的行在判断ESAM参数时使用,实际应用时不需要,Data[0]=0x3b表示正向约定,0x3F表示反向约定*/
}


/*
	PSAM命令发送和接收
*/
static int SC_SendRecv(int CLA, int INS, int P1, int P2,
	int Lc, const u8 *in, int Le, u8 *out)
{
	int  SW1, SW2;
	u8 ret;
	u8 i;
	SC_BEGINSEND();
	SC_SendHdr(CLA, INS, P1, P2, Lc > 0 ? Lc : Le);   //发送5字节的命令头部
	SC_ENDSEND();
    while(!(UART_FlagStatus(UART1)&UART_RxBufFull));   //阻塞收取过程字节
   UART_ByteReceive(UART1,&ret,0x0F);
	if(ret < 0)
		return -1;
	if(ret == INS || ret == (INS ^ 255))
	{   
	  
		if(Lc > 0)
		{
			int i;
			for(i = 0; i < 8; i++);
			SC_BEGINSEND();
			SC_SendData(in, Lc);  //发送命令体
			SC_ENDSEND();
		}
		else
		{   
		
			while(Le > 0)
			{
				ret = SC_RecvByte();   //接收响应域
				if(ret < 0)
					return -1;
				*out++ = ret, Le--;
			}
		}
		while(!(UART_FlagStatus(UART1)&UART_RxBufFull));
        UART_ByteReceive(UART1,&ret,0xFF);
        while(ret==0x60)  //很重要,这是一个表示NULL的过程字节,very important
        {
        //while(!(UART_FlagStatus(UART1)&UART_RxBufFull));   //测试用,IC卡的情况,不注释会死掉
        UART_ByteReceive(UART1,&ret,0xFF);
        }
         SW1=ret;   
		if(SW1 < 0)
			return -1;
	}
	else
		SW1 = ret;
	    //while(!(UART_FlagStatus(UART1)&UART_RxBufFull)); //测试用,IC卡的情况,不注释会死掉
        UART_ByteReceive(UART1,&ret,0xFF);
        SW2=ret;
	if(SW2 < 0)
		return -1;
	return SW1 << 8 | SW2;
}
/*
	ESAM和IC卡的接口
	CLA是命令类型,INS是命令码,P1,P2是控制参数,Lc是命令体长度,Le是接收的字节数,*La=Le
*/
int ESC_Command(int CLA, int INS, int P1, int P2,
	int Lc, const u8 *in, int Le, u8 *out, int *La)
{
	int ret = SC_SendRecv(CLA, INS, P1, P2, Lc, in, Le, out), SW1, SW2;
	if(ret < 0)
		return -1;
	SW1 = ret >> 8, SW2 = ret & 255;
	switch(SW1)
	{
	case 0x6C:
		if(Le > SW2)
			Le = SW2;
		ret = SC_SendRecv(CLA, INS, P1, P2, 0, NULL, Le, out);
		break;
	case 0x61:
		if(Le > SW2)
			Le = SW2;
		ret = SC_SendRecv(0x00, 0xC0, 0x00, 0x00, 0, NULL, Le, out);
		break;
	}
	
	if(La)
		*La = Le;
	return ret;
}


⌨️ 快捷键说明

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