STM32f2 ADC + DMA

#3806425
Lesenswert?

Hallo,
Es geht um die Verarbeitung von Analogsignalen beim STM32f2 64pin.
Pro ADC möchte ich im Dual simultan. Mode 3 Kanäle verarbeiten.
Die Analogwerte sollen dann im Scanmode über DMA ins RAM geschrieben 
werden.
Beim auslesen bekomme ich aber nicht die gewünschten Werte angezeigt.
Kann mir da jemand weiterhelfen?

Library: libopencm3

ADC1+2:
Scan-mode
Contineous-mode
Dual regular simultaneous mode (ADC1 + 2)


DMA:
DMA2 für ADC1 und ADC2
Stream0/Ch0 bzw. Stream2/Ch1
Circular mode


p.s.: Clock hab ich vorher bereits eingestellt, auch für die Ports A,C
Grüße
Jam

1
.
2
.
3
.
4
void init_a2d_1(void) {
5
  int i = 0;
6

7
  /*****  Clock_init  *****/
8
  rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_ADC1EN); /**< Enable internal clock APB2 (60MHZ) for ADC1 */
9
  rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_ADC2EN); /**< Enable internal clock APB2 (60MHZ) for ADC2 */
10
  //rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPAEN); /**< Enable internal clock AHB1 (120MHZ) for analog-input Port A */
11
  //rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPCEN); /**< Enable internal clock AHB1 (120MHZ) for analog-input Port C */
12
  rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_DMA2EN); /**< Enable internal clock AHB1 (120MHZ) for DMA2 */
13

14
  /*++++++++++++++++++++ gpio_a ++++++++++++++++++++*/
15
  /*****  Analog, no push/pull to HI or LOW  *****/
16
  gpio_mode_setup(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO5 | GPIO6 | GPIO7);  //optPower, temp1+2
17
  gpio_mode_setup(GPIOC, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO0 | GPIO4);      //stackVoltage, hum
18

19
  /***** enable DMA and config *****/
20
#ifdef DMA_ON
21
  /**
22
   * Reference manual 10.9
23
   *    DMA mode 2: on the first request ADC2 and ADC1 are transfered
24
   *    (ADC2 data take the upper half-word and ADC1 data take the lower half-word)
25
   */
26
  dma_setup();
27
  nvic_enable_irq(NVIC_DMA2_STREAM0_IRQ);
28
  nvic_set_priority(NVIC_DMA2_STREAM0_IRQ, configMAX_SYSCALL_INTERRUPT_PRIORITY);
29
  nvic_enable_irq(NVIC_DMA2_STREAM2_IRQ);
30
  nvic_set_priority(NVIC_DMA2_STREAM2_IRQ, configMAX_SYSCALL_INTERRUPT_PRIORITY);
31
#endif  // DMA_ON
32
  /********** SINGLE MODE -> ADC1 ***********/
33
  /*****  Make sure the ADC doesn't run during config  *****/
34
  adc_off(ADC1);
35
  adc_off(ADC2);
36

37
  /*****  12-bit  *****/
38
  adc_set_resolution(ADC1, ADC_CR1_RES_12BIT);
39
  adc_set_resolution(ADC2, ADC_CR1_RES_12BIT);
40

41
  /*****  Prescaler 60MHZ/By2 = 30MHZ  *****/
42
  adc_set_clk_prescale(ADC_CCR_ADCPRE_BY2);
43

44
#ifdef DMA_ON
45
  adc_enable_scan_mode(ADC1);
46
  adc_enable_scan_mode(ADC2);
47

48
//  adc_set_single_conversion_mode(ADC1);
49
//  adc_set_single_conversion_mode(ADC2);
50

51
  adc_set_continuous_conversion_mode(ADC1);
52
  adc_set_continuous_conversion_mode(ADC2);
53

54
  /***** Trigger none *****/
55
  adc_disable_external_trigger_regular(ADC1);
56
  adc_disable_external_trigger_regular(ADC2);
57

58
#else
59
  adc_set_single_conversion_mode(ADC1);
60
  adc_set_single_conversion_mode(ADC2);
61
#endif  // DMA_ON
62
  /***** result is stored right-aligned *****/
63
  adc_set_right_aligned(ADC1); //The result is right_aligned in a 32bit result-register
64
  adc_set_right_aligned(ADC2); //The result is right_aligned in a 32bit result-register
65

66
  /***** sampling_time from ADC *****/
67
  /* Fast_convertion at 3CYC by reducing the resolution, 28CYC sampletime is much more precise */
68
  //adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_112CYC);
69
  //adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_56CYC);
70
  //adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_28CYC);
71
  adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_15CYC);
72
  adc_set_sample_time_on_all_channels(ADC2, ADC_SMPR_SMP_15CYC);
73
  //adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_3CYC);
74

75
  /***** eoc interrupt *****/
76
  adc_enable_eoc_interrupt(ADC1);    //Interrupt
77
  adc_enable_eoc_interrupt(ADC2);
78

79
  uint8_t groupOfChannnels1[3];
80
  groupOfChannnels1[0] = ADC_CHANNEL6;  //ADC1
81
  groupOfChannnels1[1] = ADC_CHANNEL7;  //ADC1
82
  groupOfChannnels1[2] = ADC_CHANNEL5;  //ADC1
83

84
  /***** regular group (channel selection) *****/
85
  adc_set_regular_sequence(ADC1, 3, groupOfChannnels1);
86

87
  uint8_t groupOfChannnels2[3];
88
  groupOfChannnels2[0] = ADC_CHANNEL10;  //ADC2
89
  groupOfChannnels2[1] = ADC_CHANNEL14;  //ADC2
90
  groupOfChannnels2[2] = ADC_CHANNEL10;  //ADC2
91

92
  /***** regular group (channel selection) *****/
93
  adc_set_regular_sequence(ADC2, 3, groupOfChannnels2);
94

95
  /*****  ADC2 for DualMode - activate DualMode just before start ADC1+2 *****/
96
  /********* DUAL MODE -> ADC1 + ADC2 *********/
97
  /***** Dual mode: regular simultaneous mode *****/
98
  adc_set_multi_mode(ADC_CCR_MULTI_DUAL_REGULAR_SIMUL);
99

100
  /***** Start ADC *****/
101
  adc_power_on(ADC1);
102
  adc_power_on(ADC2);
103

104
  /***** Wait for ADC is up *****/
105
  for (i = 0; i < 800000; i++) /* Wait a bit. */
106
    __asm__("nop");
107

108
  /***** Start conversion (in simultaneous-mode only ADC1 to be triggered) *****/
109
  adc_start_conversion_regular(ADC1);
110

111
  /***** NVIC interrupt ADC *****/
112
//  nvic_enable_irq(NVIC_ADC_IRQ);
113
//  nvic_set_priority(NVIC_ADC_IRQ, configMAX_SYSCALL_INTERRUPT_PRIORITY);
114
}
115

116
/**
117
 *  DMA setup for ADC conversion
118
 *
119
 *    DMA2 -  For ADC-converter you must use the DMA2 (Reference Manual 9.3.3)
120
 *        and make sure, you are using the right streams and channels
121
 *
122
 *     ADC1: DMA2, Channel0, Stream0 and Stream4
123
 *     ADC2: DMA2, Channel1, Stream2 and Stream3
124
 *     ADC3: DMA2, Channel2, Stream0 and Stream1
125
 *
126
 */
127
void dma_setup() {
128
  /**
129
   *  DMA Stream
130
   *     - Init-procedure is shown in Reference Manual 9.3.17
131
   *
132
   *     Check:
133
   *     - Step 4. Number of data
134
   */
135
  /***************************** Stream configuration procedure **********************************/
136

137
  extern ringbufferOUTadc2[3];
138
  extern ringbufferOUTadc1[3];
139
  extern ringbufferINadc2[3];
140
  extern ringbufferINadc1[3];
141

142
  dma_stream_reset(DMA2, DMA_STREAM0);
143
  dma_stream_reset(DMA2, DMA_STREAM2);
144

145
  /***** first step, disable streams. Last step, enable stream again! *****/
146
  dma_disable_stream(DMA2, DMA_STREAM0);
147
  dma_disable_stream(DMA2, DMA_STREAM2);
148

149
  // 2. Set the peripheral port register address in the DMA_SxPAR register. The
150
  // data will be moved from/ to this address to/ from the peripheral port
151
  // after the peripheral event.
152
//  dma_set_peripheral_address(DMA2, DMA_STREAM0, (uint32_t) &DMA_SPAR(DMA_STREAM0, 3) );
153
//  dma_set_peripheral_address(DMA2, DMA_STREAM2, (uint32_t) &DMA_SPAR(DMA_STREAM2, 3) );
154
  dma_set_peripheral_address(DMA2, DMA_STREAM0, (uint32_t) ringbufferINadc1);
155
  dma_set_peripheral_address(DMA2, DMA_STREAM2, (uint32_t) ringbufferINadc2);
156

157
  // 3. Set the memory address in the DMA_SxMA0R register (and in the DMA_SxMA1R
158
  // register in the case of a double buffer mode). The data will be written
159
  // to or read from this memory after the peripheral event.
160
//  dma_set_memory_address(DMA2, DMA_STREAM0, (uint32_t) &DMA_SM0AR(DMA_STREAM0, 3) );
161
//  dma_set_memory_address(DMA2, DMA_STREAM2, (uint32_t) &DMA_SM0AR(DMA_STREAM2, 3) );
162
  dma_set_memory_address(DMA2, DMA_STREAM0, (uint32_t) &ringbufferOUTadc1);
163
  dma_set_memory_address(DMA2, DMA_STREAM2, (uint32_t) &ringbufferOUTadc2);
164

165
  // 4. Configure the total number of data items to be transferred in the
166
  // DMA_SxNDTR register. After each peripheral event or each beat of the
167
  // burst, this value is
168
  // decremented.
169
  dma_set_number_of_data(DMA2, DMA_STREAM0, 3);
170
  dma_set_number_of_data(DMA2, DMA_STREAM2, 3);
171
  // 5. Select the DMA channel (request) using CHSEL[2:0] in the DMA_SxCR
172
  // register.
173
  dma_channel_select(DMA2, DMA_STREAM0, DMA_SxCR_CHSEL_0);
174
  dma_channel_select(DMA2, DMA_STREAM2, DMA_SxCR_CHSEL_1);
175
  // 6. If the peripheral is intended to be the flow controller and if it
176
  // supports this feature, set the PFCTRL bit in the DMA_SxCR register.
177
  // Nope
178
  // 7. Configure the stream priority using the PL[1:0] bits in the DMA_SxCR
179
  // register.
180
  dma_set_priority(DMA2, DMA_STREAM0, DMA_SxCR_PL_MEDIUM);
181
  dma_set_priority(DMA2, DMA_STREAM2, DMA_SxCR_PL_MEDIUM);
182
  // 8. Configure the FIFO usage (enable or disable, threshold in transmission
183
  // and reception) Leave as default (direct mode)
184
  // 9. Configure the:
185
  // - data transfer direction,
186
  dma_set_transfer_mode(DMA2, DMA_STREAM0, DMA_SxCR_DIR_PERIPHERAL_TO_MEM);
187
  dma_set_transfer_mode(DMA2, DMA_STREAM2, DMA_SxCR_DIR_PERIPHERAL_TO_MEM);
188
  // - peripheral and memory incremented/fixed mode,
189
  dma_disable_peripheral_increment_mode(DMA2, DMA_STREAM0);
190
  dma_disable_peripheral_increment_mode(DMA2, DMA_STREAM2);
191
  dma_enable_memory_increment_mode(DMA2, DMA_STREAM0);
192
  dma_enable_memory_increment_mode(DMA2, DMA_STREAM2);
193
  // - single or burst transactions,
194
  // Single is default
195
  // - peripheral and memory data widths,
196
  dma_set_memory_size(DMA2, DMA_STREAM0, DMA_SxCR_MSIZE_32BIT);
197
  dma_set_memory_size(DMA2, DMA_STREAM2, DMA_SxCR_MSIZE_32BIT);
198
  dma_set_peripheral_size(DMA2, DMA_STREAM0, DMA_SxCR_PSIZE_16BIT);
199
  dma_set_peripheral_size(DMA2, DMA_STREAM2, DMA_SxCR_PSIZE_16BIT);
200
  // - Circular mode, DMA-controller starts from base-address when internal counter reached 0
201
  dma_enable_circular_mode(DMA2, DMA_STREAM0);
202
  dma_enable_circular_mode(DMA2, DMA_STREAM2);
203
  // - Double buffer mode
204
  // Not enabled
205
  // - interrupts after half and/or full transfer,
206
//  ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);
207
  // Not yet...
208
  // - and/or errors in the DMA_SxCR register.
209
  // Not yet...
210

211
  /***** Last step: enable streams again. Activate the stream by setting the EN bit in the DMA_SxCR register. *****/
212
  dma_enable_stream(DMA2, DMA_STREAM0);
213
  dma_enable_stream(DMA2, DMA_STREAM2);
214

215
  /***** Enable DMA for ADC1, ADC2, ADC3 *****/
216
  adc_enable_dma(ADC1);
217
  adc_enable_dma(ADC2);
218

219
  /***** Set DMA to Continue *****/
220
//  adc_set_dma_continue(ADC1);
221
//  adc_set_dma_continue(ADC2);
222

223
//    /*****  select channel for ADC1, ADC2, ADC3  *****/
224
//    dma_channel_select(DMA2, DMA_STREAM0, 0);
225
//    dma_channel_select(DMA2, DMA_STREAM2, 1);
226
}

-> Lesen
1
.
2
.
3
.
4
uint16_t ringbufferOUTadc1[3] = { 0xAAAA, 0xAAAA, 0xAAAA };
5
uint16_t ringbufferOUTadc2[3] = { 0xBBBB, 0xBBBB, 0xBBBB };
6
uint16_t ringbufferINadc1[3];
7
uint16_t ringbufferINadc2[3];
8
uint32_t raw_value, test;
9
.
10
.
11
.
12

13
/**
14
 * TSK_ReadSensor
15
 *
16
 * Read adc inputs
17
 *
18
 * @param pvParameters
19
 */
20
void TSK_ReadSensor(void *pvParameters) {
21

22
  int idx, k = 0;
23
  uint16_t valueADC1, valueADC2, valueADC3, valueADC4, valueADC5, valueADC6;
24
  
25
  for (;;) {
26
//      raw_value = adc_read_regular(ADC1);
27
//      test = raw_value;
28

29
//        while (!(adc_eoc(ADC1)))
30
//          ;
31
//      valueADC1 = raw_value;
32
//      valueADC2 = raw_value >> 16;
33

34
        /***** read analog values *****/
35
        ringbufferOUTadc1[k] = ringbufferINadc1[k];
36
        ringbufferOUTadc2[k] = ringbufferINadc2[k];
37
        k++;
38
  }
39
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren