Микроконтроллеры

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Микроконтроллеры » STM32 » ADC1 от TIM1_CC1+DMA


ADC1 от TIM1_CC1+DMA

Сообщений 1 страница 7 из 7

1

stm32f103c8t6
Поставил цель запустить преобразование ацп1 от сравнения 1 канала 1 таймера и потом передавать через DMA. Есть опыт запуска от 3 таймера по TIM3_TRGO на SPL.
Думаю заодно будут исходник для начинающих
Пока хочу запустить без DMA. Поделился исходником NewWriter,но возник вопрос не будет ли управление выводом PA8 от сравнения 1 канала 1 таймера ? Мне просто нужен запуск от таймера ацп,а вывод оставлю свободным.

Код:
#include "adc.h"


void adc_init(void)
{
	// АЦП у нас 1 канал,он на PA0 , запуск от внешнего тригера TRM1 1 канала
	
	RCC->AHBENR|=RCC_AHBENR_DMA1EN;
	RCC->APB2ENR|=RCC_APB2ENR_AFIOEN|RCC_APB2ENR_IOPAEN|RCC_APB2ENR_ADC1EN|RCC_APB2ENR_TIM1EN;
	
	// тактирование ацп 
	RCC->CFGR&=~(RCC_CFGR_ADCPRE);
	RCC->CFGR|=RCC_CFGR_ADCPRE_1;
	
	// аналоговый вход
	GPIOA->CRL&= ~(GPIO_CRL_MODE0);
	GPIOA->CRL&= ~(GPIO_CRL_CNF0); 
	
	// настройка ацп: 
	ADC1->SMPR2 |= ADC_SMPR2_SMP0_2 ;                 // AN0: 41.5 мкс 
	 ADC1->CR2 |= ADC_CR2_ADON;                                // включаем
	/* регулярная группа */
   ADC1->SQR3 = 1;                                 // 1 канал в первую группу
	
	// Калибровка ацп
      ADC1->CR2 |= ADC_CR2_CAL;                                  // запуск калибровки
     while (ADC1->CR2 & ADC_CR2_CAL);                         // ожидаем конца калибровки
	
	 
	 ADC1->CR2 |=ADC_CR2_EXTTRIG;                    // запуск от сравнения по TIM1_CC1
	 ADC1->CR2 &=~(ADC_CR2_EXTSEL);                  //  000 это по TIM1_CC1
	 
	 // дма передача
	 //ADC1->CR2 |=ADC_CR2_DMA;
	 
	 // прерывание от ацп1
    ADC1->SR&=~ADC_SR_EOC;   // очищаем флаг преобразования
	 ADC1->CR1|=ADC_CR1_EOCIE;  // включаем прерывание
	 NVIC_SetPriority(ADC1_2_IRQn,0);
	  NVIC_EnableIRQ(ADC1_2_IRQn);
    
    ////////////////////////////////////////////////////////////////
    // Настраиваем таймер 1 для ацп1
    ///////////////////////////////////////////////////////////////
    TIM1->PSC = (SystemCoreClock/1000)-1;  // 1 ms
    TIM1->ARR = 2000;  // 2 секунды период
    TIM1->CCR1 = 700;  // через 0.7 начать преобразование
    TIM1->CCMR1 |= TIM_CCMR1_OC1M;                // Ch1: PWM mode2
                TIM1->CCER |= TIM_CCER_CC1E;                      //<! Ch1 out enable
                TIM1->BDTR |= TIM_BDTR_MOE;                        //<! main out enable (!!!)
                TIM1->CR1 |= TIM_CR1_CEN;                              // TIM1 enable

               /* ---- АЦП запущен, с AN1 измеряется ---- */
    
}



Есть хорошая табличка.
http://s8.uploads.ru/t/tZ2G1.png

ацп работает от таймера. А вот почему на выходе PA8 нет,может порт не настроен,буду смотреть дальше.
http://s5.uploads.ru/t/jvEdc.png

Отредактировано CERGEI (2017-04-08 04:35:46)

2

Как я и говорил вывод надо переводить в альтернативную функцию,тогда он подключается к таймеру сравнения.

Вот весь код с DMA и TIM1_CC1
К тому же заметил,прерывание от АЦП не наступает когда работает DMA на АЦП.

adc.h

Код:
#ifndef INIT_ADC
#define INIT_ADC


#include "stm32f10x.h"

extern uint16_t buff[10];

void adc_init(void);

#endif


adc.c

Код:
#include "adc.h"


void adc_init(void)
{
	// АЦП у нас 1 канал,он на PA0 , запуск от внешнего тригера TRM1 1 канала
	
	RCC->AHBENR|=RCC_AHBENR_DMA1EN;
	RCC->APB2ENR|=RCC_APB2ENR_AFIOEN|RCC_APB2ENR_IOPAEN|RCC_APB2ENR_ADC1EN|RCC_APB2ENR_TIM1EN;
	
	// тактирование ацп 
	RCC->CFGR&=~(RCC_CFGR_ADCPRE);
	RCC->CFGR|=RCC_CFGR_ADCPRE_1;
	
	// аналоговый вход
	GPIOA->CRL&= ~(GPIO_CRL_MODE0);
	GPIOA->CRL&= ~(GPIO_CRL_CNF0); 
	 
	
	// Выход TIM1_CC1  = PA8
	//GPIOA->CRH&= ~(GPIO_CRH_MODE8);
	//GPIOA->CRH|=GPIO_CRH_MODE8;
	//GPIOA->CRH&= ~(GPIO_CRH_CNF8);
	//GPIOA->CRH|=GPIO_CRH_CNF8_1;
	
	// настройка ацп: 
	ADC1->SMPR2 |= ADC_SMPR2_SMP0_2 ;                 // AN0: 41.5 мкс 
	 ADC1->CR2 |= ADC_CR2_ADON;                                // включаем
	/* регулярная группа */
   ADC1->SQR3 = 1;                                 // 1 канал в первую группу
	
	// Калибровка ацп
      ADC1->CR2 |= ADC_CR2_CAL;                                  // запуск калибровки
     while (ADC1->CR2 & ADC_CR2_CAL);                         // ожидаем конца калибровки
	
	 
	 ADC1->CR2 |=ADC_CR2_EXTTRIG;                    // запуск от сравнения по TIM1_CC1
	 ADC1->CR2 &=~(ADC_CR2_EXTSEL);                  //  000 это по TIM1_CC1

  // настройка дма канала для ацп
	
	DMA1_Channel1->CPAR = (uint32_t)&(ADC1->DR); // откуда забираем
	DMA1_Channel1->CMAR = (uint32_t)buff; // буфер в RAM
	DMA1_Channel1->CCR &= ~DMA_CCR1_DIR; // указываем направление передачи из перефирии в память
	DMA1_Channel1->CNDTR = 0x0A; // передаем 10 значений
	DMA1_Channel1->CCR &= ~DMA_CCR1_PINC; // адрес перефирии не инкриминируем
	DMA1_Channel1->CCR |= DMA_CCR1_MINC; // а вот адрес в папмяти инкриминируем
	DMA1_Channel1->CCR |= DMA_CCR1_PSIZE_0; // размерность перефирии 16 бит
	DMA1_Channel1->CCR |= DMA_CCR1_MSIZE_0; // размерность памяти 16 бит
	DMA1_Channel1->CCR |= DMA_CCR1_PL; // приоритет высокий 
	DMA1_Channel1->CCR |= DMA_CCR1_CIRC; // циклический режим
	DMA1_Channel1->CCR |= DMA_CCR1_EN; // включаем 1 канал DMA
	
	 ADC1->CR2 |=ADC_CR2_DMA;
	 
	 // прерывание от ацп1
    ADC1->SR&=~ADC_SR_EOC;   // очищаем флаг преобразования
	 ADC1->CR1|=ADC_CR1_EOCIE;  // включаем прерывание
	 NVIC_SetPriority(ADC1_2_IRQn,0);
	  //NVIC_EnableIRQ(ADC1_2_IRQn);
    
    ////////////////////////////////////////////////////////////////
    // Настраиваем таймер 1 для ацп1
    ///////////////////////////////////////////////////////////////
    TIM1->PSC = (SystemCoreClock/1000)-1;  // 1 ms
    TIM1->ARR = 2000;  // 2 секунды период
    TIM1->CCR1 = 700;  // через 0.7 начать преобразование
    TIM1->CCMR1 |= TIM_CCMR1_OC1M;                // Ch1: PWM mode2
    TIM1->CCER |= TIM_CCER_CC1E;                      //<! Ch1 out enable
    TIM1->BDTR |= TIM_BDTR_MOE;                        //<! main out enable (!!!)
    TIM1->CR1 |= TIM_CR1_CEN;                              // TIM1 enable
    
}


http://sg.uploads.ru/t/pZMXb.png

Отредактировано CERGEI (2017-04-11 03:26:08)

3

Перенесём топик в STM32 ADC ?

4

Можно,оба варианта оставить. 1 сообщение-вариант это от таймера с прерыванием и 2 сообщение таймер+DMA

5

изучал тему ацп на F1 и нашел интересную инфу по L

на 17 канале АЦП1 находит внутреннее опорное напряжение .
калибруется на заводе при 3В и записывается в память

пункт 6.3.3 Datasheet

1.202 1.224 1.242 V

VREFINT_CAL Raw data acquired at
temperature of 30 °C, VDDA= 3 V
0x1FF8 0078-0x1FF8 0079

тем самым, опрашивая канал 17, достаточно точно можно прикинуть что приходит на VDDA и прикинуть реальные данные с каналов АЦП.

6

Встроенный ацп оставляет желать лучшего. Хочу попробовать ADS1115 : 12 бит точность,встроенный опорник,изменяемый коэффициент усиления и 4 входа или 2 дифференциальных.

7

ну это да...
в разработке что на работе тоже нужна точность и используем AD7686BRM с внешними опорниками .   Но для дома как то жаба душит за такие деньги ацп внешнее брать. вот и пытаюсь штатное заставить работать. Но насколько я понял - дело это не простое , особенно в корпусах где нет Vref-


Вы здесь » Микроконтроллеры » STM32 » ADC1 от TIM1_CC1+DMA