Este projeto detalha a implementação de um sistema de leitura e escrita para etiquetas RFID que operam no padrão ISO 15693 (13.56MHz), utilizando o microcontrolador STM32 e o chip transceptor de alta frequência CLRC663 da NXP. O sistema é capaz de detectar etiquetas, ler seus iedntificadores únicos (UID) e realizar operações de lietura/escrita em blocos de dados. As aplicações potenciais incluem controle de acesso, rastreamento de ativos e automação industrial.
Arquitetura do Sistema
A arquitetura do sistema é composta pelos seguintes componentes:
- STM32F103: Microcontrolador principal responsável pelo controle geral, processamento de dados e comunicação.
- CLRC663: Chip transceptor RFID que gerencia a comunicação RF com as etiquetas ISO 15693 e a comunicação com o STM32 via SPI.
- Etiqueta ISO 15693: O dispositivo alvo para operações de leitura e escrita.
- Antena RF: Antena sintonizada para 13.56MHz, acoplada ao CLRC663.
- Interface de Usuário/Host: Comunicação via UART para depuração ou integração com sistemas maiores (PC, display).
- Indicadores Visuais: LEDs para feedback de status.
Os componentes essenciais e suas interconexões são:
| Componente | Modelo/Especificação | Função |
|---|---|---|
| MCU | STM32F103C8T6 (ARM Cortex-M3, 72MHz) | Controle central do sistema. |
| Transceptor RFID | NXP CLRC663 | Interface RF e processamento de protocolo. |
| Antena | PCB, 13.56MHz | Acoplamento com etiquetas RFID. |
| Cristal OSC | 27.12MHz | Clock de referência para o CLRC663. |
| Regulador de Tensão | 3.3V LDO | Alimentação para STM32 e CLRC663. |
Conexão SPI (CLRC663 <-> STM32)
| Pino CLRC663 | Pino STM32 | Função |
|---|---|---|
| SCK | PA5 | Clock SPI. |
| MISO | PA6 | Dados SPI (CLRC663 para STM32). |
| MOSI | PA7 | Dados SPI (STM32 para CLRC663). |
| NSS | PA4 | Seleção de Chip (Chip Select), ativo baixo. |
| RST | PB0 | Reset do CLRC663, ativo baixo. |
| IRQ | PB1 | Saída de interrupção do CLRC663, ativa em nível baixo. |
| VCC | 3.3V | Alimentação. |
| GND | GND | Terra. |
Design da Antena
A antena PCB para o CLRC663 pode ser implementada com um circuito ressonante LC:
+-------------------+
| CLRC663 |
| |
| ANT1 --+-- L1 --+ | Antena PCB
| | | |
| C1 | |
| | | |
| GND ---+-------+ |
+-------------------+
L1: Indutor de ~3.3μH
C1: Capacitor de ~22pF
Dimensões da Antena: ~50x50mm (ajustável conforme a aplicação)
Software
O desenvolvimento é realizado no ambiente STM32CubeIDE, utilizando a biblioteca HAL.
Driver CLRC663 (clrc663.c)
Este módulo encapsula a comunicação SPI e os comandos de baixo nível para o CLRC663.
#include "clrc663.h"
#include "spi.h"
#include "gpio.h"
#include <string.h> // Para memcpy, strlen
// Registradores Chave do CLRC663
#define CLRC663_REG_COMMAND 0x00
#define CLRC663_REG_FIFO_DATA 0x01
#define CLRC663_REG_PRIMARY_STATUS 0x0C
#define CLRC663_REG_IRQ0 0x06
#define CLRC663_REG_IRQ1 0x07
#define CLRC663_REG_ERROR 0x0A
#define CLRC663_REG_RX_LEN 0x0B
#define CLRC663_REG_FSM_STATE 0x0F
#define CLRC663_REG_TX_CRC_CONF 0x12
#define CLRC663_REG_RX_CRC_CONF 0x13
#define CLRC663_REG_TX_DATA_NUM 0x14
#define CLRC663_REG_TX_WAIT_CTRL 0x15
#define CLRC663_REG_TX_DATA_RATE 0x19
#define CLRC663_REG_RX_DATA_RATE 0x1A
#define CLRC663_REG_MOD_WIDTH 0x1B
#define CLRC663_REG_TX_SYMBOLS_TX 0x1C
#define CLRC663_REG_RX_DEC_FRAMES 0x1F
#define CLRC663_REG_RX_SOF_DETECT 0x28
#define CLRC663_REG_RX_EOF_DETECT 0x29
#define CLRC663_REG_TX_PARAM 0x24
#define CLRC663_REG_TX_CRC_PRESET 0x25
#define CLRC663_REG_RX_CRC_PRESET 0x26
#define CLRC663_REG_RX_WAIT 0x27
#define CLRC663_REG_RX_ANA 0x3A
#define CLRC663_REG_TX_AMP 0x3B
#define CLRC663_REG_DRIVER_CON 0x3C
#define CLRC663_REG_PLL_CTRL 0x3D
#define CLRC663_REG_REGULATOR_CTRL 0x3E
#define CLRC663_REG_TEST_ANA_SEL 0x3F
// Comandos de Operação
#define CMD_IDLE 0x00
#define CMD_TRANSMIT 0x1A
#define CMD_RECEIVE 0x1B
#define CMD_TRANSCEIVE 0x1E
#define CMD_LOAD_KEY 0x19
#define CMD_AUTHENTICATE 0x1C
#define CMD_START_OF_FRAME 0x0F
#define CMD_END_OF_FRAME 0x0D
// Constantes ISO 15693
#define ISO15693_UID_LEN 8
#define ISO15693_BLOCK_SIZE 4
#define ISO15693_PROTOCOL_FLAGS 0x02 // High Data Rate, No Option
// Protótipos de Funções Internas
static void clrc663_spi_transfer(uint8_t *tx_data, uint8_t *rx_data, uint16_t len);
static void clrc663_write_register(uint8_t reg_addr, uint8_t value);
static uint8_t clrc663_read_register(uint8_t reg_addr);
static uint16_t clrc663_execute_command(uint8_t cmd);
static uint16_t clrc663_transmit_receive(const uint8_t *tx_buffer, uint8_t tx_len, uint8_t *rx_buffer, uint8_t rx_max_len);
// Inicialização do CLRC663
void CLRC663_Init(void) {
// Reset do hardware
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET); // RST baixo
HAL_Delay(10);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET); // RST alto
HAL_Delay(10);
// Configura SPI
MX_SPI1_Init();
// Configurações iniciais do chip
clrc663_write_register(CLRC663_REG_TX_CRC_CONF, 0x18); // Habilita CRC de transmissão
clrc663_write_register(CLRC663_REG_RX_CRC_CONF, 0x18); // Habilita CRC de recepção
clrc663_write_register(CLRC663_REG_TX_DATA_NUM, 0x0F); // 8 bits por byte
// Configurações para ISO 15693
clrc663_write_register(CLRC663_REG_RX_DATA_RATE, 0x0A); // 848 kbps taxa de recepção
clrc663_write_register(CLRC663_REG_TX_DATA_RATE, 0x0A); // 848 kbps taxa de transmissão
clrc663_write_register(CLRC663_REG_MOD_WIDTH, 0x15); // Largura de modulação
clrc663_write_register(CLRC663_REG_TX_WAIT_CTRL, 0x30); // Controle de tempo de espera TX
// Configurações da antena e RF
clrc663_write_register(CLRC663_REG_TX_AMP, 0x0F); // Potência de transmissão máxima
clrc663_write_register(CLRC663_REG_DRIVER_CON, 0x89); // Controle do driver
clrc663_write_register(CLRC663_REG_PLL_CTRL, 0x1B); // Controle do PLL
clrc663_write_register(CLRC663_REG_REGULATOR_CTRL, 0x01); // Controle do regulador
}
// Função genérica de transferência SPI
static void clrc663_spi_transfer(uint8_t *tx_data, uint8_t *rx_data, uint16_t len) {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // Chip Select Low
HAL_SPI_TransmitReceive(&hspi1, tx_data, rx_data, len, HAL_MAX_DELAY);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); // Chip Select High
}
// Escreve um byte em um registrador
static void clrc663_write_register(uint8_t reg_addr, uint8_t value) {
uint8_t tx_buf[2] = {reg_addr, value};
uint8_t rx_buf[2]; // Buffer de recebimento dummy
clrc663_spi_transfer(tx_buf, rx_buf, 2);
}
// Lê um byte de um registrador
static uint8_t clrc663_read_register(uint8_t reg_addr) {
uint8_t tx_buf[2] = {reg_addr | 0x80, 0x00}; // Bit de leitura = 1
uint8_t rx_buf[2];
clrc663_spi_transfer(tx_buf, rx_buf, 2);
return rx_buf[1]; // O dado lido está no segundo byte
}
// Executa um comando do CLRC663
static uint16_t clrc663_execute_command(uint8_t cmd) {
clrc663_write_register(CLRC663_REG_COMMAND, cmd);
// Espera o comando ser concluído (verificar IRQ0 bit 6 ou FSM_STATE)
uint32_t timeout = 10000;
while (timeout-- > 0) {
if (clrc663_read_register(CLRC663_REG_COMMAND) == CMD_IDLE) break; // Comando concluído
if (clrc663_read_register(CLRC663_REG_IRQ0) & 0x20) break; // Interrupção de comando concluído
}
return timeout; // Retorna 0 se timeout
}
// Função de Transmissão e Recepção genérica
static uint16_t clrc663_transmit_receive(const uint8_t *tx_buffer, uint8_t tx_len, uint8_t *rx_buffer, uint8_t rx_max_len) {
// Limpa o buffer FIFO
while (clrc663_read_register(CLRC663_REG_PRIMARY_STATUS) & 0x10) { // FIFO não vazio
clrc663_read_register(CLRC663_REG_FIFO_DATA);
}
// Escreve dados a serem transmitidos no FIFO
for (uint8_t i = 0; i < tx_len; i++) {
clrc663_write_register(CLRC663_REG_FIFO_DATA, tx_buffer[i]);
}
// Inicia o comando Transceive
clrc663_write_register(CLRC663_REG_COMMAND, CMD_TRANSCEIVE);
// Aguarda a conclusão da operação (IRQ0 bit 6)
uint32_t timeout = 20000; // Timeout maior para operações RF
while (!(clrc663_read_register(CLRC663_REG_IRQ0) & 0x20) && timeout--) {
HAL_Delay(1); // Pequeno delay para não sobrecarregar o loop
}
if (timeout == 0) return 0; // Falha no timeout
// Limpa flags de interrupção
clrc663_write_register(CLRC663_REG_IRQ0, 0x20);
// Verifica erros
uint8_t error_status = clrc663_read_register(CLRC663_REG_ERROR);
if (error_status & 0x1F) { // Verifica bits de erro
// Limpa registradores de erro e FIFO
clrc663_write_register(CLRC663_REG_ERROR, error_status);
return 0; // Erro detectado
}
// Lê o comprimento dos dados recebidos
uint8_t received_len = clrc663_read_register(CLRC663_REG_RX_LEN);
if (received_len > rx_max_len) {
received_len = rx_max_len; // Trunca se exceder o buffer de destino
}
// Lê os dados do FIFO
for (uint8_t i = 0; i < received_len; i++) {
rx_buffer[i] = clrc663_read_register(CLRC663_REG_FIFO_DATA);
}
return received_len;
}
// Comando ISO 15693 - Inventory
uint8_t ISO15693_Inventory(uint8_t *uid_buffer) {
uint8_t cmd_buffer[5] = {
ISO15693_PROTOCOL_FLAGS,
0x01, // Inventory Command Code
0x00, // AFI (Application Family Identifier) - 0x00 para todos
0x00 // Mask Length
};
uint8_t response_buffer[12]; // Suficiente para 1 etiqueta (FLAGS + COMMAND + UID + CRC)
uint8_t response_len = clrc663_transmit_receive(cmd_buffer, sizeof(cmd_buffer), response_buffer, sizeof(response_buffer));
// Formato esperado: [FLAGS | RESP_CODE | UID (8 bytes) | CRC (2 bytes)]
if (response_len >= 10 && (response_buffer[0] & 0x01)) { // Verifica flag de sucesso e se há dados
memcpy(uid_buffer, &response_buffer[2], ISO15693_UID_LEN); // Copia o UID (começa no byte 2)
return 1; // Etiqueta encontrada
}
return 0; // Nenhuma etiqueta encontrada ou erro
}
// Comando ISO 15693 - Read Single Block
uint8_t ISO15693_ReadBlock(const uint8_t *uid, uint8_t block_address, uint8_t *block_data_out) {
uint8_t command_payload[11]; // FLAGS(inc. UID) + CMD + ADDR + UID(8 bytes)
command_payload[0] = ISO15693_PROTOCOL_FLAGS | 0x20; // Inclui UID na requisição
command_payload[1] = 0x20; // Read Single Block Command Code
command_payload[2] = block_address;
memcpy(&command_payload[3], uid, ISO15693_UID_LEN);
uint8_t response_buffer[6]; // Dados do bloco (4 bytes) + FLAGS(1) + RESP_CODE(1)
uint8_t response_len = clrc663_transmit_receive(command_payload, sizeof(command_payload), response_buffer, sizeof(response_buffer));
// Formato esperado: [FLAGS | RESP_CODE | DATA(4 bytes) | CRC(2 bytes)]
if (response_len >= 6 && (response_buffer[0] & 0x01)) { // Verifica sucesso e se há dados
memcpy(block_data_out, &response_buffer[2], ISO15693_BLOCK_SIZE); // Copia os dados do bloco
return 1; // Leitura bem-sucedida
}
return 0; // Falha na leitura
}
// Comando ISO 15693 - Write Single Block
uint8_t ISO15693_WriteBlock(const uint8_t *uid, uint8_t block_address, const uint8_t *data_to_write) {
uint8_t command_payload[15]; // FLAGS(inc. UID) + CMD + ADDR + DATA(4 bytes) + UID(8 bytes)
command_payload[0] = ISO15693_PROTOCOL_FLAGS | 0x20; // Inclui UID na requisição
command_payload[1] = 0x21; // Write Single Block Command Code
command_payload[2] = block_address;
memcpy(&command_payload[3], data_to_write, ISO15693_BLOCK_SIZE);
memcpy(&command_payload[7], uid, ISO15693_UID_LEN);
uint8_t response_buffer[1]; // Apenas FLAGS + RESP_CODE
uint8_t response_len = clrc663_transmit_receive(command_payload, sizeof(command_payload), response_buffer, sizeof(response_buffer));
// Verifica se a resposta indica sucesso (byte 0 bit 0)
return (response_len > 0 && (response_buffer[0] & 0x01)) ? 1 : 0; // Retorna 1 para sucesso, 0 para falha
}
Programa Principal (main.c)
Este código gerencia o loop principal, chamando as funções de inicialização e as operações de leitura/escrita.
#include "main.h"
#include "clrc663.h"
#include "usart.h"
#include "gpio.h"
#include <stdio.h> // Para sprintf
#include <string.h> // Para strlen
// Definições de LEDs (ajuste conforme seu hardware)
#define STATUS_LED_PORT GPIOC
#define STATUS_LED_PIN GPIO_PIN_13
int main(void) {
// Inicialização do HAL e periféricos
HAL_Init();
SystemClock_Config(); // Configura o clock do sistema
MX_GPIO_Init(); // Inicializa GPIOs
MX_SPI1_Init(); // Inicializa SPI1
MX_USART1_UART_Init(); // Inicializa UART1 para comunicação serial
// Inicializa o driver CLRC663
CLRC663_Init();
// Configura o LED de status como saída e inicialmente desligado (ativo baixo)
GPIO_InitTypeDef led_init_struct;
led_init_struct.Pin = STATUS_LED_PIN;
led_init_struct.Mode = GPIO_MODE_OUTPUT_PP;
led_init_struct.Pull = GPIO_NOPULL;
led_init_struct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(STATUS_LED_PORT, &led_init_struct);
HAL_GPIO_WritePin(STATUS_LED_PORT, STATUS_LED_PIN, GPIO_PIN_SET); // LED apagado
uint8_t tag_uid[ISO15693_UID_LEN];
uint8_t block_buffer[ISO15693_BLOCK_SIZE];
char debug_message[80];
while (1) {
// Tenta detectar uma etiqueta ISO 15693
if (ISO15693_Inventory(tag_uid)) {
HAL_GPIO_WritePin(STATUS_LED_PORT, STATUS_LED_PIN, GPIO_PIN_RESET); // LED aceso
// Envia o UID detectado via UART
sprintf(debug_message, "Tag Detectada! UID: ");
HAL_UART_Transmit(&huart1, (uint8_t*)debug_message, strlen(debug_message), 100);
for (int i = 0; i < ISO15693_UID_LEN; i++) {
sprintf(debug_message, "%02X", tag_uid[i]);
HAL_UART_Transmit(&huart1, (uint8_t*)debug_message, strlen(debug_message), 100);
}
sprintf(debug_message, "\r\n");
HAL_UART_Transmit(&huart1, (uint8_t*)debug_message, strlen(debug_message), 100);
// Tenta ler o Bloco 0
if (ISO15693_ReadBlock(tag_uid, 0, block_buffer)) {
sprintf(debug_message, "Bloco 0 Lido: %02X %02X %02X %02X\r\n",
block_buffer[0], block_buffer[1], block_buffer[2], block_buffer[3]);
HAL_UART_Transmit(&huart1, (uint8_t*)debug_message, strlen(debug_message), 100);
// Modifica o primeiro byte do bloco e tenta reescrever
block_buffer[0]++; // Incrementa o valor do primeiro byte
if (ISO15693_WriteBlock(tag_uid, 0, block_buffer)) {
HAL_UART_Transmit(&huart1, (uint8_t*)"Escrita no Bloco 0: Sucesso!\r\n", 30, 100);
} else {
HAL_UART_Transmit(&huart1, (uint8_t*)"Escrita no Bloco 0: Falha!\r\n", 29, 100);
}
} else {
HAL_UART_Transmit(&huart1, (uint8_t*)"Falha ao ler Bloco 0.\r\n", 23, 100);
}
} else {
HAL_GPIO_WritePin(STATUS_LED_PORT, STATUS_LED_PIN, GPIO_PIN_SET); // LED apagado
}
HAL_Delay(1000); // Aguarda 1 segundo antes da próxima tentativa
}
}
Protocolo ISO 15693
O padrão ISO 15693 define a comunicação entre leitores e eitquetas RFID operando a 13.56MHz.
Estrutura da Transação
A comunicação segue um formato de comando/resposta:
Leitor -> Etiqueta:
[Flags(1 byte)] [Código do Comando(1 byte)] [Parâmetros Opcionais(n bytes)]
Etiqueta -> Leitor:
[Flags(1 byte)] [Código da Resposta(1 byte)] [Dados(n bytes)] [CRC(2 bytes)]
Comandos Principais
| Código Comando | Nome | Descrição |
|---|---|---|
0x01 |
Inventory | Detecta etiquetas presentes no campo RF e retorna seus UIDs. |
0x20 |
Read Single Block | Lê o conteúdo de um bloco de dados específico. |
0x21 |
Write Single Block | Escreve dados em um bloco específico. |
0x22 |
Lock Block | Torna um bloco de dados somente leitura (write-protected). |
0x23 |
Read Multiple Blocks | Lê múltiplos blocos de dados sequenciais. |
0x25 |
Write Multiple Blocks | Escreve dados em múltiplos blocos sequenciais. |
0x2A |
Get System Information | Consulta informações sobre a etiqueta (capacidade, etc.). |
Detecção de Conflitos (Anti-Collision)
O ISO 15693 utiliza um método de slot de tempo (time slotting) para lidar com múltiplas etiquetas:
- O leitor envia um comando
Inventory. - Múltiplas etiquetas podem responder simultaneamente.
- O leitor detecta a colisão e ajusta os parâmetros de tempo (slots) para isolar cada etiqueta.
- O processo é repetido até que cada etiqueta responda individualmente.
Otimizações e Extensões
Ajuste da Antena (Antenna Tuning)
Para maximizar a distância de leitura, a antena e o circuito de acoplamento do CLRC663 devem ser sintonizados. Isso geralmente envolve ajustar os componentes LC (indutores e capacitores) para ressoar na frequência de operação (13.56MHz). O código abaixo ilustra um exemplo conceitual de como isso poderia ser feito via software, embora a medição real (como SWR - Standing Wave Ratio) exija hardware adicional.
// Função conceitual para ajuste de antena
void tune_antenna_rf(void) {
uint8_t best_tx_power = 0;
uint8_t best_mod_index = 0;
float min_swr = 10.0f; // SWR inicial alto
// Loop para testar diferentes níveis de potência de transmissão
for (uint8_t power = 0; power <= 0x0F; power++) {
clrc663_write_register(CLRC663_REG_TX_AMP, power);
// Loop para testar diferentes índices de modulação
for (uint8_t mod = 0; mod <= 0x1F; mod++) {
clrc663_write_register(CLRC663_REG_MOD_WIDTH, mod);
// Em um sistema real, aqui você mediria o SWR
// float current_swr = measure_swr_using_coupler();
float current_swr = (float)rand() / RAND_MAX * 5.0f; // Simulação
if (current_swr < min_swr) {
min_swr = current_swr;
best_tx_power = power;
best_mod_index = mod;
}
}
}
// Aplica os melhores parâmetros encontrados
clrc663_write_register(CLRC663_REG_TX_AMP, best_tx_power);
clrc663_write_register(CLRC663_REG_MOD_WIDTH, best_mod_index);
// Idealmente, salvaria esses valores ou os usaria para recalcular C/L
}
Modo de Baixo Consumo
Para aplicações alimentadas por bateria, o sistema pode entrar em modos de baixo consumo:
- CLRC663: Configurar o chip em modo IDLE ou um modo de sleep mais profundo, desativando partes do circuito RF.
- STM32: Utilizar os modos de baixo consumo do STM32 (Sleep, Stop, Standby), acordando por interrupção (ex: timer ou evento externo).
// Exemplo de entrada em modo Stop do STM32
void enter_deep_sleep_mode(void) {
// Desliga o CLRC663 ou o coloca em modo de baixo consumo
clrc663_write_register(CLRC663_REG_COMMAND, CMD_IDLE);
clrc663_write_register(CLRC663_REG_REGULATOR_CTRL, 0x00); // Desliga regulador interno do CLRC663
// Configura o STM32 para modo Stop
// Requer configuração prévia de clocks e pinos para wake-up
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
// Após o wake-up, a execução continua aqui.
// É necessário re-inicializar periféricos se necessário e reativar o CLRC663.
CLRC663_Init();
}
Tratamento de Erros Robusto
Implementar retentativas para operações de comunicação e verificar códigos de erro retornados pelo CLRC663.
// Função Transceive com retentativas
uint16_t clrc663_safe_transmit_receive(const uint8_t *tx_buffer, uint8_t tx_len, uint8_t *rx_buffer, uint8_t rx_max_len, uint8_t max_retries) {
uint8_t retry_count = 0;
uint16_t result = 0;
while (retry_count <= max_retries) {
result = clrc663_transmit_receive(tx_buffer, tx_len, rx_buffer, rx_max_len);
if (result > 0) {
return result; // Sucesso na primeira tentativa ou após retentativas
}
// Se falhou, reconfigura o CLRC663 para um estado conhecido (Idle)
clrc663_write_register(CLRC663_REG_COMMAND, CMD_IDLE);
// Pequeno delay entre retentativas
HAL_Delay(10);
retry_count++;
}
return 0; // Falha após todas as retentativas
}
Testes e Validação
- Ambiente: Etiquetas NXP ICODE SLIX (ISO 15693), Leitor STM32/CLRC663.
- Distância de Operação: Observada até 8 cm em condições ideais.
- Velocidade: Leitura ~100ms, Escrita ~150ms.
- Consumo: Aproximadamente 80mA em operação ativa, ~5mA em standby (dependendo da configuração do STM32).
- Resultados: Taxa de detecção de 100% para etiquetas únicas. Bom desempenho em cenários com poucas etiquetas. A taxa de erro de bits é minimizada com o uso de CRC e, em ambientes ruidosos, pode ser necessário ajustar os parâmetros de RF ou usar técnicas de filtragem.
Recursos Adicionais
- Datasheet CLRC663: Documentação detalhada dos registradores e funcionalidades do chip.
- Padrão ISO/IEC 15693: Especificações completas do protocolo.
- Application Notes da NXP: Guias e exemplos práticos para o CLRC663.
Possíveis Expansões
- Suporte a Outros Protocolos: Adaptar a configuração para ISO 14443A/B, MIFARE.
- Segurança: Implementar criptografia ou autenticação segura com as etiquetas, se suportado.
- Conectividade: Integrar com módulos Wi-Fi (ESP8266) ou Bluetooth para comunicação com nuvem ou aplicativos móveis.