📄 smartcard.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 + -