uriy 5 1 марта, 2012 Опубликовано 1 марта, 2012 · Жалоба Не могу понять как получать данные с двух каналов АЦП. Интересует ADC1. Регистр данных всего лишь один, хочу использовать regular режим. С одним каналом сейчас все работает, снимаю данные по таймеру. Где-то встречал упоминание что можно настроить DMA на работу с несколькими каналами АЦП. При этом определяется несколько буферов по количеству опрашиваемых каналов. Дальше АЦП (или DMA) как-то сам складывает семплы в свой буфер и генерит прерывание по заполнению буфера. Такой вариант был бы для меня идеальным. Может быть есть у кого примеры кода? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 1 марта, 2012 Опубликовано 1 марта, 2012 · Жалоба Где-то встречал упоминание что можно настроить DMA на работу с несколькими каналами АЦП. При этом определяется несколько буферов по количеству опрашиваемых каналов. Дальше АЦП (или DMA) как-то сам складывает семплы в свой буфер и генерит прерывание по заполнению буфера.Нет, буфер один, общий. И АЦП складывает в него данные по очереди от первого, второго и т.д. каналов. Готового кода у меня нет - я использую один канал, по его мотивам для двух каналов должно быть что-то такое: 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(); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 1 марта, 2012 Опубликовано 1 марта, 2012 (изменено) · Жалоба Для таких целей я включаю режим continuous mode + auto-injection. Так можно сканировать до 5 каналов: 1 regular и 4 injected (там как раз 4 регистра ADC_JDRx). Ну а если хочется через DMA, то вот пример кода: #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 */ } Изменено 1 марта, 2012 пользователем IgorKossak [codebox]!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 1 марта, 2012 Опубликовано 1 марта, 2012 · Жалоба Для таких целей я включаю режим continuous mode + auto-injection.Интересное решение. Таким образом можно двумя каналами DMA складывать два канала в два буфера. Спасибо, возьму на заметку. Добавлено: Ан нет, нельзя - АЦП заведен только на один канал DMA. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
uriy 5 2 марта, 2012 Опубликовано 2 марта, 2012 · Жалоба Жаль что не получится загнать в 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. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 2 марта, 2012 Опубликовано 2 марта, 2012 · Жалоба Жаль что не получится загнать в DMA.? Получится. Просто данные будут идти первый-второй-первый-второй... Придется делать по прерываниям. И тут похоже уже нет разницы какой режим regular или injected.Как нету? injected раскладывает каждый канал в свой регистр, regular - все валит в один. Прерывание называется: End of conversion regular group. Правильно ли я понимаю что в обработчике прерывния я должен несколько раз прочитать регистр ADC_DR? И данные будут читаться в том же порядке что были заданы в регистрах ADC_SQR.Конечно нет. Там нет никакого буфера. Поэтому если вы хотите по одному импульсу запуска преобразовывать оба канала - вам надо либо использовать regular group и DMA, либо использовать injected group и прерывание. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
uriy 5 2 марта, 2012 Опубликовано 2 марта, 2012 · Жалоба Т.е. при использовании regular group нет способа складывать данные в разные буферы? В свой буфер для каждого канала. Хорошо буду добавлять injected. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vprokofiev 0 9 апреля, 2012 Опубликовано 9 апреля, 2012 (изменено) · Жалоба Ну а если хочется через DMA, то вот пример кода: Я попробовал повторить это через библиотечные вызовы, получилось что один канал ацп влияет на другой. Почему так происходит? Т.е. если читать один канал, он начитывает ~49000, если два канала, то в первом ~43000 во втором ~5000. А так все почти работает) 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); } Изменено 9 апреля, 2012 пользователем Vladimir Prokofiev Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
maksimp 0 9 апреля, 2012 Опубликовано 9 апреля, 2012 · Жалоба Я попробовал повторить это через библиотечные вызовы, получилось что один канал ацп влияет на другой. Почему так происходит? Т.е. если читать один канал, он начитывает ~49000, если два канала, то в первом ~43000 во втором ~5000. А так все почти работает) Нужно снизить выходное сопротивление источников сигнала, поставить конденсаторы на землю. Или увеличить время выборки АЦП. Вход АЦП - конденсатор около 6 пф, который подключается по очереди к выходам двух источников сигнала, и при этом на себе переносит заряд из одного в другой. Чем больше частота переключения каналов тем больше средний результирующий ток и больше погрешность. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vprokofiev 0 10 апреля, 2012 Опубликовано 10 апреля, 2012 · Жалоба Нужно снизить выходное сопротивление источников сигнала, поставить конденсаторы на землю. Или увеличить время выборки АЦП. Вход АЦП - конденсатор около 6 пф, который подключается по очереди к выходам двух источников сигнала, и при этом на себе переносит заряд из одного в другой. Чем больше частота переключения каналов тем больше средний результирующий ток и больше погрешность. Круто, спасибо, помогло! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MiklPolikov 0 8 мая, 2012 Опубликовано 8 мая, 2012 · Жалоба STM32L151. Ни как не могу понять, чем отличаются Regular и Injected каналы АЦП ? Включил канал 0 Regular , работает . Физически он соответствует ноге ADC_IN0. А на каких ногах Injected каналы ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MiklPolikov 0 12 июня, 2012 Опубликовано 12 июня, 2012 · Жалоба Колеги, помогите разобратся с 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 каналов Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
spasbyspas 0 12 июня, 2012 Опубликовано 12 июня, 2012 (изменено) · Жалоба Для STM32L151 с "injected channels" можно так: 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); ..................... Изменено 12 июня, 2012 пользователем spasbyspas [codebox] для длинного кода!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MiklPolikov 0 14 июня, 2012 Опубликовано 14 июня, 2012 · Жалоба spasbyspas , спасибо ! Заменил в своём коде ADC1->CR1|=ADC_CR1_JDISCEN; на ADC1->CR1|=ADC_CR1_SCAN; и всё заработало как я хотел ! Семплирую два injectid канала программным тригером, получаю за раз два значения в регистрах JDR1 JDR2 , и одновременно с этим regular канал работает непрерывно с запросами DMA и одно другому не мешает ! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться