Is it possible to use SDK of nrf52840 to configure a 3wire SPI?
I saw in some posts that i can not use directly the MISO pin and not assing it in the sdk's nrf function, but is the best way to proceed?
Is it possible to use SDK of nrf52840 to configure a 3wire SPI?
I saw in some posts that i can not use directly the MISO pin and not assing it in the sdk's nrf function, but is the best way to proceed?
By SDK hopefully you mean nRF52 SDK, but in any case here's a guide using bare-metal programming which you can use to alter other examples. Tested with LIS2DH12 which starts as 4-wire SPI but can be set to 3-wire SPI. (This code assumes the SPI slave is always 3-wire so the 4-wire to 3-wire slave command is not shown). Sequence is send a 1-byte command, no rx, reverse the pin then send a dummy command and receive whatever number of rx bytes are required, in this example a single byte "I am .." response but can be longer
#define CSPIN 11 // spi chip select #define SCKPIN 12 // spi clock #define MOSIPIN 13 // spi mosi //#define MISOPIN 14 // spi miso - not used in 3-wire mode #define LIS2DH12_WHO_AM_I 0x0F // Read as 0x33 uint8_t spi3wTXBuf[] = {0x80|LIS2DH12_WHO_AM_I, 0xFF}; uint8_t spi3wRXBuf[sizeof(spi3wTXBuf)] = {0,0}; static const uint8_t m3wRxTxBufLength = sizeof(spi3wTXBuf); volatile uint32_t mSpiInterruptCounter = 0UL; void notSPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler(void) { if (NRF_SPIM0->EVENTS_END) NRF_SPIM0->EVENTS_END = 0; mSpiInterruptCounter++; } static void Test3WireSPI(void) { NRF_GPIO->PIN_CNF[CSPIN] = 0x301; // output, high drive high and low H0H1 NRF_GPIO->PIN_CNF[SCKPIN] = 0x301; // output, high drive high and low H0H1 NRF_GPIO->PIN_CNF[MOSIPIN] = 1; // output, standard drive S0S1 //NRF_GPIO->PIN_CNF[MISOPIN] = 0; // input pin, input buffer connected, no pull, S0S1, sense disabled NRF_GPIO->OUTSET = 1 << CSPIN; // deactivate by setting chip select high NRF_SPIM0->PSEL.SCK = SCKPIN; NRF_SPIM0->PSEL.MOSI = MOSIPIN; NRF_SPIM0->PSEL.MISO = 0xFFFFFFFFUL; // MISOPIN; NRF_SPIM0->CONFIG = 0; // CPOL 0 -- clock polarity active high, CPHA 1 -- sample on trailing clock edge, send Msb first NRF_SPIM0->FREQUENCY = 0x80000000UL; // 8 Mbps NRF_SPIM0->ORC =0; // Unused Tx bytes, set all low // Configure registers for 3-wire mode NRF_SPIM0->PSEL.MOSI = MOSIPIN; NRF_SPIM0->PSEL.MISO = 0xFFFFFFFFUL; // MISOPIN; NRF_GPIO->PIN_CNF[MOSIPIN] = 1; // output NRF_SPIM0->EVENTS_ENDTX = 0; //NRF_SPIM0->EVENTS_ENDRX = 0; // Disable all interrupts NRF_SPIM0->INTENCLR = 0xFFFFFFFFUL; // Enable selected interrupts NRF_SPIM0->INTENSET = 0x40; // END // Set interrupt priority and enable interrupt NVIC_SetPriority(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn, 6); NVIC_ClearPendingIRQ(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn); NVIC_EnableIRQ(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn); NRF_SPIM0->ENABLE = 7; // enable SPI // Transfer registers to set 3-wire SPI mode on target // - not required if slave only has or is already in 3-wire mode // Send 3-wire whoami command byte (1 byte only) // Connect output drive, connect 1-wire rx/tx output to MOSI NRF_SPIM0->PSEL.MISO = 0xFFFFFFFF; // MISOPIN; NRF_SPIM0->PSEL.MOSI = MOSIPIN; NRF_GPIO->PIN_CNF[MOSIPIN] = 1; // output NRF_SPIM0->TXD.PTR = (uint32_t)spi3wTXBuf; NRF_SPIM0->TXD.MAXCNT = 1; NRF_SPIM0->RXD.PTR = NULL; NRF_SPIM0->RXD.MAXCNT = 0; NRF_SPIM0->EVENTS_ENDTX = 0; NRF_GPIO->OUTCLR = 1 << CSPIN; // drive cs low to initiate spi comm NRF_SPIM0->TASKS_START = 1; while(!NRF_SPIM0->EVENTS_ENDTX); // last byte transmitted // Manual says disable SPI before changing pins, but actually doesn't matter NRF_SPIM0->ENABLE = 0; // disable SPI // Disconnect output drive, connect 1-wire rx/tx input to MISO NRF_SPIM0->PSEL.MOSI = 0xFFFFFFFFUL; // MOSIPIN; NRF_GPIO->PIN_CNF[MOSIPIN] = 0; // input pin, input buffer connected, no pull, S0S1, sense disabled NRF_SPIM0->PSEL.MISO = MOSIPIN; // MISOPIN; NRF_SPIM0->ENABLE = 7; // enable SPI spi3wRXBuf[0] = 99; spi3wRXBuf[1] = 98; NRF_SPIM0->TXD.PTR = NULL; NRF_SPIM0->TXD.MAXCNT = 0; NRF_SPIM0->RXD.PTR = (uint32_t)spi3wRXBuf; NRF_SPIM0->RXD.MAXCNT = 1; NRF_SPIM0->EVENTS_ENDRX = 0; NRF_SPIM0->TASKS_START = 1; while(!NRF_SPIM0->EVENTS_ENDRX); // last byte received NRF_SPIM0->TASKS_STOP = 1; while(!NRF_SPIM0->EVENTS_STOPPED); NRF_GPIO->OUTSET = 1 << CSPIN; while(1); }
Bunch of other links via this post: nrf52840-3-wire-spi-implementation
By SDK hopefully you mean nRF52 SDK, but in any case here's a guide using bare-metal programming which you can use to alter other examples. Tested with LIS2DH12 which starts as 4-wire SPI but can be set to 3-wire SPI. (This code assumes the SPI slave is always 3-wire so the 4-wire to 3-wire slave command is not shown). Sequence is send a 1-byte command, no rx, reverse the pin then send a dummy command and receive whatever number of rx bytes are required, in this example a single byte "I am .." response but can be longer
#define CSPIN 11 // spi chip select #define SCKPIN 12 // spi clock #define MOSIPIN 13 // spi mosi //#define MISOPIN 14 // spi miso - not used in 3-wire mode #define LIS2DH12_WHO_AM_I 0x0F // Read as 0x33 uint8_t spi3wTXBuf[] = {0x80|LIS2DH12_WHO_AM_I, 0xFF}; uint8_t spi3wRXBuf[sizeof(spi3wTXBuf)] = {0,0}; static const uint8_t m3wRxTxBufLength = sizeof(spi3wTXBuf); volatile uint32_t mSpiInterruptCounter = 0UL; void notSPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler(void) { if (NRF_SPIM0->EVENTS_END) NRF_SPIM0->EVENTS_END = 0; mSpiInterruptCounter++; } static void Test3WireSPI(void) { NRF_GPIO->PIN_CNF[CSPIN] = 0x301; // output, high drive high and low H0H1 NRF_GPIO->PIN_CNF[SCKPIN] = 0x301; // output, high drive high and low H0H1 NRF_GPIO->PIN_CNF[MOSIPIN] = 1; // output, standard drive S0S1 //NRF_GPIO->PIN_CNF[MISOPIN] = 0; // input pin, input buffer connected, no pull, S0S1, sense disabled NRF_GPIO->OUTSET = 1 << CSPIN; // deactivate by setting chip select high NRF_SPIM0->PSEL.SCK = SCKPIN; NRF_SPIM0->PSEL.MOSI = MOSIPIN; NRF_SPIM0->PSEL.MISO = 0xFFFFFFFFUL; // MISOPIN; NRF_SPIM0->CONFIG = 0; // CPOL 0 -- clock polarity active high, CPHA 1 -- sample on trailing clock edge, send Msb first NRF_SPIM0->FREQUENCY = 0x80000000UL; // 8 Mbps NRF_SPIM0->ORC =0; // Unused Tx bytes, set all low // Configure registers for 3-wire mode NRF_SPIM0->PSEL.MOSI = MOSIPIN; NRF_SPIM0->PSEL.MISO = 0xFFFFFFFFUL; // MISOPIN; NRF_GPIO->PIN_CNF[MOSIPIN] = 1; // output NRF_SPIM0->EVENTS_ENDTX = 0; //NRF_SPIM0->EVENTS_ENDRX = 0; // Disable all interrupts NRF_SPIM0->INTENCLR = 0xFFFFFFFFUL; // Enable selected interrupts NRF_SPIM0->INTENSET = 0x40; // END // Set interrupt priority and enable interrupt NVIC_SetPriority(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn, 6); NVIC_ClearPendingIRQ(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn); NVIC_EnableIRQ(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn); NRF_SPIM0->ENABLE = 7; // enable SPI // Transfer registers to set 3-wire SPI mode on target // - not required if slave only has or is already in 3-wire mode // Send 3-wire whoami command byte (1 byte only) // Connect output drive, connect 1-wire rx/tx output to MOSI NRF_SPIM0->PSEL.MISO = 0xFFFFFFFF; // MISOPIN; NRF_SPIM0->PSEL.MOSI = MOSIPIN; NRF_GPIO->PIN_CNF[MOSIPIN] = 1; // output NRF_SPIM0->TXD.PTR = (uint32_t)spi3wTXBuf; NRF_SPIM0->TXD.MAXCNT = 1; NRF_SPIM0->RXD.PTR = NULL; NRF_SPIM0->RXD.MAXCNT = 0; NRF_SPIM0->EVENTS_ENDTX = 0; NRF_GPIO->OUTCLR = 1 << CSPIN; // drive cs low to initiate spi comm NRF_SPIM0->TASKS_START = 1; while(!NRF_SPIM0->EVENTS_ENDTX); // last byte transmitted // Manual says disable SPI before changing pins, but actually doesn't matter NRF_SPIM0->ENABLE = 0; // disable SPI // Disconnect output drive, connect 1-wire rx/tx input to MISO NRF_SPIM0->PSEL.MOSI = 0xFFFFFFFFUL; // MOSIPIN; NRF_GPIO->PIN_CNF[MOSIPIN] = 0; // input pin, input buffer connected, no pull, S0S1, sense disabled NRF_SPIM0->PSEL.MISO = MOSIPIN; // MISOPIN; NRF_SPIM0->ENABLE = 7; // enable SPI spi3wRXBuf[0] = 99; spi3wRXBuf[1] = 98; NRF_SPIM0->TXD.PTR = NULL; NRF_SPIM0->TXD.MAXCNT = 0; NRF_SPIM0->RXD.PTR = (uint32_t)spi3wRXBuf; NRF_SPIM0->RXD.MAXCNT = 1; NRF_SPIM0->EVENTS_ENDRX = 0; NRF_SPIM0->TASKS_START = 1; while(!NRF_SPIM0->EVENTS_ENDRX); // last byte received NRF_SPIM0->TASKS_STOP = 1; while(!NRF_SPIM0->EVENTS_STOPPED); NRF_GPIO->OUTSET = 1 << CSPIN; while(1); }
Bunch of other links via this post: nrf52840-3-wire-spi-implementation