|
STM32 АЦП. Пожалуйста помогите разобраться |
|
|
|
Dec 23 2014, 05:25
|
Группа: Участник
Сообщений: 7
Регистрация: 23-12-14
Пользователь №: 84 246

|
Я начал разбираться с АЦП на STM32F4Discovery. Вычитал, что у АЦП существуют два метода опроса: регулярные каналы и инжектированные каналы. Разницу между ними я более менее понял. Первая группа запись данных в один регистр, вторая группа результат можно записать в один из 4-х регистров. Я стараюсь писать код используя CMSIS. К порту PA1 прикрутил переменный резистор, и по изменению значения должны зажигаться диоды на PD12, 13, 14, 15 но почему-то не работает, подскажите пожалуйста что не так. Код: CODE #include "stm32f4xx.h" uint32_t LED_STATE = 0xF000; uint32_t res; int main() { RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN|RCC_AHB1ENR_GPIODEN; RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; //GPIOA->MODER |= 0x0000000C; GPIOD->MODER |= 0x55000000; GPIOD->OTYPER |= 0; GPIOD->OSPEEDR |= 0; ADC1->SMPR2 |= (ADC_SMPR2_SMP1_2 | ADC_SMPR2_SMP1_1 | ADC_SMPR2_SMP1_0); //Задаем время выборки ADC1->CR2 |= ADC_CR2_JEXTSEL; //Преобразование инжектированной группы ADC1->CR2 |= ADC_CR2_JEXTEN; //Разрешаем внешний запуск инжектированной группы ADC1->CR2 |= ADC_CR2_CONT; //Преобразования запускаются одно за другим ADC1->CR1 |= ADC_CR1_JAUTO; ADC1->JSQR |= (1<<15); //Задаем номер канала - ADC1 ADC1->CR2 |= ADC_CR2_ADON;//Теперь включаем АЦП ADC1->CR2 |= ADC_CR2_JSWSTART; //Запуск преобразований while (!(ADC1->SR & ADC_SR_JEOC)); //ждем пока первое преобразование завершится while(1) {
res = ADC1->JDR1; if (res > 1024) { GPIOD->ODR=LED_STATE; } } } Поскольку я разбираюсь в режимах преобразования, то я так же пробовал написать код и для регулярных каналов: Код: CODE #include "stm32f4xx.h" uint32_t LED_STATE = 0xF000; int main() { RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN|RCC_AHB1ENR_GPIODEN; RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; GPIOA->MODER |= 0x0000000C; GPIOD->MODER |= 0x55000000; GPIOD->OTYPER |= 0; GPIOD->OSPEEDR |= 0;
ADC1->SMPR2 |= (ADC_SMPR2_SMP1_2 | ADC_SMPR2_SMP1_1 | ADC_SMPR2_SMP1_0); ADC1->CR2 |= ADC_CR2_EXTSEL; ADC1->CR2 |= ADC_CR2_EXTEN; ADC1->CR2 |= ADC_CR2_CONT; ADC1->SQR1 |= (1<<15); //Задаем номер канала - ADC1 ADC1->CR2 |= ADC_CR2_ADON;//Теперь включаем АЦП ADC1->CR2 |= ADC_CR2_SWSTART; //Запуск преобразований while (!(ADC1->SR & ADC_SR_EOC)); //ждем пока первое преобразование завершится uint32_t res; while(1) { res = ADC1->DR; if (res > 1024) { GPIOD->ODR=LED_STATE; } } } Но он тоже не работает((( Если честно то я ковырял пример отсюда: http://blog.radiotech.kz/blog/52.htmlИ еще ну совсем нубский вопрос. Не могу понять связь между каналом АЦП и пином с которого я хочу снять сигнал. Объясните пожалуйста. Мануал читал. Из него я понял, что на некоторых пинах висит АЦП, так кажется на PA1 висит ADC1, а что с каналами? Спасибо!
Сообщение отредактировал IgorKossak - Aug 14 2015, 16:42
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
|
|
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 14)
|
Dec 23 2014, 07:07
|
Частый гость
 
Группа: Свой
Сообщений: 185
Регистрация: 14-02-06
Из: Кемерово
Пользователь №: 14 293

|
Цитата(TmYAG @ Dec 23 2014, 12:25)  Мануал читал. Из него я понял, что на некоторых пинах висит АЦП, так кажется на PA1 висит ADC1, а что с каналами? Так там же и написано, какие каналы. Например "ADC123_IN1". Канал 1 для АЦП 1,2 и 3. Или "АDC12_IN7" - канал 7 для АЦП 1 и 2.
|
|
|
|
|
Dec 23 2014, 12:15
|
Участник

Группа: Участник
Сообщений: 58
Регистрация: 9-05-13
Из: Львов, Украина
Пользователь №: 76 782

|
Цитата(TmYAG @ Dec 23 2014, 07:25)  Я начал разбираться с АЦП на STM32F4Discovery. Во первых в первой проге заремарен GPIOA->MODER |= 0x0000000C; во вторых RCC->APB2ENR |= RCC_APB2ENR_ADC1EN | RCC_APB2ENR_SYSCFGEN; надо ещё включить тактирование на SYSCFG в третьих перед каждым забором данных из АЦП его надо запускать как я написал ниже.  ADC1->CR2 |= ADC_CR2_JSWSTART; while (!(ADC1->SR & ADC_SR_JEOC)); ADC1->SR =0; // Очищаем флаг «преобразование завершено» res = ADC1->JDR1;
|
|
|
|
|
Dec 23 2014, 18:02
|
Группа: Участник
Сообщений: 7
Регистрация: 23-12-14
Пользователь №: 84 246

|
Цитата(glags @ Dec 23 2014, 12:15)  Во первых в первой проге заремарен GPIOA->MODER |= 0x0000000C; А я пытался сконфигурировать PA1 как альтернативную функцию. Цитата в третьих перед каждым забором данных из АЦП его надо запускать как я написал ниже. sm.gif
ADC1->CR2 |= ADC_CR2_JSWSTART; while (!(ADC1->SR & ADC_SR_JEOC)); ADC1->SR =0; // Очищаем флаг «преобразование завершено» res = ADC1->JDR1; Изменил код, но проблема не исчезла=(
|
|
|
|
|
Dec 23 2014, 18:46
|
Участник

Группа: Участник
Сообщений: 58
Регистрация: 9-05-13
Из: Львов, Украина
Пользователь №: 76 782

|
Цитата(TmYAG @ Dec 23 2014, 20:02)  А я пытался сконфигурировать PA1 как альтернативную функцию.
Изменил код, но проблема не исчезла=( Полностью рабочий код инициализации ЦАП: ADC1->CR2 |= ADC_CR2_CONT; //Преобразования запускаются одно за другим ADC1->CR1 |= ADC_CR1_JAUTO | ADC_CR1_SCAN; //Разрешить автопреобразование инжектированной группы и SCAN означает брать номера каналов для сканирования из JSQR. ADC1->JSQR |= (ADC_JSQR_JSQ4_0 ); //Задаем номер канала (выбран ADC1) ADC1->CR2 |= ADC_CR2_ADON;//Теперь включаем АЦП Здесь получаем данные: ADC1->CR2 |= ADC_CR2_JSWSTART; while (!(ADC1->SR & ADC_SR_JEOC)); ADC1->SR =0; // Очищаем флаг «преобразование завершено» res = ADC1->JDR1;
|
|
|
|
|
Dec 23 2014, 19:05
|
Группа: Участник
Сообщений: 7
Регистрация: 23-12-14
Пользователь №: 84 246

|
Цитата(glags @ Dec 23 2014, 19:46)  Полностью рабочий код инициализации ЦАП: ADC1->CR2 |= ADC_CR2_CONT; //Преобразования запускаются одно за другим ADC1->CR1 |= ADC_CR1_JAUTO | ADC_CR1_SCAN; //Разрешить автопреобразование инжектированной группы и SCAN означает брать номера каналов для сканирования из JSQR. ADC1->JSQR |= (ADC_JSQR_JSQ4_0 ); //Задаем номер канала (выбран ADC1) ADC1->CR2 |= ADC_CR2_ADON;//Теперь включаем АЦП
Здесь получаем данные: ADC1->CR2 |= ADC_CR2_JSWSTART; while (!(ADC1->SR & ADC_SR_JEOC)); ADC1->SR =0; // Очищаем флаг «преобразование завершено» res = ADC1->JDR1; Спасибо, большое, завтра попробую в камне. А что насчет регулярных каналов? По идее те же яйца только в профиль. Код ADC1->CR2 |= ADC_CR2_CONT; //Преобразования запускаются одно за другим ADC1->CR1 |= ADC_CR1_AUTO | ADC_CR1_SCAN; //Разрешить автопреобразование инжектированной группы и SCAN означает брать номера каналов для сканирования из JSQR. ADC1->JSQR |= (ADC_SQR_SQ4_0 ); //Задаем номер канала (выбран ADC1) ADC1->CR2 |= ADC_CR2_ADON;//Теперь включаем АЦП
Здесь получаем данные: ADC1->CR2 |= ADC_CR2_SWSTART; while (!(ADC1->SR & ADC_SR_EOC)); ADC1->SR =0; // Очищаем флаг «преобразование завершено» res = ADC1->DR; Наверно так, да? И что на счет конфигурации пина PA1? надо его на альтернативную функцию настраивать? Ведь SYSCFG мы для тактирования альтернативных функций и включали.
|
|
|
|
|
Dec 23 2014, 20:31
|
Участник

Группа: Участник
Сообщений: 58
Регистрация: 9-05-13
Из: Львов, Украина
Пользователь №: 76 782

|
Там целая наука. Дело в том что инжектированных каналов может быть максимум 4 и каждый имеет свой регистр данных, а регулярных 16 и у них один регистр данных на всех. По этому данные из них можно читать либо по прерыванию (окончание преобразования) либо DMA. Здесь если всё писать то целая статья выйдет. Дело в том что АЦП не сложный, но навороченный. Например он может вызывать прерывания при достижении определённого уровня сигнала на входе и т.д. Скажу только про один момент с инжектированными каналами. В инжектированных каналах есть одно неудобство, когда конфигуришь один канал, то в регистр ADC1->JSQR надо заполнять его как четвёртый. Это многих сбивает с толку. Да SYSCFG мы для тактирования альтернативных функций и включали. Но для конфигурации порта мы их не используем. Просто в модере включаем аналоговый режим. Альтернативные функции касаются таймеров уартсов и прочего что конфигурится в GPIOA->AFR. Здесь на всякий случай  . Просьба, если всё запашет, то отпишитесь.
Сообщение отредактировал glags - Dec 24 2014, 16:59
|
|
|
|
|
Dec 25 2014, 09:12
|
Группа: Участник
Сообщений: 7
Регистрация: 23-12-14
Пользователь №: 84 246

|
Цитата(glags @ Dec 23 2014, 20:31)  Просьба, если всё запашет, то отпишитесь. CODE #include "stm32f4xx.h" uint32_t LED_STATE = 0xF000; uint32_t res; int main() { RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN|RCC_AHB1ENR_GPIODEN; RCC->APB2ENR |= RCC_APB2ENR_ADC1EN|RCC_APB2ENR_SYSCFGEN; GPIOA->MODER |= 0x0000000C; GPIOD->MODER |= 0x55000000; GPIOD->OTYPER |= 0; GPIOD->OSPEEDR |= 0; ADC1->SMPR2 |= (ADC_SMPR2_SMP1_2 | ADC_SMPR2_SMP1_1 | ADC_SMPR2_SMP1_0); //Задаем время выборки ADC1->CR2 |= ADC_CR2_JEXTSEL; //Преобразование инжектированной группы ADC1->CR2 |= ADC_CR2_JEXTEN; //Разрешаем внешний запуск инжектированной группы ADC1->CR2 |= ADC_CR2_CONT; //Преобразования запускаются одно за другим ADC1->CR1 |= ADC_CR1_JAUTO; //ADC1->CR1 |= 0x00000020; ADC1->JSQR |= ADC_JSQR_JSQ4_0; //Задаем номер канала - ADC1 ADC1->CR2 |= ADC_CR2_ADON;//Теперь включаем АЦП while(1) { ADC1->CR2 |= ADC_CR2_JSWSTART; //Запуск преобразований while (!(ADC1->SR & ADC_SR_JEOC)); //ждем пока первое преобразование завершится ADC1->SR = 0; res = ADC1->JDR1; if (res > 1024) { GPIOD->ODR = LED_STATE; } else { GPIOD->ODR ^= LED_STATE; } } } Ну эта бредятина работает в режиме отладки. Проблема была в JSQR. С регулярными каналами пока бьюсь. Потом планирую перейти на прерывания по EOC Вот не могу понять связь между JSQR и PA1 по какому принципу я должен выставлять биты в регистре, чтобы читать именно из этого пина? Цитата(TmYAG @ Dec 25 2014, 08:37)  Ну эта бредятина работает в режиме отладки. Проблема была в JSQR. И не только) Код GPIOD->ODR ^= LED_STATE; - неправильно) У меня всегда диоды будут вкл))) В общем инжектированные каналы работают) буду ковырять регулярные и прерывания затем. Цитата(TmYAG @ Dec 25 2014, 09:03)  буду ковырять регулярные и прерывания затем. CODE #include "stm32f4xx.h" uint32_t LED_STATE = 0xF000; uint32_t res; int main() { RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN|RCC_AHB1ENR_GPIODEN; RCC->APB2ENR |= RCC_APB2ENR_ADC1EN|RCC_APB2ENR_SYSCFGEN; GPIOA->MODER |= 0x0000000C; GPIOD->MODER |= 0x55000000; GPIOD->OTYPER |= 0; GPIOD->OSPEEDR |= 0; ADC1->SMPR2 |= (ADC_SMPR2_SMP1_2 | ADC_SMPR2_SMP1_1 | ADC_SMPR2_SMP1_0); //Задаем время выборки ADC1->CR2 |= ADC_CR2_EXTSEL; //Преобразование инжектированной группы ADC1->CR2 |= ADC_CR2_EXTEN; //Разрешаем внешний запуск инжектированной группы ADC1->CR2 |= ADC_CR2_CONT; //Преобразования запускаются одно за другим ADC1->SQR3 |= ADC_SQR3_SQ1_0; //Задаем номер канала - ADC1 ADC1->CR2 |= ADC_CR2_ADON;//Теперь включаем АЦП while(1) { ADC1->CR2 |= ADC_CR2_SWSTART; //Запуск преобразований while (!(ADC1->SR & ADC_SR_EOC)); //ждем пока первое преобразование завершится ADC1->SR = 0; res = ADC1->DR; if (res > 1024) { GPIOD->ODR = LED_STATE; } else { GPIOD->BSRRH |= (1 << 15)|(1 << 14)|(1 << 13)|(1 << 12); } } } Собственно методом тыка заработали и регулярные каналы)))
Сообщение отредактировал IgorKossak - Aug 14 2015, 16:45
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!
|
|
|
|
|
Dec 25 2014, 18:28
|
Участник

Группа: Участник
Сообщений: 58
Регистрация: 9-05-13
Из: Львов, Украина
Пользователь №: 76 782

|
Цитата(TmYAG @ Dec 25 2014, 11:12)  Вот не могу понять связь между JSQR и PA1 по какому принципу я должен выставлять биты в регистре, чтобы читать именно из этого пина? Привожу таблицу зависимости между ADC_JDR1 и JSQR Кол-во каналов (JL) ADC_JDR1 ADC_JDR2 ADC_JDR3 ADC_JDR4 4.................................JSQ1........JSQ2...........JSQ3........JSQ4 3.................................JSQ2........JSQ3...........JSQ4 2.................................JSQ3........JSQ4 1.................................JSQ4 Например если один канал, то заполняем биты JSQ4 и данные будут при этом читатся из ADC1->JDR1 В регистре JSQR 4 бита для JSQ4, если их заполнить 0011 это будет третий канал ADC что соответствует РА3.
Сообщение отредактировал glags - Dec 25 2014, 19:24
|
|
|
|
|
Aug 14 2015, 13:18
|

Знающий
   
Группа: Свой
Сообщений: 604
Регистрация: 5-05-06
Из: Нижегородская обл.
Пользователь №: 16 819

|
Здравствуйте. Я только осваиваю АЦП у STM32. Поставил задачу. Имеем 2 канала IN0 и IN1 ADC1. Сделать регулярными каналами. Значения забирать из регистра данных через прерывания. Когда пробовал с одним каналом, то всё хорошо. Для интереса замерил частоту преобразования ~27 кГц. Когда стал пробовать уже два канала, то по идее частота не должна уменьшиться в 2 раза (если прерывание будет после преобразования каждого канала)? А она уже 14 кГц. Что меня наводит на мысль, что прерывание происходит после 2-х преобразований. Как надо настроить ADC для правильного прерывания? CODE RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
// ноги PA0 и PA1 по умолчанию настроены на вход
ADC_StructInit(&ADC_InitStructure); ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult; //Режим Регулярный Одновременный 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); ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE); // прерывание от окончании преобразования
ADC_Cmd(ADC1, ENABLE); // включение ADC // настройка канала ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5); ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_55Cycles5);
// калибровка АЦП ADC_ResetCalibration(ADC1); while (ADC_GetResetCalibrationStatus(ADC1)); ADC_StartCalibration(ADC1); while (ADC_GetCalibrationStatus(ADC1));
/* NVIC configuration */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);
ADC_SoftwareStartConvCmd(ADC1, ENABLE); прерывание Код void ADC1_2_IRQHandler (void) { ADC_ClearITPendingBit(ADC1, ADC_IT_EOC); switch(cnt_number_channel_ADC1++) { case 0: ADC1_IN0_Value = ADC1->DR; break; case 1: cnt_number_channel_ADC1 = 0; ADC1_IN1_Value = ADC1->DR; break; default: break; } // передаем FlagADC1 = 1; }
Сообщение отредактировал IgorKossak - Aug 14 2015, 16:46
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!
--------------------
Кризис - это не отсутствие денег, а отсутствие идей! Учитесь и никаких кризисов не будет.
|
|
|
|
|
Aug 14 2015, 13:42
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата(KARLSON @ Aug 14 2015, 16:18)  Что меня наводит на мысль, что прерывание происходит после 2-х преобразований. Как надо настроить ADC для правильного прерывания? Почитать мануал: Цитата The EOC bit is set in the ADC_SR register: • At the end of each regular group sequence if the EOCS bit is cleared to 0 • At the end of each regular channel conversion if the EOCS bit is set to 1 PS. В линейке STM32 очень много семейств с совершенно различными АЦП. Лучше указывать конкретный камень.
|
|
|
|
|
Aug 14 2015, 16:51
|

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

|
Если хотите читать несколько регулярных каналов то только по DMA. Если не хотите DMA можно использовать инжектированные каналы. Там до 4 каналов можно читать из разных регистров. Вот из моих проектов два канала по DMA. АЦП тактируется от TIM3. Прерывание по DMA по заполнению половины буферы и всего буфера. CODE void InitADC(void) { ADC_InitTypeDef ADC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; DMA_InitTypeDef DMA_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOC, &GPIO_InitStructure);
/* DMA1 channel1 configuration ----------------------------------------------*/ //DMA_DeInit(DMA1_Channel1); //DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1->DR; DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; #warning check it DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)adc_buf; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = ADC_BUF_SIZE; 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_ClearITPendingBit(DMA1_IT_HT1); DMA_ClearITPendingBit(DMA1_IT_TC1);
DMA_ITConfig(DMA1_Channel1, (DMA_IT_TC | DMA_IT_HT), ENABLE); //DMA_ITConfig(DMA1_Channel1, DMA1_IT_TC1, ENABLE); /* Enable DMA1 channel1 */ DMA_Cmd(DMA1_Channel1, ENABLE);
NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); NVIC_EnableIRQ(DMA1_Channel1_IRQn);
/* ADC1 configuration ------------------------------------------------------*/ ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = ENABLE; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T3_TRGO; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel = 2; ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channel Configuration */ ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_239Cycles5); ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_239Cycles5);
ADC_ExternalTrigConvCmd(ADC1, ENABLE);
/* Enable ADC1 DMA */ ADC_DMACmd(ADC1, ENABLE);
/* Enable ADC1 */ ADC_Cmd(ADC1, ENABLE);
/* Enable ADC1 reset calibaration register */ ADC_ResetCalibration(ADC1); /* Check the end of ADC1 reset calibration register */ while (ADC_GetResetCalibrationStatus(ADC1));
/* Start ADC1 calibaration */ ADC_StartCalibration(ADC1); /* Check the end of ADC1 calibration */ while (ADC_GetCalibrationStatus(ADC1));
}
void InitTimer3(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
/* TIM3 clock enable */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
/* Time base configuration */ TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); TIM_TimeBaseStructure.TIM_Period = 23999; /// 1 khz clock required nned to check core frequency TIM_TimeBaseStructure.TIM_Prescaler = 2; TIM_TimeBaseStructure.TIM_ClockDivision = 0x0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
/* TIM3 TRGO selection */ TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update);
/* TIM3 enable counter */ TIM_Cmd(TIM3, ENABLE); }
void DMA1_Channel1_IRQHandler(void) { portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
if (DMA_GetITStatus(DMA1_IT_HT1)) { DMA_ClearITPendingBit(DMA1_IT_HT1); xSemaphoreGiveFromISR(xSemaphoreADC_DMA_HT, &xHigherPriorityTaskWoken ); } if (DMA_GetITStatus(DMA1_IT_TC1)) { DMA_ClearITPendingBit(DMA1_IT_TC1); xSemaphoreGiveFromISR(xSemaphoreADC_DMA_TC, &xHigherPriorityTaskWoken ); } DMA_ClearITPendingBit(DMA1_IT_GL1); portEND_SWITCHING_ISR( xHigherPriorityTaskWoken ); }
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|