Forum: Mikrocontroller und Digitale Elektronik STM32f3 ADC injected Conversion


von Alex R. (edge0xc)


Lesenswert?

Moin,

ich versuche gerade den ADC auf meinem STM32f3 discovery board zum 
laufen zu bekommen. Leider klappt es nicht so ganz. Die Conversion soll 
über T1 CC4 getriggert werden. ich wollte ADC1 & 2 nutzen. es muss 
jeweils nur ein kanal umgesetzt werden. hier ist mein code, der leider 
noch nicht funktioniert. es wäre toll, wenn jemand mal einen blick drauf 
werfen könnte:
1
    RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div2);
2
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
3
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ADC12, ENABLE);
4
5
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2;
6
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
7
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
8
    GPIO_Init(GPIOA, &GPIO_InitStructure);
9
10
    ADC_InitStructure.ADC_ContinuousConvMode = ADC_ContinuousConvMode_Disable;
11
    ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
12
    ADC_InitStructure.ADC_ExternalTrigConvEvent = ADC_ExternalTrigConvEvent_0;
13
    ADC_InitStructure.ADC_ExternalTrigEventEdge = ADC_ExternalTrigEventEdge_None;
14
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
15
    ADC_InitStructure.ADC_OverrunMode = ADC_OverrunMode_Disable;
16
    ADC_InitStructure.ADC_AutoInjMode = ADC_AutoInjec_Disable;
17
    ADC_InitStructure.ADC_NbrOfRegChannel = 1;
18
19
    ADC_Init(ADC1, &ADC_InitStructure);
20
    ADC_Init(ADC2, &ADC_InitStructure);
21
22
    ADC_InjectedInitStructure.ADC_ExternalTrigInjecConvEvent = ADC_ExternalTrigInjecConvEvent_1;
23
    ADC_InjectedInitStructure.ADC_ExternalTrigInjecEventEdge = ADC_ExternalTrigInjecEventEdge_RisingEdge;
24
    ADC_InjectedInitStructure.ADC_NbrOfInjecChannel = 1;
25
    ADC_InjectedInitStructure.ADC_InjecSequence1 = ADC_InjectedChannel_2;
26
27
    ADC_InjectedInit(ADC1, &ADC_InjectedInitStructure);
28
29
    ADC_InjectedInitStructure.ADC_ExternalTrigInjecConvEvent = ADC_ExternalTrigInjecConvEvent_1;
30
    ADC_InjectedInitStructure.ADC_ExternalTrigInjecEventEdge = ADC_ExternalTrigInjecEventEdge_RisingEdge;
31
    ADC_InjectedInitStructure.ADC_NbrOfInjecChannel = 1;
32
    ADC_InjectedInitStructure.ADC_InjecSequence1 = ADC_InjectedChannel_3;
33
34
    ADC_InjectedInit(ADC2, &ADC_InjectedInitStructure);
35
36
    ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
37
    ADC_CommonInitStructure.ADC_Clock = ADC_Clock_AsynClkMode;
38
    ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
39
      ADC_CommonInitStructure.ADC_DMAMode = ADC_DMAMode_OneShot;
40
    ADC_CommonInitStructure.ADC_TwoSamplingDelay = 0;
41
42
    ADC_CommonInit(ADC1, &ADC_CommonInitStructure);
43
    ADC_CommonInit(ADC2, &ADC_CommonInitStructure);
44
45
    ADC_InjectedChannelSampleTimeConfig(ADC1, ADC_InjectedChannel_2, ADC_SampleTime_1Cycles5);
46
    ADC_InjectedChannelSampleTimeConfig(ADC2, ADC_InjectedChannel_3, ADC_SampleTime_1Cycles5);
47
48
    ADC_Cmd(ADC1, ENABLE);
49
    ADC_Cmd(ADC2, ENABLE);

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Die Fehlerbeschreibung "funktioniert nicht" ist ... nicht hilfreich.


Du solltest schon beschreiben, was Du erwartest, und was stattdessen 
geschieht.

von Alex R. (edge0xc)


Lesenswert?

Hey,
da hast du wohl recht. inzwischen bin ich auch weg von der injected 
group. leider klappt es immernoch nicht, der DMA IT TC wird nur einmal 
aufgerufen und es wird auch nur der erste ADC wert übertragen, der 
zweite teil bleibt leer.
1
void ADC_DMA_Config(void){
2
3
4
    RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div2);
5
6
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ADC12, ENABLE);
7
8
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
9
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
10
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
11
12
13
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 ;
14
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
15
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
16
    GPIO_Init(GPIOA, &GPIO_InitStructure);
17
18
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 ;
19
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
20
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
21
    GPIO_Init(GPIOA, &GPIO_InitStructure);
22
23
    ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
24
    ADC_CommonInitStructure.ADC_Clock = ADC_Clock_AsynClkMode;
25
    ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
26
    ADC_CommonInitStructure.ADC_DMAMode = ADC_DMAMode_OneShot;
27
    ADC_CommonInitStructure.ADC_TwoSamplingDelay = 10;
28
29
    ADC_CommonInit(ADC1, &ADC_CommonInitStructure);
30
31
    ADC_InitStructure.ADC_ContinuousConvMode = ADC_ContinuousConvMode_Disable;
32
    ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
33
    ADC_InitStructure.ADC_ExternalTrigConvEvent = ADC_ExternalTrigConvEvent_0;
34
    ADC_InitStructure.ADC_ExternalTrigEventEdge = ADC_ExternalTrigEventEdge_None;
35
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
36
    ADC_InitStructure.ADC_OverrunMode = ADC_OverrunMode_Disable;
37
    ADC_InitStructure.ADC_AutoInjMode = ADC_AutoInjec_Disable;
38
    ADC_InitStructure.ADC_NbrOfRegChannel = 2;
39
    ADC_Init(ADC1, &ADC_InitStructure);
40
41
    /* ADC1 regular channel7 configuration */
42
    ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 1, ADC_SampleTime_7Cycles5);
43
    ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 2, ADC_SampleTime_7Cycles5);
44
45
46
    DMA_StructInit(&DMA_InitStructure);
47
    DMA_InitStructure.DMA_PeripheralBaseAddr  = (uint32_t)&(ADC1->DR);
48
    DMA_InitStructure.DMA_MemoryBaseAddr  = (uint32_t)&ADCBuffer;
49
    DMA_InitStructure.DMA_DIR  = DMA_DIR_PeripheralSRC;
50
    DMA_InitStructure.DMA_BufferSize  = 2;
51
    DMA_InitStructure.DMA_PeripheralInc  = DMA_PeripheralInc_Disable;
52
    DMA_InitStructure.DMA_MemoryInc  = DMA_MemoryInc_Enable;
53
    DMA_InitStructure.DMA_PeripheralDataSize  = DMA_PeripheralDataSize_HalfWord;
54
    DMA_InitStructure.DMA_MemoryDataSize  = DMA_MemoryDataSize_HalfWord;
55
    DMA_InitStructure.DMA_Mode  = DMA_Mode_Normal;
56
    DMA_InitStructure.DMA_Priority  = DMA_Priority_Medium;
57
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
58
    DMA_Init(DMA1_Channel1, &DMA_InitStructure);
59
    DMA_ClearITPendingBit(DMA1_IT_TC1);
60
    DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
61
62
63
    NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
64
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
65
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
66
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
67
    NVIC_Init(&NVIC_InitStructure);
68
69
70
    ADC_DMAConfig( ADC1, ADC_DMAMode_OneShot);
71
    ADC_DMACmd(ADC1, ENABLE);
72
    ADC_Cmd(ADC1, ENABLE);
73
  }

Über
1
DMA_SetCurrDataCounter(DMA1_Channel1, 2);
2
DMA_Cmd(DMA1_Channel1, ENABLE);
3
ADC_StartConversion(ADC1);

soll das ganze über ein TImer CC ausgelöst werden.

LG Alex

von Christof K. (ckris)


Lesenswert?

Hi,

hast Du auch den Timer im Mastermodus konfiguriert?
Bei mir (STM32f4) sieht das für das Update-Event als Trigger mit 
HAL-Treibern folgendermaßen aus:
1
sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
2
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;

Dein ADC scheint nicht im Triggermodus konfiguriert zu sein. Bei mir 
wäre das:
1
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
2
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T2_TRGO;

Es müssen zudem kontinuierlich DMA-Requests generiert werden, sonst wird 
eben nur einmalig ein Wert übertragen (nicht verwechseln mit 
ContinuousConvMode):
1
hadc1.Init.DMAContinuousRequests = ENABLE;

Hoffe es hilft weiter!

Gruß
Christof

von Alex R. (edge0xc)


Lesenswert?

Hey,

ich mache das im moment noch per hand, also im TIM1IRQ starte ich die 
conversion.

LG Alex

von Christof K. (ckris)


Lesenswert?

Ok. Dennoch produziert dein ADC keine kontinuierlichen Requests. Beim f3 
wird's etwas anders als bei meinem f4 gemacht:

> DMA one shot mode (DMACFG=0)
> In this mode, the ADC generates a DMA transfer request each time a new
> conversion data is available and stops generating DMA requests once
> the DMA has reached the last DMA transfer (when DMA_EOT interrupt occurs
> - refer to DMA paragraph) even if a conversion has been started again.

Also musst Du den DMA circular mode (DMACFG=1) benutzen, damit nach 
jeder Wandlungsfolge ein Request ausgelöst wird.

von Alex R. (edge0xc)


Lesenswert?

Hey,
ich habe auf circular umgestellt, dann wird der DMA_IT_TC auch immer 
aufgerufen, allerdings passen die werte im ADC überhauptnicht, bzw das 
buffer wird nicht vollständig beschrieben.

LG Alex

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.