Forum: Mikrocontroller und Digitale Elektronik STM32 mit CUBE, ADC mit mehreren Kanälen ansprechen


von Kurt H. (Firma: KHTronik) (kurtharders)


Lesenswert?

Hallo,
das Topic sagt schon, womit ich Probleme habe:
Ich habe mit dem STM32CUBE-Tool vier Analogeingänge gewählt und den Code 
erzeugt. Die Eingänge möchte ich in vier Variable einlesen. Das Ganze 
dann alle 10-100ms. Bisheriger Stand:
1
int value1, value2, value3, value4;
2
3
...
4
5
HAL_ADC_Start(&hadc);
6
value1 = HAL_ADC_GetValue(&hadc);
7
value2 = HAL_ADC_GetValue(&hadc);
8
value3 = HAL_ADC_GetValue(&hadc);
9
value4 = HAL_ADC_GetValue(&hadc);
Leider tut sich nichts. Die Zeilen werden durchlaufen, aber die 
Variablen bleiben 0.

Hat jemand eine Idee, was ich da falsch verstehe?

Grüße, Kurt

von Jim M. (turboj)


Lesenswert?

Der Fehler ist im nicht geposteten Teil des Codes - oder halt 50 cm vor 
dem Bildschirm.

von Kurt H. (Firma: KHTronik) (kurtharders)


Lesenswert?

Hallo Jim,
auch wenn ich 60cm vom Bildschirm sitze, hast Du ja recht. Mir ist klar, 
dass ich irgend etwas an der Verarbeitung des ADC noch nicht verstanden 
habe, und ich hoffe, dass mich jemand erleuchtet :-). Schon ein kleiner 
Hinweis kann oft reichen.
Grüße, Kurt

von Bernd K. (prof7bit)


Lesenswert?

Wahrscheinlich fehlt irgendwas. Schwer zu sagen was genau es ist, der 
nicht gepostete Teil des Codes ist nicht besonders gut zu erkennen.

von Kurt H. (Firma: KHTronik) (kurtharders)


Lesenswert?

Hallo Bernd,
es war noch nicht einmal der nicht gepostete Code, sondern der Code, der 
durch unvollständige Konfiguration im STM32CUBE erzeugt wurde. Ich hatte 
die Anzahl der Kanäle und das Ende der Konversion falsch eingestellt. 
Die Anzahl musste (natürlich) auf 4 stehen, und das Ende der Konversion 
ist das Ende der Sequenz. Jetzt läuft der Code schon mal ein wenig, es 
sind wohl noch die Kanäle durcheinander.
Grüße, und danke, Kurt

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Mehrere AD Kanäle mit dem STM32 gehen eigentlich nur sinnvoll mit DMA. 
Polling würde ich da gar nicht erst anfangen. Die Kiste hat nun mal nur 
ein Ergebnisregister, und sagt auch nicht, welcher Kanalwert da gerade 
drin ist. Da macht DMA wesentlich weniger Fehler, sobald sie läuft.

von DD4DA (Gast)


Lesenswert?

Dann probier's mal damit - ich lese 4 Kanäle mit DMA auf einem 
STM32F407VG (Disco)aus und schreibe sie in eine Struktur.


/**
  ************************************************************************ 
******
  * @file    ADC/ADC1_DMA/main.c
  * @author  DD4DA
  * @version V1.0
  * @date    17.06.2013
  * @brief   Main program body
  ************************************************************************ 
******
  * @attention
  * The Program demonstrate how the ADC works with DMA on a 
STM32F407Discovery
  * using ADC1. The used CMSIS Lib is version 1.0.
  * The ADC1 is configured to use Regular Groups by using DMA2,Stream0.
  * <h2><center>DD4DA</center></h2>
  ************************************************************************ 
******
  */

#include <stdio.h>
#include "stm32f4xx.h"
#include "adc1.h"


#define ADC1_DR_Address    ((uint32_t) 0x4001204C )   // ADC1 @ 
$4001:2000  + register offset $4C == $4001244C  <--  ADC1 Data Register

ADC_InitTypeDef         ADC_InitStructure;
ADC_CommonInitTypeDef   ADC_CommonInitStructure;
DMA_InitTypeDef         DMA_InitStructure;
GPIO_InitTypeDef         GPIO_InitStructure;


double Temperature,Voltage; 
// Variables for calculating Temperatur and Voltage

#define V25           0.760
#define AVG_SLOPE     25.0

#define Num_used_ADC_Channels    5 
// The number of ADC channels that will be used.
volatile uint16_t ADCBuffer[Num_used_ADC_Channels + 1] = { 0 , 0 , 0 , 0 
, 0,  0xAA };  // DMA Buffers - one halfword used by every ADC-Channel.
enum _ADC_CHAN_BUFF_ORDER_ { CH0 = 1, CH1 = 2 , TEMP = 3 , VREF = 4, 
VBAT =5 };



void Init_ADC ( void )
{
    // ############## ADC 
######################################################################## 
##################################
    // ---------- Configure PB0 and PB1 (ADC Channel1 and ADC Channel2 ) 
as analog input ------------------
    //
    // GPIOB function block clock enable

    RCC_APB2PeriphClockCmd ( RCC_APB2Periph_ADC1, ENABLE );
    RCC_AHB1PeriphClockCmd ( RCC_AHB1Periph_GPIOB, ENABLE );

    GPIO_InitStructure.GPIO_Pin         = GPIO_Pin_0 | GPIO_Pin_1;    // 
Init Pin 8 and A1
    GPIO_InitStructure.GPIO_Mode         = GPIO_Mode_AN;
    GPIO_InitStructure.GPIO_PuPd         = GPIO_PuPd_NOPULL ;
    GPIO_Init ( GPIOB, &GPIO_InitStructure );                  // Init 
GPIO-PORTA as Analog input



    // DMA2 Stream0 configuration 
------------------------------------------------------------------------ 
------------------------
    //
    // Enable DMA2 clock

    RCC_AHB1PeriphClockCmd ( RCC_AHB1Periph_DMA2, ENABLE );
    DMA_DeInit ( DMA2_Stream0 );

    DMA_InitStructure.DMA_Channel             = DMA_Channel_0;
    DMA_InitStructure.DMA_PeripheralBaseAddr   = 
(uint32_t)ADC1_DR_Address;
    DMA_InitStructure.DMA_Memory0BaseAddr     = (uint32_t)&ADCBuffer;
    DMA_InitStructure.DMA_DIR                 = 
DMA_DIR_PeripheralToMemory;
    DMA_InitStructure.DMA_BufferSize           = Num_used_ADC_Channels;
    DMA_InitStructure.DMA_PeripheralInc       = 
DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc           = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize   = 
DMA_PeripheralDataSize_HalfWord;
    DMA_InitStructure.DMA_MemoryDataSize       = 
DMA_MemoryDataSize_HalfWord;
    DMA_InitStructure.DMA_Mode                 = DMA_Mode_Circular;
    DMA_InitStructure.DMA_Priority             = DMA_Priority_High;
    DMA_InitStructure.DMA_FIFOMode             = DMA_FIFOMode_Disable;
    DMA_InitStructure.DMA_FIFOThreshold       = 
DMA_FIFOThreshold_HalfFull;
    DMA_InitStructure.DMA_MemoryBurst         = DMA_MemoryBurst_Single;
    DMA_InitStructure.DMA_PeripheralBurst     = 
DMA_PeripheralBurst_Single;

    DMA_Init ( DMA2_Stream0, &DMA_InitStructure );
    DMA_Cmd  ( DMA2_Stream0, ENABLE );


    // ------------------ ADC1 configuration 
-------------------------------------------------------
    //

    ADC_DeInit();

    ADC_CommonInitStructure.ADC_Mode               = 
ADC_Mode_Independent;
    ADC_CommonInitStructure.ADC_Prescaler         = ADC_Prescaler_Div2;
    ADC_CommonInitStructure.ADC_DMAAccessMode    = 
ADC_DMAAccessMode_Disabled;
    ADC_CommonInitStructure.ADC_TwoSamplingDelay = 
ADC_TwoSamplingDelay_20Cycles;

    ADC_CommonInit(&ADC_CommonInitStructure);

    // ########################### ADC1 Init 
#########################################

    ADC_InitStructure.ADC_Resolution               = ADC_Resolution_12b;
    ADC_InitStructure.ADC_ScanConvMode             = ENABLE;
    ADC_InitStructure.ADC_ContinuousConvMode       = ENABLE;
    ADC_InitStructure.ADC_ExternalTrigConvEdge    = 
ADC_ExternalTrigConvEdge_None;
    ADC_InitStructure.ADC_ExternalTrigConv        = 0;
    ADC_InitStructure.ADC_DataAlign               = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfConversion        = 
Num_used_ADC_Channels;

    ADC_Init(ADC1, &ADC_InitStructure);
    ADC_DMACmd ( ADC1, ENABLE );           /* Enable ADC1 DMA */

    // ######### ADC1 regular conversation mode  configuration 
####################################
    //                         ADC ,  CHANNEL,           DMA 
MemoryOrder,    SampleTime
    //
    ADC_RegularChannelConfig(ADC1, ADC_Channel_8,           CH0, 
ADC_SampleTime_3Cycles);
    ADC_RegularChannelConfig(ADC1, ADC_Channel_9,           CH1, 
ADC_SampleTime_3Cycles);
    ADC_RegularChannelConfig(ADC1, ADC_Channel_Vbat,        VBAT, 
ADC_SampleTime_3Cycles);
    ADC_RegularChannelConfig(ADC1, ADC_Channel_TempSensor, TEMP, 
ADC_SampleTime_3Cycles);
    ADC_RegularChannelConfig(ADC1, ADC_Channel_Vrefint,    VREF, 
ADC_SampleTime_3Cycles);


    ADC_VBATCmd ( ENABLE );                               // Enable VBAT 
at channel 18
    ADC_TempSensorVrefintCmd ( ENABLE );                  // Enable 
TempSensor and Vrefint at channels 16 and 17

    ADC_DMARequestAfterLastTransferCmd ( ADC1, ENABLE );  // Enable DMA 
request after last transfer (Single-ADC mode)
    ADC_Cmd ( ADC1, ENABLE );                             // Enable ADC1

    ADC_SoftwareStartConv ( ADC1 );                        // Start ADC1 
Software Conversion

    return;
}

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.