Forum: Mikrocontroller und Digitale Elektronik STM32f2 ADC + DMA


von Jam B. (jamixxl)


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
}

von Jam B. (jamixxl)


Lesenswert?

Hat vielleicht jemand einen Tipp?

grüße
Jam

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.