-         
Ergebnis 1 bis 8 von 8

Thema: IMU über SPI steigt nach wenigen Sekunden aus

  1. #1
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    14.04.2005
    Ort
    Freiberg
    Alter
    37
    Beiträge
    306

    IMU über SPI steigt nach wenigen Sekunden aus

    Anzeige

    Hallo zusammen,

    ich habe ein Nucleo-64 Board (STM32F411). Ich möchte (irgendwann mal eine Reihe von) Sensoren über SPI ansprechen. Dazu habe ich mir eine Platine gebaut, die die drei SPI-Bahnen SCLK, MOSI und MISO vom STM32 aufteilt (jede hat noch 100 Ohm in Reihe), und über die ich jeweils mit einem Flachbandkabel jeden Sensor nach belieben dran stecken kann. Jeder Sensor hat natürlich seinen eigenen SS-Pin.

    Jetzt "scheitere" ich an: Sensor 1!

    Zur Info, was vorher geschah: ich habe mir ein selbst zusammengebauten Controller (nennen wir ihn auch mal "Sensor") als SPI-Slave konfiguriert und kann erfolgreich nach Belieben alle Daten hin und her schieben. Beliebig oft und lange.
    SPI funktioniert also erstmal über den STM32.

    Jetzt klemme ich den ersten echten Sensor an: einen LSM6DS3, Breakout-Board von Sparkfun (Link). Davon habe ich ca. 3 Stk hier funktionsfähig, und auch schon teilweise erfolgreich in einer anderen Konfiguration eingesetzt. Bei allen drei Sensoren ist das Problem das gleiche.

    Was jetzt passiert: ich frage das WHO_AM_I-Register ab, um zu überprüfen, ob er da ist.
    Jedes Mal, wenn ich den Sensor anstecke, wird das Register erfolgreich ausgelesen. Nach mal 1s, mal 20s verweigert der LSM allerdings die Antwort. Dann aber auch für immer. Erst wenn ich den Sensor abziehe und wieder auf mein Board stecke, wird er wieder aktiv - erneut für 1-20s. Danach steigt er wieder aus.

    Ich habe mir am Oszi alle Kanäle angeschaut: SS, SCLK und MOSI sind im erfolgreichen Betrieb identisch, wie in dem Fall, wenn der Sensor aussteigt - keine Qualitätseinbußen. Ich habe jetzt mal SCLK bei 500kHz und 1MHz getestet - das Verhalten ist bei beiden Taktraten identisch.
    Diese Register frage ich im Full Duplex-Mode ab:
    1) WHO_AM_I
    2) Gyro_x_low-Byte
    3) Gyro_x_high-Byte
    4) Gyro_y_low-Byte
    5) Gyro_y_high-Byte
    6) Gyro_z_low-Byte
    7) Gyro_z_high-Byte
    Acc_x_low-Byte
    9) Acc_x_high-Byte
    ...
    13) Acc_z_high-Byte
    14) 0x00 - dient nur zum Lesen des letzten Registers

    Wenn der Sensor aussteigt, passiert es lediglich eher zufällig (gefühlt einer von 5 Abfrage-Sätzen, dass der MISO vom Sensor während Befehl 1 (WHO_AM_I) auf komplett low bleibt, genau ab dem Beginn von Befehl 2 (also mit dem ersten clk auf SCLK) komplett auf high geht und dort bleibt, bis der SS wieder deaktiviert wird).

    Zugegeben, ich weiß nichtmal, was euch weiterhelfen könnte, um mir weiterzuhelfen.
    Hat jemand von euch schonmal so ein Problem gehabt? Oder wenn ihr sagt, in welche Richtung ich schauen sollte, dann gebt mal Bescheid - dann stelle ich dann noch ein paar mehr Infos zur Verfügung.

    Grüß, NRicola
    Gurken schmecken mir nicht, wenn sie Pelz haben!

  2. #2
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    14.04.2005
    Ort
    Freiberg
    Alter
    37
    Beiträge
    306
    Hallo zusammen,

    altes Thema, leider immernoch aktuell. Jetzt nur nochmal von einer anderen Seite angegangen.
    Ich habe jetzt mal ein neues Board gemacht, wo ich die SPI-Bahnen sauber verlegt habe. Im Gegensatz zu damals wird der Sensor nun über die gleiche Spannungsquelle versorgt, wie der STM32. Es sind noch immer die Sparkfun-Boards mit dem LSM6DS3, die ich in Betrieb nehme.

    Zu den Details bei SPI:
    SCLK, MISO und MOSI haben 100Ohm in Serie eingereiht.
    MISO hat noch einen Pull-Down mit 10kOhm, da ich festgestellt habe, dass der Sensor im Tri-state bleibt, wenn er nichts rausschreibt.
    SPI-Frequenz: 500kHz

    Ich habe auf dem Board mehrere Sensoranschlüsse platziert, die die gleichen SPI-Kanal-Signalleitungen nutzen. Daran habe ich nur einen IMU angeschlossen.
    Ich kann drei Sachen beobachten:
    - Der Sensor läuft so weitestgehend normal - zumindest erhalte ich korrekte Antworten beim Abfragen einiger Register.
    - Klemme ich mein Oszi (Impedanz 1 MOhm) an den SCLK reagiert der Sensor nicht mehr. Das ist auch der Fall, wenn ich nur den Plus-Pol des Oszi-Kanals dranklemme, dessen GND-Pin aber unangeschlossen lasse. Klemme ich nur den GND-Pin dran, dann stört es den Sensor nicht.
    - Der Sensor steigt auch dann aus, wenn ich (ohne Oszi) einen zweiten identischen Sensor an einen anderen SPI-Anschluss dranklemme.

    Ich habe jetzt schon versucht, zusätzlich die drei Pins MOSI, MISO und SCLK mit 4,7kOhm hoch auf 3,3V oder runter auf GND zu ziehen. Beides brachte nichts.

    Habt ihr irgendwelche Ideen dazu, was ich noch machen könnte?
    Leider - wie gesagt - kann ich nichtmal mit meinem Oszi das Problem analysieren, da ich nicht weiß, wie alle Signale aussehen, wenn der Sensor korrekt tut.

    Ich bin für jeden Tipp dankbar!

    Ich bin jetzt nicht sicher, ob ich mal die Pololu-Board mit den Spannungsreglern noch probieren sollte: https://www.pololu.com/product/2736. Ich vermute, dass ich da in das gleiche Problem reinlaufe.

    Habt ihr schon mal ein ähnliches Problem mit mehreren Sensoren über SPI gehabt?

    Grüß, NRicola
    Gurken schmecken mir nicht, wenn sie Pelz haben!

  3. #3
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    08.09.2007
    Ort
    Berlin
    Alter
    27
    Beiträge
    1.568
    Hi,

    zeig doch mal deinen Source-Code
    V.a. die Initialisierung der Pins wäre in dem Fall interessant, trotzdem bitte den gesamten Code posten.
    Ohne den ist es nur eine Raterei.
    Hast du die Taktrate deines uC überprüft?

    Gruß
    Chris

  4. #4
    Erfahrener Benutzer Robotik Einstein Avatar von Moppi
    Registriert seit
    18.03.2018
    Beiträge
    2.287
    Blog-Einträge
    21
    Hallo!

    Ich habe noch nichts mit mehreren SPI-Slaves gemacht.
    Allerdings: "die die drei SPI-Bahnen SCLK, MOSI und MISO vom STM32 aufteilt (jede hat noch 100 Ohm in Reihe)"
    und: "
    Ich habe jetzt schon versucht, zusätzlich die drei Pins MOSI, MISO und SCLK mit 4,7kOhm hoch auf 3,3V oder runter auf GND zu ziehen. Beides brachte nichts."

    Dann schaue ich hier:
    https://de.wikipedia.org/wiki/Datei:SPI_three_slaves.svg

    und hier:
    http://www.learningaboutelectronics....controller.php

    Sehe keine Widerstände...

    Leider hast Du keinen Schaltplan zur Verfügung gestellt. Vielleicht ist das mal eine gute Idee und Du bekommst eher Antworten, von Leuten, die schon oft was mit mehreren SPI-Slaves gemacht haben.


    MfG

  5. #5
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    14.04.2005
    Ort
    Freiberg
    Alter
    37
    Beiträge
    306
    Hallo Chris und Moppi,

    danke für euer Reindenken. Hier die benötigten Informationen:

    @Chris:
    Der STM32 läuft mit 16MHz. Das reicht erstmal aus, um auch bei einer SCLK-Rate von 1MHz noch den einen Sensor erfolgreich auszulesen - wenn nichts anderes angeschlossen ist. Wie gesagt: neuerdings auf 500kHz reduziert.
    Der Code ist unten. Ich habe ihn mal auf die SPI- und IMU-relevanten Sachen beschnitten. Dann müsst ihr nicht die ganzen 900 Zeilen Code durchschauen.
    Ich gestalte lediglich die SS-Initialisierung mit:
    SS auf high (Zeile 103)

    Die anderen Leitungen stimmen zumindest zwischen den einzelnen SPI-Übertragung in der Polarität.
    Wenn der Sensor positiv mit WHO_AM_I antwortet, aber noch nicht richtig konfiguriert ist, dann wird er erneut konfiguriert (Zeile 196). Dass das ab und zu passiert, sehe ich an einer LED, die in dann immer schalten lasse.

    @Moppi:
    Den Schaltplan habe ich angehangen. Auch reduziert auf's Wesentliche. Der Schaltplan vom IMU-Breakout-Board ist hier:https://cdn.sparkfun.com/datasheets/...eakout_v10.pdf
    Ohne 100Ohm in Serie hatte ich es am Anfang des Jahres probiert. Diese Wiederstände bügeln etwas die steigenden und fallenden Flanken. Gerade bei langen Leitungen bekommt man die übertragenen Bits wieder etwas den Rechteck-Verläufen angenähert. Ansonsten kommt es zu teils recht starken Über- und Unterschwingern auf den Zielspannungsniveaus. Dann muss man allerdings mit der SCLK-Frequenz aufpassen, dass die nicht zu hoch gewählt wird, da sonst die Spannungsniveaus nicht mehr erreicht werden. Bei 500kHz ist das Verhalten aber ohnehin vernachlässigbar. Aber durchaus gängige Praxis, siehe

    hier: https://www.first-sensor.com/cms/upl...CE_D_11156.pdf (S. 10)
    oder hier: https://www.edaboard.com/threads/spi-serial-resistor.345440/

    Wenn ihr noch etwas braucht, gebt Bescheid!
    Vielen Dank euch!

    Grüß, NRicola

    Code:
    /* Includes ------------------------------------------------------------------*/
    #include "main.h"
    
    /* Private includes ----------------------------------------------------------*/
    /* USER CODE BEGIN Includes */
    #include "stdbool.h"
    #include "math.h"
    #include "../Peripherals/LSM6DS3.h"        // Funktionen sind hier angehangen (siehe unten)
    #include "../Peripherals/OLED_128x32.h"
    /* USER CODE END Includes */
    
    /* Private typedef -----------------------------------------------------------*/
    /* USER CODE BEGIN PTD */
    
    /* USER CODE END PTD */
    
    /* Private define ------------------------------------------------------------*/
    /* USER CODE BEGIN PD */
        
    /* USER CODE END PD */
    
    /* Private macro -------------------------------------------------------------*/
    /* USER CODE BEGIN PM */
    
    /* USER CODE END PM */
    
    /* Private variables ---------------------------------------------------------*/
    I2C_HandleTypeDef hi2c3;
    
    SPI_HandleTypeDef hspi2;
    
    UART_HandleTypeDef huart2;
    DMA_HandleTypeDef hdma_usart2_rx;
    
    /* USER CODE BEGIN PV */
        const uint8_t IMU_datlength = 8;        // die letzten x Messwerte werden mitgespeichert
        struct IMU_Struct IMU1;                // besteht aus IMU1.status, sowie 6 Arrays [0:IMU_datlength-1] für acc und gyr in x,y,z
    /* USER CODE END PV */
    
    /* Private function prototypes -----------------------------------------------*/
    void SystemClock_Config(void);
    static void MX_GPIO_Init(void);
    static void MX_DMA_Init(void);
    static void MX_USART2_UART_Init(void);
    static void MX_SPI2_Init(void);
    static void MX_I2C3_Init(void);
    /* USER CODE BEGIN PFP */
            
    /* USER CODE END PFP */
    
    /* Private user code ---------------------------------------------------------*/
    /* USER CODE BEGIN 0 */
    
    /* USER CODE END 0 */
    
    /**
      * @brief  The application entry point.
      * @retval int
      */
    int main(void)
    {
      /* USER CODE BEGIN 1 */
    
      /* USER CODE END 1 */
    
      /* MCU Configuration--------------------------------------------------------*/
    
      /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
      HAL_Init();
    
      /* USER CODE BEGIN Init */
    
      /* USER CODE END Init */
    
      /* Configure the system clock */
      SystemClock_Config();
    
      /* USER CODE BEGIN SysInit */
    
      /* USER CODE END SysInit */
    
      /* Initialize all configured peripherals */
      MX_GPIO_Init();
      MX_DMA_Init();
      MX_USART2_UART_Init();
      MX_SPI2_Init();
      MX_I2C3_Init();
      /* USER CODE BEGIN 2 */
    
    
        IMU1.status=0;
        for(uint8_t i=0;i<IMU_datlength-1;i++){
                IMU1.acc_x[i] = 0;
                IMU1.acc_y[i] = 0;
                IMU1.acc_z[i] = 0;
                IMU1.gyr_x[i] = 0;
                IMU1.gyr_y[i] = 0;
                IMU1.gyr_z[i] = 0;
        }
    
        //--------------------------------
    
        IMU1_SS_Disable();    // SS auf high
        HAL_Delay(20);        // 20ms start-up time für IMUs
        
        //        OLED-Display
        uint16_t OLED_refresh_cntr=0;
        uint16_t OLED_refresh_max=5;
        OLED_Init();
        OLED_Clear_Screen();
        OLED_IMU1_vars();
        
        
      /* USER CODE END 2 */
    
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
      while (1)
      {
        /* USER CODE END WHILE */
    
        /* USER CODE BEGIN 3 */
    
            IMU1 = IMU1_Read_Values();
            if(OLED_refresh_cntr>=OLED_refresh_max){    OLED_refresh_cntr=0; OLED_IMU1_vars();    // Messwerte des IMU1 anzeigen
            }else{                        OLED_refresh_cntr++;
            }
            
      }
      /* USER CODE END 3 */
    }
    
    /**
      * @brief SPI2 Initialization Function
      * @param None
      * @retval None
      */
    static void MX_SPI2_Init(void)
    {
    
      /* USER CODE BEGIN SPI2_Init 0 */
    
      /* USER CODE END SPI2_Init 0 */
    
      /* USER CODE BEGIN SPI2_Init 1 */
    
      /* USER CODE END SPI2_Init 1 */
      /* SPI2 parameter configuration*/
      hspi2.Instance = SPI2;
      hspi2.Init.Mode = SPI_MODE_MASTER;
      hspi2.Init.Direction = SPI_DIRECTION_2LINES;
      hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
      hspi2.Init.CLKPolarity = SPI_POLARITY_HIGH;
      hspi2.Init.CLKPhase = SPI_PHASE_2EDGE;
      hspi2.Init.NSS = SPI_NSS_SOFT;
      hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
      hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
      hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
      hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
      hspi2.Init.CRCPolynomial = 10;
      if (HAL_SPI_Init(&hspi2) != HAL_OK)
      {
        Error_Handler();
      }
      /* USER CODE BEGIN SPI2_Init 2 */
    
      /* USER CODE END SPI2_Init 2 */
    
    }
    
    //-------------------------------------------------------------------------------
    //---------- Inhalt LSM6DS3.c ---------------------------------------------------
    //-------------------------------------------------------------------------------
    
    void IMU1_config(void){
        
        const uint8_t CTRL1_XL_addr    = 0x10;
        const uint8_t CTRL1_XL_write    = 0x3B;        // 0011_10_11
        const uint8_t CTRL2_G_addr    = 0x11;
        const uint8_t CTRL2_G_write      = 0x34;    // 0011_01_0_0
    
        Send_2Bytes_IMU1(CTRL1_XL_addr,CTRL1_XL_write);
        Send_2Bytes_IMU1(CTRL2_G_addr,CTRL2_G_write);
    }
    
    struct IMU_Struct IMU1_Read_Values(void){
        const uint8_t WHO_AM_I = 0x69;            // ist die korrekte Antwort, falls der Sensor da ist
        const uint8_t addr_WHO_AM_I_read = 0x8F;
        const uint8_t addr_CTRL1_XL_read = 0x90;
        const uint8_t addr_acc_x_l_read  = 0xA8;
        const uint8_t addr_acc_x_h_read  = 0xA9;
        //------------------------------        
        //--------------------------------------------------
        if (Read_1Byte_IMU1(addr_WHO_AM_I_read) == WHO_AM_I){    // Wenn IMU1 auf WHO_AM_I reagiert,
            IMU1.status=1;                    // 
            if (Read_1Byte_IMU1(addr_CTRL1_XL_read) == 0){        IMU1_config();        // Falls der Accelerometer im Sensor nicht korrekt konfiguriert ist, konfiguriere nochmal neu
                                        HAL_GPIO_TogglePin(LED_GN_GPIO_Port, LED_GN_Pin);
            }
        }else{
            IMU1.status=0;                    // Status: Sensor ist nicht angeschlossen
        }
        if(IMU1.status==1){                    // Wenn IMU1 erkannt, 
            IMU1_Status_SET();                // dann Status-LED anschalten
        }else{
            IMU1_Status_RESET();                // ansonsten Status-LED ausschalten
        }
        
        IMU1.acc_x[IMU_datlength-1]=Read_1Byte_IMU1(addr_acc_x_l_read);    // einen Messwert lesen
        return IMU1;
    }
    
    void Send_2Bytes_IMU1(uint8_t Byte1,uint8_t Byte2){
            const uint8_t timeout = 10;
            uint8_t TxBuffer[2];
                TxBuffer[0]=Byte1;
                TxBuffer[1]=Byte2;
            IMU1_SS_Enable();                // SS auf low
            HAL_SPI_Transmit(&hspi2, TxBuffer, 2, timeout); 
            IMU1_SS_Disable();                // SS auf high
    }
    
    uint8_t Read_1Byte_IMU1(uint8_t Byte){
            const uint8_t timeout = 10;
            uint8_t TxBuffer[2];
                TxBuffer[0]=Byte;            // Adresse des Read-Bytes
                TxBuffer[1]=0;
            uint8_t RxBuffer[2];
            IMU1_SS_Enable();                // SS auf low
            HAL_SPI_TransmitReceive(&hspi2, TxBuffer, RxBuffer, 2, timeout);
            IMU1_SS_Disable();                // SS auf high
            return RxBuffer[1];
    }
    Angehängte Dateien Angehängte Dateien
    Geändert von NRicola (29.10.2020 um 12:07 Uhr)
    Gurken schmecken mir nicht, wenn sie Pelz haben!

  6. #6
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    08.09.2007
    Ort
    Berlin
    Alter
    27
    Beiträge
    1.568
    Einen vollständigen Code hätte ich schon ganz gerne, sonst bin ich raus, ohne Grundlage kann man nur schwer etwas vermuten....
    Der ganze Code muss nicht sein, aber alle Routinen die du aufrufst (v.a. MX_GPIO_Init() und alle anderen Peripherie-Initialisierungen) sollten schon vorhanden sein.
    Auch wenn ich sehe, dass du das wohl mit Cube erstellst hast und somit SW-Fehler unwahrscheinlich sind, würde ein Blick darauf wohl dennoch nicht schaden.

    Beim Schaltplan ist es ähnlich, das ist kein Schaltplan, sondern lediglich ein kleiner Ausschnitt davon. Was soll man da erkennen?

  7. #7
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    14.04.2005
    Ort
    Freiberg
    Alter
    37
    Beiträge
    306
    Hallo Chris,

    dann also hier die fehlenden Funktionen im Code und der Schaltplan des Nucleo-Shields. Sollte dir noch etwas fehlen, gib Bescheid!

    Grüß, NRicola

    Code:
    /* Includes ------------------------------------------------------------------*/
    #include "main.h"
    
    /* Private includes ----------------------------------------------------------*/
    /* USER CODE BEGIN Includes */
    #include "stdbool.h"
    #include "math.h"
    #include "../Peripherals/LSM6DS3.h"        // Funktionen sind hier angehangen (siehe unten)
    #include "../Peripherals/OLED_128x32.h"
    /* USER CODE END Includes */
    
    /* Private typedef -----------------------------------------------------------*/
    /* USER CODE BEGIN PTD */
    
    /* USER CODE END PTD */
    
    /* Private define ------------------------------------------------------------*/
    /* USER CODE BEGIN PD */
        
    /* USER CODE END PD */
    
    /* Private macro -------------------------------------------------------------*/
    /* USER CODE BEGIN PM */
    
    /* USER CODE END PM */
    
    /* Private variables ---------------------------------------------------------*/
    I2C_HandleTypeDef hi2c3;
    
    SPI_HandleTypeDef hspi2;
    
    UART_HandleTypeDef huart2;
    DMA_HandleTypeDef hdma_usart2_rx;
    
    /* USER CODE BEGIN PV */
        const uint8_t IMU_datlength = 8;        // die letzten x Messwerte werden mitgespeichert
        struct IMU_Struct IMU1;                // besteht aus IMU1.status, sowie 6 Arrays [0:IMU_datlength-1] für acc und gyr in x,y,z
    /* USER CODE END PV */
    
    /* Private function prototypes -----------------------------------------------*/
    void SystemClock_Config(void);
    static void MX_GPIO_Init(void);
    static void MX_DMA_Init(void);
    static void MX_USART2_UART_Init(void);
    static void MX_SPI2_Init(void);
    static void MX_I2C3_Init(void);
    /* USER CODE BEGIN PFP */
            
    /* USER CODE END PFP */
    
    /* Private user code ---------------------------------------------------------*/
    /* USER CODE BEGIN 0 */
    
    /* USER CODE END 0 */
    
    /**
      * @brief  The application entry point.
      * @retval int
      */
    int main(void)
    {
      /* USER CODE BEGIN 1 */
    
      /* USER CODE END 1 */
    
      /* MCU Configuration--------------------------------------------------------*/
    
      /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
      HAL_Init();
    
      /* USER CODE BEGIN Init */
    
      /* USER CODE END Init */
    
      /* Configure the system clock */
      SystemClock_Config();
    
      /* USER CODE BEGIN SysInit */
    
      /* USER CODE END SysInit */
    
      /* Initialize all configured peripherals */
      MX_GPIO_Init();
      MX_DMA_Init();
      MX_USART2_UART_Init();
      MX_SPI2_Init();
      MX_I2C3_Init();
      /* USER CODE BEGIN 2 */
    
    
        IMU1.status=0;
        for(uint8_t i=0;i<IMU_datlength-1;i++){
                IMU1.acc_x[i] = 0;
                IMU1.acc_y[i] = 0;
                IMU1.acc_z[i] = 0;
                IMU1.gyr_x[i] = 0;
                IMU1.gyr_y[i] = 0;
                IMU1.gyr_z[i] = 0;
        }
    
        //--------------------------------
    
        Mot001_SS_Disable();    // SS auf high
        IMU1_SS_Disable();    // SS auf high
        HAL_Delay(20);        // 20ms start-up time für IMUs
        
        //        OLED-Display
        uint16_t OLED_refresh_cntr=0;
        uint16_t OLED_refresh_max=5;
        OLED_Init();
        OLED_Clear_Screen();
        OLED_IMU1_vars();
        
        
      /* USER CODE END 2 */
    
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
      while (1)
      {
        /* USER CODE END WHILE */
    
        /* USER CODE BEGIN 3 */
    
            IMU1 = IMU1_Read_Values();
            if(OLED_refresh_cntr>=OLED_refresh_max){    OLED_refresh_cntr=0; OLED_IMU1_vars();    // Messwerte des IMU1 anzeigen
            }else{                        OLED_refresh_cntr++;
            }
            
      }
      /* USER CODE END 3 */
    }
    
    void SystemClock_Config(void)
    {
      RCC_OscInitTypeDef RCC_OscInitStruct = {0};
      RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    
      /** Configure the main internal regulator output voltage
      */
      __HAL_RCC_PWR_CLK_ENABLE();
      __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
      /** Initializes the RCC Oscillators according to the specified parameters
      * in the RCC_OscInitTypeDef structure.
      */
      RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
      RCC_OscInitStruct.HSIState = RCC_HSI_ON;
      RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
      RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
      if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
      {
        Error_Handler();
      }
      /** Initializes the CPU, AHB and APB buses clocks
      */
      RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                                  |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
      RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
      RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
      RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
      RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    
      if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
      {
        Error_Handler();
      }
    }
    
    /**
      * @brief I2C3 Initialization Function
      * @param None
      * @retval None
      */
    static void MX_I2C3_Init(void)
    {
    
      /* USER CODE BEGIN I2C3_Init 0 */
    
      /* USER CODE END I2C3_Init 0 */
    
      /* USER CODE BEGIN I2C3_Init 1 */
    
      /* USER CODE END I2C3_Init 1 */
      hi2c3.Instance = I2C3;
      hi2c3.Init.ClockSpeed = 400000;
      hi2c3.Init.DutyCycle = I2C_DUTYCYCLE_2;
      hi2c3.Init.OwnAddress1 = 0;
      hi2c3.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
      hi2c3.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
      hi2c3.Init.OwnAddress2 = 0;
      hi2c3.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
      hi2c3.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
      if (HAL_I2C_Init(&hi2c3) != HAL_OK)
      {
        Error_Handler();
      }
      /* USER CODE BEGIN I2C3_Init 2 */
    
      /* USER CODE END I2C3_Init 2 */
    
    }
    
    /**
      * @brief SPI2 Initialization Function
      * @param None
      * @retval None
      */
    static void MX_SPI2_Init(void)
    {
    
      /* USER CODE BEGIN SPI2_Init 0 */
    
      /* USER CODE END SPI2_Init 0 */
    
      /* USER CODE BEGIN SPI2_Init 1 */
    
      /* USER CODE END SPI2_Init 1 */
      /* SPI2 parameter configuration*/
      hspi2.Instance = SPI2;
      hspi2.Init.Mode = SPI_MODE_MASTER;
      hspi2.Init.Direction = SPI_DIRECTION_2LINES;
      hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
      hspi2.Init.CLKPolarity = SPI_POLARITY_HIGH;
      hspi2.Init.CLKPhase = SPI_PHASE_2EDGE;
      hspi2.Init.NSS = SPI_NSS_SOFT;
      hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
      hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
      hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
      hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
      hspi2.Init.CRCPolynomial = 10;
      if (HAL_SPI_Init(&hspi2) != HAL_OK)
      {
        Error_Handler();
      }
      /* USER CODE BEGIN SPI2_Init 2 */
    
      /* USER CODE END SPI2_Init 2 */
    
    }
    
    /**
      * @brief USART2 Initialization Function
      * @param None
      * @retval None
      */
    static void MX_USART2_UART_Init(void)
    {
    
      /* USER CODE BEGIN USART2_Init 0 */
    
      /* USER CODE END USART2_Init 0 */
    
      /* USER CODE BEGIN USART2_Init 1 */
    
      /* USER CODE END USART2_Init 1 */
      huart2.Instance = USART2;
      huart2.Init.BaudRate = 115200;
      huart2.Init.WordLength = UART_WORDLENGTH_8B;
      huart2.Init.StopBits = UART_STOPBITS_1;
      huart2.Init.Parity = UART_PARITY_NONE;
      huart2.Init.Mode = UART_MODE_TX_RX;
      huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
      huart2.Init.OverSampling = UART_OVERSAMPLING_16;
      if (HAL_UART_Init(&huart2) != HAL_OK)
      {
        Error_Handler();
      }
      /* USER CODE BEGIN USART2_Init 2 */
    
      /* USER CODE END USART2_Init 2 */
    
    }
    
    /**
      * Enable DMA controller clock
      */
    static void MX_DMA_Init(void)
    {
    
      /* DMA controller clock enable */
      __HAL_RCC_DMA1_CLK_ENABLE();
    
      /* DMA interrupt init */
      /* DMA1_Stream5_IRQn interrupt configuration */
      HAL_NVIC_SetPriority(DMA1_Stream5_IRQn, 0, 0);
      HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn);
    
    }
    
    /**
      * @brief GPIO Initialization Function
      * @param None
      * @retval None
      */
    static void MX_GPIO_Init(void)
    {
      GPIO_InitTypeDef GPIO_InitStruct = {0};
    
      /* GPIO Ports Clock Enable */
      __HAL_RCC_GPIOC_CLK_ENABLE();
      __HAL_RCC_GPIOA_CLK_ENABLE();
      __HAL_RCC_GPIOB_CLK_ENABLE();
    
      /*Configure GPIO pin Output Level */
      HAL_GPIO_WritePin(GPIOA, LED_GN_Pin|LED_RD_Pin|Mot003_Status_Pin|Mot002_Status_Pin
                              |IMU2_SS_Pin|IMU3_SS_Pin, GPIO_PIN_RESET);
    
      /*Configure GPIO pin Output Level */
      HAL_GPIO_WritePin(GPIOC, IMU1_Status_Pin|IMU2_Status_Pin|Mot001_Status_Pin|Mot003_SS_Pin
                              |IMU3_Status_Pin, GPIO_PIN_RESET);
    
      /*Configure GPIO pin Output Level */
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0|IMU1_SS_Pin|Mot001_SS_Pin|HDMode_LED_Pin
                              |Mot002_SS_Pin, GPIO_PIN_RESET);
    
      /*Configure GPIO pins : Reset_SW_Pin Hall_Detection_Button_PC14_Pin */
      GPIO_InitStruct.Pin = Reset_SW_Pin|Hall_Detection_Button_PC14_Pin;
      GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    
      /*Configure GPIO pins : LED_GN_Pin LED_RD_Pin Mot003_Status_Pin Mot002_Status_Pin
                               IMU2_SS_Pin IMU3_SS_Pin */
      GPIO_InitStruct.Pin = LED_GN_Pin|LED_RD_Pin|Mot003_Status_Pin|Mot002_Status_Pin
                              |IMU2_SS_Pin|IMU3_SS_Pin;
      GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
      HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
      /*Configure GPIO pins : IMU1_Status_Pin IMU2_Status_Pin Mot001_Status_Pin Mot003_SS_Pin
                               IMU3_Status_Pin */
      GPIO_InitStruct.Pin = IMU1_Status_Pin|IMU2_Status_Pin|Mot001_Status_Pin|Mot003_SS_Pin
                              |IMU3_Status_Pin;
      GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
      HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    
      /*Configure GPIO pins : PB0 IMU1_SS_Pin Mot001_SS_Pin HDMode_LED_Pin
                               Mot002_SS_Pin */
      GPIO_InitStruct.Pin = GPIO_PIN_0|IMU1_SS_Pin|Mot001_SS_Pin|HDMode_LED_Pin
                              |Mot002_SS_Pin;
      GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
      HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    
      /*Configure GPIO pins : Mot002_Error_Pin_Pin Mot003_Error_Pin_Pin Mot001_Error_Pin_Pin HDMode_SW_Pin */
      GPIO_InitStruct.Pin = Mot002_Error_Pin_Pin|Mot003_Error_Pin_Pin|Mot001_Error_Pin_Pin|HDMode_SW_Pin;
      GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    
    }
    
    /* USER CODE BEGIN 4 */
    
    /* USER CODE END 4 */
    
    /**
      * @brief  This function is executed in case of error occurrence.
      * @retval None
      */
    void Error_Handler(void)
    {
      /* USER CODE BEGIN Error_Handler_Debug */
      /* User can add his own implementation to report the HAL error return state */
    
      /* USER CODE END Error_Handler_Debug */
    }
    
    #ifdef  USE_FULL_ASSERT
    /**
      * @brief  Reports the name of the source file and the source line number
      *         where the assert_param error has occurred.
      * @param  file: pointer to the source file name
      * @param  line: assert_param error line source number
      * @retval None
      */
    void assert_failed(uint8_t *file, uint32_t line)
    {
      /* USER CODE BEGIN 6 */
      /* User can add his own implementation to report the file name and line number,
         tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
      /* USER CODE END 6 */
    }
    #endif /* USE_FULL_ASSERT */
    
    /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
    
    
    
    //-------------------------------------------------------------------------------
    //---------- Inhalt LSM6DS3.c ---------------------------------------------------
    //-------------------------------------------------------------------------------
    
    void IMU1_config(void){
        
        const uint8_t CTRL1_XL_addr    = 0x10;
        const uint8_t CTRL1_XL_write    = 0x3B;        // 0011_10_11
        const uint8_t CTRL2_G_addr    = 0x11;
        const uint8_t CTRL2_G_write      = 0x34;    // 0011_01_0_0
    
        Send_2Bytes_IMU1(CTRL1_XL_addr,CTRL1_XL_write);
        Send_2Bytes_IMU1(CTRL2_G_addr,CTRL2_G_write);
    }
    
    struct IMU_Struct IMU1_Read_Values(void){
        const uint8_t WHO_AM_I = 0x69;            // ist die korrekte Antwort, falls der Sensor da ist
        const uint8_t addr_WHO_AM_I_read = 0x8F;
        const uint8_t addr_CTRL1_XL_read = 0x90;
        const uint8_t addr_acc_x_l_read  = 0xA8;
        const uint8_t addr_acc_x_h_read  = 0xA9;
        //------------------------------        
        //--------------------------------------------------
        if (Read_1Byte_IMU1(addr_WHO_AM_I_read) == WHO_AM_I){    // Wenn IMU1 auf WHO_AM_I reagiert,
            IMU1.status=1;                    // 
            if (Read_1Byte_IMU1(addr_CTRL1_XL_read) == 0){        IMU1_config();        // Falls der Accelerometer im Sensor nicht korrekt konfiguriert ist, konfiguriere nochmal neu
                                        HAL_GPIO_TogglePin(LED_GN_GPIO_Port, LED_GN_Pin);
            }
        }else{
            IMU1.status=0;                    // Status: Sensor ist nicht angeschlossen
        }
        if(IMU1.status==1){                    // Wenn IMU1 erkannt, 
            IMU1_Status_SET();                // dann Status-LED anschalten
        }else{
            IMU1_Status_RESET();                // ansonsten Status-LED ausschalten
        }
        
        IMU1.acc_x[IMU_datlength-1]=Read_1Byte_IMU1(addr_acc_x_l_read);    // einen Messwert lesen
        return IMU1;
    }
    
    void Send_2Bytes_IMU1(uint8_t Byte1,uint8_t Byte2){
            const uint8_t timeout = 10;
            uint8_t TxBuffer[2];
                TxBuffer[0]=Byte1;
                TxBuffer[1]=Byte2;
            IMU1_SS_Enable();                // SS auf low
            HAL_SPI_Transmit(&hspi2, TxBuffer, 2, timeout); 
            IMU1_SS_Disable();                // SS auf high
    }
    
    uint8_t Read_1Byte_IMU1(uint8_t Byte){
            const uint8_t timeout = 10;
            uint8_t TxBuffer[2];
                TxBuffer[0]=Byte;            // Adresse des Read-Bytes
                TxBuffer[1]=0;
            uint8_t RxBuffer[2];
            IMU1_SS_Enable();                // SS auf low
            HAL_SPI_TransmitReceive(&hspi2, TxBuffer, RxBuffer, 2, timeout);
            IMU1_SS_Disable();                // SS auf high
            return RxBuffer[1];
    }
    Angehängte Dateien Angehängte Dateien
    Gurken schmecken mir nicht, wenn sie Pelz haben!

  8. #8
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    08.09.2007
    Ort
    Berlin
    Alter
    27
    Beiträge
    1.568
    So ist das schon viel besser
    Also ich kann in deinem Code keine Pin-Definitionen für die SPI-Pins, und auch für die anderen Peripherie-Pins erkennen (bis auf SS und deine Status-Pins).
    Leider fehlen aber wieder ein paar Infos, die Defines, die du verwendest, kennen wir alle nicht...
    Auch finde ich den Code im allgemeinen sehr "unschön", hab mich nie mit Cube anfreunden können.
    Ich programmiere die STM32 nach wie vor mit der SPL, auch wenns veraltet ist, damit bin ich "groß" geworden.
    Auf die schnelle hab ich dir mal was zusammengebastelt, kanns leider nicht testen, sollte aber tun:
    Code:
    #include "stm32f4xx_conf.h"
    #include "arm_math.h"
    
    
    
    #define IMU1_SS_LOW         GPIOB->ODR &= ~GPIO_Pin_12
    #define IMU1_SS_HIGH        GPIOB->ODR |= GPIO_Pin_12
    
    #define LSM6DS3WRITEREG     0x00
    #define LSM6DS3READREG      0x80
    
    #define WHOAMIREG           0x0F
    #define WHOAMIVALUE         0x69
    
    
    
    int main(void);
    void InitSpi2(uint16_t Prescaler);
    uint8_t Spi2Transfer(uint8_t Data);
    void Delay(uint32_t t);
    
    
    
    volatile uint8_t WhoAmI;
    
    
    int main(void){
    
        SystemInit();
        
        InitSpi2(2);
        
        while(1)
        {
            Delay(1000); //! just a 'random' Delay
            IMU1_SS_LOW;
            WhoAmI = Spi2Transfer(WHOAMIREG | LSM6DS3READREG); //! read out
            IMU1_SS_HIGH;
            if(WhoAmI==WHOAMIVALUE)
            {
                //! Correct answer
            }else
            {
                //! False or no answer
            }
        }
    }
    
    
    
    void Delay(uint32_t t){
        for(uint32_t i=0;i<t;i+=1) ;
    }
    
    
    
    
    void InitSpi2(uint16_t Prescaler){
        GPIO_InitTypeDef GPIO_InitTypeDefStruct;
        SPI_InitTypeDef SPI_InitTypeDefStruct;
    
    
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
        
    
        SPI_Cmd(SPI2, DISABLE);
        if(Prescaler==2)
        {
            SPI_InitTypeDefStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
        }else if(Prescaler==4)
        {
            SPI_InitTypeDefStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
        }
        else if(Prescaler==128)
        {
            SPI_InitTypeDefStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;
        }else
        {
            SPI_InitTypeDefStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;
        }
        SPI_InitTypeDefStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
        SPI_InitTypeDefStruct.SPI_Mode = SPI_Mode_Master;
        SPI_InitTypeDefStruct.SPI_DataSize = SPI_DataSize_8b;
        SPI_InitTypeDefStruct.SPI_NSS = SPI_NSS_Soft;
        SPI_InitTypeDefStruct.SPI_FirstBit = SPI_FirstBit_MSB;
        SPI_InitTypeDefStruct.SPI_CPOL = SPI_CPOL_Low;
        SPI_InitTypeDefStruct.SPI_CPHA = SPI_CPHA_1Edge;
        SPI_Init(SPI2, &SPI_InitTypeDefStruct);
    
    
        
        //! SCK, MISO, MOSI
        GPIO_InitTypeDefStruct.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_14 | GPIO_Pin_15;
        GPIO_InitTypeDefStruct.GPIO_Mode = GPIO_Mode_AF;
        GPIO_InitTypeDefStruct.GPIO_Speed = GPIO_Speed_100MHz;
        GPIO_InitTypeDefStruct.GPIO_OType = GPIO_OType_PP;
        GPIO_InitTypeDefStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
        GPIO_Init(GPIOB, &GPIO_InitTypeDefStruct);
    
    
        //! SS
        GPIO_InitTypeDefStruct.GPIO_Pin = GPIO_Pin_12;
        GPIO_InitTypeDefStruct.GPIO_Mode = GPIO_Mode_OUT;
        GPIO_InitTypeDefStruct.GPIO_Speed = GPIO_Speed_100MHz;
        GPIO_InitTypeDefStruct.GPIO_PuPd = GPIO_PuPd_UP;
        GPIO_InitTypeDefStruct.GPIO_OType = GPIO_OType_PP;
        GPIO_Init(GPIOB, &GPIO_InitTypeDefStruct);
    
        //! Connect Pins to Peripheral
        GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_SPI2);
        GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_SPI2);
        GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_SPI2);
    
        //! ENABLE SPI2
        SPI_Cmd(SPI2, ENABLE);
    
        //! PULL SS HIGH
        IMU1_SS_HIGH;
    }
    
    uint8_t Spi2Transfer(uint8_t Data){
        uint8_t dump = 0;
    
        while(!(SPI2->SR&SPI_SR_TXE));
        SPI2->DR = Data;
        while(!(SPI2->SR&SPI_SR_RXNE));
        dump = SPI2->DR;
        return (dump);
    }
    Wenn du ein Nucleo-Board nutzt, kannst du wahrscheinlich über SWD debuggen? Das ist schonmal eine sehr große Hilfe.
    Für den Anfang würde ich alles unnütze (LED, LCD, etc...) weglassen und nurmal die Kommunikation zum laufen bringen.
    Welche IDE benutzt du?

    Gruß
    Chris

Ähnliche Themen

  1. nodeMCU zu nodeMCU: keine Kommunikations-Verbindung mehr nach wenigen Minuten
    Von HaWe im Forum NodeMCU-Board und ESP8266, ESP32-Serie
    Antworten: 0
    Letzter Beitrag: 02.10.2017, 15:01
  2. Elektromobilität: Die Nachfrage nach Elektroautos steigt - aber bei uns nicht
    Von Roboternetz-News im Forum Neuigkeiten / Technik-News / Nachrichten / Aktuelles
    Antworten: 1
    Letzter Beitrag: 13.06.2017, 13:57
  3. Weltrekord: Kleiner Quadrocopter steigt in knapp 4 Sekunden um 100 Meter
    Von Roboternetz-News im Forum Neuigkeiten / Technik-News / Nachrichten / Aktuelles
    Antworten: 0
    Letzter Beitrag: 25.02.2016, 08:10
  4. Verstärker geht nach wenigen Sekunden aus
    Von Cysign im Forum Elektronik
    Antworten: 3
    Letzter Beitrag: 27.12.2014, 05:24
  5. LCD Display steigt nach einiger Zeit aus
    Von surfer007 im Forum AVR Hardwarethemen
    Antworten: 10
    Letzter Beitrag: 04.12.2007, 15:07

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •