2020-11-10 03:44 AM
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.
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.
Why there is no 0x03 in the first part of transmission and MOSI is keep sending something while receiving?
2023-06-04 03:21 AM
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.
2023-06-04 08:46 AM
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.