PN532 I2C模式STM32开发

您所在的位置:网站首页 温州考驾照哪里报名 PN532 I2C模式STM32开发

PN532 I2C模式STM32开发

2024-01-04 02:41| 来源: 网络整理| 查看: 265

PN532 I2C模式STM32开发 PN532介绍简介特性硬件连接 通讯流程主机和PN532通讯流向如何唤醒PN532 示例代码

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 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. * * © COPYRIGHT 2017 MindX ****************************************************************************** */ #include "pn532_i2c.h" #include #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. * * © COPYRIGHT 2017 MindX ****************************************************************************** */ #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. * * © COPYRIGHT 2017 MindX ****************************************************************************** */ #include "stm32f10x.h" #include "pn532_i2c.h" #include #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可以刷不同类型的卡,每种卡的读写稍有不同,就不在例程中做了。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3