Forum: Mikrocontroller und Digitale Elektronik STM32L433 Gpio Read verhält sich falsch


von Johnny S. (sgt_johnny)


Lesenswert?

Ich habe einen STM32L433 welcher über einen Taster, welcher durch ein 
mechanisches Teil aktiviert wird aus dem Shutdown-Mode erwacht werden 
kann.

Vor dem Shutdown wird der Aufwach-Pin wie folgt initialisiert:

    /*Configure GPIO pin : PA0 */
    GPIO_InitStruct.Pin = GPIO_PIN_0;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

          HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1_HIGH);

Danach geht der MCU erfolgreich in den Shutdown und verweilt dort so 
lange wie der Taster nicht gedrückt ist.
Der Taster ist mit 100k Pulldown und 100nF Decoupling ausgestattet. Wird 
nun der MCU über den Taster aufgeweckt (der Taster ist in diesem Fall 
dauergerdückt durch mechanischen Anschlag, und bleibt die komplette Zeit 
gedrückt. Nachgemsessen mit dem Oszi mit Trigger auf 2.4V fallende 
Flanke (V+=3.3V))

Der MCU wacht aus dem Shutdown auf, und konfiguriert den Pin 0 wie folgt 
neu:

    HAL_GPIO_DeInit(GPIOA,GPIO_PIN_0);

    /*Configure GPIO pin : PA0 */
    GPIO_InitStruct.Pin = GPIO_PIN_0;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

Danach wird ein Startvorgang ausgeführt welcher die verschiedene 
Ausführungen macht, und nach ca. 50ms per HAL_GPIO_ReadPin() nochmals 
prüft ob der Taster immernoch gedrückt ist.  Diese Abfrage erzielt das 
FALSCHE Resultat von "0" - also nicht gedrückt. Dadurch wird der MCU 
wieder in den Shutdown gebracht, wovon er direkt wieder aufwacht, nach 
dem zweiten Aufwachen funktioniert es jedoch einwandfrei, der Taster 
wird auch nach 50ms als "On". Wird im Betrieb dann irgendwann der Taster 
wieder ent-drückt, geht der MCU in den Shutdown und beim erneuten 
drücken taucht das Problem wieder auf.

Folgendes wurde als Fehlerbehebung probiert:

-Einbau einer Zeitmessung (also der Taster muss x nicht gedrückt sein 
bis der MCU in den Shutdown geht. Aktuell muss er satte 500ms ungedrückt 
sein, und trotzdem tritt das Problem auf)
- Kontrolle per Oszi auf elektrische Signale am Taster (kein "LOW" 
Signal am Taster gefunden)
- Pulldown am IO konfiguriert. Keine Änderung passiert

Das Problem tritt sogar auf, wenn der Tasterkontakt überlötet wird, so 
das also "immer" gedrückt wird

Der Pin liest 0 obwohl eine elektrische 1 ansteht (saubere 3.3V).

Woran kann das liegen?

von Guest (Gast)


Lesenswert?

Spontan würde ich vermuten du hast vergessen die Clock für Port A zu 
aktivieren.

__HAL_RCC_GPIOA_CLK_ENABLE();

Ich bin mir auch nicht ganz sicher ob du den DeInit wirklich machen 
musst. Der WakeUp braucht meine ich keinen Initialisierten Pin du kannst 
den WakeUp einfach ausschalten:

HAL_PWR_DisableWakeUpPin();

von Johnny S. (sgt_johnny)


Lesenswert?

Guest schrieb:
> Spontan würde ich vermuten du hast vergessen die Clock für Port A zu
> aktivieren.
>
> __HAL_RCC_GPIOA_CLK_ENABLE();
>
> Ich bin mir auch nicht ganz sicher ob du den DeInit wirklich machen
> musst. Der WakeUp braucht meine ich keinen Initialisierten Pin du kannst
> den WakeUp einfach ausschalten:
>
> HAL_PWR_DisableWakeUpPin();


Port A wird direkt nach der Clock COnfig aktiviert mit allen Anderen 
(B,C,H) aktiviert

Der DeInit wurde aktuell auch nur hinzugefügt um sicherzugehen das der 
Pin nicht irgendeine andere Config hat... Ohne/Mit diesem Befehl änder 
sich leider nichts

von Max (Gast)


Lesenswert?

Hi,

wie sieht den die ClockConfig aus. Das IDR Register des GPIOs wird mit 
jedem AHB clock aktualisiert. Wenn dieser nicht richtig läuft kann es 
passieren das du immer nur eine 0 liest (default nach reset). Am besten 
mal bissl mehr code zeigen.

So was gleiches habe ich gerade bei einem STM32G071GBU6 gemacht, nach 
dem Shutdown den WK-PIN nachmals auf "ON" prüfen. Dabei hatte ich keine 
Probleme festgestellt (ok klar anderer µC).

von Stolper/Hoppla (Gast)


Lesenswert?

Guest schrieb:
> die Clock

die Clock  -->  die Uhr
der Clock  -->  der Takt

von Guest (Gast)


Lesenswert?

Stolper/Hoppla schrieb:
> die Clock  -->  die Uhr
> der Clock  -->  der Takt

Für Klugscheißer gibt's hier eine extra Topic ?. Wenn du nichts 
sinnvolles beizutragen hast halt dich doch bitte da auf. Es ist ohnehin 
sinnlos mit deutscher Grammatik an englische Begriffe heran zu gehen.

von Stolper/Hoppla (Gast)


Lesenswert?

Guest schrieb:
> Es ist ohnehin
> sinnlos mit deutscher Grammatik an englische Begriffe heran zu gehen.

Dann sagst du auch sicherlich bei jeder Gelegenheit nach Belieben
"der Power" oder "das Power", gelle?

Ach sooo, das war ein Ausrutscher, du verwendest nie englische
Ausdrücke, daher brauchst du dich um Artikel auch gar nicht zu
kümmern.

von Johnny S. (sgt_johnny)


Lesenswert?

Hier die Takteinstellung


void sysClockConfig(void)
{
   RCC_OscInitTypeDef RCC_OscInitStruct;
    RCC_ClkInitTypeDef RCC_ClkInitStruct;
    RCC_PeriphCLKInitTypeDef PeriphClkInit;

      /**Initializes the CPU, AHB and APB busses clocks
      */
    HAL_PWR_EnableBkUpAccess();

    //__HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);

    //RCC_OscInitStruct.OscillatorType = 
RCC_OSCILLATORTYPE_MSI|RCC_OSCILLATORTYPE_LSE;
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
    RCC_OscInitStruct.MSIState = RCC_MSI_ON;
    //RCC_OscInitStruct.LSEState = RCC_LSE_ON;
    RCC_OscInitStruct.MSICalibrationValue = 0;
    RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    {
      _Error_Handler(_FILE_, _LINE_);
    }

      /**Initializes the CPU, AHB and APB busses clocks
      */
    RCC_ClkInitStruct.ClockType = 
RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                                |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

    if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != 
HAL_OK)
    {
      _Error_Handler(_FILE_, _LINE_);
    }

    PeriphClkInit.PeriphClockSelection = 
RCC_PERIPHCLK_USART1|RCC_PERIPHCLK_I2C2
                                |RCC_PERIPHCLK_ADC;
    PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
    PeriphClkInit.I2c2ClockSelection = RCC_I2C2CLKSOURCE_PCLK1;
    PeriphClkInit.AdcClockSelection = RCC_ADCCLKSOURCE_SYSCLK;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
    {
      _Error_Handler(_FILE_, _LINE_);
    }

//    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC;
//    PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
//    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
//    {
//      _Error_Handler(_FILE_, _LINE_);
//    }

      /**Configure the main internal regulator output voltage
      */
    if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != 
HAL_OK)
    {
      _Error_Handler(_FILE_, _LINE_);
    }

      /**Configure the Systick interrupt time
      */
    HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

      /**Configure the Systick
      */
    HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

    /* SysTick_IRQn interrupt configuration */
    HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);


   // HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_SYSCLK, RCC_MCODIV_1);

    //sysRtcConfig();

         __HAL_RCC_GPIOC_CLK_ENABLE();
         __HAL_RCC_GPIOH_CLK_ENABLE();
         __HAL_RCC_GPIOA_CLK_ENABLE();
         __HAL_RCC_GPIOB_CLK_ENABLE();
         __HAL_RCC_ADC_CLK_ENABLE();
         __HAL_RCC_PWR_CLK_ENABLE();
         __HAL_RCC_DMA1_CLK_ENABLE();

}

von Maxim (Gast)


Lesenswert?

Stolper/Hoppla schrieb:
> Dann sagst du auch sicherlich bei jeder Gelegenheit nach Belieben
> "der Power" oder "das Power", gelle?
>
> Ach sooo, das war ein Ausrutscher, du verwendest nie englische
> Ausdrücke, daher brauchst du dich um Artikel auch gar nicht zu
> kümmern.

Du bist als Kind auch zu heiß gebadet worden oder ? vielleicht stand 
auch die Schaukel zu nah an der Wand....

von Guest (Gast)


Lesenswert?

Maxim schrieb:
> Du bist als Kind auch zu heiß gebadet worden oder ? vielleicht stand
> auch die Schaukel zu nah an der Wand....

Lass ihn er braucht das für sein Ego....

Nochmal zu dem eigentlichen Inhalt des Posts. Hast du dir mal im 
Debugger die Register angesehen und geschaut was im IDR drin steht bzw. 
ob die Config Register richtig sind.

von Johnny S. (sgt_johnny)


Lesenswert?

IDR ist = 1111000000000000
MODER ist = 1101001011111011110101111111111

von Johnny S. (sgt_johnny)


Lesenswert?

Ich habe die Variable nochmals beobachtet Hier jeweils nur die letzen 
zwei stellen (da dies ja GPIOA ist)


Cycle:   MODER:    ODR:
45924    11        01
46593    00        01
48372    00        00
48625    11        00
49308    11        00

Beitrag #6054896 wurde von einem Moderator gelöscht.
von Johnny S. (sgt_johnny)


Lesenswert?

Wie es aussieht wurde das Problem von der ADC-Initialisierung erzeugt


Orginal :

      /**ADC1 GPIO Configuration
      PA2     ------> ADC1_IN7
      PA3     ------> ADC1_IN8
      PA4     ------> ADC1_IN9
      */
      GPIO_InitStruct.Pin = 2|3|4;
      GPIO_InitStruct.Mode = GPIO_MODE_ANALOG_ADC_CONTROL;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);


Fix

      /**ADC1 GPIO Configuration
      PA2     ------> ADC1_IN7
      PA3     ------> ADC1_IN8
      PA4     ------> ADC1_IN9
      */
      GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4;
      GPIO_InitStruct.Mode = GPIO_MODE_ANALOG_ADC_CONTROL;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Johnny S. schrieb:
> GPIO_InitStruct.Pin = 2|3|4;

Aua.

GPIO_PIN_x sind Bitmasken, also Zweierpotenzen, wo nur ein Bit gesetzt 
ist.

Diese kann man nicht einfach durch die Zahlen 2,3,4 ersetzen. Da kommt 
bei '2|3|4' etwas ganz anderes raus.

von Johnny S. (sgt_johnny)


Lesenswert?

Frank M. schrieb:
> Johnny S. schrieb:
>> GPIO_InitStruct.Pin = 2|3|4;
>
> Aua.
>
> GPIO_PIN_x sind Bitmasken, also Zweierpotenzen, wo nur ein Bit gesetzt
> ist.
>
> Diese kann man nicht einfach durch die Zahlen 2,3,4 ersetzen. Da kommt
> bei '2|3|4' etwas ganz anderes raus.

Ja, nur hatte ich die Funktion bis jetz nicht angefasst, das wurde also 
so generiert von ST.

von Guest (Gast)


Lesenswert?

Johnny S. schrieb:
> Ja, nur hatte ich die Funktion bis jetz nicht angefasst, das wurde also
> so generiert von ST.

Das kann ich mir fast nicht Vorstellen. Womit soll das generiert worden 
sein? Und jetzt sag nicht CubeMX das sieht anders aus :D

von Bernd K. (prof7bit)


Lesenswert?

Das ist der "Ich hab nichts gemacht!"-Reflex.

von Johnny S. (sgt_johnny)


Lesenswert?

Jo, es handelt sich um CubeMX

Kann man eigentlich alle GPIO bereits vor den Pheris initialisieren?

Also z.b. einmal eine Funktion "GPIO_Init" wo sämtliche Pins 
initialisiert werden auch die von SPI und ADC bevor aber der ADC selbst 
initialisiert ist.

Find ich irgendwie nicht so "schön" das X-mal irgendwo pins 
initialisiert werden.

Kontrekt gibt es bei mir:

normale GPIO
SPI pins
ADC pins
Timer pins

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.