Obsługa kart chipowych Smart Card
Rys. 9. Podstawowe drzewo plików w standardzie GSM11.11
Kod funkcji main() przedstawiono na listingu 1. Przed przystąpieniem do nawiązywania komunikacji z kartą identyfikacyjną należy odpowiednio skonfigurować system zegarowy mikrokontrolera STM32, timer systemowy SysTick oraz wyprowadzenie mikrokontrolera, do którego podłączony jest pin gniazda, wykrywający obecność karty (w tej roli użyto wyprowadzenie PE14). Obecność karty w gnieździe ma generować przerwanie, a więc trzeba skonfigurować sterownik przerwań NVIC oraz sterownik przerwań zewnętrznych EXTI. Stosowny fragment programu, ciało funkcji SC_DetectPinConfig(), zamieszczono na listingu 2.
Listing 1. Kod funkcji main()
int main(void) { SC_State SCState = SC_POWER_OFF; /* Inicjalizacja sygnałów zegarowych dla CPU i magistral */ RCC_Configuration(); /* Przerwanie od timera SysTick będzie generowane co 1 ms */ SysTick_Config(SystemFrequency / 1000); /* Konfiguracja wyprowadzenia PE14 jako wykrywającego * obecność karty identyfikacyjnej w gnieździe */ SC_DetectPinConfig(); while(1) { while(CardInserted == 0) { } /* Oczekiwanie na ATR */ SCState = SC_POWER_ON; SC_ADPU.Header.CLA = 0x00; SC_ADPU.Header.INS = SC_GET_ATR; SC_ADPU.Header.P1 = 0x00; SC_ADPU.Header.P2 = 0x00; SC_ADPU.Body.LC = 0x00; while(SCState != SC_ACTIVE_ON_T0) { SC_Handler(&SCState, &SC_ADPU, &SC_Responce); } /* Konfiguracja USART do pełnienia alternatywnej funkcji * interfejsu Smartcard. Negocjacja prędkości wymiany danych */ SC_PTSConfig(); /* Opoznienie 400 ms potrzebne do resynchronizacji z karta */ Delay(400); /* Wybranie MF */ SC_ADPU.Header.CLA = SC_CLA_GSM11; SC_ADPU.Header.INS = SC_SELECT_FILE; SC_ADPU.Header.P1 = 0x00; SC_ADPU.Header.P2 = 0x00; SC_ADPU.Body.LC = 0x02; for(i = 0; i < SC_ADPU.Body.LC; i++) { SC_ADPU.Body.Data[i] = MasterRoot[i]; } while(i < LC_MAX) { SC_ADPU.Body.Data[i++] = 0; } SC_ADPU.Body.LE = 0; SC_Handler(&SCState, &SC_ADPU, &SC_Responce); /* Odebranie odpowiedzi od MF */ if(SC_Responce.SW1 == SC_DF_SELECTED) { SC_ADPU.Header.CLA = SC_CLA_GSM11; SC_ADPU.Header.INS = SC_GET_RESPONCE; SC_ADPU.Header.P1 = 0x00; SC_ADPU.Header.P2 = 0x00; SC_ADPU.Body.LC = 0x00; SC_ADPU.Body.LE = SC_Responce.SW2; SC_Handler(&SCState, &SC_ADPU, &SC_Responce); } /* Wybranie ICCID */ if(((SC_Responce.SW1 << 8) | (SC_Responce.SW2)) == SC_OP_TERMINATED) { SC_ADPU.Header.CLA = SC_CLA_GSM11; SC_ADPU.Header.INS = SC_SELECT_FILE; SC_ADPU.Header.P1 = 0x00; SC_ADPU.Header.P2 = 0x00; SC_ADPU.Body.LC = 0x02; for(i = 0; i < SC_ADPU.Body.LC; i++) { SC_ADPU.Body.Data[i] = ICCID[i]; } while(i < LC_MAX) { SC_ADPU.Body.Data[i++] = 0; } SC_ADPU.Body.LE = 0; SC_Handler(&SCState, &SC_ADPU, &SC_Responce); } /* Odczyt zawartości ICCID */ if(SC_Responce.SW1 == SC_EF_SELECTED) { SC_ADPU.Header.CLA = SC_CLA_GSM11; SC_ADPU.Header.INS = SC_READ_BINARY; SC_ADPU.Header.P1 = 0x00; SC_ADPU.Header.P2 = 0x00; SC_ADPU.Body.LC = 0x00; SC_ADPU.Body.LE = 10; SC_Handler(&SCState, &SC_ADPU, &SC_Responce); } } }