Forum: Mikrocontroller und Digitale Elektronik stm32f303RE - initialisierungen verbeissen sich


von bingo (Gast)


Lesenswert?

Hi @all
Es sieht mehr aus als es ist, so bitte lasst euch nicht vom langen Code 
abschrecken.
Ich habe ein kleines Problem und zwar habe ich definiert:
1
typedef struct TIMxPIN{
2
  GPIO_TypeDef* port;
3
  uint16_t pin;
4
} TIMxPIN_t;
5
6
// ADC definitions
7
#define ADC1_Channel_IN1                        (TIMxPIN_t){GPIOC, GPIO_PIN_0}
8
#define ADC1_Channel_IN2                        (TIMxPIN_t){GPIOC, GPIO_PIN_1}
9
#define ADC1_Channel_IN3                        (TIMxPIN_t){GPIOC, GPIO_PIN_2}
10
#define ADC1_Channel_IN4                        (TIMxPIN_t){GPIOC, GPIO_PIN_3}
11
#define ADC1_Channel_IN7                        (TIMxPIN_t){GPIOA, GPIO_PIN_2}
12
#define ADC1_Channel_IN8                        (TIMxPIN_t){GPIOA, GPIO_PIN_3}
13
#define ADC1_Channel_IN9                        (TIMxPIN_t){GPIOA, GPIO_PIN_4}
14
#define ADC1_Channel_IN10                       (TIMxPIN_t){GPIOA, GPIO_PIN_5}
15
#define ADC1_Channel_IN11                       (TIMxPIN_t){GPIOA, GPIO_PIN_6}
16
#define ADC1_Channel_IN12                       (TIMxPIN_t){GPIOA, GPIO_PIN_7}
17
#define ADC1_Channel_IN16                       (TIMxPIN_t){GPIOB, GPIO_PIN_1}
18
19
// Board Button Definition
20
#define PushButton                              (TIMxPIN_t){GPIOC, GPIO_PIN_13}

dazu habe ich eine Funktion geschrieben, die mir ein Array nach dem 
Drücken des Buttons ausliest:
1
void ReadOutIntArray()
2
{
3
  if (HAL_GPIO_ReadPin(PushButton.port, PushButton.pin)==0){
4
    for (uint16_t i = 0; i <= 1027; i++)
5
    {        
6
      adcValue = dma0_buffer[i];
7
      USART_Transmit_Int(adcValue);
8
      USART_sendChar('\n');
9
      for (count = 0; count <= 50000; count++);
10
   }
11
  }   
12
}
1
   /**ADC1 GPIO Configuration  */
2
    GPIO_InitStruct.Pin = ADC1_Channel_IN1.pin;
3
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG_ADC_CONTROL;
4
    GPIO_InitStruct.Pull = GPIO_NOPULL;
5
    HAL_GPIO_Init(ADC1_Channel_IN1.port, &GPIO_InitStruct);
6
    
7
    GPIO_InitStruct.Pin = ADC1_Channel_IN2.pin;
8
    HAL_GPIO_Init(ADC1_Channel_IN2.port, &GPIO_InitStruct);
9
    
10
    GPIO_InitStruct.Pin = ADC1_Channel_IN3.pin;
11
    HAL_GPIO_Init(ADC1_Channel_IN3.port, &GPIO_InitStruct);
12
    
13
    GPIO_InitStruct.Pin = ADC1_Channel_IN4.pin;
14
    HAL_GPIO_Init(ADC1_Channel_IN4.port, &GPIO_InitStruct);
15
16
//    GPIO_InitStruct.Pin = ADC1_Channel_IN7.pin ;
17
//    HAL_GPIO_Init(ADC1_Channel_IN7.port, &GPIO_InitStruct);
18
19
    GPIO_InitStruct.Pin = ADC1_Channel_IN8.pin;
20
    HAL_GPIO_Init(ADC1_Channel_IN8.port, &GPIO_InitStruct);
21
22
    GPIO_InitStruct.Pin = ADC1_Channel_IN9.pin;
23
    HAL_GPIO_Init(ADC1_Channel_IN9.port, &GPIO_InitStruct);
24
    
25
    GPIO_InitStruct.Pin = ADC1_Channel_IN10.pin;
26
    HAL_GPIO_Init(ADC1_Channel_IN10.port, &GPIO_InitStruct);
27
28
    GPIO_InitStruct.Pin = ADC1_Channel_IN11.pin;
29
    HAL_GPIO_Init(ADC1_Channel_IN11.port, &GPIO_InitStruct);
30
31
    GPIO_InitStruct.Pin = ADC1_Channel_IN12.pin;
32
    HAL_GPIO_Init(ADC1_Channel_IN12.port, &GPIO_InitStruct);
33
34
    GPIO_InitStruct.Pin = ADC1_Channel_IN16.pin;
35
    HAL_GPIO_Init(ADC1_Channel_IN16.port, &GPIO_InitStruct);
Ich verstehe jetzt nicht, warum das Auslesen durch Drücken des Buttons 
nicht mehr funktioniert, wenn lediglich der
ADC1_Channel_IN7 aktiv ist. Wenn ich diesen im ADC_init auskommentiere, 
funktionierts wieder.
Könnte mir jemand weiterhelfen. Die Ports PA2 und PC13 haben miteinander 
auch nichts zu tun. Ich zumindest sehe keinen Fehler.

von Basic Programmer (Gast)


Lesenswert?

Wie gross ist dein dma0_buffer ?

von bingo (Gast)


Lesenswert?

Hi

zum Lösen des Problems denke ich ist das noch nützlich
1
void activateReadOutButton()
2
{
3
   GPIO_InitTypeDef GPIO_InitStruct;
4
5
  /* GPIO Ports Clock Enable */
6
  __HAL_RCC_GPIOC_CLK_ENABLE();
7
8
   /*Configure GPIO pin : B1_Pin */
9
  GPIO_InitStruct.Pin = PushButton.pin;
10
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
11
  GPIO_InitStruct.Pull = GPIO_NOPULL;
12
  HAL_GPIO_Init(PushButton.port, &GPIO_InitStruct); 
13
}

Der Buffer ist 1027 lang
1
#define DataLength                                 1027
2
uint16_t dma0_buffer[DataLength];

von Dr. Sommer (Gast)


Lesenswert?

Glaubst du nicht dass der Code für die DMA und ADC Initialisierung dafür 
relevant wäre?
Warum benutzt du kein Array für die ganzen TIMxPIN Instanzen, durch 
welches du dann einfach iterieren kannst anstatt den selben Code Zig mal 
zu kopieren?

von Basic Programmer (Gast)


Lesenswert?

bingo schrieb:
> Der Buffer ist 1027 lang
> #define DataLength    1027
> uint16_t dma0_buffer[DataLength];

Dann sollte dir hier was auffallen:

bingo schrieb:
> for (uint16_t i = 0; i <= 1027; i++)

von bingo (Gast)


Angehängte Dateien:

Lesenswert?

Dr. Sommer schrieb:
> Glaubst du nicht dass der Code für die DMA und ADC Initialisierung
> dafür
> relevant wäre?
> Warum benutzt du kein Array für die ganzen TIMxPIN Instanzen, durch
> welches du dann einfach iterieren kannst anstatt den selben Code Zig mal
> zu kopieren?

Hi Dr. Sommer
Ich dachte, dass dies nicht relevant wäre. Entschuldigen Sie mich für 
den Irrtum. Die Dateien habe ich angehängt.

Basic Programmer schrieb:
> bingo schrieb:
>> Der Buffer ist 1027 lang
>> #define DataLength    1027
>> uint16_t dma0_buffer[DataLength];
>
> Dann sollte dir hier was auffallen:
>
> bingo schrieb:
>> for (uint16_t i = 0; i <= 1027; i++)

Gleich nach deiner Frage habe ich den Fehler korrigiert und es zu i < 
1027 abgeändert. Leider kein Erfolg

von bingo (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Glaubst du nicht dass der Code für die DMA und ADC Initialisierung
> dafür
> relevant wäre?
> Warum benutzt du kein Array für die ganzen TIMxPIN Instanzen, durch
> welches du dann einfach iterieren kannst anstatt den selben Code Zig mal
> zu kopieren?

Uebrigens, ich finde deinen Ansatz eine sehr gute Idee, aber wenn ich 
bereits eine Schleife drin gehabt hätte, hätte ich wahrscheinlich nicht 
einmal erkannt, dass der Fehler am ADC Kanal IN7 liegt.

Ich optimiere den Code aber gerne, wenn dieser funktioniert.

von Dr. Sommer (Gast)


Lesenswert?

Welche deiner drei ADC-Initialisierungen ist denn jetzt relevant, 
Init_ADC1 oder Init_ADC1_Test_single oder Init_ADC1_Test_differential?
1
sConfig.Channel = ADC1_Channel_IN1.pin | ADC1_Channel_IN2.pin | ADC1_Channel_IN3.pin | ADC1_Channel_IN4.pin | ADC1_Channel_IN7.pin | ADC1_Channel_IN8.pin | ADC1_Channel_IN11.pin | ADC1_Channel_IN12.pin;

Das ist doch verkehrt. Du kannst hier einen einzelnen Channel 
übergeben, also z.B. ADC_CHANNEL_1. Das ist eine Channel -Nummer, und 
keine Pin -Nummer. Wo ist dein DMA-Interrupt wo du auf Fertigstellung 
reagierst?
1
 ADC1->CFGR &= ~ADC_CFGR_DMACFG;
Du schaltes den Continuous Mode aus, d.h. es werden alle Channels nur 
einmal konvertiert? Warum greifst du überhaupt direkt auf die 
Konfigurations-Register zu, wenn du vorher die HAL genutzt hast?
1
ADC1->SQR1 &= ~ADC_SQR1_L_0;
Du stellst 2 Channels ein, wo du doch vorher offensichtlich (aber 
falsch) versuchst 8 Channels zu nutzen? Aber du setzt dennoch
1
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
 um doch nur einen Channel zu konvertieren?
1
ADC1->CR &= ~ADC_CR_ADSTART;
Du schaltest den ADC aus aber nicht wieder an?

Deine ADC-Konfiguration ist derart vermurkst, es ist ein Wunder dass da 
überhaupt was passiert. Das hat auf jeden Fall nichts mit eventuellen 
Problemen in deinem Anfangs-Code zu tun. Vielleicht solltest du dir 
erstmal Gedanken machen was du genau machen willst, welche Abläufe dein 
Programm nimmt, und das hier genau erläutern.

von bingo (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Dr. Sommer

Dr. Sommer schrieb:
> Welche deiner drei ADC-Initialisierungen ist denn jetzt relevant,
> Init_ADC1 oder Init_ADC1_Test_single oder Init_ADC1_Test_differential?
> sConfig.Channel = ADC1_Channel_IN1.pin | ADC1_Channel_IN2.pin |
> ADC1_Channel_IN3.pin | ADC1_Channel_IN4.pin | ADC1_Channel_IN7.pin |
> ADC1_Channel_IN8.pin | ADC1_Channel_IN11.pin | ADC1_Channel_IN12.pin;
> Das ist doch verkehrt. Du kannst hier einen einzelnen Channel
> übergeben, also z.B. ADC_CHANNEL_1. Das ist eine Channel -Nummer, und
> keine Pin -Nummer. Wo ist dein DMA-Interrupt wo du auf Fertigstellung
> reagierst?

Sie haben völlig Recht. Ich habe die Änderungen vorgenommen und das File 
nochmals angehängt.

>  ADC1->CFGR &= ~ADC_CFGR_DMACFG;Du schaltes den Continuous Mode aus,
> d.h. es werden alle Channels nur
> einmal konvertiert? Warum greifst du überhaupt direkt auf die
> Konfigurations-Register zu, wenn du vorher die HAL genutzt hast?

Ich hatte etwas probiert und war mir nicht sicher warum die Bits nicht 
gesetzt wurden. Das Problem hat sich danach irgendwie selbst gelöst.
Ich habe die Zeilen auch nun entfernt.
Jedoch, um zB die Länge im SQR1 Register festzulegen, müsste ich auf 
Registerebene zurückgreifen, auch wenn ich die HAL zuvor verwendet habe. 
Dafür gibt es ja keine Funktion.

> ADC1->SQR1 &= ~ADC_SQR1_L_0;Du stellst 2 Channels ein, wo du doch vorher
> offensichtlich (aber
> falsch) versuchst 8 Channels zu nutzen? Aber du setzt
> dennochhadc1.Init.ScanConvMode = ADC_SCAN_DISABLE; um doch nur einen
> Channel zu konvertieren?
> ADC1->CR &= ~ADC_CR_ADSTART;Du schaltest den ADC aus aber nicht wieder
> an?

Ich benötige den One Shot mode. Ich konvertiere immer nur einen Wert. 
Der ADC wird getriggert, da ich diesen nur zu bestimmten Zeiten 
benötige.
Stimmt die Länge benötige ich nicht, da Scanconvmode disabled ist.
Ich habe den Code entsprechend angepasst.
Den ADC starte ich später, wenn ich ihn benötige. Dies geschieht anfangs 
im Main und später in den jeweiligen Interrupts etc.

>
> Deine ADC-Konfiguration ist derart vermurkst, es ist ein Wunder dass da
> überhaupt was passiert. Das hat auf jeden Fall nichts mit eventuellen
> Problemen in deinem Anfangs-Code zu tun. Vielleicht solltest du dir
> erstmal Gedanken machen was du genau machen willst, welche Abläufe dein
> Programm nimmt, und das hier genau erläutern.

Kurz: Der ADC wird getriggert, nach jeder einzelnen Conversion sollte 
die DMA die Daten wegschaufeln. Das funktioniert soweit.

Ich weiss schon was ich möchte, ich kann Ihnen leider nicht die ganze 
Story erklären. Ich denke, es ist einfacher, wenn Sie mir die Fragen 
direkt stellen. Ansonsten wird das hier nur eine Prosa.
Ich weiss schon, was ich tue und benötige. Die Einstellungen des ADC 
jedoch ist eine andere Sache, aber ich habe da auch wieder dazugelernt.

Obwohl ich aber die Änderungen vorgenommen habe, scheint das mit dem 
Button immer noch nicht zu funktionieren.

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.