Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: ищу пример использования 4 и более канала ADC в stm32f105/107
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
super_puper
нужно на стд перифе 3.5.0.
нашел пример но он видимо для другой линейки контролеров и на моем не работает у меня линейка CL а он обращается почему то к файлам другой линейки.. визуально заметил что в моих работающих примерах пишется "структуре" а тут "структ" пробовал заменить не помогло.
CODE

RCC_ADCCLKConfig(RCC_PCLK2_Div4); //Устанавливаем предделитель тактовой АЦП.
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);//Включаем тактирование.

// ADC1 configuration
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 2;
ADC_Init(ADC1, &ADC_InitStructure);

//Теперь, когда общая инициализация прошла успешно, нам надо настроить регистры инжекторных каналов, куда будут писаться наши данные. Ведь именно для этого мы их и используем.
//Устанавливаем количество каналов, которые мы собираемся считывать. Программа тогда сразу будет знать сколько вы в неё собираетесь записать каналов. Помните, что нельзя использовать одновременно более 4-х каналов, т.к. у инжекторных каналов только 4 различных регистра.

ADC_InjectedSequencerLengthConfig(ADC1, 2);

//Сопоставляем каналы регистрам. За регистры отвечает 3-й параметр. Параллельно настраиваем порты.
ADC_InjectedChannelConfig(ADC1, ADC_Channel_7, 1, ADC_SampleTime_71Cycles5);
ADC_InjectedChannelConfig(ADC1, ADC_Channel_16, 2, ADC_SampleTime_71Cycles5);
//ADC_InjectedChannelConfig(ADC1, ADC_Channel_14, 3, ADC_SampleTime_71Cycles5);

//Выключаем тригер.
ADC_ExternalTrigInjectedConvConfig(ADC1, ADC_ExternalTrigInjecConv_None);

// Enable automatic injected conversion start after regular one
ADC_AutoInjectedConvCmd(ADC1, ENABLE);//Это похоже запускает инжекторный канал вместе с регулярным. Т.е. в будущем будем запускать регулярный канал, а снимать с инжекторных. Хотя по поводу данной функции я могу ошибаться.

//Включили прерывания с инжекторного канала по окончании преобразования.
ADC_ITConfig(ADC1, ADC_IT_JEOC, ENABLE);

//Включили прерывания АЦП.
NVIC_EnableIRQ(ADC1_2_IRQn);

//Включили АЦП
ADC_Cmd(ADC1, ENABLE);
/*Теперь надо сделать калибровку. В этом я тоже не разбирался. Так что тут приведена стандартная процедура.*/
// Enable ADC1 reset calibration register
ADC_ResetCalibration(ADC1);
// Check the end of ADC1 reset calibration register
while(ADC_GetResetCalibrationStatus(ADC1));

// Start ADC1 calibration
ADC_StartCalibration(ADC1);

// Check the end of ADC1 calibration
while(ADC_GetCalibrationStatus(ADC1));

//На этом заканчивается инициализация.

//Для запуска АЦП пишем:
ADC_SoftwareStartConvCmd(ADC1, ENABLE);

}

//Для чтения полученных данных:
//void ADC1_2_IRQHandler(void)//ADC interrupt
//{
//ADC1->SR&=~ADC_SR_JEOC;
//DataConvX = ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_1);
//DataConvY = ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_2);
//DataConvZ = ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_3);
//ADC_Data_TX = EN;
//}


и вот ещё классный пример!! только не на структурах(
http://mycontroller.ru/stm32-adc-primeryi-...annyie-kanalyi/
kan35
Кусок инициализации. Данные ловишь в прерывании DMA, обработчики тут не приведены. Включение тактирования и глобальные переменные так же за пределами этого примера.
CODE

// инициализация линий ввода-вывода
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;

GPIO_InitStructure.GPIO_Pin = PIN_ACC_VOLT; GPIO_Init(PORT_ACC_VOLT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = PIN_POWER_VOLT; GPIO_Init(PORT_POWER_VOLT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = PIN_ACC_CURRENT; GPIO_Init(PORT_ACC_CURRENT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = PIN_POWER_CURRENT; GPIO_Init(PORT_POWER_CURRENT, &GPIO_InitStructure);
//GPIO_InitStructure.GPIO_Pin = PIN_MODEM_ANALOG_IN; GPIO_Init(PORT_MODEM_ANALOG_IN, &GPIO_InitStructure);

// DMA1 channel1 configuration ----------------------------------------------
DMA_DeInit(DMA1_Channel1);
DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
DMA_InitStructure.DMA_MemoryBaseAddr = (unsigned long)dmaarray;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = sizeof(dmaarray)/sizeof(*dmaarray);
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_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);

DMA_ITConfig(DMA1_Channel1, DMA_IT_TC | DMA_IT_HT, ENABLE);

DMA_Cmd(DMA1_Channel1, ENABLE);

// ADC SETUP-----------------------------------------------------------------
ADC_Cmd(ADC1, DISABLE);

ADC_DeInit(ADC1);
// ADCx Configuration (ADC1CLK = 14 MHz) -----------------------------------
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 5;
ADC_Init(ADC1, &ADC_InitStructure);

// Enable ADCx
ADC_Cmd(ADC1, ENABLE);

ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1) == SET);
ADC_StartCalibration(ADC1);
while (ADC_GetCalibrationStatus(ADC1) == SET);

// термоканал
ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 1, ADC_SampleTime_239Cycles5);

ADC_RegularChannelConfig(ADC1, CH_ACC_CURREN, 2, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1, CH_ACC_VOLT, 3, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1, CH_POWER_CURREN, 4, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1, CH_POWER_VOLT, 5, ADC_SampleTime_239Cycles5);

ADC_DMACmd(ADC1, ENABLE);
ADC_SoftwareStartConvCmd(ADC1, ENABLE);

// датчик температуры включили
ADC_TempSensorVrefintCmd(ENABLE);

// Configure and enable ADC interrupt
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 15;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
super_puper
вот как я сделал без прерываний удобно, работает норм, заметил что датчик температуру показывает правильно только при этом значении "циклосов" при других ахинею показывает.
CODE
//VVVVVVVVVVVVVVVV ADC VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
//vvvvvvvvv работа до 4х АЦП1 одновременно vvvvvvv
void up_to_4_chanel_ADC1_Configuration(void){
RCC_ADCCLKConfig(RCC_PCLK2_Div8);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE );

// Конфигурация АЦП1
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = ENABLE; //We will convert single channel only
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//we will convert many times
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //select no external triggering
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //right 12-bit data alignment in ADC data register
ADC_InitStructure.ADC_NbrOfChannel = 2;//single channel conversion
ADC_Init(ADC1, &ADC_InitStructure);//load structure values to control and status registers

//wake up temperature sensor
//ADC_TempSensorVrefintCmd(ENABLE);

ADC_InjectedSequencerLengthConfig(ADC1, 2);

//ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 1, ADC_SampleTime_13Cycles5);
//ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 2, ADC_SampleTime_13Cycles5);
ADC_InjectedChannelConfig(ADC1, ADC_Channel_16, 1, ADC_SampleTime_13Cycles5);
ADC_InjectedChannelConfig(ADC1, ADC_Channel_7, 2, ADC_SampleTime_13Cycles5);

/* ADC1 injected external trigger configuration */
ADC_ExternalTrigInjectedConvConfig(ADC1, ADC_ExternalTrigInjecConv_None);

/* Enable automatic injected conversion start after regular one */
ADC_AutoInjectedConvCmd(ADC1, ENABLE);

// Разрешаем АЦП1
ADC_Cmd(ADC1, ENABLE);

// Сбрасываем калибровку АЦП1
ADC_ResetCalibration(ADC1);
// Ждём окончания процедуры сброса калибровки АЦП1
while(ADC_GetResetCalibrationStatus(ADC1));

// Калибруем АЦП1
ADC_StartCalibration(ADC1);
// Ждём окончания калибровки
while(ADC_GetCalibrationStatus(ADC1));

// Запускаем АЦП1
ADC_SoftwareStartConvCmd(ADC1, ENABLE);


}
// пример считывания:
//temper = ADC1->JDR1; //прочитать результат первого преобразования (канал 16)
//adc7 = ADC1->JDR2; //прочитать результат второго преобразования (канал 7)
//tmp = ADC1->JDR3; //прочитать результат третьего преобразования (в нашем случае канал 5)
//tmp = ADC1->JDR4; //прочитать результат четвертого преобразования (в нашем случае канал 6)

// ADC_TempSensorVrefintCmd(ENABLE); //подключить температурный сенсор с каналу 16



u32 get_ADC1_ch_N(u8 nchanel){// возвращает данные с ацп канала 1-4
u32 adc_data;
switch (nchanel)
{
case 1: adc_data = ADC1->JDR1;return adc_data;
case 2: adc_data = ADC1->JDR2;return adc_data;
case 3: adc_data = ADC1->JDR3;return adc_data;
case 4: adc_data = ADC1->JDR4;return adc_data;
}
return 0xFFFF;
}

u32 Celsius_degrees(){// переводит данные с АЦП в градусы цельсия
u32 adc_data;
u32 TemperatureC;
const uint16_t V25 = 1750;// when V25=1.41V at ref 3.3V
const uint16_t Avg_Slope = 5; //when avg_slope=4.3mV/C at ref 3.3V
adc_data = ADC1->JDR1;
TemperatureC = (V25-adc_data)/Avg_Slope+25;
return TemperatureC;
}

Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.