9 years, 9 months ago.

Problems with spi-communication

Hi,

I have a Raspberry Pi and mbed Nucleo ST32F411RE connected via SPI.

This is the python's programme on the Raspberry Pi:

try:
    import tkinter as tk
except:
    import Tkinter as tk
    
import spidev
    
spi = spidev.SpiDev()
spi.open (0, 0)
import time
# spi.max_speed_hz = 1000000
    

button_width = 40

def bit_8_to_16(value=[]):    
    return ( (value[0]<<8)+value[1] )
    
def bit_16_to_8(value=0):
    return_value = []
    return_value.append(value>>8)
    return_value.append(value&0x00FF)
    return return_value

def main():
    root = tk.Tk()
    
    def do_exit():
        print ("PROGRAMM BEENDET")
        root.quit()
    
    def do_adc_task_isrunning():
        print ("ADC TASK RUNNING")
        spi.writebytes([0x00, 0xA0])
                
    def do_adc_task_start():
        print ("ADC TASK START")
        spi.writebytes([0x00, 0xA1])
                
    def do_adc_task_stopp():
        print ("ADC TASK STOPP")
        spi.writebytes([0x00, 0xA2])
                
    def do_adc_task_setfrequency():
        print ("ADC TASK SETFREQUENCY")
        spi.writebytes([0x00, 0xA3])
        time.sleep(0.1)  
        spi.writebytes([0x00, 100])      
        
    def do_fifo_anzahl_elements():
        print ("FIFO ANZAHL ELEMENTS")
        spi.writebytes([0x00, 0xB0])
        
        
    def do_fifo_get_one_element():
        print ("FIFO GET ONE ELEMENT")
        spi.writebytes([0x00, 0xB1])
        print (spi.readbytes(2))
        
    def do_fifo_get_elements():
        print ("FIFO GET ELEMENTS")        
        spi.writebytes([0x00, 0xB2])    
    
    #ADC_TASK_ISRUNNING      = 0x00A0,
    #ADC_TASK_START          = 0x00A1,
    #ADC_TASK_STOPP          = 0x00A2,
    #ADC_TASK_SETFREQUENCY   = 0x00A3,
    
    #FIFO_ANZAHL_ELEMENTS    = 0x00B0,
    #FIFO_GET_ONE_ELEMENT    = 0x00B1,
    #FIFO_GET_ELEMENTS       = 0x00B2
    
    button_1 = tk.Button(text="ADC_TASK_START", width=button_width, command=do_adc_task_start )
    button_1.pack()
    button_2 = tk.Button(text="ADC_TASK_STOPP", width=button_width, command=do_adc_task_stopp )
    button_2.pack()
    button_3 = tk.Button(text="ADC_TASK_SETFREQUENCY", width=button_width, command=do_adc_task_setfrequency )
    button_3.pack()
    button_4 = tk.Button(text="ADC_TASK_ISRUNNING", width=button_width, command=do_adc_task_isrunning )
    button_4.pack()
    button_5 = tk.Button(text="FIFO_ANZAHL_ELEMENTS", width=button_width, command=do_fifo_anzahl_elements )
    button_5.pack()
    button_6 = tk.Button(text="FIFO_GET_ONE_ELEMENT", width=button_width, command=do_fifo_get_one_element )
    button_6.pack()
    button_7 = tk.Button(text="FIFO_GET_ELEMENTS", width=button_width, command=do_fifo_get_elements )
    button_7.pack()    
    
    exit_button = tk.Button (text="Exit", command=do_exit, width=button_width)
    exit_button.pack()    
    
    root.mainloop()

if __name__ == "__main__":
    main()
    spi.close()
    

This is c-code on mbed:

#include "mbed.h"
#include "read_adc.h"
#include "ringbuffer.h"
#include "spi_commands.h"

#ifdef TARGET_NUCLEO_F411RE
    SPISlave spidevice(PA_7, PA_6, PA_5, PA_15);            // mosi, miso, sclk, ssel 
#endif

#ifdef TARGET_LPC1768
    SPISlave spidevice(p11, p12, p13, p14);            // mosi, miso, sclk, ssel 
#endif

// Ringbuffer initialisieren:
    RingBuffer ADC_Fifo;
    RingBuffer Error_Fifo;
    
// ADC_Interrupt initialisieren
    ReadADCValues read_ADC_values;

Serial pc(USBTX, USBRX);

uint32_t help, get_element=0;


void spi_evaluation(uint16_t command) {
    bool abort = false;
    switch (command) {
        case ADC_TASK_ISRUNNING: 
            pc.printf ("\n\r ADC_TASK_ISRUNNING (%d)", read_ADC_values.is_active);
            break;

        case ADC_TASK_START:
            pc.printf ("\n\r ADC_TASK_START");
            read_ADC_values.start();
            break;

        case ADC_TASK_STOPP:
            pc.printf ("\n\r ADC_TASK_STOPP");
            read_ADC_values.stopp();
            break;

        case ADC_TASK_SETFREQUENCY:
            pc.printf ("\n\r ADC_TASK_FREQUENCY");
            abort=true;
            while (abort) {
                if (spidevice.receive()) {
                    abort = false;
                    help=spidevice.read();
//                    read_ADC_values.set_sampling_rate( spidevice.read() );                    
                }
            }  // Ende while
            
            pc.printf ("\n\r NEW_FREQUENCY (%d)", help);
            
            break;            

        case FIFO_ANZAHL_ELEMENTS:
            pc.printf ("\n\r FIFO ANZAHL ELEMENTS");
            break;            
        
        case FIFO_GET_ONE_ELEMENT:
            // pc.printf ("\n\r FIFO GET ONE ELEMENT");
            spidevice.reply(get_element);
            get_element++;
            break;            
        
        case FIFO_GET_ELEMENTS:
            pc.printf ("\n\r FIFO GET ELEMENTS");
            break; 
    } // Switch Ende           
}

int main () {
    // uart konfigurieren
    pc.baud (921600);
    pc.printf ("\n\r Programm wurde gestartet");
    
    // spi konfigurieren
    spidevice.format (16, 0);
    // spidevice.frequency(1000000);
    
    // ADC-Interrupt konfigurieren
    read_ADC_values.init();
 
    while (1) {
        if (spidevice.receive()) {
             spi_evaluation (spidevice.read());
        }  // Ende if

     } // Hauptschleife Programm
}

This is SPI_COMMANDS.h

/*
In dieser Datei werden die Hexwerte für die SPI-Befehle, die vom 
SPI-Master kommen, mit lesbaren Worten codiert. 
*/

#ifndef SPI_COMMANDS_H
#define SPI_COMMANDS_H

enum SPICommands {
    ADC_TASK_ISRUNNING      = 0x00A0,
    ADC_TASK_START          = 0x00A1,
    ADC_TASK_STOPP          = 0x00A2,
    ADC_TASK_SETFREQUENCY   = 0x00A3,
    
    FIFO_ANZAHL_ELEMENTS    = 0x00B0,
    FIFO_GET_ONE_ELEMENT    = 0x00B1,
    FIFO_GET_ELEMENTS       = 0x00B2
};
#endif

I´ve a big problem:

When pressing the "FIFO GET ONE ELEMENT"-Button on Raspberry Pi I don´t receive correct values sometimes. There´s a counter in c-code and whenever data should be sended, sometimes I receive the same value several times. I don´t know what doing wrong.

        case ADC_TASK_SETFREQUENCY:
            ...
            while (abort) {
                if (spidevice.receive()) {
             ...

    def do_adc_task_setfrequency():
        print ("ADC TASK SETFREQUENCY")
        spi.writebytes([0x00, 0xA3])
        time.sleep(0.1)  
        spi.writebytes([0x00, 100])

The communication between Raspberry Pi and Nucleo contains lots of errors. Can you tell me your experiences using spi-port for communication? What´s the cause of the defect?

1 Answer

9 years, 9 months ago.

Make sure you set the GPIO speed to the highest value for the SPI pins on the Nucleo. The SPI won't work properly at speeds higher than about 2mhz without doing so. This needs to be done either through the hal or directly to the register.

Depending on which SPI you are using the bit rate may be half of what you ask for on the Nucleo since MBED doesn't calculate the speed right if the peripheral is connected to the slower bus.

Sorry to be vague but you'll need to look up the specifics in the ST datasheet.

Good luck and I hope this helps.... Doug