Skocz do zawartości

STM32L1 - problem z DMA i ADC


pbiel

Pomocna odpowiedź

Cześć,

przerabiając Kurs STM32 – #8 – DMA, czyli bezpośredni dostęp do pamięci zablokowałem się na ostatnim programie. Otóż DMA przesyła dane z ADC tylko raz, a potem zupełnie jakby ignorowało kolejne zmiany w rejestrze danych ADC. Wszystko dzieje się w oparciu o mikrokontroler STM32L100RC na płytce Discovery i środowisko Eclipse. Poniższy kod różni się od tego w poradniku w kilku miejscach, np. brak kodu z UART ze standardowych bibliotek, bo używam swojego sterownika do UART (usunięcie nie poprawia działania programu), brak sygnalizującej led,  pole struktury adc.ADC_NbrOfChannel zmienione na adc.ADC_NbrOfConversion (nie ma odpowiadającego pola w bibliotece do mojego mikrokontrolera), wykorzystuję inne kanały ADC i brak kalibracji ADC).

Debugując (zatrzymałem na wejściu do nieskończonej pętli po raz drugi, czyli po pierwszym jej obiegu) uzyskałem poniższe rzeczy. Wynika z nich, że wartość w rejestrze danych ADC różni się od tych w tablicy z danymi (zakreślone na czerwono). To nie kwestia tego, że zaraz do niej wskoczą, bo wartości w tablicy nie zmieniają się już dalej w ogóle, podczas gdy wartości w rejestrze ADC zachowują się poprawnie. Konfiguracja DMA wydaje się być w porządku, poniżej dodaję skrawek noty katalogowej z rejestrem CCRx (channel x configuration register), na zielono oznaczyłem ustawione bity.

Piszę o tym do Was, bo może napotkaliście już podobną sytuację i wiecie jak pomóc mi z tego wybrnąć. Z góry dzięki za odpowiedzi i pozdrawiam!

dma.thumb.png.7f515f98fec894d767c50527e914d76f.png dma_ccr1_ds.thumb.png.e8c207e1f54b8d1fbd6bbdfc2621f6f0.png 

 

/********************************* Includes *********************************/
#include "stm32l1xx.h"
#include "usart/usart.h"
#include <stdio.h>

/********************************* Defines **********************************/
#define		ADC_CHANNELS		2

/*********************** Global variables definitions ***********************/
uint16_t adc_value[ADC_CHANNELS];
volatile uint32_t timer_ms = 0;

/*************************** Function prototypes ****************************/
void SysTick_Handler();
void delay_ms(int time);

/********************************** MAIN ************************************/
int main(void) {

	/************************ Variables definitions *************************/
	uint8_t i;
	DMA_InitTypeDef dma;
	ADC_InitTypeDef adc;
	GPIO_InitTypeDef gpio;
	char buffer[50];	// used in uart


	/*************************** Initializations ****************************/
	USART1_Init();
	USART1_SendString("STM32L100RC - getting to know a DMA\n\r");

	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
	DMA_StructInit(&dma);
	dma.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
	dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
	dma.DMA_MemoryBaseAddr = (uint32_t)adc_value;
	dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
	dma.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
	dma.DMA_DIR = DMA_DIR_PeripheralSRC;
	dma.DMA_BufferSize = ADC_CHANNELS;
	dma.DMA_Mode = DMA_Mode_Circular;
	DMA_Init(DMA1_Channel1, &dma);
	DMA_Cmd(DMA1_Channel1, ENABLE);

	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
	GPIO_StructInit(&gpio);
	gpio.GPIO_Pin = GPIO_Pin_1;
	gpio.GPIO_Mode = GPIO_Mode_IN;
	GPIO_Init(GPIOA, &gpio);
	gpio.GPIO_Pin = GPIO_Pin_2;
	gpio.GPIO_Mode = GPIO_Mode_IN;
	GPIO_Init(GPIOA, &gpio);

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
	ADC_StructInit(&adc);
	adc.ADC_ScanConvMode = ENABLE;
	adc.ADC_ContinuousConvMode = ENABLE;
	adc.ADC_NbrOfConversion = ADC_CHANNELS;
	ADC_Init(ADC1, &adc);
	ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_384Cycles);
	ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 2, ADC_SampleTime_384Cycles);
	ADC_DMACmd(ADC1, ENABLE);
	ADC_Cmd(ADC1, ENABLE);
	ADC_SoftwareStartConv(ADC1);

	SysTick_Config(SystemCoreClock / 1000);


	/**************************** Infinite loop *****************************/
	for (;;) {

		for (i = 0; i < ADC_CHANNELS; i++) {
			sprintf(buffer, "ADC%d = %5d\n\r", i, adc_value[i]);
			USART1_SendString(buffer);
		}
		USART1_SendString("----------------\n\r");

		delay_ms(500);
	}

}

/***************************** Function bodies ******************************/
void SysTick_Handler() {
	if (timer_ms) timer_ms--;
}

void delay_ms(int time) {
	timer_ms = time;
	while (timer_ms) {
		// wait
	}
}

 

Edytowano przez pbiel
Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.