- MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad         
Ergebnis 1 bis 10 von 21

Thema: EA DOMG-163 an SPI - Ich krieg die Krise

Baum-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #8
    Erfahrener Benutzer Roboter Genie Avatar von White_Fox
    Registriert seit
    04.10.2011
    Beiträge
    1.473
    Also...ich hab in der letzten Woche das Ganze mal ohne den HAL-Kram nochmal gemacht. Um keine Verwirrung aufkommen zu lassen, der Code enthält neben der SPI-LCD-Sache noch Inits für ein paar LEDs und Taster und zukünftige Sachen...die sind aber nicht weiter wichtig bzw. funktionieren.

    Das LCD sagt wieder nichts...ich hab aber gestern mal wieder (zufällig) ein paar wirre Zeichen auf dem LCD gehabt. War nicht reproduzierbar. Langsam glaube ich aber eine Gemeinsamkeit zwischen diesem "zufälligen" Funktionieren zu erkennen. Ich hatte wohl immer ein Oszilloskop an MOSI, oder an Clk oder an beiden Pins. Ich kann allerdings nicht vorstellen, daß das Oszi vllt einen dringend notwendigen Pulldown-Widerstand geliefert hat. Immerhin hab ich die Pins des STM32 als Push-Pull-Stufen konfiguriert.

    Drei Fragen:
    1.: Kann irgendjemand aus dem Code herauslesen, ob ich etwas falsch gemacht habe?
    Datenblatt LCD: http://www.reichelt.de/index.html?AC...252Fdog-me.pdf
    Datenblatt LCD-Controller: http://www.lcd-module.de/eng/pdf/zubehoer/st7036.pd
    Die SPI-Konfiguration ist auf Seite 47 dargestellt.

    Die Registerbeschreibung für den STM32 sind hier:
    http://www.st.com/content/ccc/resour...DM00135183.pdf
    Die Beschreibung der SPI-Schnittstelle fängt ab S. 848 an, die Controllregister werden auf S. 888 beschrieben.

    Ich habe, um die Timings zu verlängern, mal vor jeder Datenübertragung (SndBfhlLCD() und SndDtnLCD()) einen Haltepunkt gesetzt und das Programm im Debug-Modus laufen lassen. >Kein Erfolg.

    2.: Sieht die Taktkonfiguration OK aus? Ich benutze keinen Quarz, mit wieviel die CPU befeuert wird ist erstmal nicht so wichtig. Daher hab ich die PLL in Ruhe gelassen. Den Bus, an dem die SPI2 hängt, will ich niedriger takten damit ich sicherheitshalber eine niedrige SPI-Frequenz generieren kann. Bei meiner aktuellen Einstellung sollte der SPI-Clock bei <10kHz liegen. Ich kann mir schwer vorstellen daß das für das LCD zu rasch ist.

    3.: Irgendwas mache ich bei der Interupt-Konfiguration noch falsch. Gibt es irgendwo sowas wie "Interrupts global aktivieren" (sei-Befehl bei den AVRs), den ich übersehen habe? Der SPI-Interrupt wird nie angesprungen.


    Ich hoffe, irgendwer hat da eine Lösung für...
    Ach ja, anbei noch der Code:
    Code:
    /*********************************************************************
    *               SEGGER MICROCONTROLLER GmbH & Co. KG                 *
    *       Solutions for real time microcontroller applications         *
    **********************************************************************
    *                                                                    *
    *       (c) 2014 - 2016  SEGGER Microcontroller GmbH & Co. KG        *
    *                                                                    *
    *       www.segger.com     Support: support@segger.com               *
    *                                                                    *
    **********************************************************************
    
    -------------------------- END-OF-HEADER -----------------------------
    
    File    : main.c
    Purpose : Generic application start
    */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <stm32f446xx.h>
    
    //Takteinstellungen konfigurieren
    void TaktInit(){
      //APB1: Tim6, SPI2, USART3
      //AHB1: PortE, PortB, PortC
      //APB2: Tim1
    
      //SysClk 16MHz (interner Oszillator) - Takt für APB1 auf 2MHz setzen
    
      RCC->CFGR |= RCC_CFGR_HPRE_DIV1;      //AHB-Prescaler /1 => 16NHz
      RCC->CFGR |= RCC_CFGR_PPRE1_DIV8;     //Takt für APB1 = AHB/8
    }
    
    //Nested Vector Interrupt Controller konfigurieren
    void NVICInit(){
      NVIC_EnableIRQ(SPI2_IRQn);
    }
    
    //Pins, die als einfache Standard-EAs (Taster/LEDs) verwendet werden,konfigurieren
    void EAInit(){
      //Pins für LEDs initialisieren
      RCC->AHB1ENR |= RCC_AHB1ENR_GPIOEEN;      //Takt für PortE aktivieren
      //PE0
      GPIOE->MODER |= GPIO_MODER_MODER0_0;
      GPIOE->MODER &= ~GPIO_MODER_MODER0_1;     //PE0 -> Ausgang MODER ->01
      GPIOE->OTYPER &= ~GPIO_OTYPER_OT_0;       //PE0 als Push-Pull-Stufe
      GPIOE->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR0; //PE0 High-Speed
      GPIOE->PUPDR &= ~GPIO_PUPDR_PUPDR0_0;
      GPIOE->PUPDR &= ~GPIO_PUPDR_PUPDR0_1;     //Pull-up/-down-Widerstände abschalten
      GPIOE->BSRR|= GPIO_BSRR_BS_0;             //LED abschalten
      //PE1
      GPIOE->MODER |= GPIO_MODER_MODER1_0;
      GPIOE->MODER &= ~GPIO_MODER_MODER1_1;     //PE1 -> Ausgang MODER ->01
      GPIOE->OTYPER &= ~GPIO_OTYPER_OT_1;       //PE1 als Push-Pull-Stufe
      GPIOE->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR1; //PE1 High-Speed
      GPIOE->PUPDR &= ~GPIO_PUPDR_PUPDR1_0;
      GPIOE->PUPDR &= ~GPIO_PUPDR_PUPDR1_1;     //Pull-up/-down-Widerstände abschalten
      GPIOE->BSRR|= GPIO_BSRR_BS_1;             //LED abschalten
      //PE2
      GPIOE->MODER |= GPIO_MODER_MODER2_0;
      GPIOE->MODER &= ~GPIO_MODER_MODER2_1;     //PE2 -> Ausgang MODER ->01
      GPIOE->OTYPER &= ~GPIO_OTYPER_OT_2;       //PE2 als Push-Pull-Stufe
      GPIOE->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR2; //PE2 High-Speed
      GPIOE->PUPDR &= ~GPIO_PUPDR_PUPDR2_0;
      GPIOE->PUPDR &= ~GPIO_PUPDR_PUPDR2_1;     //Pull-up/-down-Widerstände abschalten
      GPIOE->BSRR|= GPIO_BSRR_BS_2;             //LED abschalten
      //PE3
      GPIOE->MODER |= GPIO_MODER_MODER3_0;
      GPIOE->MODER &= ~GPIO_MODER_MODER3_1;     //PE3 -> Ausgang MODER ->01
      GPIOE->OTYPER &= ~GPIO_OTYPER_OT_3;       //PE3 als Push-Pull-Stufe
      GPIOE->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR3; //PE3 High-Speed
      GPIOE->PUPDR &= ~GPIO_PUPDR_PUPDR3_0;
      GPIOE->PUPDR &= ~GPIO_PUPDR_PUPDR3_1;     //Pull-up/-down-Widerstände abschalten
      GPIOE->BSRR|= GPIO_BSRR_BS_3;             //LED abschalten
      //PE4
      GPIOE->MODER |= GPIO_MODER_MODER4_0;
      GPIOE->MODER &= ~GPIO_MODER_MODER4_1;     //PE4 -> Ausgang MODER ->01
      GPIOE->OTYPER &= ~GPIO_OTYPER_OT_4;       //PE4 als Push-Pull-Stufe
      GPIOE->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR4; //PE4 High-Speed
      GPIOE->PUPDR &= ~GPIO_PUPDR_PUPDR4_0;
      GPIOE->PUPDR &= ~GPIO_PUPDR_PUPDR4_1;     //Pull-up/-down-Widerstände abschalten
      GPIOE->BSRR|= GPIO_BSRR_BS_4;             //LED abschalten
      //PE5
      GPIOE->MODER |= GPIO_MODER_MODER5_0;
      GPIOE->MODER &= ~GPIO_MODER_MODER5_1;     //PE5 -> Ausgang MODER ->01
      GPIOE->OTYPER &= ~GPIO_OTYPER_OT_5;       //PE5 als Push-Pull-Stufe
      GPIOE->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR5; //PE5 High-Speed
      GPIOE->PUPDR &= ~GPIO_PUPDR_PUPDR5_0;
      GPIOE->PUPDR &= ~GPIO_PUPDR_PUPDR5_1;     //Pull-up/-down-Widerstände abschalten
      GPIOE->BSRR|= GPIO_BSRR_BS_5;             //LED abschalten
      //PE6
      GPIOE->MODER |= GPIO_MODER_MODER6_0;
      GPIOE->MODER &= ~GPIO_MODER_MODER6_1;     //PE6 -> Ausgang MODER ->01
      GPIOE->OTYPER &= ~GPIO_OTYPER_OT_6;       //PE6 als Push-Pull-Stufe
      GPIOE->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR6; //PE6 High-Speed
      GPIOE->PUPDR &= ~GPIO_PUPDR_PUPDR6_0;
      GPIOE->PUPDR &= ~GPIO_PUPDR_PUPDR6_1;     //Pull-up/-down-Widerstände abschalten
      GPIOE->BSRR|= GPIO_BSRR_BS_6;             //LED abschalten
    
      //Pins für Taster initialisieren
      //PB5
      GPIOB->MODER &= ~GPIO_MODER_MODER5_0;
      GPIOB->MODER &= ~GPIO_MODER_MODER5_1;     //PB5 -> Eingang MODER ->00
      GPIOB->OTYPER &= ~GPIO_OTYPER_OT_5;
      GPIOB->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR5_0;
      GPIOB->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR5_1;
      GPIOB->PUPDR |= GPIO_PUPDR_PUPDR5_0;
      GPIOB->PUPDR &= ~GPIO_PUPDR_PUPDR5_1;     //Pull-up-Widerstände einschalten PUPDR ->0
      //PB6
      GPIOB->MODER &= ~GPIO_MODER_MODER6_0;
      GPIOB->MODER &= ~GPIO_MODER_MODER6_1;     //PB6 -> Eingang MODER ->00
      GPIOB->OTYPER &= ~GPIO_OTYPER_OT_6;
      GPIOB->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR6_0;
      GPIOB->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR6_1;
      GPIOB->PUPDR |= GPIO_PUPDR_PUPDR6_0;
      GPIOB->PUPDR &= ~GPIO_PUPDR_PUPDR6_1;     //Pull-up-Widerstände einschalten PUPDR ->01
      //PB7
      GPIOB->MODER &= ~GPIO_MODER_MODER7_0;
      GPIOB->MODER &= ~GPIO_MODER_MODER7_1;     //PB7 -> Eingang MODER ->00
      GPIOB->OTYPER &= ~GPIO_OTYPER_OT_7;
      GPIOB->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR7_0;
      GPIOB->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR7_1;
      GPIOB->PUPDR |= GPIO_PUPDR_PUPDR7_0;
      GPIOB->PUPDR &= ~GPIO_PUPDR_PUPDR7_1;     //Pull-up-Widerstände einschalten PUPDR ->01
      //PB12
      GPIOB->MODER &= ~GPIO_MODER_MODER12_0;
      GPIOB->MODER &= ~GPIO_MODER_MODER12_1;     //PB12 -> Eingang MODER ->00
      GPIOB->OTYPER &= ~GPIO_OTYPER_OT_12;
      GPIOB->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR12_0;
      GPIOB->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR12_1;
      GPIOB->PUPDR |= GPIO_PUPDR_PUPDR12_0;
      GPIOB->PUPDR &= ~GPIO_PUPDR_PUPDR12_1;     //Pull-up-Widerstände einschalten PUPDR ->01
      //PB13
      GPIOB->MODER &= ~GPIO_MODER_MODER13_0;
      GPIOB->MODER &= ~GPIO_MODER_MODER13_1;     //PB13 -> Eingang MODER ->00
      GPIOB->OTYPER &= ~GPIO_OTYPER_OT_13;
      GPIOB->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR13_0;
      GPIOB->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR13_1;
      GPIOB->PUPDR |= GPIO_PUPDR_PUPDR13_0;
      GPIOB->PUPDR &= ~GPIO_PUPDR_PUPDR13_1;     //Pull-up-Widerstände einschalten PUPDR ->01
    }
    
    //SPI2 konfigurieren, es wird nur ein LCD damit bedient.
    void SPIInit(){
      //Taktversorgung aktivieren
      RCC->AHB1ENR |= RCC_APB1ENR_SPI2EN;       //Takt für SPI2 aktivieren
      RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;      //Takt für PortB aktivieren
      RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN;      //Takt für PortC aktivieren
    
      //Pins konfigurieren
      //PB10 -> SPI2-Clock
      GPIOB->MODER &= ~GPIO_MODER_MODER10_0;
      GPIOB->MODER |= GPIO_MODER_MODER10_1;         //PB10 -> Alternate Function MODER ->10
      GPIOB->OTYPER &= ~GPIO_OTYPER_OT_10;          //PB10 als Push-Pull-Stufe
      GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR10_0;
      GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR10_1;  //PB10 High-Speed
      GPIOB->PUPDR &= ~GPIO_PUPDR_PUPDR10_0;
      GPIOB->PUPDR &= ~GPIO_PUPDR_PUPDR10_1;        //Pull-up/-down-Widerstände abschalten
      GPIOB->AFR[1] |= (0b0101<<8);                 //SPI2 AF5
    
      //PB15 -> SPI2-MoSi
      GPIOB->MODER &= ~GPIO_MODER_MODER15_0;
      GPIOB->MODER |= GPIO_MODER_MODER15_1;         //PB15 -> Alternate Function MODER ->10
      GPIOB->OTYPER &= ~GPIO_OTYPER_OT_15;          //PB15 als Push-Pull-Stufe
      GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR15_0;  
      GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR15_1;  //PB15 High-Speed
      GPIOB->PUPDR &= ~GPIO_PUPDR_PUPDR15_0;
      GPIOB->PUPDR &= ~GPIO_PUPDR_PUPDR15_1;        //Pull-up/-down-Widerstände abschalten
      GPIOB->AFR[1] |= (0b0101<<28);                 //SPI2 AF5
    
      //PC3 -> SPI2-Select LCD
      GPIOC->MODER |= GPIO_MODER_MODER3_0;
      GPIOC->MODER &= ~GPIO_MODER_MODER3_1;         //PC3 als Ausgang MODER ->01
      GPIOC->OTYPER &= ~GPIO_OTYPER_OT_3;           //PC3 als Push-Pull-Stufe
      GPIOC->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR3_0;
      GPIOC->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR3_1;   //PC3 High-Speed
      GPIOC->PUPDR &= ~GPIO_PUPDR_PUPDR3_0;
      GPIOC->PUPDR &= ~GPIO_PUPDR_PUPDR3_1;         //Pull-up/-down-Widerstände abschalten
    
      //PC2 -> SPI2-R/S
      GPIOC->MODER |= GPIO_MODER_MODER2_0;
      GPIOC->MODER |= GPIO_MODER_MODER2_1;          //PC2 als Ausgang MODER ->01
      GPIOC->OTYPER &= ~GPIO_OTYPER_OT_3;           //PC2 als Push-Pull-Stufe
      GPIOC->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR2_0;
      GPIOC->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR2_1;   //PC2 als High-Speed
      GPIOC->PUPDR &= ~GPIO_PUPDR_PUPDR2_0;
      GPIOC->PUPDR &= ~GPIO_PUPDR_PUPDR2_1;         //Pull-up/-down-Widerstände abschalten
    
      //SPI konfigurieren
      SPI2->CR1 |= SPI_CR1_BIDIMODE;                //Bidirektionaler Modus
      SPI2->CR1 |= SPI_CR1_BIDIOE;                  //Nur senden
      SPI2->CR1 &= SPI_CR1_CRCEN;                   //CRC-Berechnung abschalten
      SPI2->CR1 &= ~SPI_CR1_CRCNEXT;                //Keine CRC-Phase
      SPI2->CR1 &= ~SPI_CR1_DFF;                    //8-Bit Frameformat
      SPI2->CR1 &= ~SPI_CR1_RXONLY;                 //Receive-Only-Modus abschalten
      SPI2->CR1 &= ~SPI_CR1_SSM;                    //Software Slave Management abschalten
      //SPI2->CR1 &= ~SPI_CR1_SSI;                    //NSS-Pin
      SPI2->CR1 &= ~SPI_CR1_LSBFIRST;               //MSB zuerst übertragen
      SPI2->CR1 |= SPI_CR1_SPE;                     //SPI aktivieren
      SPI2->CR1 |= SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0; //Taktteiler 256 -> 2MHz/256 -> 7,8kHz
      SPI2->CR1 |= SPI_CR1_MSTR;                    //Master configuration
      SPI2->CR1 |= SPI_CR1_CPOL;                    //Takt=1 im Leerlauf
      SPI2->CR1 &= ~SPI_CR1_CPHA;                   //Clockphase, first clock transistion is first data capture edge
    
      SPI2->CR2 |= SPI_CR2_TXEIE;                   //Tx-buffer empty interupt aktivieren
      SPI2->CR2 &= ~SPI_CR2_RXNEIE;                 //Rx-buffer not empty interrupt deaktivieren
      SPI2->CR2 &= ~SPI_CR2_ERRIE;                  //Error Interrupt deaktivieren
      SPI2->CR2 &= ~SPI_CR2_FRF;                    //Motorola-Modus (Sandard)
      SPI2->CR2 &= ~SPI_CR2_SSOE;                   //SS Output deaktivieren
      SPI2->CR2 &= ~SPI_CR2_TXDMAEN;                //TXE DMA-Request deaktivieren
      SPI2->CR2 &= ~SPI_CR2_RXDMAEN;                //RXNE DMA Request deaktivieren
    }
    
    void LCDInit(){
      SndBfhlLCD(0b00111001);
      SndBfhlLCD(0b00010101);
      SndBfhlLCD(0b01010101);
      SndBfhlLCD(0b01101110);
    
      SndBfhlLCD(0b01110010);
      SndBfhlLCD(0b00111000);
      SndBfhlLCD(0b00001111);
      SndBfhlLCD(0b00000001);
      SndBfhlLCD(0b00000110);
      printf("Init-Befehle an LCD gesendet\n");
    }
    
    //Sendet ein Byte ans LCD
    void SndLCD(char Byte){
      while (SPI2->SR & SPI_SR_TXE){              //Warten bis Transmitpuffer frei ist
      }
      SPI2->DR = Byte;                              //Byte ins Transmitregister schreiben
    }
    
    //Sendet ein Befehlbyte ans LCD
    void SndBfhlLCD(char byte){
      while (SPI2->SR & SPI_SR_TXE){              //Warten bis Transmitpuffer frei ist
      }
      GPIOC->BSRR |= GPIO_BSRR_BR_2;              //RS-Pin zurücksetzen
      SPI2->DR = byte;                            //Byte senden
      while(SPI2->SR & SPI_SR_TXE){                     //Warten bis Übertragung abgeschlossen ist
      }
      //RS NICHT toggeln
    }
    
    //Sendet ein Datenbyte ans LCD
    void SndDtnlLCD(char byte){
      while (SPI2->SR & SPI_SR_TXE){              //Warten bis Transmitpuffer frei ist
      }
      GPIOC->BSRR |= GPIO_BSRR_BS_2;              //RS-Pin setzen
      SPI2->DR = byte;                            //Byte senden
      while(SPI2->SR & SPI_SR_TXE){               //Warten bis Übertragung abgeschlossen ist
      }
      GPIOC->BSRR |= GPIO_BSRR_BS_2;              //RS toggeln
      GPIOC->BSRR |= GPIO_BSRR_BR_2;
    }
    
    //SPI2 Interrupt
    void SPI2_IRQHandler (void){
      GPIOE->BSRR |= GPIO_BSRR_BR_4;              //LED an E4 einschalten
      printf("SPI2 Interrupt Event\n");
    }
    
    void main(void){
      TaktInit();
      NVICInit();
      EAInit();
    
      GPIOE->BSRR |= GPIO_BSRR_BR_5;              //LED an E5 einschalten
    
      SPIInit();
      LCDInit();
    
      SndDtnlLCD('T');
      SndDtnlLCD('e');
      SndDtnlLCD('s');
      SndDtnlLCD('t');
      SndDtnlLCD(' ');
      SndDtnlLCD('O');
      SndDtnlLCD('K');
    
      GPIOE->BSRR |= GPIO_BSRR_BR_1;              //LED an E1 einschalten
    }
    Geändert von White_Fox (06.11.2016 um 15:48 Uhr) Grund: Code aktualisiert

Ähnliche Themen

  1. noch ne seltsame Rechenfunktion - ich krieg die Krise!
    Von dl1akp im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 5
    Letzter Beitrag: 17.08.2008, 20:44
  2. wie, krieg ich die hex auf dem board
    Von Sp666dy im Forum AVR Hardwarethemen
    Antworten: 2
    Letzter Beitrag: 25.02.2008, 07:34
  3. Menü - ich krieg die Krise!!!
    Von dl1akp im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 3
    Letzter Beitrag: 18.11.2007, 14:41
  4. Wo krieg ich BASCOM Basic her?
    Von zwerg1 im Forum AVR Hardwarethemen
    Antworten: 23
    Letzter Beitrag: 13.02.2007, 22:34
  5. Wo krieg ich Baupläne her
    Von Aramis im Forum Elektronik
    Antworten: 5
    Letzter Beitrag: 05.09.2004, 10:16

Berechtigungen

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

Solar Speicher und Akkus Tests