Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: stm32 АЦП в инжекторном режиме
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
anubis
На stm32f107 нужно заюзать второй ADC, первый сейчас используется в регулярном режиме:
В основном коде включаю порт А:
Код
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);


Код
void AdcInit(void)
{
  RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;    // Разрешить тактирование порта PORT A
  //Конфигурирование PORT PA.3 - аналоговый вход
  GPIOA->CRL   &= ~GPIO_CRL_MODE3;       //Очистить биты MODE
  GPIOA->CRL   &= ~GPIO_CRL_CNF3;        //Очистить биты CNF

  RCC->APB2ENR |=  RCC_APB2ENR_ADC1EN;   //подаем тактирование АЦП
  RCC->CFGR    &= ~RCC_CFGR_ADCPRE;      //входной делитель
  ADC1->CR1     =  0;                    //
  ADC1->SQR1    =  0;                    //
  ADC1->CR2    |=  ADC_CR2_CAL;          //запуск калибровки
  while (!(ADC1->CR2 & ADC_CR2_CAL)){};  //ждем окончания калибровки
  ADC1->CR2     =  ADC_CR2_EXTSEL;       //выбрать источником запуска разряд  SWSTART
  ADC1->CR2    |=  ADC_CR2_EXTTRIG;      //разр. внешний запуск регулярного канала
  ADC1->CR2    |=  ADC_CR2_CONT;         //режим непрерывного преобразования

  /* Задаем длительность выборки */
    ADC1->SMPR2 |= (ADC_SMPR2_SMP4_2 | ADC_SMPR2_SMP4_1 | ADC_SMPR2_SMP4_0);

  ADC1->SQR3    =  3;                    //загрузить номер канала
  ADC1->CR2    |=  ADC_CR2_ADON;         //включить АЦП
  ADC1->CR2    |=  ADC_CR2_SWSTART;      //запустить процес преобразования
}

А вот подключить второй АЦП и заставить его работать в инжекторном режиме не получается.
Нужно считывать периодически 4 канала (на каждый подключено Vcc через кнопки), таким образом с АЦП по каждому каналу нужно проверять есть ли Vcc или нет.
Вот код для инициализации АЦП2:

Код
void AdcInjInit(void)
{
    RCC->APB2ENR |=  RCC_APB2ENR_ADC2EN;   //подаем тактирование АЦП
      RCC->CFGR    &= ~RCC_CFGR_ADCPRE;      //входной делитель
      ADC2->CR1     =  0;                    //предочистка регистра
      ADC2->CR2    |=  ADC_CR2_CAL;          //запуск калибровки
      while (!(ADC2->CR2 & ADC_CR2_CAL)){};  //ждем окончания калибровки
      ADC2->CR2     =  ADC_CR2_JEXTSEL;      //выбрать источником запуска разряд  JSWSTART
      ADC2->CR2    |=  ADC_CR2_JEXTTRIG;     //разр. внешний запуск инжектированной группы
      ADC2->CR2    |=  ADC_CR2_CONT;         //режим непрерывного преобразования
      ADC2->CR1    |=  ADC_CR1_SCAN;         //режим сканирования (т.е. несколько каналов)
      ADC2->CR1    |=  ADC_CR1_JAUTO;  //автомат. запуск инжектированной группы
      ADC2->JSQR    =  (uint32_t)(4-1)<<20;  //задаем количество каналов в инжектированной группе
      ADC2->JSQR   |=  (uint32_t)10<<(5*0);   //номер канала для первого преобразования (10)
      ADC2->JSQR   |=  (uint32_t)11<<(5*1);   //номер канала для второго преобразования (11)
      ADC2->JSQR   |=  (uint32_t)12<<(5*2);   //номер канала для третьего преобразования
      ADC2->JSQR   |=  (uint32_t)13<<(5*3);   //номер канала для четвертого преобразования
      ADC2->CR2    |=  ADC_CR2_ADON;         //включить АЦП
      ADC2->CR2    |=  ADC_CR2_JSWSTART;     //запустить процес преобразования
}


и забираю таким способом:

Код
     short  adc_btn1 = ADC2->JDR1;
     short  adc_btn2 = ADC2->JDR2;
     short  adc_btn3 = ADC2->JDR3;
     short  adc_btn4 = ADC2->JDR4;

Но на выходе почему то всегда значения 25-28 в не зависимости от нажатия кнопок.
smk
Код
unsigned short  adc_btn1 = ADC2->JDR1;


так правильнее, думаю.

Вот моя инициализация ADC1. Три канала непрерывно оцифровываются и выкладываются в буфер. Думаю из 3 сделать 4 не трудно. ADC1 поменять на ADC2 тоже. Номера каналов тоже выберете какие нужно.

Код
void ADC1_Init(void)
{
    RCC->APB2ENR |=(1UL<<2);                                    //тактирование GPIOA включить
    GPIOA->CRL &= ~0x00000FF0UL;                 // PA1 & PA2 analog input        
    
    RCC->CFGR    |= 0x8000UL;                                 //установить ADCPRE[1;0] дел. на 6 Fadc = 72/6=12 MHz
    RCC->APB2ENR |= (1UL<<9);                                    //тактирование ADC1 включить
    ADC1->JSQR    = 0x288820UL;                                //3 канала 1,2,17
    ADC1->SMPR1   = 0xE00000UL;                                //Канал 17 х 239,5 тактов
    ADC1->SMPR2   = 0x1F8UL;                                    //Канал 1 и 2 х 239,5 тактов

  ADC1->CR1    |= (1UL<< 8);                       //Scan mode on                    
    ADC1->CR2       |= (1UL<<23);                                //Включить термометр и ИОН
    ADC1->CR2       |= (7UL<<12);                                //выбрать внешним событием программный старт преобразования инж. каналов
    ADC1->CR2       |= (1UL<<15);                                //разрешить начало преобразования по внешнему событию    

  ADC1->CR2    |= (1UL <<  0);                   /* ADC enable                       */
  ADC1->CR2    |= (1UL <<  3);              /* Initialize calibration registers */
  while (ADC1->CR2 & (1UL << 3));           /* Wait for init to finish          */
  ADC1->CR2    |= (1UL <<  2);              /* Start calibration                */
  while (ADC1->CR2 & (1UL << 2));              /* Wait for calibration to finish   */    

  ADC1->CR1    |= (1UL << 10);                   // JAUTO: Automatic Injected Group conversion
    ADC1->CR2    |= (1UL <<  1);                            // CONT: Continuous conversion

    ADC1->CR2    |= (1UL <<  8);                   //DMA mode enabled
    RCC->AHBENR     |= (1UL <<  0);                   //DMA1 clock enabled
    
    DMA1_Channel1->CCR |= (1UL << 11);                                //Memory size 32-bits
    DMA1_Channel1->CCR |= (1UL <<  9);                                //Peripheral size 32-bits
    DMA1_Channel1->CCR |= (1UL <<  5);                                //Circular mode enabled
    DMA1_Channel1->CCR |= (1UL <<  6);                                //Peripheral increment mode enabled
    DMA1_Channel1->CCR |= (1UL <<  7);                                //Memory increment mode enabled    
    DMA1_Channel1->CNDTR = 3;                                                    //Number of data to transfer
    DMA1_Channel1->CPAR = (uint32_t) &ADC1->JDR1;            //Peripheral address
    DMA1_Channel1->CMAR = (uint32_t) &data_buf[0];         //Memory address

    DMA1_Channel1->CCR |= (1UL <<  0);                //Channel1 enabled

    ADC1->CR2    |= (1UL << 21);                   // Start A/D conversion инжектированных каналов    
}
fatlortroll
Цитата
Нужно считывать периодически 4 канала (на каждый подключено Vcc через кнопки), таким образом с АЦП по каждому каналу нужно проверять есть ли Vcc или нет


Я правильно понял, что для определения, единица на входе, или ноль, используется АЦП? Если да, то это уж очень явный overengineering. Не проще ли инициализировать ноги, как входы, с подтяжкой к земле встроенными резисторами (PullDown), и считывать уже их состояние?
demiurg_spb
Цитата(fatlortroll @ Oct 28 2013, 13:33) *
Бывает и такое...
fatlortroll
Цитата(demiurg_spb @ Oct 28 2013, 13:52) *
Бывает и такое...

Всё же, хотелось бы услышать непосредственно от автора, какую задачу он решает. Может, действительно её возможно реализовать заметно проще.
anubis
Цитата(fatlortroll @ Oct 28 2013, 13:55) *
Всё же, хотелось бы услышать непосредственно от автора, какую задачу он решает. Может, действительно её возможно реализовать заметно проще.

Да нужно определять нажата ли кнопка или нет.
Если есть способ более оптимальный буду благодарен за совет
demiurg_spb
Цитата(anubis @ Oct 30 2013, 13:58) *
Какая схема включения кнопок и сколько их?
anubis
4 независимых кнопки(в параллель), могут нажиматься в произвольной последовательности.
На текущий момент с одной стороны подключены к Vcc с другой на ADC
fatlortroll
Если не менять схему подключения -- то настраиваешь ноги, на которых кнопки, как входы, включаешь подтягивающие к земле резисторы на этих входах (PullDown), и из регистра InputData (он же GPIOx_IDR) считываешь состояния входов. Антидребезг -- по желанию, программный.
anubis
Спасибо, подтяжка вниз реально то что нужно было!
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.