Обещанный пример. Настраивается сбор данных с двух каналов, внешнего, 14-го (нога C4), и внутреннего, температурного. Результаты складываются в массив adc_results[]. После настройки и запуска никаких действий не требуется, знай данные забирай:-)
CODE
#include "pin.h"
typedef Pin<'C', 4> adc_pin_14_t;
#define NUM_CHANNELS (2UL)
static uint16_t adc_results[2];
void adc_init_adc()
{
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
adc_pin_14_t pin;
pin.Mode(ANALOGINPUT); // set pin C4 as analog input
ADC1->CR1 =
ADC_CR1_SCAN ; // turn on SCAN mode
ADC1->CR2 =
ADC_CR2_CONT | // Continuous Conversion
ADC_CR2_TSVREFE | // Temperature Sensor and VREFINT Enable
ADC_CR2_DMA | // DMA mode
ADC_CR2_EXTSEL ; // External Event Select for regular group
/**
* conversion times
*/
ADC1->SMPR2 =
(0x00 << 0*3) | // channel 0
(0x00 << 1*3) | // channel 1
(0x00 << 2*3) | // channel 2
(0x00 << 3*3) | // channel 3
(0x00 << 4*3) | // channel 4
(0x00 << 5*3) | // channel 5
(0x00 << 6*3) | // channel 6
(0x00 << 7*3) | // channel 7
(0x00 << 8*3) | // channel 8
(0x00 << 9*3) ; // channel 9
ADC1->SMPR1 =
(0x00 << (10-10)*3) | // channel 10
(0x00 << (11-10)*3) | // channel 11
(0x00 << (12-10)*3) | // channel 12
(0x00 << (13-10)*3) | // channel 13
(0x02 << (14-10)*3) | // channel 14 - 13.5 cycles
(0x00 << (15-10)*3) | // channel 15
(0x0F << (16-10)*3) | // channel 16 - 239.5 cycles
(0x00 << (17-10)*3) ; // channel 17
/**
* channels sequence:
*/
ADC1->SQR3 =
14 << (0 * 5) | // pos 1 -- ch 14
16 << (1 * 5) | // pos 2 -- ch 16
0 << (2 * 5) | // pos 3
0 << (3 * 5) | // pos 4
0 << (4 * 5) | // pos 5
0 << (5 * 5) ; // pos 6
ADC1->SQR2 =
0 << (0 * 5) | // pos 7
0 << (1 * 5) | // pos 8
0 << (2 * 5) | // pos 9
0 << (3 * 5) | // pos 10
0 << (4 * 5) | // pos 11
0 << (5 * 5) ; // pos 12
ADC1->SQR1 =
0 << (0 * 5) | // pos 13
0 << (1 * 5) | // pos 14
0 << (2 * 5) | // pos 15
0 << (3 * 5) | // pos 16
(NUM_CHANNELS-1) << 20;
// enable ADC1
ADC1->CR2 |= ADC_CR2_ADON;
// reset calibration
ADC1->CR2 |= ADC_CR2_RSTCAL;
while (ADC1->CR2 & ADC_CR2_RSTCAL) ;
// perform calibration
ADC1->CR2 |= ADC_CR2_CAL;
while (ADC1->CR2 & ADC_CR2_CAL) ;
// software start ADC conversion
ADC1->CR2 |= ADC_CR2_EXTTRIG | ADC_CR2_SWSTART;
}
void adc_setup_dma()
{
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
DMA1_Channel1->CCR =
DMA_CCR1_CIRC | // Circular mode
DMA_CCR1_MINC | // Memory increment mode
DMA_CCR1_PSIZE_0 | // Peripheral size = halfword
DMA_CCR1_MSIZE_0 | // Memory size = halfword
DMA_CCR1_PL_0 ; // Channel Priority level
DMA1_Channel1->CNDTR = 2;
// Peripheral address
DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR;
// Memory address
DMA1_Channel1->CMAR = (uint32_t)&adc_results;
// enable DMA channel.
DMA1_Channel1->CCR |= DMA_CCR1_EN;
}
void adc_init()
{
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
adc_setup_dma();
adc_init_adc();
}
Если бы я знал, что такое электричество...