7816協議時序和采用UART模擬7816時序與智能卡APDU指令協議


7816時序

7816時一個比較早的老通訊時序了,最近項目上需要用UART模擬所以,簡單學習時序。

 

 時序比較簡單,熟悉UART的一眼看着就像是串口的時序,只是他沒有停止位,取而代之的就是保護時間guradtime,一般是兩個etu所以可以使用兩個停止位來模擬。電路圖上就是將RX和TX短接,在發送關閉串口的接受功能反之接收時關閉發送功能就可以了。

APDU指令

 

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可以沒有。

串口模擬7816參考程序

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

初始化代碼

    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);    
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM