cancel
Showing results for 
Search instead for 
Did you mean: 

SPI write and reading from PN532 using HAL not working

KYou.1
Associate II

I am working on a project to communicate with PN532 nfc reader.

The reader work just fine with arduino code using SPI.

Below is the library I used to read and write data from PN532

https://github.com/adafruit/Adafruit-PN532

Now I switched to stm32 board I am using.

I have setup below and this is pretty much like what arduino code is using.

0693W000005Av1kQAC.png 

Below is the code I am currently using and I am stuck at write then receiving part.

#include "omo_driver_pn532.h"
#include <string.h>
 
const uint8_t pn532ack[] = {0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00};
uint8_t pn532response_firmwarevers[] = {0x00, 0x00, 0xFF, 0x06, 0xFA, 0xD5};
 
#define PN532_PACKBUFFSIZ 64
uint8_t pn532_packetbuffer[PN532_PACKBUFFSIZ];
 
OMO_PN532::OMO_PN532(SPI_HandleTypeDef* hspi, GPIO_TypeDef* GPIO, uint16_t ss)
{
   _hspi = hspi;
   _ssGPIO = GPIO;
   _ssPin = ss;
   slaveDeselect();      //SS pin default high
}
 
void OMO_PN532::begin(void)
{
   pn532_packetbuffer[0] = PN532_COMMAND_GETFIRMWAREVERSION;
   
   sendCommandCheckAck(pn532_packetbuffer, 1);
   
 
   slaveDeselect();
}
 
uint32_t OMO_PN532::getFirmwareVersion(void)
{
   uint32_t response;
   pn532_packetbuffer[0] = PN532_COMMAND_GETFIRMWAREVERSION;
   //Sending : 0x0, 0x0, 0xFF, 0x2, 0xFE, 0xD4, 0x2, 0x2A, 0x0, 
   //Reading:  0x0 0x0 0xFF 0x6 0xFA 0xD5 0x3 0x32 0x1 0x6 0x7 0xE8
   sendCommandCheckAck(pn532_packetbuffer, 1);
   // read data packet
   readdata(pn532_packetbuffer, 12);
 
   
   int offset = 7;
   response = pn532_packetbuffer[offset++];
   response <<= 8;
   response |= pn532_packetbuffer[offset++];
   response <<= 8;
   response |= pn532_packetbuffer[offset++];
   response <<= 8;
   response |= pn532_packetbuffer[offset++];
 
   return response;
}
/**************************************************************************/
/*!
    @brief  Sends a command and waits a specified period for the ACK
 
    @param  cmd       Pointer to the command buffer
    @param  cmdlen    The size of the command in bytes
    @param  timeout   timeout before giving up
 
    @returns  1 if everything is OK, 0 if timeout occured before an
              ACK was recieved
*/
/**************************************************************************/
// default timeout of one second
bool OMO_PN532::sendCommandCheckAck(uint8_t *cmd, uint8_t cmdlen,
                                         uint16_t timeout) {
  // uint16_t timer = 0;
  // write the command
  writecommand(cmd, cmdlen);
  // Wait for chip to say its ready!
   while(HAL_SPI_GetState(_hspi) != HAL_SPI_STATE_READY);
  // read acknowledgement
  if (!readack()) {
    return false;
  }
 
  return true; // ack'd command
}
/**************************************************************************/
/*!
    @brief  Reads n bytes of data from the PN532 via SPI or I2C.
 
    @param  buff      Pointer to the buffer where data will be written
    @param  n         Number of bytes to be read
*/
/**************************************************************************/
void OMO_PN532::readdata(uint8_t *buff, uint8_t n) {
   uint8_t cmd = PN532_SPI_DATAREAD;
   slaveSelect();
   HAL_Delay(1);
   
   while(HAL_SPI_GetState(_hspi) != HAL_SPI_STATE_READY);
   HAL_SPI_Transmit(_hspi, &cmd, 1, 10);
   
   while(HAL_SPI_GetState(_hspi) != HAL_SPI_STATE_READY);
   HAL_SPI_Receive(_hspi, buff, n, 10);
   slaveDeselect();
   
}
 
 
void OMO_PN532::writecommand(uint8_t *cmd, uint8_t cmdlen)
{
   //Sending : 0x0, 0x0, 0xFF, 0x2, 0xFE, 0xD4, 0x2, 0x2A, 0x0, 
   // SPI command write.
   uint8_t checksum;
   uint8_t packet[PN532_PACKBUFFSIZ];
   uint8_t *p = packet;
   cmdlen++;
   p[0] = PN532_SPI_DATAWRITE;
   p++;
   p[0] = PN532_PREAMBLE;
   p++;
   p[0] = PN532_STARTCODE1;
   p++;
   p[0] = PN532_STARTCODE2;
   p++;
   checksum = PN532_PREAMBLE + PN532_STARTCODE1 + PN532_STARTCODE2;
   p[0] = cmdlen;
   p++;
   p[0] = ~cmdlen + 1;
   p++;
   p[0] = PN532_HOSTTOPN532;
   p++;
   checksum += PN532_HOSTTOPN532;
   for (uint8_t i = 0; i < cmdlen - 1; i++) {
      p[0] = cmd[i];
      p++;
      checksum += cmd[i];
   }
   p[0] = ~checksum;
   p++;
   p[0] = PN532_POSTAMBLE;
   p++;
   
   //spi_dev->write(packet, 8 + cmdlen);
   slaveSelect();
   while(HAL_SPI_GetState(_hspi) != HAL_SPI_STATE_READY);
   HAL_SPI_Transmit(_hspi, (uint8_t *)packet, 8+cmdlen, 10);
   slaveDeselect();
}
/**************************************************************************/
/*!
    @brief  Tries to read the SPI or I2C ACK signal
*/
/**************************************************************************/
bool OMO_PN532::readack() {
   uint8_t ackbuff[6];
   uint8_t cmd = PN532_SPI_DATAREAD;
 
   slaveSelect();
   while(HAL_SPI_GetState(_hspi) != HAL_SPI_STATE_READY);
   HAL_SPI_Transmit(_hspi, (uint8_t *)cmd, 1, 10);
   while(HAL_SPI_GetState(_hspi) != HAL_SPI_STATE_READY);
   HAL_SPI_Receive(_hspi, ackbuff, 6, 10);
   slaveDeselect();
   return (0 == memcmp((char *)ackbuff, (char *)pn532ack, 6));
}
 
void OMO_PN532::slaveSelect(void)
{
   HAL_GPIO_WritePin(_ssGPIO, _ssPin, GPIO_PIN_RESET);
}
 
void OMO_PN532::slaveDeselect(void)
{
   HAL_GPIO_WritePin(_ssGPIO, _ssPin, GPIO_PIN_SET);
}
 

In this part, I am sending just 0x03 in the beginning then try to receive 6 bytes from PN532 however the scope shows entirely different thing

#define PN532_SPI_DATAREAD (0x03)

void OMO_PN532::readdata(uint8_t *buff, uint8_t n) {
   uint8_t cmd = PN532_SPI_DATAREAD;
 
   //spi_dev->write_then_read(&cmd, 1, buff, n);
   slaveSelect();
   HAL_Delay(1);
   
   while(HAL_SPI_GetState(_hspi) != HAL_SPI_STATE_READY);
   HAL_SPI_Transmit(_hspi, &cmd, 1, 10);
   
   while(HAL_SPI_GetState(_hspi) != HAL_SPI_STATE_READY);
   HAL_SPI_Receive(_hspi, buff, n, 10);
   
   slaveDeselect();
   
}

Below scope captured from MOSI (Green) and SCK (Yello) pins during below code debug.

0693W000005AvEyQAK.pngWhy there is no 0x03 in the first part of transmission and MOSI is keep sending something while receiving?

0693W000005Av2YQAS.jpg 

2 REPLIES 2
NZama.1
Associate III

Hey, I don't have an answer to your post. But I am trying to communicate these same two modules. Can you help me with the interfacing between them? You have used 4 SPI connections. SDA,SCK,MOSI,MISO. I got them. What about the IRQ and RESET pin of the PN532 module? how have you connected them and also why you are using UART (TX and RX ) pin? are these for IRQ and reset ?Thankyou.

S.Ma
Principal

Your speed is <10MHz within spec. Have you checked the PHASE / POL config bits for this slave device ? 4 possible combinations.... the MIFARE has multiple interface, make sure when plugging on the STM32 the SPI is HW selected. As there is an internal 8051 code in MIFARE, add a SW delay in main() to wait for it to be up and ready to SPI dialog.