7816协议时序和采用UART模拟7816时序与智能卡APDU指令协议
阅读原文时间:2023年07月11日阅读:2

7816时一个比较早的老通讯时序了,最近项目上需要用UART模拟所以,简单学习时序。

时序比较简单,熟悉UART的一眼看着就像是串口的时序,只是他没有停止位,取而代之的就是保护时间guradtime,一般是两个etu所以可以使用两个停止位来模拟。电路图上就是将RX和TX短接,在发送关闭串口的接受功能反之接收时关闭发送功能就可以了。

1、报文格式。

C-APDU有4字节的必备长度和1个可变长度条件体组成

CLA:命令报文类别字节

INS:命令报文指令字节

P1:参数1

P2:参数2

LC:条件体数据域的实际长度

DATA:数据域

Le:期望返回数据的长度

CLA  INS P1 P2 LC  DATA  Le 这里需注意的就是在物理链路上给卡发送APUD指令时需要按一下时序发送,先发送前5个字节然后等待卡回应INS 后才可继续发送余下的DATA,LE可以没有。

初始化同普通接口初始化相同

初始化代码

GPIO\_InitTypeDef GPIO\_InitStructure;  
NVIC\_InitTypeDef NVIC\_InitStructure;

USART\_InitTypeDef USART\_InitStructure;  
RCC\_APB2PeriphClockCmd( RCC\_APB2Periph\_GPIOB | RCC\_APB2Periph\_AFIO, ENABLE);  
RCC\_APB1PeriphClockCmd(RCC\_APB1Periph\_USART3, ENABLE);

GPIO\_InitStructure.GPIO\_Pin = FM151\_TXD\_PIN;  
GPIO\_InitStructure.GPIO\_Mode = GPIO\_Mode\_AF\_PP;  
GPIO\_InitStructure.GPIO\_Speed = GPIO\_Speed\_50MHz;  
GPIO\_Init(FM151\_PORT, &GPIO\_InitStructure);  
GPIO\_InitStructure.GPIO\_Pin = FM151\_RXD\_PIN;  
GPIO\_InitStructure.GPIO\_Mode = GPIO\_Mode\_IN\_FLOATING;  
GPIO\_InitStructure.GPIO\_Speed = GPIO\_Speed\_50MHz;  
GPIO\_Init(FM151\_PORT, &GPIO\_InitStructure);

USART\_InitStructure.USART\_BaudRate = 9600;  
USART\_InitStructure.USART\_WordLength = USART\_WordLength\_9b;//9位数据  
USART\_InitStructure.USART\_StopBits = USART\_StopBits\_1;//1位停止位  
USART\_InitStructure.USART\_Parity = USART\_Parity\_Even;//偶校验  
USART\_InitStructure.USART\_HardwareFlowControl = USART\_HardwareFlowControl\_None; //硬件流控制失能  
USART\_InitStructure.USART\_Mode = USART\_Mode\_Rx | USART\_Mode\_Tx; //发送和接受使能  
USART\_Init(USART3, &USART\_InitStructure);

//Usart1 NVIC 配置  
NVIC\_InitStructure.NVIC\_IRQChannel = USART3\_IRQn;  
NVIC\_InitStructure.NVIC\_IRQChannelPreemptionPriority = 4 ; //抢占优先级4  
NVIC\_InitStructure.NVIC\_IRQChannelSubPriority = 0;        //子优先级0  
NVIC\_InitStructure.NVIC\_IRQChannelCmd = ENABLE;            //IRQ通道使能  
NVIC\_Init(&NVIC\_InitStructure);    //根据指定的参数初始化VIC寄存器

USART\_Cmd(USART3, ENABLE);

USART\_ITConfig(USART3, USART\_IT\_RXNE, DISABLE);        //开始都不允许接受中断

这里采用中断接受,所以需要字节实现自己的中断服务函数。

发送数据

static void UartSendByte(u8 *dat)
{

while (USART\_GetFlagStatus(USART3, USART\_FLAG\_TXE) == RESET);  
USART\_SendData(USART3, \*dat);

while (USART\_GetFlagStatus(USART3, USART\_FLAG\_TC) == RESET);  
USART\_ClearFlag(USART3, USART\_FLAG\_TC);

delay\_us(guardtime);  

}

发送一定字节数据

void SendData(u8 *data, u16 datalenth)
{
u16 i;
SetUartDir(TX);
for (i = 0; i < datalenth - 1; i++)
{
UartSendByte(data + i);
}
UartSendLastByte(data + i);
SetUartDir(RX);
}

这里注意最后一个字节不需要额外的保护时间。最后就是配置UART的接受和发送的寄存器函数。

void SetUartDir( u8 dir)
{
u32 reg;
//发送时禁止接收,发送完成才开始接收
if (dir == RX)
{
reg = USART3->CR1;
reg |= USART_Mode_Rx;
reg &= (~USART_Mode_Tx);
USART3->CR1 = reg;

    USART\_ITConfig(USART3, USART\_IT\_RXNE, ENABLE);  
}  
else if (dir == UART\_TXD)  
{  
    reg = USART3->CR1;  
    reg |= USART\_Mode\_Tx;  
    reg  &= (~USART\_Mode\_Rx);  
    USART3->CR1 = (u16)reg;            

    USART\_ITConfig(USART3, USART\_IT\_RXNE, DISABLE);  
}  

}

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章