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

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • 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.