PN532 I2C模式STM32开发

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>&copy; 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>&copy; 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>&copy; 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>&copy; 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>&copy; 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可以刷不同类型的卡,每种卡的读写稍有不同,就不在例程中做了。

  • 12
    点赞
  • 79
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
好的,关于PN532STM32上的SPI模式开发,我可以给您一些简单的参考。 首先,您需要确保您的STM32PN532之间通过SPI接口进行连接。接下来,您需要使用STM32的SPI库来初始化SPI接口,并设置SPI的参数(如时钟分频、数据位数等)。然后,您需要按照PN532的通信协议来发送数据和接收数据。 以下是一个简单的示例代码,可以帮助您开始: ```c #include "stm32f4xx.h" #include "spi.h" #define PN532_SPI_CS_PORT GPIOB #define PN532_SPI_CS_PIN GPIO_Pin_12 void PN532_SPI_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; /* Enable SPI clock and GPIO clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB, ENABLE); /* Configure SPI pins */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure CS pin */ GPIO_InitStructure.GPIO_Pin = PN532_SPI_CS_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_Init(PN532_SPI_CS_PORT, &GPIO_InitStructure); /* Connect SPI pins to SPI alternate function */ GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1); GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1); GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1); /* Configure SPI */ SPI_I2S_DeInit(SPI1); SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI1, &SPI_InitStructure); /* Enable SPI */ SPI_Cmd(SPI1, ENABLE); /* Set CS pin high */ GPIO_SetBits(PN532_SPI_CS_PORT, PN532_SPI_CS_PIN); } void PN532_SPI_Write(uint8_t* data, uint16_t len) { /* Set CS pin low */ GPIO_ResetBits(PN532_SPI_CS_PORT, PN532_SPI_CS_PIN); /* Send data */ for (uint16_t i = 0; i < len; i++) { SPI_I2S_SendData(SPI1, data[i]); while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET); } /* Set CS pin high */ GPIO_SetBits(PN532_SPI_CS_PORT, PN532_SPI_CS_PIN); } void PN532_SPI_Read(uint8_t* data, uint16_t len) { /* Set CS pin low */ GPIO_ResetBits(PN532_SPI_CS_PORT, PN532_SPI_CS_PIN); /* Receive data */ for (uint16_t i = 0; i < len; i++) { SPI_I2S_SendData(SPI1, 0xFF); while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET); data[i] = SPI_I2S_ReceiveData(SPI1); } /* Set CS pin high */ GPIO_SetBits(PN532_SPI_CS_PORT, PN532_SPI_CS_PIN); } ``` 在此示例中,我们使用SPI1作为SPI接口,并将SCK、MISO、MOSI分别连接到PA5、PA6、PA7。CS引脚连接到PB12。您需要根据您的硬件连接来更改这些引脚。 在PN532_SPI_Init函数中,我们初始化SPI接口,并将CS引脚初始化为输出模式。在PN532_SPI_Write和PN532_SPI_Read函数中,我们分别用于发送和接收数据。在发送和接收数据时,我们需要检查SPI状态寄存器中的标志位,以确保数据成功发送和接收。 请注意,此示例代码仅用于参考。您需要根据您的具体要求进行修改和调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值