- LiTime Speicher und Akkus         
Seite 2 von 4 ErsteErste 1234 LetzteLetzte
Ergebnis 11 bis 20 von 32

Thema: SMT32 - Ports konfigurieren, Frage zur C-Syntax

  1. #11
    Erfahrener Benutzer Roboter Genie Avatar von White_Fox
    Registriert seit
    04.10.2011
    Beiträge
    1.473
    Anzeige

    Praxistest und DIY Projekte
    Ich kam heute mal dazu meinen code zu testen.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <stm32f446xx.h>
    
    /*********************************************************************
    *
    *       main()
    *
    *  Function description
    *   Application entry point.
    */
    void main(void) {
      GPIOA->MODER |= (GPIO_MODER_MODER5_0);    //A5 => Ausgang
      GPIOA->OTYPER |= (GPIO_OTYPER_OT_5);      //A5 0> OpenDrain
      GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPDR5);     //A5 ohne Pullup-Pulldown
    
      printf("Einstellung fertig\n");
    
      GPIOA->ODR |= (GPIO_ODR_ODR_5);           //Ausgang A5 setzen
     
      printf("LED gesetzt\n");
    
      while(1){
      }
    }
    Jetzt müßte die LED an A5 leuchten. Tut sie aber nicht. Hab ich noch was vergessen oder einen Fehler gemacht?
    Wenn ich den Debugger starte, kommen die printf-Meldungen. Der J-Link ist auch verbunden. Sagt Embedded Studio. Nurdie LED tut nix, wie gesagt...

  2. #12
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    27.08.2013
    Ort
    Region Basel
    Alter
    66
    Beiträge
    2.435
    Zitat Zitat von White_Fox Beitrag anzeigen
    Ich kam heute mal dazu meinen code zu testen.

    Jetzt müßte die LED an A5 leuchten. Tut sie aber nicht. Hab ich noch was vergessen oder einen Fehler gemacht?
    Wenn ich den Debugger starte, kommen die printf-Meldungen. Der J-Link ist auch verbunden. Sagt Embedded Studio. Nurdie LED tut nix, wie gesagt...
    Wie ist die LED angeschlossen?

    A5 setzt du als Open Drain, da schaltet der Transistor nur gegen Masse. andernfalls ist der Pin einfach hochohmig.
    Die LED muss also vom Pin über einen Widerstand gegen die positive Versorgungsspannung angeschlossen sein.

    Damit der Transistor aber nach Masse schaltet musst du eine 0 Ausgeben!

    MfG Peter(TOO)
    Manchmal frage ich mich, wieso meine Generation Geräte ohne Simulation entwickeln konnte?

  3. #13
    Erfahrener Benutzer Roboter Genie Avatar von White_Fox
    Registriert seit
    04.10.2011
    Beiträge
    1.473
    Hm...stimmt, hätte ich mal schauen sollen ob die LED an Masse oder 3%5V hängt.

    Man, Tests am Abend...

  4. #14
    Unregistriert
    Gast
    1. Hast Du den Port A mit Takt versorgt?

    Code:
    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
    2. Wieso konfigurierst Du den Port nicht auf Push-Pull?

    3. Ich empfehle Dir, das Du Dir angewöhnst, Port Pins mit Bitset (oder Bitreset) zu setzen. Deine Operation auf dem ODR ist nicht atomar, damit kannst Du also unerwünschte Nebeneffekte erzeugen, wenn andere Portpins von Port A genutzt werden. Nimm ODR nur, wenn Du den ganzen Port setzen willst.

    Code:
    GPIOA->BSRR |= GPIO_BSRR_BS_5;
    oder
    Code:
    GPIOA->BSRR |= GPIO_BSRR_BR_5;

    Zitat Zitat von White_Fox Beitrag anzeigen
    Ich kam heute mal dazu meinen code zu testen.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <stm32f446xx.h>
    
    /*********************************************************************
    *
    *       main()
    *
    *  Function description
    *   Application entry point.
    */
    void main(void) {
      GPIOA->MODER |= (GPIO_MODER_MODER5_0);    //A5 => Ausgang
      GPIOA->OTYPER |= (GPIO_OTYPER_OT_5);      //A5 0> OpenDrain
      GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPDR5);     //A5 ohne Pullup-Pulldown
    
      printf("Einstellung fertig\n");
    
      GPIOA->ODR |= (GPIO_ODR_ODR_5);           //Ausgang A5 setzen
     
      printf("LED gesetzt\n");
    
      while(1){
      }
    }
    Jetzt müßte die LED an A5 leuchten. Tut sie aber nicht. Hab ich noch was vergessen oder einen Fehler gemacht?
    Wenn ich den Debugger starte, kommen die printf-Meldungen. Der J-Link ist auch verbunden. Sagt Embedded Studio. Nurdie LED tut nix, wie gesagt...

  5. #15
    Erfahrener Benutzer Roboter Genie Avatar von White_Fox
    Registriert seit
    04.10.2011
    Beiträge
    1.473
    Hallo Unregistrierter

    1. Hast Du den Port A mit Takt versorgt?
    Gnaa....nein, das fehlt noch.
    Und eigentlich wollte ich den Ausgang PP setzen...Open Drain macht nicht allzuviel Sinn. Keine Ahnung wie sich das eingeschlichen hat.

    3. Ich empfehle Dir, das Du Dir angewöhnst, Port Pins mit Bitset (oder Bitreset) zu setzen. Deine Operation auf dem ODR ist nicht atomar, damit kannst Du also unerwünschte Nebeneffekte erzeugen, wenn andere Portpins von Port A genutzt werden. Nimm ODR nur, wenn Du den ganzen Port setzen willst.
    Wo ist denn da genau der Unterschied? Danke auf jeden Fall für den Tip, das werd ich so machen.

  6. #16
    Erfahrener Benutzer Roboter Genie Avatar von White_Fox
    Registriert seit
    04.10.2011
    Beiträge
    1.473
    Das verstehe wer will...die LED tut nix.
    Laut Dokumentation soll die LED leuchten, wenn PA5 HIGH-Pegel hat.
    Taktversorgung ist jetzt auch drin.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <stm32f446xx.h>
    
    void main(void) {
      GPIOA->MODER |= (GPIO_MODER_MODER5_0);    //A5 => Ausgang
      GPIOA->OTYPER &= ~(GPIO_OTYPER_OT_5);      //A5 0> Push-Pull
      GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPDR5);     //A5 ohne Pullup-Pulldown
      RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;      //Taktversorgung Port A
    
      //printf("Einstellung fertig\n");
    
      GPIOA->BSRR |= GPIO_BSRR_BS_5;           //Ausgang A5 setzen
     
      //printf("LED gesetzt\n");
    
      while(1){
      }
    }
    Soweit ich das sehe hab ich doch alles drin:
    • A5 als Ausgang definiert (MODER 01)
    • Outout-Type als Push-Pull definiert (OTYPER 0)
    • Pullup/down-Widerstände abgeschaltet (PUPDR 00)
    • Taktversorgung einschalten
    • PA5 setzen


    Danach: Über J-Link mit Target verbinden und dann Download File...

    Hat jemand ne Idee was da noch fehlt?


    Edit:
    Es funktioniert endlich. Die Taktversorgung gehört an den Anfang. Anscheinend werden die Befehle, mit denen die GPIO-Register beschrieben werden, ohne Taktversorgung nicht ausgeführt.

    Vielen Dank für die Hilfe bisher, vor allem an dich, Unregistrierter.
    Geändert von White_Fox (18.06.2016 um 17:58 Uhr)

  7. #17
    Unregistriert
    Gast
    Edit:
    Es funktioniert endlich. Die Taktversorgung gehört an den Anfang. Anscheinend werden die Befehle, mit denen die GPIO-Register beschrieben werden, ohne Taktversorgung nicht ausgeführt.

    Vielen Dank für die Hilfe bisher, vor allem an dich, Unregistrierter.

    Das liegt daran, dass die ganze Port-Logik deaktiviert ist, wenn der Takt nicht anliegt.

    Habe aber noch einen kleinen Fehler gemacht (der sich hier nicht auswirkt aufgrund der internen Logik des Controllers, aber nichtsdestotrotz sollte man das anders machen...):
    Das BSRR-Register ist ein Write-Only-Register. Daher muss die Anweisung wie folgt lauten - auch wenn es jetzt so klappt:

    Code:
    GPIOA->BSRR = GPIO_BSRR_BS_5;
    Also keinen Oder-Operator benutzen.

  8. #18
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    27.08.2013
    Ort
    Region Basel
    Alter
    66
    Beiträge
    2.435
    Zitat Zitat von Unregistriert Beitrag anzeigen
    Es funktioniert endlich. Die Taktversorgung gehört an den Anfang. Anscheinend werden die Befehle, mit denen die GPIO-Register beschrieben werden, ohne Taktversorgung nicht ausgeführt.
    Sinn des Ganzen ist die Stromersparnis. Bei CMOS setzt sich der Stromverbrauch aus den Leckströmen und einem Strom, welcher direkt proportional zur Taktfrequenz ist, zusammen. Bei Batteriebetrieb zählt da jedes mA! Teilweise wird aber nicht nur der Takt, sondern auch die Betriebsspannung ganzer Schaltungsteile abgeschaltet, das reduziert dann auch noch die Leckströme.

    Zitat Zitat von Unregistriert Beitrag anzeigen
    Habe aber noch einen kleinen Fehler gemacht (der sich hier nicht auswirkt aufgrund der internen Logik des Controllers, aber nichtsdestotrotz sollte man das anders machen...):
    Das BSRR-Register ist ein Write-Only-Register. Daher muss die Anweisung wie folgt lauten - auch wenn es jetzt so klappt:

    Code:
    GPIOA->BSRR = GPIO_BSRR_BS_5;
    Also keinen Oder-Operator benutzen.
    Es ist egal welche Variante du nimmst.
    Write-Only-Register lesen sich, in diesem Fall, immer als 0, egal auf welche Werte das Register gesetzt ist.

    Wenn du jetzt mehrere Bist verwalten willst, musst du ein Schatten-Register führen.
    Also eine statische Variable, welch du wie das Register behandelst. Da kannst du dann einzelne Bis setzen oder löschen.
    Wenn du mit dem Modifizieren der Bits fertig bist, schreibst du den Wert der Variablen ins Register.

    WO-Register verwendet der Hersteller für Register welche in typischen Anwendungen nur bei der Initialisierung der Anwendung beschrieben werden müssen. Das spart Einiges an Transistoren und Platz auf dem Chip. Bei untypischen Anwendungen muss man sich dann halt mit dem Schattenregister behelfen.

    Das ist auch der Grund für die HAL-Bibliotheken. Da werden, wo nötig, Schattenregister geführt und der Programmierer muss keine Ahnung von dieser Hardware-Eigenschaft haben. Über den HAL sind alle Register auch lesbar.
    Allerdings kostet dies Programmspeicher und Laufzeit. Bei zeitkritischen Aufgaben, weiss man aber nie, was der HAL so alles macht und ganz lustig kann es werden, wenn der HAL ein Update erfahren hat.

    MfG Peter(TOO)
    Geändert von Peter(TOO) (18.06.2016 um 19:47 Uhr)
    Manchmal frage ich mich, wieso meine Generation Geräte ohne Simulation entwickeln konnte?

  9. #19
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.08.2008
    Ort
    DE
    Beiträge
    523
    Hier mal die Ansteuerung für die LED bei einem F411RE, sollte aber identisch mit deinem sein.

    Code:
    #include "stm32f4xx.h"
    #include "stm32f4xx_conf.h"
    
    
    #define LED2_PIN                        GPIO_Pin_5
    #define LED2_GPIO_PORT                    GPIOA
    #define LED2_GPIO_CLK                    RCC_AHB1Periph_GPIOA
    
    
    #define USER_BUTTON_PIN                   GPIO_Pin_13
    #define USER_BUTTON_GPIO_PORT             GPIOC
    #define USER_BUTTON_GPIO_CLK             RCC_AHB1Periph_GPIOC
    #define USER_BUTTON_EXTI_LINE             EXTI_Line13
    #define USER_BUTTON_EXTI_PORT_SOURCE      GPIO_PortSourceGPIOC
    #define USER_BUTTON_EXTI_PIN_SOURCE       GPIO_PinSource13
    
    
    
    
    void SysClock_Init(void)
    {
        RCC_ClocksTypeDef RCC_Clocks;
    
    
        /* SysTick end of count event each 1ms */
          RCC_GetClocksFreq(&RCC_Clocks);
          SysTick_Config(RCC_Clocks.HCLK_Frequency / 1000);
    }
    
    
    void LED_Init(void)
    {
        GPIO_InitTypeDef GPIO_InitStructure;
    
    
        /* Enable the GPIO Clock */
        RCC_AHB1PeriphClockCmd(LED2_GPIO_CLK, ENABLE);
    
    
        /* Configure the GPIO pin */
        GPIO_InitStructure.GPIO_Pin = LED2_PIN;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
        GPIO_Init(LED2_GPIO_PORT, &GPIO_InitStructure);
    }
    
    
    void LED_SetOnOff(uint8_t state)
    {
        if(ON == state)
            GPIOA->BSRRL = GPIO_Pin_5;
        else
            GPIOA->BSRRH = GPIO_Pin_5;
    }
    
    
    void LED_Toggle(void)
    {
        GPIOA->ODR ^= GPIO_Pin_5;
    }
    mfg

  10. #20
    Unregistriert
    Gast
    Es ist egal welche Variante du nimmst.
    Write-Only-Register lesen sich, in diesem Fall, immer als 0, egal auf welche Werte das Register gesetzt ist.
    Das ist nicht richtig.
    Die Variante mit dem Oder braucht unnötigerweise etliche Takte mehr, da erst das Register gelesen werden muss, danach die Verknüpfung erfolgt und anschließend der Wert zurückgeschrieben wird -> also ein Vielfaches der Zeit.


    WO-Register verwendet der Hersteller für Register welche in typischen Anwendungen nur bei der Initialisierung der Anwendung beschrieben werden müssen. Das spart Einiges an Transistoren und Platz auf dem Chip. Bei untypischen Anwendungen muss man sich dann halt mit dem Schattenregister behelfen.
    Auch das ist nicht richtig. Der Grund ist, dass hier für den atomaren Zugriff ein Register geschaffen wurde, welches ein Setzen oder Zurücksetzen der Pins ermöglichen sollte.
    Da ist ein Lesen natürlich unsinnig. Daher ist das ein WriteOnly-Register.

Seite 2 von 4 ErsteErste 1234 LetzteLetzte

Ähnliche Themen

  1. Syntax-Frage -> writeString(char *string)
    Von Furzgas im Forum Robby RP6
    Antworten: 13
    Letzter Beitrag: 31.12.2009, 09:06
  2. Frage zum Ansteuern von Ports/Programmierfrage
    Von Geimel im Forum C - Programmierung (GCC u.a.)
    Antworten: 6
    Letzter Beitrag: 26.01.2007, 23:29
  3. Kurze Syntax Frage
    Von Brantiko im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 9
    Letzter Beitrag: 18.01.2007, 19:58
  4. Frage zum Programmieren der Ports
    Von Geimel im Forum Asuro
    Antworten: 2
    Letzter Beitrag: 07.08.2006, 20:29
  5. kleine Frage zur Syntax
    Von freddy0815 im Forum AVR Hardwarethemen
    Antworten: 2
    Letzter Beitrag: 07.02.2005, 15:19

Berechtigungen

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

LiTime Speicher und Akkus