STM32F103 (DMA+ADC+USART)
STM32F103 (DMA+ADC+USART)
Добрый вечер! Программирую связку STM32F103 DMA ADC USART. Одним каналом DMA забирает данные из регистра ADC и помещает в буфер, причем размер данных и буфера и ADC в DMA указаны как 16 бит.
После чего так же при помощи DMA перекладываю данные из буфера в USART. В инициализации DMA для буфера выбрано 16 бит а для USART 8 бит. При такой инициализации данные приходящие в компьютер не соответствуют действительности. Однако создав специальную функцию которая сдвигает значение АЦП на 4 бита вправо, я получаю идеальный синус. Помогите, как решить проблему не заморачиваясь с битовым сдвигом значения регистра АЦП, так как это занимает время которое мне в последствии пригодится. Должен быть способ настроить ДМА так чтобы он сам конвертировал 16 бит буфера в 8 бит USART.
Подскажите решение проблемы)Заранее благодарен
После чего так же при помощи DMA перекладываю данные из буфера в USART. В инициализации DMA для буфера выбрано 16 бит а для USART 8 бит. При такой инициализации данные приходящие в компьютер не соответствуют действительности. Однако создав специальную функцию которая сдвигает значение АЦП на 4 бита вправо, я получаю идеальный синус. Помогите, как решить проблему не заморачиваясь с битовым сдвигом значения регистра АЦП, так как это занимает время которое мне в последствии пригодится. Должен быть способ настроить ДМА так чтобы он сам конвертировал 16 бит буфера в 8 бит USART.
Подскажите решение проблемы)Заранее благодарен
- Реклама
Re: STM32F103 (DMA+ADC+USART)
Решений нет... Есть референс... и там английским по белому написано что и как может ДМА...
"Я не даю готовых решений, я заставляю думать!"(С)
Re: STM32F103 (DMA+ADC+USART)
У АЦП есть настройка которая указывает как выравнивать данные, по правому или по левому краю. Если по левому, то 4 младших бита из 16 будут пустыми, вот вам и приходится сдвигать на 4 бита вправо. Ну или наоборот 
Иван Сусанин - первый полупроводник 
-
uk8amk
- Поставщик валерьянки для Кота
- Сообщения: 2222
- Зарегистрирован: Вт ноя 27, 2007 11:32:06
- Откуда: Tashkent
Re: STM32F103 (DMA+ADC+USART)
Ничего никуда не надо конвертировать.
Укажите правильно размерность данных буфера SRAM 8 бит и USART 8 бит(PSIZE, MSIZE).
Укажите правильно размерность данных буфера SRAM 8 бит и USART 8 бит(PSIZE, MSIZE).
Re: STM32F103 (DMA+ADC+USART)
Спасибо за советы. Сейчас буду пробовать, завтра отпишусь что помогло а что нет)
- Реклама
Re: STM32F103 (DMA+ADC+USART)
Ни один ни другой совет результатов не дал!((
-
uk8amk
- Поставщик валерьянки для Кота
- Сообщения: 2222
- Зарегистрирован: Вт ноя 27, 2007 11:32:06
- Откуда: Tashkent
Re: STM32F103 (DMA+ADC+USART)
Попробуйте выложить код с описанием того, что делаете и как реальный результат отличается от ожидаемого.
Re: STM32F103 (DMA+ADC+USART)
Я не буду выкладывать весь код(инициализация USART, GPIO и прочего). Так как эти части программы работают сто процентно. Я выложу инициализацию ADC DMA и Прерывание в котором собственно все и происходит:
При данной настройке Программа работает и выдает синус. Однако мне нужно найти выход из положения, как получать синус не сдвигая на 4 бита вправо результат после каждого преобразования
Код: Выделить всё
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;
}
}
}-
uk8amk
- Поставщик валерьянки для Кота
- Сообщения: 2222
- Зарегистрирован: Вт ноя 27, 2007 11:32:06
- Откуда: Tashkent
Re: STM32F103 (DMA+ADC+USART)
Замечание по АЦП:
Я не понял что вы в конечном итоге желаете получить:
1) 2500 8-битных выборок
2) 2500 16-битных слов, это будет 2500*2 ДМА транзакций для УСАРТ.
Т.е. размер источника АЦП ДМА надо выставлять как 32 битное слово.11.12 ADC registers
The peripheral registers have to be accessed by words (32-bit).
Я не понял что вы в конечном итоге желаете получить:
1) 2500 8-битных выборок
2) 2500 16-битных слов, это будет 2500*2 ДМА транзакций для УСАРТ.
Re: STM32F103 (DMA+ADC+USART)
мне нужно для начала чтобы АЦП сделал 2500 преобразований а ДМА переместил их в буфер после чего ДМА отправил их по UART в компьютер, где я должен получить числа по которым смогу построить синусоиду(или не числа а символы таблицы аски которые потом можно перевести в 10ичное число и построить график в последствии)
Re: STM32F103 (DMA+ADC+USART)
И АЦП не 32 битный, а 12 бит!
12-bit resolution
12-bit resolution
-
uk8amk
- Поставщик валерьянки для Кота
- Сообщения: 2222
- Зарегистрирован: Вт ноя 27, 2007 11:32:06
- Откуда: Tashkent
Re: STM32F103 (DMA+ADC+USART)
Вне зависимости от того, сколько бит в АЦП размер слова в кортексе 32 бит. Он какбы про АЦП ничего не знает. Про это как раз и гласит вышеуказанная цитата из юзермануала.
Смотрите, 12 битное число укладывается в 16-битное полуслово.
УАРТ может выплюнуть только 8 бит. Поэтому для передачи одной выборки надо сделать две 8-битные пересылки. И число данных теперь будет CNDTR=2500*2.
Соответственно для ДМА надо указать размерность буфера 8 бит и размерность регистра УАРТ тоже 8 бит.
Вы же в своём коде указываете размерность приёмника 8 бит, а размерность источника 16 бит. Согласно документации, при этом будет копироваться только младший байт. Поэтому вам приходится сдвигать 16-битное полуслово, чтобы старшие разряды попали в младший байт.
Смотрите, 12 битное число укладывается в 16-битное полуслово.
УАРТ может выплюнуть только 8 бит. Поэтому для передачи одной выборки надо сделать две 8-битные пересылки. И число данных теперь будет CNDTR=2500*2.
Соответственно для ДМА надо указать размерность буфера 8 бит и размерность регистра УАРТ тоже 8 бит.
Вы же в своём коде указываете размерность приёмника 8 бит, а размерность источника 16 бит. Согласно документации, при этом будет копироваться только младший байт. Поэтому вам приходится сдвигать 16-битное полуслово, чтобы старшие разряды попали в младший байт.
Re: STM32F103 (DMA+ADC+USART)
Угу... но т.к. буфер объявлен как 16 бит, то всё вывернет на изнанку...uk8amk писал(а):Соответственно для ДМА надо указать размерность буфера 8 бит и размерность регистра УАРТ тоже 8 бит.
"Я не даю готовых решений, я заставляю думать!"(С)
Re: STM32F103 (DMA+ADC+USART)
Понятно. А никак нельзя по другому? без отправки 2*2500. мне просто скорость важна.
-
uk8amk
- Поставщик валерьянки для Кота
- Сообщения: 2222
- Зарегистрирован: Вт ноя 27, 2007 11:32:06
- Откуда: Tashkent
Re: STM32F103 (DMA+ADC+USART)
С какого перепугу? Какая разница ДМА как копировать буфер, побайтово или пословно. И откуда он знает как объявлен int8 buffer[], int16 buffer[] или int32 buffer[]. Единственно что побайтово будет длиннее по времени.то всё вывернет на изнанку...
По другому чтобы выделить байт надо провести определенные математические операции. ДМА это не умеет, процессор привлекать вы не хотите.А никак нельзя по другому?
В качестве бредовой идеи: сделать выравнивание результата налево(ALIGN) и провести невыровненный байтовый доступ к старщему байту регистра ADC_DR. Вдруг получится.
Да и что за задача у вас такая, что отправить через медленный УАРТ у вас времени хватает, а быстро сделать сдвиг - нет?
- balmer
- Это не хвост, это антенна
- Сообщения: 1433
- Зарегистрирован: Вс дек 02, 2012 03:13:48
- Откуда: Калининград
Re: STM32F103 (DMA+ADC+USART)
Что-бы не грузить процессор можно сделать так.Foxek писал(а):Понятно. А никак нельзя по другому? без отправки 2*2500. мне просто скорость важна.
- запустить DAC так, чтобы он через DMA складывал данные в буфер.
- реализовать обработчики прерываний "заполнена половина буфера" и "заполнен весь буыфер"
- когда один из этих обработчиков срабатывает - быстро копируем все готовые данные в DMA буфер для UART и запускаем, чтобы передавал.
А если важна скорость - прикрутите передачу через USB.
-
misyachniy
- Прорезались зубы
- Сообщения: 219
- Зарегистрирован: Вт июл 02, 2013 09:17:49
Re: STM32F103 (DMA+ADC+USART)
Лирическое отступление:
Но обычно в микроконтроллерах DMA требует выравнивание на границу равную 4 байта.
Для ATMEL SAM3U - я выравнивал. (директивой pragma data alignment)
По сути:
У вас:
В примерах
Может бит только на запись?
В STM32F103 DMA не запускал.uk8amk писал(а): С какого перепугу? Какая разница ДМА как копировать буфер, побайтово или пословно. И откуда он знает как объявлен int8 buffer[], int16 buffer[] или int32 buffer[]. Единственно что побайтово будет длиннее по времени.
Но обычно в микроконтроллерах 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;
Re: STM32F103 (DMA+ADC+USART)
Тема, конечно, безнадежно устарела. Но решение есть:
Может кому и пригодится.
Код: Выделить всё
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;


