STM32F103 (DMA+ADC+USART)

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
Foxek
Первый раз сказал Мяу!
Сообщения: 35
Зарегистрирован: Сб дек 28, 2013 20:31:22

STM32F103 (DMA+ADC+USART)

Сообщение Foxek »

Добрый вечер! Программирую связку STM32F103 DMA ADC USART. Одним каналом DMA забирает данные из регистра ADC и помещает в буфер, причем размер данных и буфера и ADC в DMA указаны как 16 бит.
После чего так же при помощи DMA перекладываю данные из буфера в USART. В инициализации DMA для буфера выбрано 16 бит а для USART 8 бит. При такой инициализации данные приходящие в компьютер не соответствуют действительности. Однако создав специальную функцию которая сдвигает значение АЦП на 4 бита вправо, я получаю идеальный синус. Помогите, как решить проблему не заморачиваясь с битовым сдвигом значения регистра АЦП, так как это занимает время которое мне в последствии пригодится. Должен быть способ настроить ДМА так чтобы он сам конвертировал 16 бит буфера в 8 бит USART.
Подскажите решение проблемы)Заранее благодарен
Реклама
HHIMERA
Друг Кота
Сообщения: 4583
Зарегистрирован: Вс дек 05, 2010 06:10:34
Откуда: ЮВ

Re: STM32F103 (DMA+ADC+USART)

Сообщение HHIMERA »

Решений нет... Есть референс... и там английским по белому написано что и как может ДМА...
"Я не даю готовых решений, я заставляю думать!"(С)
Реклама
Аватара пользователя
Myp3ik
Мучитель микросхем
Сообщения: 450
Зарегистрирован: Вс янв 09, 2011 23:05:37
Откуда: СССР

Re: STM32F103 (DMA+ADC+USART)

Сообщение Myp3ik »

У АЦП есть настройка которая указывает как выравнивать данные, по правому или по левому краю. Если по левому, то 4 младших бита из 16 будут пустыми, вот вам и приходится сдвигать на 4 бита вправо. Ну или наоборот :roll:
Иван Сусанин - первый полупроводник :solder:
uk8amk
Поставщик валерьянки для Кота
Сообщения: 2222
Зарегистрирован: Вт ноя 27, 2007 11:32:06
Откуда: Tashkent

Re: STM32F103 (DMA+ADC+USART)

Сообщение uk8amk »

Ничего никуда не надо конвертировать.
Укажите правильно размерность данных буфера SRAM 8 бит и USART 8 бит(PSIZE, MSIZE).
Реклама
Эиком - электронные компоненты и радиодетали
Foxek
Первый раз сказал Мяу!
Сообщения: 35
Зарегистрирован: Сб дек 28, 2013 20:31:22

Re: STM32F103 (DMA+ADC+USART)

Сообщение Foxek »

Спасибо за советы. Сейчас буду пробовать, завтра отпишусь что помогло а что нет)
Реклама
Foxek
Первый раз сказал Мяу!
Сообщения: 35
Зарегистрирован: Сб дек 28, 2013 20:31:22

Re: STM32F103 (DMA+ADC+USART)

Сообщение Foxek »

Ни один ни другой совет результатов не дал!((
Реклама
uk8amk
Поставщик валерьянки для Кота
Сообщения: 2222
Зарегистрирован: Вт ноя 27, 2007 11:32:06
Откуда: Tashkent

Re: STM32F103 (DMA+ADC+USART)

Сообщение uk8amk »

Попробуйте выложить код с описанием того, что делаете и как реальный результат отличается от ожидаемого.
Foxek
Первый раз сказал Мяу!
Сообщения: 35
Зарегистрирован: Сб дек 28, 2013 20:31:22

Re: STM32F103 (DMA+ADC+USART)

Сообщение Foxek »

Я не буду выкладывать весь код(инициализация USART, GPIO и прочего). Так как эти части программы работают сто процентно. Я выложу инициализацию ADC DMA и Прерывание в котором собственно все и происходит:

Код: Выделить всё

void ADC_Configuration(void)// Стандартная инициализация АЦП( по таймеру с ДМА)
uint16_t buffer[0];
{
	RCC->CFGR&= ~RCC_CFGR_ADCPRE;
	RCC->CFGR|=RCC_CFGR_ADCPRE_DIV2;
	RCC->APB2ENR|=RCC_APB2ENR_ADC1EN;

	ADC1->CR2 |= ADC_CR2_CAL;
	while (!(ADC1->CR2 & ADC_CR2_CAL)){ }
	
	ADC1->CR2 &= ~ADC_CR2_ALIGN; //Выравнивание по правому краю
	ADC1->CR2 |= ADC_CR2_CONT;
	ADC1->CR2 |= ADC_CR2_EXTTRIG;
	ADC1->CR2 |= ADC_CR2_EXTSEL_2;
	ADC1->SMPR1 &= ~ADC_SMPR1_SMP14;

	ADC1->SQR3|=(ADC_SQR3_SQ1_1|ADC_SQR3_SQ1_2|ADC_SQR3_SQ1_3);
	ADC1->CR1 |= ADC_CR1_EOCIE;
	ADC1->CR2 |= ADC_CR2_DMA;
	ADC1->CR2|=ADC_CR2_ADON;

}

void DMA_Configuration(void) // Инициализация DMA(Channel1 - ADC1->buffer)(Channel7 - buffer->USART2)
{
  RCC->AHBENR |= RCC_AHBENR_DMA1EN;

	DMA1_Channel1->CPAR |= (uint32_t) &ADC1->DR; 
	DMA1_Channel1->CMAR |= (uint32_t) &Buffer[0]; 
	DMA1_Channel1->CNDTR = 2500;
	DMA1_Channel1->CCR =  0;
	DMA1_Channel1->CCR &= ~DMA_CCR1_DIR; 
	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_TCIE; 
	DMA1_Channel1->CCR |= DMA_CCR1_EN; 
	
	DMA1_Channel7->CPAR |=  (uint32_t)&USART2->DR;  
	DMA1_Channel7->CMAR |=  (uint32_t)&Buffer[0];   
	DMA1_Channel7->CNDTR =  2500;                      
	DMA1_Channel7->CCR =  0;
	//DMA1_Channel7->CCR |= DMA_CCR7_CIRC; 
	DMA1_Channel7->CCR |=  DMA_CCR7_DIR;
	DMA1_Channel7->CCR &= ~DMA_CCR7_PINC; 
	DMA1_Channel7->CCR &= ~(DMA_CCR7_PSIZE_0|DMA_CCR7_PSIZE_1);// 8-бит USART
	DMA1_Channel7->CCR |= DMA_CCR7_MSIZE_0;
	DMA1_Channel7->CCR |=  DMA_CCR7_MINC; 
	DMA1_Channel7->CCR |= DMA_CCR7_TCIE; 	
}

void DMA1_Channel1_IRQHandler(void)
{
	if(DMA1->ISR & DMA_ISR_TCIF1)// Если АЦП конвертировал 2500 точек
	{
		DMA1_Channel1->CCR &= (uint16_t)(~DMA_CCR1_EN);// отключаем DMA от АЦП
		for (i = 0; i<= 2500; i++)
		{
		Buffer[i]=Buffer[i]>>4;// Сдвигаем на 4 бита	
		}
	DMA1_Channel7->CNDTR =  2500;      
	DMA1_Channel7->CCR |= DMA_CCR7_EN;// запускаем DMA для USART
	DMA1->IFCR |= DMA_IFCR_CTCIF1;
	}
}
}
При данной настройке Программа работает и выдает синус. Однако мне нужно найти выход из положения, как получать синус не сдвигая на 4 бита вправо результат после каждого преобразования
uk8amk
Поставщик валерьянки для Кота
Сообщения: 2222
Зарегистрирован: Вт ноя 27, 2007 11:32:06
Откуда: Tashkent

Re: STM32F103 (DMA+ADC+USART)

Сообщение uk8amk »

Замечание по АЦП:
11.12 ADC registers
The peripheral registers have to be accessed by words (32-bit).
Т.е. размер источника АЦП ДМА надо выставлять как 32 битное слово.

Я не понял что вы в конечном итоге желаете получить:
1) 2500 8-битных выборок
2) 2500 16-битных слов, это будет 2500*2 ДМА транзакций для УСАРТ.
Foxek
Первый раз сказал Мяу!
Сообщения: 35
Зарегистрирован: Сб дек 28, 2013 20:31:22

Re: STM32F103 (DMA+ADC+USART)

Сообщение Foxek »

мне нужно для начала чтобы АЦП сделал 2500 преобразований а ДМА переместил их в буфер после чего ДМА отправил их по UART в компьютер, где я должен получить числа по которым смогу построить синусоиду(или не числа а символы таблицы аски которые потом можно перевести в 10ичное число и построить график в последствии)
Foxek
Первый раз сказал Мяу!
Сообщения: 35
Зарегистрирован: Сб дек 28, 2013 20:31:22

Re: STM32F103 (DMA+ADC+USART)

Сообщение Foxek »

И АЦП не 32 битный, а 12 бит!

12-bit resolution
uk8amk
Поставщик валерьянки для Кота
Сообщения: 2222
Зарегистрирован: Вт ноя 27, 2007 11:32:06
Откуда: Tashkent

Re: STM32F103 (DMA+ADC+USART)

Сообщение uk8amk »

Вне зависимости от того, сколько бит в АЦП размер слова в кортексе 32 бит. Он какбы про АЦП ничего не знает. Про это как раз и гласит вышеуказанная цитата из юзермануала.

Смотрите, 12 битное число укладывается в 16-битное полуслово.
УАРТ может выплюнуть только 8 бит. Поэтому для передачи одной выборки надо сделать две 8-битные пересылки. И число данных теперь будет CNDTR=2500*2.
Соответственно для ДМА надо указать размерность буфера 8 бит и размерность регистра УАРТ тоже 8 бит.

Вы же в своём коде указываете размерность приёмника 8 бит, а размерность источника 16 бит. Согласно документации, при этом будет копироваться только младший байт. Поэтому вам приходится сдвигать 16-битное полуслово, чтобы старшие разряды попали в младший байт.
HHIMERA
Друг Кота
Сообщения: 4583
Зарегистрирован: Вс дек 05, 2010 06:10:34
Откуда: ЮВ

Re: STM32F103 (DMA+ADC+USART)

Сообщение HHIMERA »

uk8amk писал(а):Соответственно для ДМА надо указать размерность буфера 8 бит и размерность регистра УАРТ тоже 8 бит.
Угу... но т.к. буфер объявлен как 16 бит, то всё вывернет на изнанку...
"Я не даю готовых решений, я заставляю думать!"(С)
Foxek
Первый раз сказал Мяу!
Сообщения: 35
Зарегистрирован: Сб дек 28, 2013 20:31:22

Re: STM32F103 (DMA+ADC+USART)

Сообщение Foxek »

Понятно. А никак нельзя по другому? без отправки 2*2500. мне просто скорость важна.
uk8amk
Поставщик валерьянки для Кота
Сообщения: 2222
Зарегистрирован: Вт ноя 27, 2007 11:32:06
Откуда: Tashkent

Re: STM32F103 (DMA+ADC+USART)

Сообщение uk8amk »

то всё вывернет на изнанку...
С какого перепугу? Какая разница ДМА как копировать буфер, побайтово или пословно. И откуда он знает как объявлен int8 buffer[], int16 buffer[] или int32 buffer[]. Единственно что побайтово будет длиннее по времени.
А никак нельзя по другому?
По другому чтобы выделить байт надо провести определенные математические операции. ДМА это не умеет, процессор привлекать вы не хотите.
В качестве бредовой идеи: сделать выравнивание результата налево(ALIGN) и провести невыровненный байтовый доступ к старщему байту регистра ADC_DR. Вдруг получится.

Да и что за задача у вас такая, что отправить через медленный УАРТ у вас времени хватает, а быстро сделать сдвиг - нет?
Аватара пользователя
balmer
Это не хвост, это антенна
Сообщения: 1433
Зарегистрирован: Вс дек 02, 2012 03:13:48
Откуда: Калининград

Re: STM32F103 (DMA+ADC+USART)

Сообщение balmer »

Foxek писал(а):Понятно. А никак нельзя по другому? без отправки 2*2500. мне просто скорость важна.
Что-бы не грузить процессор можно сделать так.
- запустить DAC так, чтобы он через DMA складывал данные в буфер.
- реализовать обработчики прерываний "заполнена половина буфера" и "заполнен весь буыфер"
- когда один из этих обработчиков срабатывает - быстро копируем все готовые данные в DMA буфер для UART и запускаем, чтобы передавал.

А если важна скорость - прикрутите передачу через USB.
misyachniy
Прорезались зубы
Сообщения: 219
Зарегистрирован: Вт июл 02, 2013 09:17:49

Re: STM32F103 (DMA+ADC+USART)

Сообщение misyachniy »

Лирическое отступление:
uk8amk писал(а): С какого перепугу? Какая разница ДМА как копировать буфер, побайтово или пословно. И откуда он знает как объявлен int8 buffer[], int16 buffer[] или int32 buffer[]. Единственно что побайтово будет длиннее по времени.
В STM32F103 DMA не запускал.
Но обычно в микроконтроллерах DMA требует выравнивание на границу равную 4 байта.
Для ATMEL SAM3U - я выравнивал. (директивой pragma data alignment)

По сути:
Foxek писал(а):При данной настройке Программа работает и выдает синус. Однако мне нужно найти выход из положения, как получать синус не сдвигая на 4 бита вправо результат после каждого преобразования.
Тут явно проблема с выравниванием
У вас:

Код: Выделить всё

ADC1->CR2 &= ~ADC_CR2_ALIGN; //Выравнивание по правому краю
В примерах

Код: Выделить всё

//right 12-bit data alignment in ADC data register
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
Может бит только на запись?
vdavid
Мучитель микросхем
Сообщения: 410
Зарегистрирован: Чт ноя 13, 2008 16:33:42

Re: STM32F103 (DMA+ADC+USART)

Сообщение vdavid »

Тема, конечно, безнадежно устарела. Но решение есть:

Код: Выделить всё

    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(ADC1->DR)+1;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;


    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Left;
Может кому и пригодится.
Ответить

Вернуться в «ARM»