STM32F411: uff... ADC works. Really? Really!
Was a little bit tricky. When using ADC with DMA and infitiy readings, everthing is ok. But we don't need so much readings. To read only one shot after starting the ADC, we need something more. Disabling continuous conversion and unset the DMA bit. So conversion is stopped. Else the next conversion could start at any ADC. For a restart just enable again the DMA bit, the continuous conversion and start the ADC.
This commit is contained in:
parent
767c4a6911
commit
dea9cec217
|
|
@ -12,11 +12,10 @@
|
||||||
#include "pinio.h"
|
#include "pinio.h"
|
||||||
#include "delay.h"
|
#include "delay.h"
|
||||||
#include "temp.h"
|
#include "temp.h"
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
// DMA ADC-buffer
|
// DMA ADC-buffer
|
||||||
#define OVERSAMPLE 6
|
#define OVERSAMPLE 6
|
||||||
static uint16_t BSS adc_buffer[NUM_TEMP_SENSORS * OVERSAMPLE];
|
static uint16_t BSS adc_buffer[OVERSAMPLE][NUM_TEMP_SENSORS];
|
||||||
|
|
||||||
// Private functions
|
// Private functions
|
||||||
void init_analog(void);
|
void init_analog(void);
|
||||||
|
|
@ -41,6 +40,8 @@ void analog_init() {
|
||||||
*/
|
*/
|
||||||
void init_analog() {
|
void init_analog() {
|
||||||
|
|
||||||
|
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; //Enable clock
|
||||||
|
|
||||||
#undef DEFINE_TEMP_SENSOR
|
#undef DEFINE_TEMP_SENSOR
|
||||||
/*
|
/*
|
||||||
config analog pins
|
config analog pins
|
||||||
|
|
@ -55,8 +56,6 @@ void init_analog() {
|
||||||
#include "config_wrapper.h"
|
#include "config_wrapper.h"
|
||||||
#undef DEFINE_TEMP_SENSOR
|
#undef DEFINE_TEMP_SENSOR
|
||||||
|
|
||||||
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; //Enable clock
|
|
||||||
|
|
||||||
/* Set ADC parameters */
|
/* Set ADC parameters */
|
||||||
/* Set the ADC clock prescaler */
|
/* Set the ADC clock prescaler */
|
||||||
ADC->CCR |= ADC_CCR_ADCPRE;
|
ADC->CCR |= ADC_CCR_ADCPRE;
|
||||||
|
|
@ -102,9 +101,10 @@ void init_analog() {
|
||||||
ADC1->CR2 |= ADC_CR2_SWSTART;
|
ADC1->CR2 |= ADC_CR2_SWSTART;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Init the DMA for ADC
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Init the DMA for ADC
|
||||||
|
*/
|
||||||
void init_dma() {
|
void init_dma() {
|
||||||
|
|
||||||
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN; // Enable clock
|
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN; // Enable clock
|
||||||
|
|
@ -123,18 +123,15 @@ void init_dma() {
|
||||||
DMA2_Stream4->PAR = (uint32_t)&ADC1->DR;
|
DMA2_Stream4->PAR = (uint32_t)&ADC1->DR;
|
||||||
|
|
||||||
// 3. memory address
|
// 3. memory address
|
||||||
DMA2_Stream4->M0AR = (uint32_t)&adc_buffer;
|
DMA2_Stream4->M0AR = (uint32_t)adc_buffer;
|
||||||
|
|
||||||
// 4. total number of data items
|
// 4. total number of data items
|
||||||
DMA2_Stream4->NDTR = NUM_TEMP_SENSORS * OVERSAMPLE;
|
DMA2_Stream4->NDTR = NUM_TEMP_SENSORS * OVERSAMPLE;
|
||||||
|
|
||||||
// 5. DMA channel
|
// 5. DMA channel
|
||||||
// channel 0
|
|
||||||
tmp_CR &= ~(DMA_SxCR_CHSEL);
|
tmp_CR &= ~(DMA_SxCR_CHSEL);
|
||||||
|
|
||||||
// 6.
|
|
||||||
// 7. priority
|
// 7. priority
|
||||||
// Very high
|
|
||||||
tmp_CR |= DMA_SxCR_PL;
|
tmp_CR |= DMA_SxCR_PL;
|
||||||
|
|
||||||
// 8. FIFO
|
// 8. FIFO
|
||||||
|
|
@ -150,13 +147,32 @@ void init_dma() {
|
||||||
tmp_CR |= DMA_SxCR_MSIZE_0 |
|
tmp_CR |= DMA_SxCR_MSIZE_0 |
|
||||||
DMA_SxCR_PSIZE_0 |
|
DMA_SxCR_PSIZE_0 |
|
||||||
DMA_SxCR_MINC |
|
DMA_SxCR_MINC |
|
||||||
DMA_SxCR_CIRC;
|
DMA_SxCR_CIRC |
|
||||||
|
DMA_SxCR_TCIE;
|
||||||
|
|
||||||
DMA2_Stream4->CR = tmp_CR;
|
DMA2_Stream4->CR = tmp_CR;
|
||||||
|
|
||||||
// 10. Enable DMA-Stream
|
// 10. Enable DMA-Stream
|
||||||
DMA2_Stream4->CR |= DMA_SxCR_EN;
|
DMA2_Stream4->CR |= DMA_SxCR_EN;
|
||||||
while(!(DMA2_Stream4->CR & DMA_SxCR_EN));
|
while(!(DMA2_Stream4->CR & DMA_SxCR_EN));
|
||||||
|
|
||||||
|
NVIC_SetPriority(DMA2_Stream4_IRQn,
|
||||||
|
NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 3, 3));
|
||||||
|
NVIC_EnableIRQ(DMA2_Stream4_IRQn); // Enable interrupt generally.
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
DMA2 Stream4 interrupt.
|
||||||
|
|
||||||
|
Happens every time the complete stream is written.
|
||||||
|
In that case we stop the continious conversion and clear the DMA bit.
|
||||||
|
|
||||||
|
Must have the same name as in cmsis-startup_stm32f411xe.s.
|
||||||
|
*/
|
||||||
|
void DMA2_Stream4_IRQHandler(void) {
|
||||||
|
DMA2->HIFCR = DMA_HIFCR_CTCIF4;
|
||||||
|
ADC1->CR2 &= ~(ADC_CR2_CONT | ADC_CR2_DMA);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Read analog value.
|
/** Read analog value.
|
||||||
|
|
@ -166,7 +182,6 @@ void init_dma() {
|
||||||
\return Analog reading, 10-bit right aligned.
|
\return Analog reading, 10-bit right aligned.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
uint16_t analog_read(uint8_t index) {
|
uint16_t analog_read(uint8_t index) {
|
||||||
if (NUM_TEMP_SENSORS > 0) {
|
if (NUM_TEMP_SENSORS > 0) {
|
||||||
uint16_t r = 0;
|
uint16_t r = 0;
|
||||||
|
|
@ -175,7 +190,7 @@ uint16_t analog_read(uint8_t index) {
|
||||||
uint16_t min_temp = 0xffff;
|
uint16_t min_temp = 0xffff;
|
||||||
|
|
||||||
for (uint8_t i = 0; i < OVERSAMPLE; i++) {
|
for (uint8_t i = 0; i < OVERSAMPLE; i++) {
|
||||||
temp = adc_buffer[index + NUM_TEMP_SENSORS * i];
|
temp = adc_buffer[i][index];
|
||||||
max_temp = max_temp > temp ? max_temp : temp;
|
max_temp = max_temp > temp ? max_temp : temp;
|
||||||
min_temp = min_temp < temp ? min_temp : temp;
|
min_temp = min_temp < temp ? min_temp : temp;
|
||||||
r += temp;
|
r += temp;
|
||||||
|
|
@ -186,15 +201,18 @@ uint16_t analog_read(uint8_t index) {
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// memset(adc_buffer[!(DMA2_Stream4->CR & DMA_SxCR_CT)], 0, sizeof(adc_buffer[0]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Start a new ADC conversion.
|
Start a new ADC conversion.
|
||||||
*/
|
*/
|
||||||
void start_adc() {
|
void start_adc() {
|
||||||
ADC1->CR2 &= ~(ADC_CR2_DMA);
|
/* To restart the DMA, clear (done in the TCI) and set the DMA bit.
|
||||||
ADC1->CR2 |= ADC_CR2_DMA;
|
Then enable the continious conversion and start the ADC again.
|
||||||
|
*/
|
||||||
|
ADC1->CR2 |= ADC_CR2_DMA |
|
||||||
|
ADC_CR2_CONT |
|
||||||
|
ADC_CR2_SWSTART;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* defined TEACUP_C_INCLUDE && defined __ARM_STM32F411__ */
|
#endif /* defined TEACUP_C_INCLUDE && defined __ARM_STM32F411__ */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue