PN532介绍
简介
PN532是一个高度集成的非接触读写芯片,它包含80C51微控制器内核(这个8051用户是不能对它编程的,它是用来内置NFC的底层通信协议栈),集成了13.56MHz下的各种主动/被动式非接触通信方法和协议。
PN532传输模块支持6种不同的工作模式:
-
读写器模式,支持ISO/IEC 14443A / MIFARE?机制
-
读写器模式,支持 FeliCa机制
-
读写器模式,支持ISO/IEC 14443B机制
-
卡操作模式,支持ISO 14443A / MIFARE?机制
-
卡操作模式,FeliCa机制
-
ISO/IEC18092,ECM340点对点
特性
带40 kB ROM和1 kB RAM的80C51微控制器内核
高度集成的模拟电路,解调和译码响应
输出缓冲驱动器通过最少量的外部无源器件连接天线
集成了RF场检测器
集成了数据模式检测器
支持ISO/IEC 14443A / MIFARE?
只在读写器模式中支持ISO/IEC 14443B
在读写器模式中典型工作距离超过50mm,具体距离由天线尺寸、调谐和电源决定
在NFCIP-1模式下工作距离高达50mm,具体视天线的尺寸、调谐以及电源而定
在卡操作模式中典型工作距离约为100mm,具体距离由天线尺寸、调谐和外部场强度决定
在读写器模式中,支持Mifare Classic加密,可支持212 kbit/s和424 kbit/s两种更高数据传输速率
FeliCa模式下,支持106kbit/s 、212kbit/s和424kbit/s的通信波特率
集成了NFCIP-1的RF接口,传输速率高达424kbit/s
灵活的中断模式
低功耗模式 一硬件掉电模式 一软件掉电模式
当器件处于掉电模式时能够通过I2C、HSU和SPI接口自动唤醒
可编程定时器
石英晶体振荡器
2.7V~5.5V的电源
供外部加密芯片使用的电源切换功能
控制外部设备的专用I/O管脚
供产品测试使用的集成天线检测器
与外部加密IC连接的ECMA 373 NFC-WI接口
硬件连接
如使用I2C模式,拨码开关应打到【1,0】模式。
模块需要连接VCC,GND,SDA,SCL,IRQ,RSTO,6根线。
其中,RSTO是PN532的复位线,低电平复位。
IRQ,是响应的中断线,可由程序选择是否启用,PN532有响应发生时,该引脚产生一个下降沿。
通讯流程
主机和PN532通讯流向
如何唤醒PN532
I2C 模式下,主机发送PN532 I2C地址(0x48),PN532会拉低SCL线 1ms。可以让主机释放SCL线,此时如果SCL线为低电平,表示此时PN532还未唤醒。
void I2C_Send_Byte(uint8_t byte)
{
uint8_t i = 8;
while(i)
{
if (byte & 0x80)
{
SDA_H;
}
else
{
SDA_L;
}
sw_delay_us(I2C_WIDTH);
SCL_H;
sw_delay_us(I2C_WIDTH);
/*Wait PN532 Wakeup*/
while(!SCL_READ)
{
SCL_H;
}
SCL_L;
sw_delay_us(I2C_WIDTH);
byte <<= 1;
i--;
}
SCL_L;
sw_delay_us(I2C_WIDTH);
}
示例代码
sw_i2c.c
/**
******************************************************************************
* @file sw_i2c.c
* @author zhujun
* @version V1.0
* @date 2019-07-01
* @brief 软件模拟I2C
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>© COPYRIGHT 2017 MindX</center></h2>
******************************************************************************
*/
#include "sw_i2c.h"
#include "delay.h"
/**
******************************************************************************
* @brief Soft I2C GPIO initial.
* @return None.
******************************************************************************/
void I2C_Initial(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(I2C_SCL_RCC | I2C_SDA_RCC, ENABLE);
GPIO_SetBits(I2C_SCL_PORT, I2C_SCL_PIN);
GPIO_SetBits(I2C_SDA_PORT, I2C_SDA_PIN);
GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Init(I2C_SCL_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = I2C_SDA_PIN;
GPIO_Init(I2C_SDA_PORT, &GPIO_InitStructure);
}
/**
******************************************************************************
* @brief I2C send start signal.
* @return None.
******************************************************************************/
void I2C_Start(void)
{
SDA_H;
SCL_H;
sw_delay_us(I2C_WIDTH);
SDA_L;
sw_delay_us(I2C_WIDTH);
SCL_L;
sw_delay_us(I2C_WIDTH * 2);
}
/**
******************************************************************************
* @brief I2C send stop signal.
* @return None.
******************************************************************************/
void I2C_Stop(void)
{
SCL_L;
SDA_L;
sw_delay_us(I2C_WIDTH);
SCL_H;
sw_delay_us(I2C_WIDTH);
SDA_H;
sw_delay_us(I2C_WIDTH);
}
/**
******************************************************************************
* @brief I2C send ack signal.
* @return None.
******************************************************************************/
void I2C_Ack(void)
{
SCL_L;
SDA_L;
sw_delay_us(I2C_WIDTH);
SCL_H;
sw_delay_us(I2C_WIDTH);
SCL_L;
sw_delay_us(I2C_WIDTH);
SDA_H;
}
/**
******************************************************************************
* @brief I2C send nack signal.
* @return None.
******************************************************************************/
void I2C_NAck(void)
{
SCL_L;
SDA_H;
sw_delay_us(I2C_WIDTH);
SCL_H;
sw_delay_us(I2C_WIDTH);
SCL_L;
sw_delay_us(I2C_WIDTH);
}
/**
******************************************************************************
* @brief I2C Wait slave send ack signal.
* @return Result 0-OK
* 1-ERROR
******************************************************************************/
uint8_t I2C_Wait_Ack(void)
{
uint8_t temp;
SDA_H;
sw_delay_us(I2C_WIDTH);
SCL_H;
sw_delay_us(I2C_WIDTH);
if(SDA_READ)
{
temp = 1;
}
else
{
temp = 0;
}
SCL_L;
sw_delay_us(I2C_WIDTH);
return temp;
}
/**
******************************************************************************
* @brief I2C send one byte.
* @param byte, One byte data.
* @return None.
******************************************************************************/
void I2C_Send_Byte(uint8_t byte)
{
uint8_t i = 8;
while(i)
{
if (byte & 0x80)
{
SDA_H;
}
else
{
SDA_L;
}
sw_delay_us(I2C_WIDTH);
SCL_H;
sw_delay_us(I2C_WIDTH);
while(!SCL_READ)
{
SCL_H;
}
SCL_L;
sw_delay_us(I2C_WIDTH);
byte <<= 1;
i--;
}
SCL_L;
sw_delay_us(I2C_WIDTH);
}
/**
******************************************************************************
* @brief I2C receive one byte.
* @return One byte data..
******************************************************************************/
uint8_t I2C_Recv_Byte(void)
{
uint8_t i,temp=0;
for(i = 0; i < 8; i++)
{
SCL_H;
sw_delay_us(I2C_WIDTH);
temp<<=1;
if(SDA_READ)
{
temp |= 0x01;
}
SCL_L;
sw_delay_us(I2C_WIDTH);
}
return temp;
}
/**
******************************************************************************
* @brief I2C send byte(s) with address.
* @param pbuf, data buffer.
* @param length, data length.
* @param addr, i2c slave address.
* @return Write result.
******************************************************************************/
uint8_t I2C_Write(uint8_t* pbuf, u16 length, uint8_t addr)
{
I2C_Start();
I2C_Send_Byte(addr);
if(I2C_Wait_Ack())
{
I2C_Stop();
return 0;
}
sw_delay_us(I2C_WIDTH);
while(length)
{
I2C_Send_Byte(*pbuf);
I2C_Wait_Ack();
length--;
pbuf++;
sw_delay_us(I2C_WIDTH);
}
I2C_Stop();
return 1;
}
/**
******************************************************************************
* @brief I2C send one byte.
* @param pbuf, data buffer.
* @param length, data length.
* @param addr, i2c slave address.
* @return Read result.
******************************************************************************/
uint8_t I2C_Read(uint8_t* pbuf, uint16_t length, uint8_t addr)
{
I2C_Start();
I2C_Send_Byte(addr);
if(I2C_Wait_Ack())
{
I2C_Stop();
return 0;
}
while(length)
{
if(length == 1)
{
*pbuf++ = I2C_Recv_Byte();
I2C_NAck();
}
else
{
*pbuf++ = I2C_Recv_Byte();
I2C_Ack();
}
length--;
}
I2C_Stop();
return 1;
}
/*********************************END FILE********************************************/
sw_i2c.h
/**
******************************************************************************
* @file sw_i2c.h
* @author zhujun
* @version V1.0
* @date 2019-07-01
* @brief 软件模拟I2C相关操作头文件
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>© COPYRIGHT 2017 MindX</center></h2>
******************************************************************************
*/
#ifndef __SW_I2C_H__
#define __SW_I2C_H__
#include "stm32f10x.h"
#define I2C_SCL_RCC RCC_APB2Periph_GPIOB
#define I2C_SCL_PORT GPIOB
#define I2C_SCL_PIN GPIO_Pin_6
#define I2C_SDA_RCC RCC_APB2Periph_GPIOB
#define I2C_SDA_PORT GPIOB
#define I2C_SDA_PIN GPIO_Pin_7
#define SCL_H I2C_SCL_PORT->BSRR = I2C_SCL_PIN
#define SCL_L I2C_SCL_PORT->BRR = I2C_SCL_PIN
#define SDA_H I2C_SDA_PORT->BSRR = I2C_SDA_PIN
#define SDA_L I2C_SDA_PORT->BRR = I2C_SDA_PIN
#define SCL_READ ((I2C_SCL_PORT->IDR & I2C_SCL_PIN) != (uint32_t)Bit_RESET)
#define SDA_READ ((I2C_SDA_PORT->IDR & I2C_SDA_PIN) != (uint32_t)Bit_RESET)
#define I2C_WIDTH 5
void I2C_Initial(void);
void I2C_Start(void);
void I2C_Stop(void);
void I2C_Ack(void);
void I2C_NAck(void);
uint8_t I2C_Wait_Ack(void);
void I2C_Send_Byte(uint8_t data);
uint8_t I2C_Read_Byte(void);
uint8_t I2C_Read(uint8_t* pbuf, uint16_t length, uint8_t addr);
uint8_t I2C_Write(uint8_t* pbuf, u16 length, uint8_t addr);
#endif
pn532_i2c.c
/**
******************************************************************************
* @file pn532_i2C.c
* @author zhujun
* @version V1.0
* @date 2019-07-01
* @brief PN532操作
* SCL ---- PB6
* SDA ---- PB7
* RESET -- PB8
* IQR ---- PB5
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>© COPYRIGHT 2017 MindX</center></h2>
******************************************************************************
*/
#include "pn532_i2c.h"
#include <string.h>
#include "delay.h"
#include "sw_i2c.h"
/**
******************************************************************************
* @brief PN532 data package
* @param in_buf, data buffer.
* @param in_len, data length.
* @param out_buf, output data buffer.
* @return output data length.
******************************************************************************/
static int PN532_Package(uint8_t *in_buf, int in_len, uint8_t* out_buf)
{
int i = 0;
uint8_t checksum = 0;
/*PREAMBLE*/
out_buf[0] = PN532_PREAMBLE;
/*START CODE*/
out_buf[1] = PN532_STARTCODE1;
out_buf[2] = PN532_STARTCODE2;
/*LEN*/
out_buf[3] = in_len + 1;
/*LCS*/
out_buf[4] = (uint8_t)(0x100 - out_buf[3]);
/*TFI*/
out_buf[5] = STM32_TO_PN532;
checksum += out_buf[5];
/*Data*/
for(i = 0; i < in_len; i++)
{
out_buf[i + 6] = in_buf[i];
checksum += in_buf[i];
}
/*DCS*/
out_buf[in_len + 6] = (uint8_t)(0x100 - checksum);
/*Tail*/
out_buf[in_len + 7] = 0x00;
return in_len + 8;
}
/**
******************************************************************************
* @brief PN532 data parse
* @param buf, input data buffer.
* @param length, input data length.
* @param out_buf, output data buffer.
* @return output data length.
* -1, error
******************************************************************************/
static int PN532_Parse(uint8_t *buf, int length, uint8_t *out_buf)
{
int ret = -1;
int i;
uint8_t len;
if(len < 7)
{
goto EXIT;
}
if((buf[0] != 0x00) || (buf[1] != 0x00) || (buf[2] != 0xff))
{
goto EXIT;
}
if(buf[3] != (0x100 - buf[4]))
{
goto EXIT;
}
if(buf[3] > len - 7)
{
goto EXIT;
}
len = buf[3];
if(buf[len + 7 - 1] != 0x00)
{
goto EXIT;
}
if(buf[5] != PN532_TO_STM32)
{
goto EXIT;
}
for(i = 0; i < buf[3]; i++)
{
out_buf[i] = buf[6 + i];
}
return i;
EXIT:
return ret;
}
/**
******************************************************************************
* @brief PN532 GPIO Initial.
* @return None.
******************************************************************************/
void PN532_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(PN532_RESET_RCC | PN532_IRQ_RCC, ENABLE);
I2C_Initial();
GPIO_InitStructure.GPIO_Pin = PN532_RESET_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(PN532_RESET_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = PN532_IRQ_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(PN532_IRQ_PORT, &GPIO_InitStructure);
}
/**
******************************************************************************
* @brief Reset PN532.
* @return None.
******************************************************************************/
void PN532_Reset(void)
{
GPIO_SetBits(PN532_RESET_PORT, PN532_RESET_PIN);
GPIO_ResetBits(PN532_RESET_PORT, PN532_RESET_PIN);
sw_delay_ms(40);
GPIO_SetBits(PN532_RESET_PORT, PN532_RESET_PIN);
sw_delay_ms(10);
}
/**
******************************************************************************
* @brief Wait I2C bus ready.
* @param timeout, wait time, unit us.
* @return Result.
******************************************************************************/
PN532_RES PN532_WaitReady(int timeout)
{
while(GPIO_ReadInputDataBit(PN532_IRQ_PORT, PN532_IRQ_PIN))
{
sw_delay_us(1);
if(timeout == -1)
{
continue;
}
else if(!timeout--)
{
return PN532_TIMEOUT;
}
}
return PN532_OK;
}
/**
******************************************************************************
* @brief I2C data buffer, and wait pn532 ack.
* @param pbuf, data buffer.
* @param len, data length.
* @param timeout, wait time, unit us.
* @return Result.
******************************************************************************/
PN532_RES PN532_Write_WaitAck(uint8_t *pbuf, uint16_t len, uint32_t timeout)
{
uint8_t ack[] = {0x01, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00};
uint8_t res[7];
I2C_Write(pbuf, len, PN532_I2C_ADDR);
if(PN532_WaitReady(timeout) != 0)
{
return PN532_TIMEOUT;
}
I2C_Read(res, 7, PN532_I2C_ADDR | 0x01);
if(memcmp(ack, res, 7) == 0)
{
return PN532_OK;
}
return PN532_DATA_ERROR;
}
/**
******************************************************************************
* @brief Wait PN532 response.
* @param pbuf, data buffer.
* @param len, data length.
* @param timeout, wait time, unit us.
* @return Result.
******************************************************************************/
PN532_RES PN532_Response(uint8_t *pbuf, uint16_t len, int timeout)
{
if(PN532_WaitReady(timeout) != 0)
{
return PN532_TIMEOUT;
}
I2C_Read(pbuf, len, PN532_I2C_ADDR | 0x01);
return PN532_OK;
}
/**
******************************************************************************
* @brief Get PN532 version.
* @param ver, version 2 bytes.
* @return Result.
******************************************************************************/
PN532_RES PN532_Get_Version(uint8_t *ver)
{
//uint8_t buf[] = {0x00, 0x00, 0xff, 0x02, 0xfe, 0xd4, 0x02, 0x2a, 0x00};
uint8_t pbuf[] = {CMD_GET_FW_VERSION};
uint8_t pack[16];
uint8_t res[16];
int ret;
ret = PN532_Package(pbuf, 1, pack);
if(PN532_Write_WaitAck(pack, ret, 2000) != 0)
{
return PN532_TIMEOUT;
}
if(PN532_Response(res, 16, 1000) != 0)
{
return PN532_TIMEOUT;
}
ver[0] = res[9];
ver[1] = res[10];
sw_delay_us(1000);
return PN532_OK;
}
/**
******************************************************************************
* @brief Config SAM.
* @return Result.
******************************************************************************/
PN532_RES PN532_SAMConfig(void)
{
//uint8_t buf[] = {0x00, 0x00, 0xff, 0x05, 0xfb, 0xd4, 0x14, 0x01, 0x14, 0x01, 0x02, 0x00};
uint8_t pbuf[3];
uint8_t pack[16];
uint8_t res[16];
int ret;
pbuf[0] = CMD_SAM_CONFIG;
pbuf[1] = FIND_NFCCARD_MAXNUM;
pbuf[2] = NFC_106K_PROTOCOL;
ret = PN532_Package(pbuf, 3, pack);
if(PN532_Write_WaitAck(pack, ret, 2000) != 0)
{
return PN532_TIMEOUT;
}
if(PN532_Response(res, 8, 1000) != 0)
{
return PN532_TIMEOUT;
}
sw_delay_us(1000);
if(res[7] == 0x15)
{
return PN532_OK;
}
else
{
return PN532_DATA_ERROR;
}
}
/**
******************************************************************************
* @brief Wait passive card.
* @param card_id, card id.
* @param id_len, card bytes count.
* @return Result.
******************************************************************************/
PN532_RES PN532_ReadPassiveTargetID(uint8_t *card_id, uint8_t *id_len)
{
uint8_t buf[3];
uint8_t pack[64];
uint8_t res[32];
uint8_t pdata[16];
int ret;
buf[0] = CMD_IN_LIST_PASSIVE_TARGET;
buf[1] = FIND_NFCCARD_MAXNUM;
buf[2] = NFC_106K_PROTOCOL;
ret = PN532_Package(buf, 3, pack);
if(PN532_Write_WaitAck(pack, ret, 1000) != 0)
{
return PN532_TIMEOUT;
}
if(PN532_Response(res, 23, -1) != 0)
{
return PN532_TIMEOUT;
}
if(res[0] == 0x01)
{
ret = PN532_Parse(&res[1], 22, pdata);
if(ret > 0)
{
*id_len = pdata[6];
for(uint8_t i = 0; i < *id_len; i++)
{
card_id[i] = pdata[7+i];
}
return PN532_OK;
}
}
else
{
return PN532_TIMEOUT;
}
sw_delay_us(1000);
return PN532_OK;
}
pn532_i2c.h
/**
******************************************************************************
* @file pn532_i2c.h
* @author zhujun
* @version V1.0
* @date 2019-07-01
* @brief PN532相关操作头文件
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>© COPYRIGHT 2017 MindX</center></h2>
******************************************************************************
*/
#ifndef __PN532_I2C_H__
#define __PN532_I2C_H__
#include "stm32f10x.h"
#include "sw_i2c.h"
#define PN532_RESET_RCC RCC_APB2Periph_GPIOB
#define PN532_RESET_PORT GPIOB
#define PN532_RESET_PIN GPIO_Pin_8
#define PN532_IRQ_RCC RCC_APB2Periph_GPIOB
#define PN532_IRQ_PORT GPIOB
#define PN532_IRQ_PIN GPIO_Pin_5
#define PN532_PREAMBLE 0x00
#define PN532_STARTCODE1 0x00
#define PN532_STARTCODE2 0xFF
#define STM32_TO_PN532 0xD4
#define PN532_TO_STM32 0xD5
/*Miscellaneous*/
#define CMD_DIAGONOSE 0x00
#define CMD_GET_FW_VERSION 0x02
#define CMD_GET_GEN_STATUS 0x04
#define CMD_READ_REG 0x06
#define CMD_WRITE_REG 0x08
#define CMD_READ_GPIO 0x0C
#define CMD_WRITE_GPIO 0x0E
#define CMD_SET_SERIAL_RATE 0x10
#define CMD_SET_PARAM 0x12
#define CMD_SAM_CONFIG 0x14
#define CMD_POWERDOWN 0x16
/*RF Communication*/
#define CMD_RFConfig 0x32
#define CMD_RFRegationTest 0x58
/*Initiator*/
#define CMD_IN_JUMP_FOR_DEP 0x56
#define CMD_In_JUMP_FOR_PSL 0x46
#define CMD_IN_LIST_PASSIVE_TARGET 0x4a
#define CMD_IN_ATR 0x50
#define CMD_IN_PSL 0x4E
#define CMD_IN_DATA_EXCHANGE 0x40
#define CMD_IN_COMM_THRU 0x42
#define CMD_IN_DESELECT 0x44
#define CMD_IN_RELEASE 0x52
#define CMD_IN_SELECET 0x54
#define CMD_IN_AUTOPOLL 0x60
#define FIND_NFCCARD_MAXNUM 0x01
#define NFC_106K_PROTOCOL 0x00
#define PN532_I2C_ADDR (0x48)
typedef enum
{
PN532_OK = 0,
PN532_TIMEOUT = -1,
PN532_DATA_ERROR = -2,
}PN532_RES;
void PN532_GPIO_Init(void);
void PN532_Reset(void);
PN532_RES PN532_Get_Version(uint8_t *ver);
PN532_RES PN532_SAMConfig(void);
PN532_RES PN532_ReadPassiveTargetID(uint8_t *card_id, uint8_t *id_len);
#endif
main.c
/**
******************************************************************************
* @file main.c
* @author zhujun
* @version V1.0
* @date 2019-07-01
* @brief Main
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>© COPYRIGHT 2017 MindX</center></h2>
******************************************************************************
*/
#include "stm32f10x.h"
#include "pn532_i2c.h"
#include <stdio.h>
#if 0
#define LOG printf
#else
#define LOG(...)
#endif
int main(void)
{
int ret;
uint8_t ver[2];
uint8_t cardid[8];
uint8_t id_len;
PN532_GPIO_Init();
PN532_Reset();
ret = PN532_Get_Version(ver);
if(ret != PN532_OK)
{
LOG("Read Version ERROR.");
while(1)
{
}
}
LOG("PN532 Version %d.%d.\r\n", ver[0], ver[1]);
if((ver[0] != 0x01) || (ver[1] != 0x06))
{
LOG("Version not match!\r\n");
}
ret = PN532_SAMConfig();
if(ret != PN532_OK)
{
LOG("PN532 SAMConfig ERROR.");
while(1)
{
}
}
while(1)
{
ret = PN532_ReadPassiveTargetID(cardid, &id_len);
if(ret == PN532_OK)
{
LOG("Found Card\r\n");
for(int i = 0; i < id_len; i++)
{
LOG("%02x ", cardid[i]);
}
LOG("\r\n");
}
}
}
#ifdef USE_FULL_ASSERT
/**
******************************************************************************
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @return None
******************************************************************************/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
while (1)
{}
}
#endif
代码工程,可下载查看https://download.csdn.net/download/imzhujun/11267066
示例工程只做了发现卡,因为PN532可以刷不同类型的卡,每种卡的读写稍有不同,就不在例程中做了。