Jump to content

    
Alex_Golubev

Не могу запустить АЦП на stm32h743

Recommended Posts

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

  /*настройка ДМА для АЦП*/
    DMAMUX1_Channel0->CCR = (9 << DMAMUX_CxCR_DMAREQ_ID_Pos); // подключение через MUXDMA DMA к ADC
    DMA1_Stream0->CR &= ~DMA_SxCR_EN; // выключаем DMA
    while(DMA1_Stream0->CR & DMA_SxCR_EN); // ждем гарантированого выключения DMA на всякий случай
    DMA1_Stream0->CR = DMA_SxCR_MINC | DMA_SxCR_TRBUFF | DMA_SxCR_DIR_0 | DMA_SxCR_CIRC; // настройка ДМА для АЦП
    DMA1_Stream0->NDTR = 5; // количество данных для передачи с АЦП в ОЗУ буфер
    DMA1_Stream0->PAR = (uint32_t)&ADC1->DR; // адрес от куда брать данные (АЦП)
    DMA1_Stream0->M0AR = (uint32_t)&bufAdcData; // указываем адрес масива куда писать
    ADC12_COMMON->CCR = ADC_CCR_PRESC_0 | ADC_CCR_PRESC_1 | ADC_CCR_PRESC_2; // делитель у АЦП1_2 на 16 включаем ДМА для цеклической передачи данных максимальная входная частота 36 МГц.
    ADC1->CR |= ADC_CR_ADVREGEN; // включаем LDO
    while(ADC1->ISR & (1<<12)); // ждем сигнала готовности LDORDY
    ADC1->CR |= ADC_CR_ADEN;
    while(ADC1->IER & ADC_ISR_ADRDY); // ждем когда АЦП станет готов к работе
    ADC1->CR |= ADC_CR_ADCAL;
    while (!(ADC1->CR & ADC_CR_ADCAL)); // калибровка АЦП
    ADC1->CFGR = (ADC_CFGR_DISCNUM_2 | ADC_CFGR_DISCNUM_0) | ADC_CFGR_DISCEN | ADC_CFGR_CONT | ADC_CFGR_DMNGT_1 | ADC_CFGR_DMNGT_0;
    ADC1->CFGR2 = 0
            | 0*ADC_CFGR2_LSHIFT
            | 0*ADC_CFGR2_OVSR;
    ADC1->SMPR1 = 0x00;
    ADC1->SMPR2 = ADC_SMPR2_SMP18_2; // задержка комутационого ключа на 32,5 такта тактироемой частоты
    ADC1->PCSEL = ADC_PCSEL_PCSEL_19 | ADC_PCSEL_PCSEL_18 | ADC_PCSEL_PCSEL_15 | ADC_PCSEL_PCSEL_9 | ADC_PCSEL_PCSEL_3; // 19,18,15,9,3
    ADC1->LTR1 = 0x00; // установка нижнего уровня аналогового компаратора
    ADC1->LTR2 = 0x00; // установка нижнего уровня аналогового компаратора
    ADC1->LTR3 = 0x00; // установка нижнего уровня аналогового компаратора
    ADC1->HTR1 = 0x00; // установка верхнего уровня аналогового компаратора
    ADC1->HTR2 = 0x00; // установка верхнего уровня аналогового компаратора
    ADC1->HTR3 = 0x00; // установка верхнего уровня аналогового компаратора
    ADC1->SQR1 = ADC_SQR1_SQ1_1 | ADC_SQR1_SQ1_0; // как понял для шагов опроса каналов АЦП опрос идет 3 --> 9 ---> 15 ---> 18 ---> 19
    DMA1_Stream0->CR |= DMA_SxCR_EN; // включаем DMA для АЦП
    ADC1->CR |= ADC_CR_ADSTART; // запуск приобразования АЦП
    MODIFY_REG(GPIOA->MODER, GPIO_MODER_MODE3, 0x3 << GPIO_MODER_MODE3_Pos); // перевод порта на аналоговый режим функцию ADC1-15
    MODIFY_REG(GPIOA->MODER, GPIO_MODER_MODE4, 0x3 << GPIO_MODER_MODE4_Pos); // перевод порта на аналоговый режим функцию ADC1-18
    MODIFY_REG(GPIOA->MODER, GPIO_MODER_MODE5, 0x3 << GPIO_MODER_MODE5_Pos); // перевод порта на аналоговый режим функцию ADC1-19
    MODIFY_REG(GPIOA->MODER, GPIO_MODER_MODE6, 0x3 << GPIO_MODER_MODE6_Pos); // перевод порта на аналоговый режим функцию ADC1-3
    MODIFY_REG(GPIOB->MODER, GPIO_MODER_MODE0, 0x3 << GPIO_MODER_MODE0_Pos); // перевод порта на аналоговый режим функцию ADC1-9
    MODIFY_REG(GPIOA->OSPEEDR, GPIO_OSPEEDR_OSPEED3,0x0 << GPIO_OSPEEDR_OSPEED3_Pos); // настройка скорости фронта
    MODIFY_REG(GPIOA->OSPEEDR, GPIO_OSPEEDR_OSPEED4,0x0 << GPIO_OSPEEDR_OSPEED4_Pos); // настройка скорости фронта
    MODIFY_REG(GPIOA->OSPEEDR, GPIO_OSPEEDR_OSPEED5,0x0 << GPIO_OSPEEDR_OSPEED5_Pos); // настройка скорости фронта
    MODIFY_REG(GPIOA->OSPEEDR, GPIO_OSPEEDR_OSPEED6,0x0 << GPIO_OSPEEDR_OSPEED6_Pos); // настройка скорости фронта
    MODIFY_REG(GPIOB->OSPEEDR, GPIO_OSPEEDR_OSPEED0,0x0 << GPIO_OSPEEDR_OSPEED0_Pos); // настройка скорости фронта
    MODIFY_REG(GPIOA->PUPDR, GPIO_PUPDR_PUPD3, 0x00 << GPIO_PUPDR_PUPD3_Pos); // отключение подтяжки
    MODIFY_REG(GPIOA->PUPDR, GPIO_PUPDR_PUPD4, 0x00 << GPIO_PUPDR_PUPD4_Pos); // отключение подтяжки
    MODIFY_REG(GPIOA->PUPDR, GPIO_PUPDR_PUPD5, 0x00 << GPIO_PUPDR_PUPD5_Pos); // отключение подтяжки
    MODIFY_REG(GPIOA->PUPDR, GPIO_PUPDR_PUPD6, 0x00 << GPIO_PUPDR_PUPD6_Pos); // отключение подтяжки
    MODIFY_REG(GPIOB->PUPDR, GPIO_PUPDR_PUPD0, 0x00 << GPIO_PUPDR_PUPD0_Pos); // отключение подтяжки
    MODIFY_REG(GPIOA->AFR[0], GPIO_AFRL_AFSEL3, 0x0 << GPIO_AFRL_AFSEL3_Pos); // переключение на альтернативный режим AF0
    MODIFY_REG(GPIOA->AFR[0], GPIO_AFRL_AFSEL4, 0x0 << GPIO_AFRL_AFSEL4_Pos); // переключение на альтернативный режим AF0
    MODIFY_REG(GPIOA->AFR[0], GPIO_AFRL_AFSEL5, 0x0 << GPIO_AFRL_AFSEL5_Pos); // переключение на альтернативный режим AF0
    MODIFY_REG(GPIOA->AFR[0], GPIO_AFRL_AFSEL6, 0x0 << GPIO_AFRL_AFSEL6_Pos); // переключение на альтернативный режим AF0
    MODIFY_REG(GPIOB->AFR[0], GPIO_AFRL_AFSEL0, 0x0 << GPIO_AFRL_AFSEL0_Pos); // переключение на альтернативный режим AF0
    // АЦП не заработал. Хочу получить в циклическом режиме данные через DMA. Но не заработало.

 

Share this post


Link to post
Share on other sites

Не могу найти ошибку вроде все правильно сделал: В буфере bufAdcData все нули. bufAdcData точно прописан в область памяти где есть доступ DMA.

Скрытый текст

	MODIFY_REG(RCC->D2CCIP2R, RCC_D2CCIP2R_USART16SEL, 0 << RCC_D2CCIP2R_USART16SEL_Pos);// подключаем тактирование USART1 к линии "rcc_pclk2"
	RCC->AHB1ENR |= RCC_AHB1ENR_ADC12EN; // подключаем АЦП1_2 к 32-разрядной шине AHB1 для обмена данными  

/*настройка портов для работы АЦП1
     * задействаны порты:
     * PA3 ADC1-15 делитель 24 В
     * PA4 ADC1-18 шунт 24В
     * PA5 ADC1-19 делитель 5В
     * PA6 ADC1-3 шунт 5В
     * PB0 ADC1-9 напряжения на резервном питании кондесатор 100 мкФ.
     * */

	/*настройка ДМА для АЦП*/
	DMAMUX1_Channel0->CCR = (9 << DMAMUX_CxCR_DMAREQ_ID_Pos); // подключение через MUXDMA DMA1_стрим_0 к ADC1

	DMA1_Stream0->CR &= ~DMA_SxCR_EN; // выключаем DMA
	while(DMA1_Stream0->CR & DMA_SxCR_EN); // ждем гарантированого выключения DMA на всякий случай
	DMA1_Stream0->CR = DMA_SxCR_MSIZE_0 | DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC | DMA_SxCR_CIRC | DMA_SxCR_DIR_0; // настройка ДМА для АЦП
	DMA1_Stream0->NDTR = 5; // количество данных для передачи с АЦП в ОЗУ буфер
	DMA1_Stream0->PAR = (uint32_t)&ADC1->DR; // адрес от куда брать данные (АЦП)
	DMA1_Stream0->M0AR = (uint32_t)&bufAdcData; // указываем адрес масива куда писать

	ADC12_COMMON->CCR = ADC_CCR_VBATEN
			| ADC_CCR_TSEN
			| ADC_CCR_VREFEN
			| ADC_CCR_PRESC_0 | ADC_CCR_PRESC_1 | ADC_CCR_PRESC_2 | ADC_CCR_PRESC_3
			| ADC_CCR_CKMODE_0; // делитель у АЦП1_2 на 16 подключения питания датчика температуры, включение опоры напряжения, делитель ckmode/1.

	ADC1->CR &= ~ADC_CR_DEEPPWD; // отключение низкого элетропотребления АЦП

	ADC1->CR |= ADC_CR_ADVREGEN; // включаем LDO
	while(!(ADC1->ISR & (1<<12))); // ждем сигнала готовности LDORDY

	ADC1->CR |= ADC_CR_ADEN; // включаем АЦП
	while(ADC1->IER & ADC_ISR_ADRDY); // ждем когда АЦП станет готов к работе

	ADC1->CR |= ADC_CR_ADCAL;
	while(!(ADC1->CR & ADC_CR_ADCAL)); // калибровка АЦП

    ADC1->CFGR = ADC_CFGR_JQDIS | (ADC_CFGR_DISCNUM_2 | ADC_CFGR_DISCNUM_0) | ADC_CFGR_DISCEN | ADC_CFGR_CONT | ADC_CFGR_DMNGT_1 | ADC_CFGR_DMNGT_0; // циклическая передача через DMA

	ADC1->CFGR2 = 0;
	
	ADC1->SMPR1 = ADC_SMPR1_SMP9_2 | ADC_SMPR1_SMP3_2; // задержка комутационого ключа на 32,5 такта тактироемой частоты
	ADC1->SMPR2 = ADC_SMPR2_SMP19_2 | ADC_SMPR2_SMP18_2 | ADC_SMPR2_SMP15_2; // задержка комутационого ключа на 32,5 такта тактироемой частоты
	ADC1->PCSEL = ADC_PCSEL_PCSEL_19 | ADC_PCSEL_PCSEL_18 | ADC_PCSEL_PCSEL_15 | ADC_PCSEL_PCSEL_9 | ADC_PCSEL_PCSEL_3; // 19,18,15,9,3

	ADC1->LTR1 = 0x00; // установка нижнего уровня аналогового компаратора
	ADC1->LTR2 = 0x00; // установка нижнего уровня аналогового компаратора
	ADC1->LTR3 = 0x00; // установка нижнего уровня аналогового компаратора
	ADC1->HTR1 = 0x00; // установка верхнего уровня аналогового компаратора
	ADC1->HTR2 = 0x00; // установка верхнего уровня аналогового компаратора
	ADC1->HTR3 = 0x00; // установка верхнего уровня аналогового компаратора

	ADC1->SQR1 = (ADC_SQR1_SQ1_1 | ADC_SQR1_SQ1_0)
			| (ADC_SQR1_SQ2_3 |  ADC_SQR1_SQ2_0)
			| (ADC_SQR1_SQ3_3 | ADC_SQR1_SQ3_2 | ADC_SQR1_SQ3_1 | ADC_SQR1_SQ3_0)
			| (ADC_SQR1_SQ4_4 | ADC_SQR1_SQ4_1); // шаги опроса каналов АЦП 3 --> 9 ---> 15 ---> 18 ---> 19

	ADC1->SQR2 = (ADC_SQR2_SQ5_4 | ADC_SQR2_SQ5_1 | ADC_SQR2_SQ5_0); // 19 канал АЦП
	ADC1->SQR3 = 0; // остальных каналов как бы нет
	ADC1->SQR4 = 0; // остальных каналов как бы нет

	DMA1_Stream0->CR |= DMA_SxCR_EN; // включаем DMA для АЦП
	while(!(DMA1_Stream0->CR & DMA_SxCR_EN)); // ждем когда включиться dma

	MODIFY_REG(GPIOA->MODER, GPIO_MODER_MODE3, 0x3 << GPIO_MODER_MODE3_Pos); // перевод порта на аналоговый режим функцию ADC1-15
	MODIFY_REG(GPIOA->MODER, GPIO_MODER_MODE4, 0x3 << GPIO_MODER_MODE4_Pos); // перевод порта на аналоговый режим функцию ADC1-18
	MODIFY_REG(GPIOA->MODER, GPIO_MODER_MODE5, 0x3 << GPIO_MODER_MODE5_Pos); // перевод порта на аналоговый режим функцию ADC1-19
	MODIFY_REG(GPIOA->MODER, GPIO_MODER_MODE6, 0x3 << GPIO_MODER_MODE6_Pos); // перевод порта на аналоговый режим функцию ADC1-3
	MODIFY_REG(GPIOB->MODER, GPIO_MODER_MODE0, 0x3 << GPIO_MODER_MODE0_Pos); // перевод порта на аналоговый режим функцию ADC1-9

	MODIFY_REG(GPIOA->OSPEEDR, GPIO_OSPEEDR_OSPEED3,0x0 << GPIO_OSPEEDR_OSPEED3_Pos); // настройка скорости фронта
	MODIFY_REG(GPIOA->OSPEEDR, GPIO_OSPEEDR_OSPEED4,0x0 << GPIO_OSPEEDR_OSPEED4_Pos); // настройка скорости фронта
	MODIFY_REG(GPIOA->OSPEEDR, GPIO_OSPEEDR_OSPEED5,0x0 << GPIO_OSPEEDR_OSPEED5_Pos); // настройка скорости фронта
	MODIFY_REG(GPIOA->OSPEEDR, GPIO_OSPEEDR_OSPEED6,0x0 << GPIO_OSPEEDR_OSPEED6_Pos); // настройка скорости фронта
	MODIFY_REG(GPIOB->OSPEEDR, GPIO_OSPEEDR_OSPEED0,0x0 << GPIO_OSPEEDR_OSPEED0_Pos); // настройка скорости фронта

	MODIFY_REG(GPIOA->PUPDR, GPIO_PUPDR_PUPD3, 0x00 << GPIO_PUPDR_PUPD3_Pos); // отключение подтяжки
	MODIFY_REG(GPIOA->PUPDR, GPIO_PUPDR_PUPD4, 0x00 << GPIO_PUPDR_PUPD4_Pos); // отключение подтяжки
	MODIFY_REG(GPIOA->PUPDR, GPIO_PUPDR_PUPD5, 0x00 << GPIO_PUPDR_PUPD5_Pos); // отключение подтяжки
	MODIFY_REG(GPIOA->PUPDR, GPIO_PUPDR_PUPD6, 0x00 << GPIO_PUPDR_PUPD6_Pos); // отключение подтяжки
	MODIFY_REG(GPIOB->PUPDR, GPIO_PUPDR_PUPD0, 0x00 << GPIO_PUPDR_PUPD0_Pos); // отключение подтяжки

	MODIFY_REG(GPIOA->AFR[0], GPIO_AFRL_AFSEL3, 0x0 << GPIO_AFRL_AFSEL3_Pos); // переключение на альтернативный режим AF0
	MODIFY_REG(GPIOA->AFR[0], GPIO_AFRL_AFSEL4, 0x0 << GPIO_AFRL_AFSEL4_Pos); // переключение на альтернативный режим AF0
	MODIFY_REG(GPIOA->AFR[0], GPIO_AFRL_AFSEL5, 0x0 << GPIO_AFRL_AFSEL5_Pos); // переключение на альтернативный режим AF0
	MODIFY_REG(GPIOA->AFR[0], GPIO_AFRL_AFSEL6, 0x0 << GPIO_AFRL_AFSEL6_Pos); // переключение на альтернативный режим AF0
	MODIFY_REG(GPIOB->AFR[0], GPIO_AFRL_AFSEL0, 0x0 << GPIO_AFRL_AFSEL0_Pos); // переключение на альтернативный режим AF0

	ADC1->CR |= ADC_CR_ADSTART; // запуск приобразования АЦП

 

 

Share this post


Link to post
Share on other sites
3 hours ago, Alex_Golubev said:

Не могу найти ошибку вроде все правильно сделал: В буфере bufAdcData все нули. bufAdcData точно прописан в область памяти где есть доступ DMA.

Попробуйте запустить для начала без DMA. Так вы убедитесь, что сам АЦП у вас настроен правильно.

Share this post


Link to post
Share on other sites
10.12.2020 в 14:36, Alex_Golubev сказал:

DMA1_Stream0->CR |= DMA_SxCR_EN; // включаем DMA для АЦП

ADC1->CR |= ADC_CR_ADSTART; // запуск преобразования АЦП

Вы твердо уверены, что у STM32H7-го Stream0 1-ого DMA обслуживает ADC1? А то я на этот момент уже спотыкалась на STM32F4, когда выяснила, что для обслуживания ADC1 нужен не DMA1, а DMA2. Для STM32H7 такой таблицы не нашла, но для STM32F4 она такая:

image.thumb.png.0f4d367783b28d3ae7efcfb077bf9d03.png

Share this post


Link to post
Share on other sites
1 час назад, Alex_Golubev сказал:

Никто помочь не может?

У меня работал этот АЦП через DMA нормально, только была одна проблема - запускался 1 раз :) Второй раз приходилось делать сброс чипа, но мне хватало, поэтому глубоко не копал. Настраивал с помощью CubeMX.

Share this post


Link to post
Share on other sites
On 12/17/2020 at 1:26 PM, Alex_Golubev said:

Никто помочь не может?

У меня работал этот АЦП через DMA нормально, и запускался столько раз сколько надо. Первоначально настраивал АЦП в Cube, затем настраивал регистрами то чего не хватало. Многие ошибки в настройке выяснил при отладке. В Вашем коде не нашел настройки Boost mode. Эта настройка "Must be used when ADC clock > 20 MHz". Еще помню, что после калибровки, некоторые регистры сбрасывались и приходилось делать инициализацию АЦП после калибровки, поэтому сначала делал минимальную настройку для проведения калибровки, затем калибровал, а потом всю инициализацию АЦП по полной. Проверяйте тактирование АЦП и контроллера DMA.

Edited by LAS9891

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.