реклама на сайте
подробности

 
 
> STM32 АЦП. Пожалуйста помогите разобраться
TmYAG
сообщение Dec 23 2014, 05:25
Сообщение #1





Группа: Участник
Сообщений: 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] - для короткого!!!
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
glags
сообщение Dec 23 2014, 12:15
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 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
в третьих перед каждым забором данных из АЦП его надо запускать как я написал ниже. sm.gif

ADC1->CR2 |= ADC_CR2_JSWSTART;
while (!(ADC1->SR & ADC_SR_JEOC));
ADC1->SR =0; // Очищаем флаг «преобразование завершено»
res = ADC1->JDR1;
Go to the top of the page
 
+Quote Post
TmYAG
сообщение Dec 23 2014, 18:02
Сообщение #3





Группа: Участник
Сообщений: 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;

Изменил код, но проблема не исчезла=(
Go to the top of the page
 
+Quote Post
glags
сообщение Dec 23 2014, 18:46
Сообщение #4


Участник
*

Группа: Участник
Сообщений: 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;
Go to the top of the page
 
+Quote Post
TmYAG
сообщение Dec 23 2014, 19:05
Сообщение #5





Группа: Участник
Сообщений: 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 мы для тактирования альтернативных функций и включали.
Go to the top of the page
 
+Quote Post
glags
сообщение Dec 23 2014, 20:31
Сообщение #6


Участник
*

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



Там целая наука. Дело в том что инжектированных каналов может быть максимум 4 и каждый имеет свой регистр данных, а регулярных 16 и у них один регистр данных на всех. По этому данные из них можно читать либо по прерыванию (окончание преобразования) либо DMA. Здесь если всё писать то целая статья выйдет. Дело в том что АЦП не сложный, но навороченный. Например он может вызывать прерывания при достижении определённого уровня сигнала на входе и т.д. Скажу только про один момент с инжектированными каналами. В инжектированных каналах есть одно неудобство, когда конфигуришь один канал, то в регистр ADC1->JSQR надо заполнять его как четвёртый. Это многих сбивает с толку.
Да SYSCFG мы для тактирования альтернативных функций и включали. Но для конфигурации порта мы их не используем. Просто в модере включаем аналоговый режим. Альтернативные функции касаются таймеров уартсов и прочего что конфигурится в GPIOA->AFR. Здесь на всякий случай sm.gif.
Просьба, если всё запашет, то отпишитесь.

Сообщение отредактировал glags - Dec 24 2014, 16:59
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- TmYAG   STM32 АЦП. Пожалуйста помогите разобраться   Dec 23 2014, 05:25
- - vovanse   Цитата(TmYAG @ Dec 23 2014, 12:25) Мануал...   Dec 23 2014, 07:07
|- - TmYAG   Цитата(glags @ Dec 23 2014, 20:31) Просьб...   Dec 25 2014, 09:12
|- - glags   Цитата(TmYAG @ Dec 25 2014, 11:12) Вот не...   Dec 25 2014, 18:28
- - KARLSON   Здравствуйте. Я только осваиваю АЦП у STM32. Поста...   Aug 14 2015, 13:18
|- - adnega   Цитата(KARLSON @ Aug 14 2015, 16:18) Что ...   Aug 14 2015, 13:42
- - uriy   Если хотите читать несколько регулярных каналов то...   Aug 14 2015, 16:51
- - KARLSON   Камень 103VG То что лучше с DMA и по таймеру это п...   Aug 15 2015, 06:20
|- - adnega   Цитата(KARLSON @ Aug 15 2015, 09:20) Каме...   Aug 15 2015, 06:42
|- - KARLSON   Теперь всё ясно. Благодарю. Буду переходить на DMA...   Aug 15 2015, 14:18
- - smk   Для пытливых умов. Код инициализации АЦП и ДМА. Ре...   Aug 18 2015, 04:42


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 08:50
Рейтинг@Mail.ru


Страница сгенерированна за 0.01418 секунд с 7
ELECTRONIX ©2004-2016