|
STM32 ADC, Как сэмплировать два канала? |
|
|
|
 |
Ответов
(1 - 13)
|
Mar 1 2012, 14:27
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (uriy @ Mar 1 2012, 15:30)  Где-то встречал упоминание что можно настроить DMA на работу с несколькими каналами АЦП. При этом определяется несколько буферов по количеству опрашиваемых каналов. Дальше АЦП (или DMA) как-то сам складывает семплы в свой буфер и генерит прерывание по заполнению буфера. Нет, буфер один, общий. И АЦП складывает в него данные по очереди от первого, второго и т.д. каналов. Готового кода у меня нет - я использую один канал, по его мотивам для двух каналов должно быть что-то такое: CODE extern "C" void DMA1_Channel1_IRQHandler();
class adc {
public: typedef uint8_t sample_t[2]; static size_t const ADC_BUFFER_SIZE = 128; sample_t const * result() { Ready.wait(); return Ready; } private: void dma_handler(); friend void DMA1_Channel1_IRQHandler(); private: typedef sample_t buffer_t[ADC_BUFFER_SIZE]; buffer_t Buffer[2]; // twice the buffer size, to get DMA "half ready" int in the middle OS::message<sample_t *> Ready; }
adc::adc() { // --------- ADC setup ----------- ADC1->CR1 = 0 | 15 * ADC_CR1_AWDCH_0 // Analog watchdog channel, unused channel | 0 * ADC_CR1_EOCIE // EOC interrupt disabled | 0 * ADC_CR1_AWDIE // Analog Watchdog interrupt disabled | 0 * ADC_CR1_JEOCIE // Injected channels interrupt disabled | 1 * ADC_CR1_SCAN // Scan mode, enabled | 1 * ADC_CR1_AWDSGL // watchdog on a single (AWDCH) channel in scan mode | 0 * ADC_CR1_JAUTO // Automatic injected group conversion | 1 * ADC_CR1_DISCEN // Discontinuous mode on regular channels, enabled. One pulse=all conversions | 0 * ADC_CR1_JDISCEN // Discontinuous mode on injected channels | 1 * ADC_CR1_DISCNUM_0 // Discontinuous mode channel count = 2 | 0 * ADC_CR1_JAWDEN // Analog watchdog disabled on injected channels | 0 * ADC_CR1_AWDEN // Analog watchdog disabled on regular channels ; // calibrate ADC ADC1->CR2 = 0 | 1 * ADC_CR2_ADON // A/D Converter ON | 0 * ADC_CR2_CONT // Continuous Conversion disabled | 1 * ADC_CR2_CAL // A/D Calibration | 0 * ADC_CR2_RSTCAL // Reset Calibration | 0 * ADC_CR2_DMA // Direct Memory access mode | 0 * ADC_CR2_ALIGN // Data Alignment: right | 0 * ADC_CR2_JEXTSEL_0 // External event for injected group: TIM2CC1 | 0 * ADC_CR2_JEXTTRIG // External Trigger Conversion mode for injected channels: disabled | 0 * ADC_CR2_EXTSEL_0 // External Event for regular group: TIM2CC2 | 0 * ADC_CR2_EXTTRIG // External Trigger Conversion mode for regular channels: enabled | 0 * ADC_CR2_JSWSTART // Start Conversion of injected channels | 0 * ADC_CR2_SWSTART // Start Conversion of regular channels | 0 * ADC_CR2_TSVREFE // Temperature Sensor and VREFINT disabled ; /* default values ADC1->SMPR1 = 0 | 0 * ADC_SMPR1_SMP10_0 // Channel 10 Sample time - 1.5 ticks | 0 * ADC_SMPR1_SMP11_0 // Channel 11 Sample time - 1.5 ticks | 0 * ADC_SMPR1_SMP12_0 // Channel 12 Sample time - 1.5 ticks | 0 * ADC_SMPR1_SMP13_0 // Channel 13 Sample time - 1.5 ticks | 0 * ADC_SMPR1_SMP14_0 // Channel 14 Sample time - 1.5 ticks | 0 * ADC_SMPR1_SMP15_0 // Channel 15 Sample time - 1.5 ticks | 0 * ADC_SMPR1_SMP16_0 // Channel 16 Sample time - 1.5 ticks | 0 * ADC_SMPR1_SMP17_0 // Channel 17 Sample time - 1.5 ticks ; */ ADC1->SMPR2 = 0 | ADC_SAMPLE_TIME * ADC_SMPR2_SMP0_0 // Channel 0 Sample time | ADC_SAMPLE_TIME * ADC_SMPR2_SMP1_0 // Channel 1 Sample time | ADC_SAMPLE_TIME * ADC_SMPR2_SMP2_0 // Channel 2 Sample time | ADC_SAMPLE_TIME * ADC_SMPR2_SMP3_0 // Channel 3 Sample time | 0 * ADC_SMPR2_SMP4_0 // Channel 4 Sample time - 1.5 ticks | 0 * ADC_SMPR2_SMP5_0 // Channel 5 Sample time - 1.5 ticks | ADC_SAMPLE_TIME * ADC_SMPR2_SMP6_0 // Channel 6 Sample time | ADC_SAMPLE_TIME * ADC_SMPR2_SMP7_0 // Channel 7 Sample time | ADC_SAMPLE_TIME * ADC_SMPR2_SMP8_0 // Channel 8 Sample time | ADC_SAMPLE_TIME * ADC_SMPR2_SMP9_0 // Channel 9 Sample time ; /* default values ADC1->JOFR1 = 0; // Injected channel offset ADC1->JOFR2 = 0; ADC1->JOFR3 = 0; ADC1->JOFR4 = 0; ADC1->HTR = 0xFFF; ADC1->LTR = 0; */ ADC1->SQR1 = 0 | 0 * ADC_SQR1_SQ13_0 // 13th conversion in regular sequence channel: default | 0 * ADC_SQR1_SQ14_0 // 14th conversion in regular sequence channel: default | 0 * ADC_SQR1_SQ15_0 // 15th conversion in regular sequence channel: default | 0 * ADC_SQR1_SQ16_0 // 16th conversion in regular sequence channel: default | 1 * ADC_SQR1_L_0 // Regular channel sequence length: 2 ; /* default ADC1->SQR2 = 0 | 0 * ADC_SQR2_SQ12_0 // 12th conversion in regular sequence channel: default | 0 * ADC_SQR2_SQ11_0 // 11th conversion in regular sequence channel: default | 0 * ADC_SQR2_SQ10_0 // 10th conversion in regular sequence channel: default | 0 * ADC_SQR2_SQ9_0 // 9th conversion in regular sequence channel: default | 0 * ADC_SQR2_SQ8_0 // 8th conversion in regular sequence channel: default | 0 * ADC_SQR2_SQ7_0 // 7th conversion in regular sequence channel: default ; */ ADC1->SQR3 = 0 | 0 * ADC_SQR3_SQ6_0 // 6th conversion in regular sequence channel: default | 0 * ADC_SQR3_SQ5_0 // 5th conversion in regular sequence channel: default | 0 * ADC_SQR3_SQ4_0 // 4th conversion in regular sequence channel: default | 0 * ADC_SQR3_SQ3_0 // 3rd conversion in regular sequence channel: default | 8 * ADC_SQR3_SQ2_0 // 2nd conversion in regular sequence channel: ADC_IN8 | 9 * ADC_SQR3_SQ1_0 // 1st conversion in regular sequence channel: ADC_IN9 ; /* default value ADC1->JSQR = 0; */
// --------- DMA setup ----------- DMA1_Channel1->CPAR = uintptr_t(((uint8_t *)&ADC1->DR) + 1); // hi byte of left-aligned result DMA1_Channel1->CMAR = uintptr_t(Buffer[0]); DMA1_Channel1->CNDTR = sizeof(Buffer) / sizeof(Buffer[0][0]); DMA1_Channel1->CCR = 0 | 1 * DMA_CCR1_EN // Channel enable | 1 * DMA_CCR1_TCIE // Transfer complete interrupt enable | 1 * DMA_CCR1_HTIE // Half Transfer interrupt enable | 0 * DMA_CCR1_TEIE // Transfer error interrupt enable | 0 * DMA_CCR1_DIR // Data transfer direction: Peripheral->Memory | 1 * DMA_CCR1_CIRC // Circular mode | 0 * DMA_CCR1_PINC // Peripheral increment mode | 1 * DMA_CCR1_MINC // Memory increment mode | 0 * DMA_CCR1_PSIZE_0 // Peripheral size: 8 bits | 0 * DMA_CCR1_MSIZE_0 // Memory size: 8 bits | 0 * DMA_CCR1_PL_0 // Channel Priority level: lowest, conversion frequency is low enough | 0 * DMA_CCR1_MEM2MEM // Memory to memory mode disabled ;
// wait until calibration is complete while(ADC1->CR2 & ADC_CR2_CAL) ; // start conversions ADC1->CR2 = 0 | 1 * ADC_CR2_ADON // A/D Converter ON | 0 * ADC_CR2_CONT // Continuous Conversion disabled | 0 * ADC_CR2_CAL // A/D Calibration | 0 * ADC_CR2_RSTCAL // Reset Calibration | 1 * ADC_CR2_DMA // Direct Memory access enabled | 1 * ADC_CR2_ALIGN // Data Alignment: left | 3 * ADC_CR2_JEXTSEL_0 // External event for injected group: TIM2CC1 | 0 * ADC_CR2_JEXTTRIG // External Trigger Conversion mode for injected channels: disabled | 3 * ADC_CR2_EXTSEL_0 // External Event for regular group: TIM2CC2 | 1 * ADC_CR2_EXTTRIG // External Trigger Conversion mode for regular channels: enabled | 0 * ADC_CR2_JSWSTART // Start Conversion of injected channels | 0 * ADC_CR2_SWSTART // Start Conversion of regular channels | 0 * ADC_CR2_TSVREFE // Temperature Sensor and VREFINT disabled ; }
INLINE void adc::dma_handler() { if(DMA1->ISR & DMA_ISR_HTIF1) { Ready = Buffer[0]; Ready.send_isr(); DMA1->IFCR = DMA_IFCR_CHTIF1; } if(DMA1->ISR & DMA_ISR_TCIF1) { Ready = Buffer[1]; Ready.send_isr(); DMA1->IFCR = DMA_IFCR_CTCIF1; } }
extern "C" void DMA1_Channel1_IRQHandler(void) { OS::TISRW ISR_wrapper; ADC.dma_handler(); }
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Mar 1 2012, 14:31
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Для таких целей я включаю режим continuous mode + auto-injection. Так можно сканировать до 5 каналов: 1 regular и 4 injected (там как раз 4 регистра ADC_JDRx). Ну а если хочется через DMA, то вот пример кода: CODE #define AVERAGING 128 #define ADC_NCHANNELS 6
static uint16_t volatile buf[AVERAGING][ADC_NCHANNELS];
void adc_init(void) { /* enable clocking of ADC1, PORT A */ RCC_APB2ENR |= 0x00000204; /* configure PA0,1,2,3,4,6 as analog inputs */ GPIOA_CRL &= 0xF0F00000; /* enable clocking of DMA1 */ REGBIT(RCC_AHBENR, 0) = 1; ADC1_CR2 = 0; /* turn ADC off */ timer_delay(2); /* wait at least 2 ADC clock cycles before calibration */ ADC1_CR1 = (1 << 8); /* enable scan mode */ ADC1_CR2 = (1 << 23) /* enable Vrefint */ | (1 << 8) /* enable DMA mode */ | (1 << 1) /* enable continuous conversion mode */ | (1 << 0);/* switch ADC on */ ADC1_SMPR2 = 0x3FFFFFFF; /* sample time 239.5 cycles for ch. 0-9 */ /* conversion sequence: ch. 0, 1, 2, 3, 6, 17 */ ADC1_SQR3 = (0 << 0) | (1 << 5) | (2 << 10) | (3 << 15) | (6 << 20) | (17 << 25); ADC1_SQR1 = ((ADC_NCHANNELS - 1) << 20); /* sequence length */ REGBIT(ADC1_CR2, 2) = 1; /* start ADC calibration */ while (REGBIT(ADC1_CR2, 2) != 0) { /* wait for calibration to complete */ } DMA1_CNDTR(1) = AVERAGING * ADC_NCHANNELS; DMA1_CPAR(1) = (uint32_t)&ADC1_DR; DMA1_CMAR(1) = (uint32_t)buf; DMA1_CCR(1) = (1 << 10) /* memory size 16 bits */ | (1 << 8) /* peripheral size 16 bits */ | (1 << 7) /* memory increment mode */ | (1 << 5) /* circular mode */ | (1 << 1) /* transfer complete interrupt enable */ | (1 << 0);/* channel enable */ REGBIT(ADC1_CR2, 0) = 1; /* start ADC conversions */ }
Сообщение отредактировал IgorKossak - Mar 1 2012, 14:34
Причина редактирования: [codebox]!!!
|
|
|
|
|
Mar 1 2012, 18:23
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (scifi @ Mar 1 2012, 16:31)  Для таких целей я включаю режим continuous mode + auto-injection. Интересное решение. Таким образом можно двумя каналами DMA складывать два канала в два буфера. Спасибо, возьму на заметку. Добавлено: Ан нет, нельзя - АЦП заведен только на один канал DMA.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Mar 2 2012, 05:27
|

Гуру
     
Группа: Свой
Сообщений: 2 429
Регистрация: 30-11-05
Из: Ижевск
Пользователь №: 11 606

|
Жаль что не получится загнать в DMA. Придется делать по прерываниям. И тут похоже уже нет разницы какой режим regular или injected. Только не могу понять одну вещь. Прерывание называется: End of conversion regular group. Правильно ли я понимаю что в обработчике прерывния я должен несколько раз прочитать регистр ADC_DR? И данные будут читаться в том же порядке что были заданы в регистрах ADC_SQR. ----------------- Что-то не выходит. Делаю следующим образом: Имеется обработчик прерываний таймера - 8 КГц. В нем запускаю Код val_1 = ADC_GetConversionValue(ADC1); val_2 = ADC_GetConversionValue(ADC1); ADC_SoftwareStartConvCmd(ADC1, ENABLE); В val_1 и val_2 получаю одинаковые значения. Данные соответствуют выводу ADC_Channel_11. Они корректы, я их использую для декодирования DTMF. Инициализация ADC Код ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel = 2; ADC_Init(ADC1, &ADC_InitStructure); /* ADC1 regular channels configuration */ ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_28Cycles5); ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 2, ADC_SampleTime_28Cycles5); Многие не доверяют библиотекам ST поэтому привожу картинку из KEIL.
|
|
|
|
|
Mar 2 2012, 07:00
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (uriy @ Mar 2 2012, 07:27)  Жаль что не получится загнать в DMA. ? Получится. Просто данные будут идти первый-второй-первый-второй... QUOTE (uriy @ Mar 2 2012, 07:27)  Придется делать по прерываниям. И тут похоже уже нет разницы какой режим regular или injected. Как нету? injected раскладывает каждый канал в свой регистр, regular - все валит в один. QUOTE (uriy @ Mar 2 2012, 07:27)  Прерывание называется: End of conversion regular group. Правильно ли я понимаю что в обработчике прерывния я должен несколько раз прочитать регистр ADC_DR? И данные будут читаться в том же порядке что были заданы в регистрах ADC_SQR. Конечно нет. Там нет никакого буфера. Поэтому если вы хотите по одному импульсу запуска преобразовывать оба канала - вам надо либо использовать regular group и DMA, либо использовать injected group и прерывание.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Apr 9 2012, 14:57
|
Участник

Группа: Участник
Сообщений: 47
Регистрация: 9-03-11
Пользователь №: 63 481

|
Цитата Ну а если хочется через DMA, то вот пример кода: Я попробовал повторить это через библиотечные вызовы, получилось что один канал ацп влияет на другой. Почему так происходит? Т.е. если читать один канал, он начитывает ~49000, если два канала, то в первом ~43000 во втором ~5000. А так все почти работает) CODE void APADC_Init( void ){ ADC_InitTypeDef ADC_InitStructure; ADC_CommonInitTypeDef ADC_CommonInitStructure; DMA_InitTypeDef DMA_InitStructure; GPIO_InitTypeDef GPIO_InitStructure;
/* Enable ADC3, DMA2 and GPIO clocks ****************************************/ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOC, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);
/* DMA2 Stream0 channel2 configuration **************************************/ DMA_InitStructure.DMA_Channel = DMA_Channel_2; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC3_DR_ADDRESS; DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)ADC3ConvertedValues; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; DMA_InitStructure.DMA_BufferSize = 2; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(DMA2_Stream0, &DMA_InitStructure); DMA_Cmd(DMA2_Stream0, ENABLE);
/* Configure ADC3 Channel7 pin as analog input ******************************/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; GPIO_Init(GPIOC, &GPIO_InitStructure);
/* ADC Common Init **********************************************************/ ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; ADC_CommonInit(&ADC_CommonInitStructure);
/* ADC3 Init ****************************************************************/ ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; ADC_InitStructure.ADC_ScanConvMode = ENABLE; ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfConversion = 2; //ADC_InitStructure.ADC_NbrOfChannel = 2; ADC_Init(ADC3, &ADC_InitStructure);
/* ADC3 regular channel7 configuration *************************************/ ADC_RegularChannelConfig(ADC3, ADC_Channel_10, 1, ADC_SampleTime_3Cycles); ADC_RegularChannelConfig(ADC3, ADC_Channel_11, 2, ADC_SampleTime_3Cycles);
/* Enable DMA request after last transfer (Single-ADC mode) */ ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE);
/* Enable ADC3 DMA */ ADC_DMACmd(ADC3, ENABLE);
/* Enable ADC3 */ ADC_Cmd(ADC3, ENABLE); ADC_SoftwareStartConv(ADC3); }
Сообщение отредактировал Vladimir Prokofiev - Apr 9 2012, 14:59
|
|
|
|
|
Apr 9 2012, 17:10
|
Местный
  
Группа: Участник
Сообщений: 313
Регистрация: 2-07-11
Пользователь №: 66 023

|
Цитата(Vladimir Prokofiev @ Apr 9 2012, 18:57)  Я попробовал повторить это через библиотечные вызовы, получилось что один канал ацп влияет на другой. Почему так происходит? Т.е. если читать один канал, он начитывает ~49000, если два канала, то в первом ~43000 во втором ~5000. А так все почти работает) Нужно снизить выходное сопротивление источников сигнала, поставить конденсаторы на землю. Или увеличить время выборки АЦП. Вход АЦП - конденсатор около 6 пф, который подключается по очереди к выходам двух источников сигнала, и при этом на себе переносит заряд из одного в другой. Чем больше частота переключения каналов тем больше средний результирующий ток и больше погрешность.
|
|
|
|
|
Apr 10 2012, 07:35
|
Участник

Группа: Участник
Сообщений: 47
Регистрация: 9-03-11
Пользователь №: 63 481

|
Цитата(maksimp @ Apr 9 2012, 21:10)  Нужно снизить выходное сопротивление источников сигнала, поставить конденсаторы на землю. Или увеличить время выборки АЦП. Вход АЦП - конденсатор около 6 пф, который подключается по очереди к выходам двух источников сигнала, и при этом на себе переносит заряд из одного в другой. Чем больше частота переключения каналов тем больше средний результирующий ток и больше погрешность. Круто, спасибо, помогло!
|
|
|
|
|
Jun 12 2012, 00:21
|

Гуру
     
Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702

|
Колеги, помогите разобратся с injected каналами в STM32L151 Нужно не часто получать значения по двум каналам. Нстраиваю injected каналы как показано ниже, и жду что после выставления бита JSWSTART в регистрах JDR4 JDR3 появятся значения каналов 0 и 8. Вместо этого значение почему-то появляется в регистре JDR1 , в остальных JDR нули. Причём, Если сделать так ADC1->JSQR|=(0<<10)|(8<<15); , то в JDR1 ,будет значение канала 8. Если сделать так ADC1->JSQR|=(8<<10)|(0<<15); , то в JDR1 будет значение канала 0 То есть, работает так, как будно в цепочке только одно преобразование. Но ведь их два , указано и в битах ADC_JSQR_JL, и в битах ADC_CR1_DISCNUM . Чего я не понимаю ? Код ADC1->CR1|=ADC_CR1_JDISCEN;//включаем Discontinuous mode , что бы преобразовывалась вся цепочка за раз ADC1->CR1|=ADC_CR1_DISCNUM_0;//2 преобразования в цепочке ADC1->JSQR|=ADC_JSQR_JL_0; //2 преобразования в цепочке injectid каналов ADC1->JSQR|=(0<<10)|(8<<15); //injected каналы 1 и 8
......................
ADC->CR2|=ADC_CR2_JSWSTART; //запускаем преобразование injectid каналов
--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
|
|
|
|
|
Jun 12 2012, 09:08
|
Участник

Группа: Участник
Сообщений: 29
Регистрация: 31-08-08
Пользователь №: 39 908

|
Для STM32L151 с "injected channels" можно так: CODE void ADC_Config( void ) { GPIO_InitTypeDef GPIO_InitStructure; ADC_InitTypeDef ADC_InitStructure; ADC_CommonInitTypeDef ADC_CommonInitStruct;
//+ Enable The HSI (16Mhz) RCC_HSICmd(ENABLE); //+ Check that HSI oscillator is ready while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);
//+ Enable the GPIOB Clock RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); //+ Configure PB.0 PB.1(ADC Channel8 and 9) in analog mode GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOB, &GPIO_InitStructure);
/* ADC1 Configuration ------------------------------------------------------*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); /* ADC1 DeInit */ ADC_DeInit(ADC1);
ADC_CommonInitStruct.ADC_Prescaler = ADC_Prescaler_Div4; ADC_CommonInit(&ADC_CommonInitStruct);
/* ADC1 Configuration of channel8 and channel9 */ ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; ADC_InitStructure.ADC_ScanConvMode = ENABLE; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfConversion = 2; ADC_Init(ADC1, &ADC_InitStructure);
ADC_InjectedSequencerLengthConfig(ADC1, 2); //+ ADC1 Injected Channel Config ADC_InjectedChannelConfig(ADC1, ADC_Channel_9, 1, ADC_SampleTime_24Cycles); ADC_InjectedChannelConfig(ADC1, ADC_Channel_8, 2, ADC_SampleTime_24Cycles);
//+ Enables the ADC1 Power Down during Delay ADC_PowerDownCmd(ADC1, ADC_PowerDown_Idle_Delay, ENABLE); //+ Delay until the converted data has been read ADC_DelaySelectionConfig(ADC1, ADC_DelayLength_None);
//+ Enable ADC1 ADC_Cmd(ADC1, ENABLE);
//+ Wait until the ADC1 is ready while(ADC_GetFlagStatus(ADC1, ADC_FLAG_ADONS) == RESET); }
..................... //запускаем преобразование "injected" каналов while(ADC_GetSoftwareStartInjectedConvCmdStatus(ADC1) == SET); ADC_SoftwareStartInjectedConv(ADC1);
//+ Wait until ADC Channel 8 end of conversion while (ADC_GetFlagStatus(ADC1, ADC_FLAG_JEOC) == RESET);
adc_ch0 = ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_1); adc_ch1 = ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_2);
.....................
Сообщение отредактировал spasbyspas - Jun 12 2012, 09:19
Причина редактирования: [codebox] для длинного кода!!!
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|