Use this forum to chat about hardware specific topics for the ESP8266 (peripherals, memory, clocks, JTAG, programming)

User avatar
By metalphreak
#14168 https://github.com/MetalPhreak/ESP8266_SPI_Driver

Currently supports sending data packets up to 32bits in length.

There's a few setup functions but if you just want to get cracking try the following code:

Code: Select allspi_init(HSPI);

spi_tx8(HSPI, 0x7A); //send 8 bits of data

spi_tx16(HSPI, 0x7A43); //send 16 bits of data

spi_tx32(HSPI, 0xCAFEFEED); //send 32 bits of data

spi_txd(HSPI, 9, 0b101101110); //send 9 bits of data (useful for driving LCDs with 9bit commands).

spi_txd(HSPI, 28, 0x1337CAD);


spi_init function sets it up for 4MHz clock and swaps the write byte order. What you put in is exactly what gets clocked out, regardless of the number of bits.

You can change the clock frequency by modifying the defines at the top of spi.c
SPI_CLK_CNTDIV must always be 2 or higher.

Reading in data is very similar, but I have yet to write and test the functions for it. Hopefully will be coming soon but I'm travelling interstate for a bit.


Each of the above tx commands actual output:

Image
Image
Image
Image
Image
User avatar
By metalphreak
#14906 Major update to the code.

Implemented one single "SPI Transaction" function to handle all combinations of CMD/ADDR/MISO/MOSI/DUMMY.

Now has the ability to both Read and Write up to 32bits of data (plus 16bits of Command data + 32bits of address data!)

Dummy bits don't seem too useful. Some more info here: http://d.av.id.au/blog/esp8266-spi-dummy-bits/


Now, you aren't going to want to write out the massive spi_transaction command and it's variables every time. I have provided a number of macro functions for simple read/write operations of 8/16/32 bits or an arbitrary number of bits up to 32. These are in spi.h and are fairly self explanatory.

Writing Data:
Code: Select alluint8 byte = 0xEF;
uint16 word = 0xBEEF;
uint32 dword = 0xDEADBEEF;
uint16 9bit = 0b101010101;

spi_tx8(HSPI, byte);
spi_tx16(HSPI, word);
spi_tx32(HSPI, dword);
spi_txd(HSPI, 9, 9bit);


Reading Data:
Code: Select alluint8 byte;
uint16 word;
uint32 dword;
uint16 9bit;

byte = (uint8) spi_rx8(HSPI); //returned value is uint32. Cast to uint8
word = (uint16) spi_rx16(HSPI); //returned value is uint32. Cast to uint16
dword = spi_rx32(HSPI); //No type casting needed
9bit = (uint16) spi_rxd(HSPI, 9); //returned value is uint32. Cast to uint16


The function always returns a 32bit unsigned integer. You should probably cast this when assigning to your own variable when it's returned.

You can define your own custom macros. I have the following two for reading/writing data to an SPI EEPROM:
Code: Select all#define eeprom_write(addr, data) spi_transaction(HSPI, 3, 0b101, 9, addr, 8, data, 0, 0)
#define eeprom_read(addr) spi_transaction(HSPI, 3, 0b110, 9, addr, 0, 0, 8, 0)



Enjoy. Let me know if there's any bugs. I haven't tested every single combinations of bit lengths etc.

Best to make sure SPI_WR_BYTE_ORDER and SPI_RD_BYTE_ORDER are set in the SPI_USER register. This is already done for you in the default spi_init() function.