vsergeev / python-periphery

A pure Python 2/3 library for peripheral I/O (GPIO, LED, PWM, SPI, I2C, MMIO, Serial) in Linux.
MIT License
529 stars 139 forks source link

Spi - Chip select deactivates #8

Closed killian441 closed 7 years ago

killian441 commented 7 years ago

Hi, I'm trying to use your code to talk across the spidev bus through python on an Arm7 processor. Using your code the spi bus deactivates the chip select after each write but the device I'm writing to needs the chip select to be active through the response. Is this an issue you have run into or have any suggestions on how to implement?

vsergeev commented 7 years ago

SPI is always shifting to and from the slave on every clock -- there is no separate write or read operation -- so you'll typically batch your write and read bytes into one contiguous transaction, using dummy bytes for the read phase. For example:

data_out = [0x01, 0x15, 0x00, 0x00]
data_in = spi.transfer(data_out)

where 0x01 and 0x15 represent a fictional command, and the following two 0x00 bytes are dummy read bytes. data_in might look like [0x00, 0x00, 0x12, 0x34], where the slave responded with 0x12 and 0x34 in the read phase.

meikuam commented 2 years ago

Had a struggle with this.

I connected arduino mega 2560 to orangepi PC2 (armbian) via spi and use arduino as slave (handling with ISR function).

For example I have command 0x11, which should responce with 0xCC, 0x05.

If we set max_speed too much, arduino will not have time to set data to SPDR.

For this example code for orangepi:

import periphery

spi = periphery.SPI(devpath="/dev/spidev1.0", mode=0, max_speed=1000000, bit_order="msb", bits_per_word=8)

data_out = [0x11, 0x00, 0x00, 0x00]
data_in = spi.transfer(data_out)
print(["0x{:02x}".format(d) for d in data_in])

We would get something like this:

['0x00', '0x11', '0x00']

Sometimes I've got smth like:

['0x05', '0x11', '0x00']

At first I thought that sequense is inversed, but actually when master transmit first byte, slave shifts data from previous value of SPDR, from previous attempts. Set max_speed=100000 soloved problem, and we get this:

['0x00', '0xcc', '0x05']

For arduino I used this settings:

#define SCK_PIN   52 
#define MISO_PIN  50 
#define MOSI_PIN  51
#define SS_PIN    53 
void setup()
{
    pinMode(SCK_PIN, INPUT);
    pinMode(MOSI_PIN, INPUT);
    pinMode(MISO_PIN, OUTPUT);
    pinMode(SS_PIN, INPUT);

    bitSet(SPCR, SPIE);
    bitSet(SPCR, SPE);
    bitClear(SPCR, DORD);
    bitClear(SPCR, MSTR);

    // use SPI_MODE0
    bitClear(SPCR, CPOL);
    bitClear(SPCR, CPHA);
}
volatile uint8_t spdr_buffer;
volatile int i = 0;
ISR (SPI_STC_vect) 
{
  spdr_buffer = SPDR;
  // some shitty code to set output data here.. f.e.:
   SPDR = i++;
}

void loop() {
}