Forum: Mikrocontroller und Digitale Elektronik STM32F103 Probleme mit PD2


von Christoph R. (christoph_r463)


Lesenswert?

Hallo Zusammen,

Ich habe gerade meine neue Platine mit STM32F103 RBT6 (LQFP64 pinout) in 
Betrieb genommen und mein Software Projekt dahingehend angepasst 
(pin-defines). Ich habe bei der neuen Platine eine Status LED auf dem 
PD2 liegen. Immer wenn mein Programm aktiv ist, geht die LED an und am 
Ende wieder aus (soweit die Theorie). Bei meinem bisherigen Board hatte 
ich die LED auf einem anderen Pin (B0).

Mein Programm bleibt nun aber immer nach ein paar Durchläufen einfach 
stehen. Nichtmal der SysTick_Handler wird noch angesprungen. Ich 
vermute, dass da vielleicht irgendwo ein Interrupt von dem PD2 erzeugt 
wird, finde aber nichts. Den HardFault_Handler() und BusFault_Handler() 
habe ich mal eingebaut um dort einen Breakpoint zu setzten, aber auch 
die werden nicht angesprungen.

Wenn ich nun einfach die LED nicht nutze (initialisieren aber nicht 
schalten), funktioniert alles wunderbar.
Was stimmt mit diesem Pin nicht?

Danke und Grüße
Chris

von Uwe B. (Firma: TU Darmstadt) (uwebonnes)


Lesenswert?

PD2 ist auch TIM3_ETR. Hast Dur TIM3 in Benutzung?

von Christoph R. (christoph_r463)


Lesenswert?

Uwe B. schrieb:
> PD2 ist auch TIM3_ETR. Hast Dur TIM3 in Benutzung?

Hi Uwe,

der sollte nicht aktiv sein (habe auch mal den TIM3_IRQHandler mit 
Breakpoint versehen, - ohne Resultat).
Bewusst habe ich lediglich den Systick Interrupt in Benutzung. Für 
weitere Timings nutze ich noch den TIM2.

Muss man den PD2 aktiv von TIM3_ETR umschalten auf normal Modus? Im 
Datenblatt sieht es so aus, als ob er Standardmäßig ein normaler GPIO 
ist. Und wenn man die Alternativ-Funktion aktiviert, wird er per default 
zum TIM3_ETR... sehe ich das richtig, oder gibt es da noch was anderes 
zu beachten?

Grüße
Chris

von Herbert (Gast)


Lesenswert?

Christoph R. schrieb:
> Wenn ich nun einfach die LED nicht nutze (initialisieren aber nicht
> schalten), funktioniert alles wunderbar.
> Was stimmt mit diesem Pin nicht?

Poste doch mal deinen Code

von Christopher B. (chrimbo) Benutzerseite


Lesenswert?

Offensichtlich hast du einen Debugger angeschlossen. Kannst du nicht 
einfach anhalten wenn er sich aufhaengt?

von Christoph R. (christoph_r463)


Lesenswert?

Herbert schrieb:
> Christoph R. schrieb:
>> Wenn ich nun einfach die LED nicht nutze (initialisieren aber nicht
>> schalten), funktioniert alles wunderbar.
>> Was stimmt mit diesem Pin nicht?
>
> Poste doch mal deinen Code


Hi Herbert,

Ich habe versucht die wichtigen Codestellen zu extrahieren:

defines:
1
#define PORT_A_PIN_OUT      GPIO_Pin_0
2
#define PORT_B_PIN_OUT      GPIO_Pin_0 | GPIO_Pin_14
3
#define PORT_D_PIN_OUT      GPIO_Pin_2
4
#define PORT_C_PIN_IN       GPIO_Pin_0

GPIO Initialisierung:
1
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOD, ENABLE);
2
3
GPIO_InitStructure.GPIO_Pin = PORT_A_PIN_OUT;
4
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
5
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
6
GPIO_Init(GPIOA, &GPIO_InitStructure);
7
8
GPIO_InitStructure.GPIO_Pin = PORT_B_PIN_OUT;
9
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
10
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
11
GPIO_Init(GPIOB, &GPIO_InitStructure);
12
13
GPIO_InitStructure.GPIO_Pin = PORT_D_PIN_OUT;
14
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
15
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
16
GPIO_Init(GPIOD, &GPIO_InitStructure);
17
18
GPIO_InitStructure.GPIO_Pin = PORT_C_PIN_IN;
19
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
20
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
21
GPIO_Init(GPIOC, &GPIO_InitStructure);


Main:
1
main(void)
2
{
3
  ...Initialisierung (timer, GPIOs systick, usw)...
4
5
  GPIO_SetBits(GPIOC, GPIO_Pin_2);
6
7
  while(1)
8
  {
9
    GPIO_SetBits(GPIOD, GPIO_Pin_2);
10
11
    ... das eigentliche Programm ~20ms-2sek mit Timeout value (globale volatile Variable)
12
13
    GPIO_ResetBits(GPIOD, GPIO_Pin_2);
14
  }
15
16
}

Jede 1 ms:
1
void SysTick_Handler(void)
2
{
3
  ...Timeout value dekrementieren..
4
}

von Christoph R. (christoph_r463)


Lesenswert?

Christopher B. schrieb:
> Offensichtlich hast du einen Debugger angeschlossen. Kannst du nicht
> einfach anhalten wenn er sich aufhaengt?

Hi Christopher,

ja, hätte ich tun können... irgendwie vergessen :D ... danke für den 
Tipp,

Somit bin ich zumindest schonmal soweit, dass ich weiß, wo es hängt:

In einer while-Schleife in meinem Programm:
1
...
2
    /* wait for start */
3
    while(    (1 == GPIO_READBIT(GPIOC->IDR, GPIO_Pin_0)) 
4
            && (true == bIsRunning)); // wird aus dem Timeout value abgeleitet (siehe code Schnipsel im vorherigen Post)
5
...

Er kommt niemals aus dieser while-Schleife heraus, da die Timeout 
Variable im Systick dekrementiert wird, der aber hängt und nicht mehr 
läuft.

Was kann wohl dazu führen, dass der PD2 meinen Systick stoppt?

Danke und Grüße
Chris

von aSma>> (Gast)


Lesenswert?

Servus,
ich muss bei deinen Programm ein paar Anmerkungen machen. Du schreibst 
defines für deine Pins nutzt die aber nicht im Programm. Das ist nicht 
so schlau.
1
#define PORT_A_PIN_OUT          GPIO_Pin_0
2
  #define PORT_B_PIN_0_OUT        GPIO_Pin_0
3
  #define PORT_B_PIN_14_OUT       GPIO_Pin_14
4
#define PORT_B_PIN_OUT          PORT_B_PIN_0_OUT | PORT_B_PIN_14_OUT
5
#define PORT_D_PIN_OUT          GPIO_Pin_2
6
#define PORT_C_PIN_IN           GPIO_Pin_0
7
8
//weiterhin kann man folgendes define erstellen:
9
#define    SET_GPIOC_PIN2         GPIO_SetBits(GPIOC, GPIO_Pin_2)
10
#define  RESET_GPIOC_PIN2         GPIO_ResetBits(GPIOC, GPIO_Pin_2)
11
...
12
13
//oder
14
#define  SET_GPIOC_PIN(Pin)     GPIOC->BSRR = Pin
15
#define  RESET_GPIOC_PIN(Pin)   GPIOC->BRR  = Pin
16
...
17
18
//oder
19
#define SET_PIN(GPIOx, Pin)       GPIOx->BSRR = Pin
20
#define RESET_PIN(GPIOx, Pin)     GPIOx->BRR  = Pin

weiterhin, diese Funktion kenne ich aus SPL nicht:
1
GPIO_READBIT(GPIOC->IDR, GPIO_Pin_0)
sondern
1
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

Von deinen Codeschnipsel wird keiner schlau. Schau dir doch einfach die 
Variablen im Debbugmodus an. Es gibt nur zwei Variablen warum du in 
dieser Schleife verhaarst, aber unendlich viele für den 
HardFault_Handler() Fehler.

mfg

von Christoph R. (christoph_r463)


Lesenswert?

aSma>> schrieb:
> Servus,
> ich muss bei deinen Programm ein paar Anmerkungen machen. Du schreibst
> defines für deine Pins nutzt die aber nicht im Programm. Das ist nicht
> so schlau.
>
>
1
> #define PORT_A_PIN_OUT          GPIO_Pin_0
2
>   #define PORT_B_PIN_0_OUT        GPIO_Pin_0
3
>   #define PORT_B_PIN_14_OUT       GPIO_Pin_14
4
> #define PORT_B_PIN_OUT          PORT_B_PIN_0_OUT | PORT_B_PIN_14_OUT
5
> #define PORT_D_PIN_OUT          GPIO_Pin_2
6
> #define PORT_C_PIN_IN           GPIO_Pin_0
7
> 
8
> //weiterhin kann man folgendes define erstellen:
9
> #define    SET_GPIOC_PIN2         GPIO_SetBits(GPIOC, GPIO_Pin_2)
10
> #define  RESET_GPIOC_PIN2         GPIO_ResetBits(GPIOC, GPIO_Pin_2)
11
> ...
12
> 
13
> //oder
14
> #define  SET_GPIOC_PIN(Pin)     GPIOC->BSRR = Pin
15
> #define  RESET_GPIOC_PIN(Pin)   GPIOC->BRR  = Pin
16
> ...
17
> 
18
> //oder
19
> #define SET_PIN(GPIOx, Pin)       GPIOx->BSRR = Pin
20
> #define RESET_PIN(GPIOx, Pin)     GPIOx->BRR  = Pin
21
>


Hi aSma

keine Sorge, ich nutze alle GPIOs die ich initialisiere. Mein gesamter 
Code wäre einfach zu lang, um hier alles zu posten (irgendwas ~1000 
codezeilen)

In meinem Code nutze ich GPIO_SetBits/GPIO_ResetBits und GPIOx->BSRR/BRR 
nur für GPIOs die ich häufig nutze. Das Verhalten ist bei beiden 
identisch.


> weiterhin, diese Funktion kenne ich aus SPL nicht:
>
1
> GPIO_READBIT(GPIOC->IDR, GPIO_Pin_0)
2
>
> sondern
>
1
> uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
2
>
>

oh ja, das ist mein Macro:
1
#define GPIO_READBIT(reg, pin)   (((reg & pin) != Bit_RESET) ? (Bit_SET) : (Bit_RESET))

> Von deinen Codeschnipsel wird keiner schlau. Schau dir doch einfach die
> Variablen im Debbugmodus an. Es gibt nur zwei Variablen warum du in
> dieser Schleife verhaarst, aber unendlich viele für den
> HardFault_Handler() Fehler.

Habe mir alle Variablen angeschaut und sie passen auch, - lediglich der 
systick läuft nimmer.

Grüße
Chris

von Christopher B. (chrimbo) Benutzerseite


Lesenswert?

Dann kannst du ja auch in den Peripherie Registern nachschauen, ob der 
Systick noch zählt?! (Adresse 0xE000E018)

von Christoph R. (christoph_r463)


Lesenswert?

Christopher B. schrieb:
> Dann kannst du ja auch in den Peripherie Registern nachschauen, ob der
> Systick noch zählt?! (Adresse 0xE000E018)

Hallo Christopher,

Ich nutze die CooCox IDE (basiert auf Eclipse) und habe da auf die 
Schnelle nicht gefunden, wo man in den Speicher schauen kann. Also habe 
ich eine kleine Funktion hinzugefügt, die mir den systick liefert... 
usw... lange Rede kurzer Sinn: sobald ich nur den Code (siehe unten) bei 
mir in der Datei über der Fehlerhaften Funktion einfüge (also ohne ihn 
auszuführen), geht alles ohne zu stoppen. Ich denke also, dass ich es 
irgendwie hinbekommen habe, dass mir irgendwo der Speicher zerschrieben 
wird oder ähnlich doofes.
1
#define SYSTICKS_REG 0xE000E018
2
3
uint32_t *get_systicks (void)
4
{
5
    return (uint32_t *) SYSTICKS_REG;
6
}

Danke und Grüße
Chris

von aSma>> (Gast)


Lesenswert?

Christoph R. schrieb:
> void SysTick_Handler(void)
> {
>   ...Timeout value dekrementieren..
> }

Das hier hört sich nach einen Überlauf an. Es ist besser eine Variable 
laufen zu lassen und mit Modulo zu arbeiten.

Du musst deinen Debugger besser kennen lernen. Beim CooCox im Reiter 
!View kannst du Peripharals anmachen. Dort kannst du alle möglichen 
Register sehen.

Wie groß ist dein Programmsize?

mfg

von Christoph R. (christoph_r463)


Lesenswert?

aSma>> schrieb:
> Christoph R. schrieb:
>> void SysTick_Handler(void)
>> {
>>   ...Timeout value dekrementieren..
>> }
>
> Das hier hört sich nach einen Überlauf an. Es ist besser eine Variable
> laufen zu lassen und mit Modulo zu arbeiten.
>
> Du musst deinen Debugger besser kennen lernen. Beim CooCox im Reiter
> !View kannst du Peripharals anmachen. Dort kannst du alle möglichen
> Register sehen.
>
> Wie groß ist dein Programmsize?
>
> mfg

Hi aSma,

Das mit dem Überlauf sollte nicht passieren, da ich sowas "detektiere"
1
  if(0 < dwRcvTimer)
2
  {
3
    if(1 == dwRcvTimer)
4
    {
5
      bIsRunning = false;
6
    }
7
    dwRcvTimer--;
8
  }

ah, das mit den Peripherals ist ein guter Hinweis, danke!

Mein Programm:
1
Program Size:
2
      text     data      bss      dec      hex  filename
3
     20676     1120      488    22284     570c  myproj.elf

Grüße
Chris

von PG-For (Gast)


Lesenswert?

Übrigens:

> (habe auch mal den TIM3_IRQHandler mit
>Breakpoint versehen, - ohne Resultat).

Das ist kein Beweis, dass der Timer nicht in Benutzung ist. Er muss ja 
nicht notwendigerweise einen Interrupt auslösen.

Kannst Du nicht den Sourcecode durchsuchen, oder disassamblieren, 
oder...)?

von Christoph R. (christoph_r463)


Lesenswert?

PG-For schrieb:
> Übrigens:
>
>> (habe auch mal den TIM3_IRQHandler mit
>>Breakpoint versehen, - ohne Resultat).
>
> Das ist kein Beweis, dass der Timer nicht in Benutzung ist. Er muss ja
> nicht notwendigerweise einen Interrupt auslösen.
>
> Kannst Du nicht den Sourcecode durchsuchen, oder disassamblieren,
> oder...)?

Hi PG-For,

disassemblieren habe ich auch schon gemacht... aber da schaue ich wie 
ein Schwein in Uhrwerk.
Beim reinen Sourcecode des Programms bin ich recht sicher, dass der TIM3 
nicht genutzt wird... allerdings weiß ich nicht, was die Cocoox 
stm32-libraries so tun, - könnte schon sein, dass die irgendwo etwas 
seltsam initialisieren.

Grüße
Chris

von Martin Beuttenmüller (Gast)


Lesenswert?

Guten Abend,

habe den Thread gerade erst entdeckt - daher die Verzögerung.

Im ersten Code(-Schnipsel) schaltest Du den Takt für
GPIO_A, GPIO_B und GPIO_D ein. Das sind die Ausgänge.

GPIO_C - Dein Eingang, den Du lesen willst - hast Du
nicht mit Takt versorgt (ich konnte in Deinem Code nix finden).

---

Ich vermute, ohne Takt veweigert Dein Eingangspin die
Zusammenarbeit. Du schriebst, es hängt beim lesen ...

Viel Erfolg
Martin

von Christoph R. (christoph_r463)


Lesenswert?

Hallo Zusammen,

es war am Ende gar nicht der Code, sondern der fehlende Anschluss der 
Versorgungs- und Massepins der IO-Ports (also Vss und so). Die STM32 
library für Eagle hat scheinbar beim STM32f103 RBT6 einen kleinen 
Fehler, - die Pins werden irgendwie nicht automatisch geroutet (wie zB 
bei allen anderen STM32ern).

Danke euch Allen für die Hilfe und das Mitdenken!
Grüße
Chris

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.