STM32 новичку в ARM что к чему

Кто любит RISC в жизни, заходим, не стесняемся.
Аватара пользователя
pavell
Открыл глаза
Сообщения: 56
Зарегистрирован: Вт дек 29, 2015 11:33:49

Re: STM32 новичку в ARM что к чему

Сообщение pavell »

Уважаемые, подскажите по организации кольцевого буфера.
Для примера возьмем самый распространенный вариант: АЦП -> DMA -> UART.
Создаем буфер размеров 10 байт. После того, как АЦП заполнил первые 5 байт вызывается обработчик прерывания DMA (половина буфера), который эти же первые 5 байт отправляет в UART, параллельно АЦП отправляет вторые 5 байт в буфер. По заполнению буфера вызывается второй обработчик прерывания (полный буфер) который отправляет вторые 5 байт в UART. Пока ход моих мыслей правильный?

Но тут возникает вопрос синхронизации, т.к. ADC->DMA явно быстрее DMA->UART. То возможна ситуация когда АЦП уже заполнил первые 5 байт буфера, а USART еще не отправил вторые 5 байт буфера, как тут поступить?
Реклама
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: STM32 новичку в ARM что к чему

Сообщение Reflector »

[uquote="pavell",url="/forum/viewtopic.php?p=3569044#p3569044"]Но тут возникает вопрос синхронизации, т.к. ADC->DMA явно быстрее DMA->UART. То возможна ситуация когда АЦП уже заполнил первые 5 байт буфера, а USART еще не отправил вторые 5 байт буфера, как тут поступить?[/uquote]
Для начала нужно четко понять что именно хочется получить, потому что судя по написанному ты хочешь непрерывно отправлять по USART данные которые складываются в буфер быстрее, чем физически их можно оттуда забирать...
Реклама
Аватара пользователя
pavell
Открыл глаза
Сообщения: 56
Зарегистрирован: Вт дек 29, 2015 11:33:49

Re: STM32 новичку в ARM что к чему

Сообщение pavell »

[uquote="Reflector",url="/forum/viewtopic.php?p=3569107#p3569107"]Для начала нужно четко понять что именно хочется получить, ...[/uquote]
Непрерывная передача данных из АЦП в УАРТ посредством DMA
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: STM32 новичку в ARM что к чему

Сообщение Reflector »

[uquote="pavell",url="/forum/viewtopic.php?p=3569112#p3569112"]Непрерывная передача данных из АЦП в УАРТ посредством DMA[/uquote]
Вот, если непрерывная, значит нужно чтобы скорость с которой АЦП складывает данные в буфер была как минимум не больше, а лучше чуть меньше скорости, с которой УАРТ эти данные будет забирать. Значит нужно замедлять АЦП, там есть делитель частоты, десяток фиксированных значений для Sampling time и всегда можно в качестве триггера использовать таймер, тогда скорость может быть практически какой угодно.
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
pavell
Открыл глаза
Сообщения: 56
Зарегистрирован: Вт дек 29, 2015 11:33:49

Re: STM32 новичку в ARM что к чему

Сообщение pavell »

Таймер имеется ввиду пинать АЦП?
Без снижения частоты шины только делителем и выбором времени семплирования АЦП получается самое медленное 126мкс@8МГц. УАРТ - либо 72мкс (115200), либо 138мкс (57600). Если я правильно понимаю, то эта разница времени обработки будет проявляться только в моменты ожидания заполнения буфера и его отправки. И тут чем больше буфер, тем более она заметна?
Реклама
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: STM32 новичку в ARM что к чему

Сообщение Reflector »

[uquote="pavell",url="/forum/viewtopic.php?p=3569268#p3569268"]Таймер имеется ввиду пинать АЦП?
Без снижения частоты шины только делителем и выбором времени семплирования АЦП получается самое медленное 126мкс@8МГц. УАРТ - либо 72мкс (115200), либо 138мкс (57600). Если я правильно понимаю, то эта разница времени обработки будет проявляться только в моменты ожидания заполнения буфера и его отправки. И тут чем больше буфер, тем более она заметна?[/uquote]
Таймер генерит, например, Update, значит в поле CR2_MMS выбираем соответствующий режим. При этом он пинает АЦП, хоть раз в минуту, для этого нужно указать в поле ADC_CFGR_EXTSEL подходящее событие, сам АЦП при этом может работать с минимальными делителями и временем семплирования. Для начала я бы взял достаточно большой буфер и заполнял его один раз подавая на вход меандр, потом передаешь весь буфер по USART и смотришь что получилось. Если все в порядке, можно пытаться передавать непрерывно, проще наверное оцифровывать медленнее и в прерывании по заполнению половины буфера запускать более быструю отправку. И почему только 115200? 2М должно работать, или даже 2.5М...
Реклама
Аватара пользователя
pavell
Открыл глаза
Сообщения: 56
Зарегистрирован: Вт дек 29, 2015 11:33:49

Re: STM32 новичку в ARM что к чему

Сообщение pavell »

Спасибо, вечером по экспериментирую.

[uquote="Reflector",url="/forum/viewtopic.php?p=3569302#p3569302"]И почему только 115200? 2М должно работать, или даже 2.5М...[/uquote]

Вот я тупанул, STM до 6М позволяет же )
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: STM32 новичку в ARM что к чему

Сообщение Reflector »

[uquote="pavell",url="/forum/viewtopic.php?p=3569310#p3569310"]Вот я тупанул, STM до 6М позволяет же )[/uquote]
Смотря куда передавать, если на комп, то распространенные адаптеры больше 2-2.5M не тянут.
Аватара пользователя
hosturik
Потрогал лапой паяльник
Сообщения: 354
Зарегистрирован: Чт июл 24, 2014 23:09:23
Откуда: Киев

Re: STM32 новичку в ARM что к чему

Сообщение hosturik »

Привет.
Осваиваю STM32 и столкнулся с проблемой, вроде решил, но не понятно почему она возникает.
Когда меняю частоту ШИМ в процессе выполнения программы
происходит остановка таймера, а через несколько секунд запуск уже с новой частотой.
Меняю вот так в главном цикле:
if(flag){
flag = 0;
TIM2->ARR = new_freq;
}
Проблема уходит если этот код выполнять в обработчике прерывания или а callback функции.
Подскажите почему так происходит, хочется разобраться в причине
Аватара пользователя
Ярослав555
Поставщик валерьянки для Кота
Сообщения: 2081
Зарегистрирован: Пт май 31, 2013 17:14:38
Откуда: Украина, Винница

Re: STM32 новичку в ARM что к чему

Сообщение Ярослав555 »

[uquote="pavell",url="/forum/viewtopic.php?p=3569044#p3569044"]АЦП -> DMA -> UART[/uquote]
Я делал ацп по юарту. У меня было 4 (внешних) ацп с периодом вычитки 20мС. Пробовал гнать по юарту и понял что часть данных бьется. На ПК написал прогу которая из потока данных делала график и там все было четко видно. Это случалось редко, но было критично для анализа работы установки и отловления глюков-багов.
Потом я в посылку прикрепил црц от модбаса и сделал избыточность посылок. А чтобы на ПК различать посылки, еще добавил порядковый номер из одного байта. Вот тогда логирование заработало стабильно. Уложился в 38400.
Аватара пользователя
pavell
Открыл глаза
Сообщения: 56
Зарегистрирован: Вт дек 29, 2015 11:33:49

Re: STM32 новичку в ARM что к чему

Сообщение pavell »

[uquote="hosturik",url="/forum/viewtopic.php?p=3569846#p3569846"]TIM2->ARR = new_freq;[/uquote]

TIM2_CR_ARPE бит установлен?

Добавлено after 8 minutes 55 seconds:
[uquote="Ярослав555",url="/forum/viewtopic.php?p=3569859#p3569859"][uquote="pavell",url="/forum/viewtopic.php?p=3569044#p3569044"]АЦП -> DMA -> UART[/uquote]
Я делал ацп по юарту.[/uquote]
Данные напрямую слались из АЦП в УАРТ? Я почему озадачился DMA, у меня данные идут с двух каналов и при пересылке напрямую тоже лагают. CRC он же только для контроля целостности полученного пакета, если же он изначально косячно сформирован то не поможет.
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: STM32 новичку в ARM что к чему

Сообщение Reflector »

[uquote="hosturik",url="/forum/viewtopic.php?p=3569846#p3569846"]Проблема уходит если этот код выполнять в обработчике прерывания или а callback функции.[/uquote]
Таймер определяет что досчитал до конца сравнивая текущее значение счетчика с ARR, а не определяя больше ли оно, т.е. если в ARR было 2000 и досчитав до 1000 принудительно записать в ARR 500, то таймер будет считать пока не переполнится, а для 32-х битного таймера это могут быть и минуты. Но все будет нормально если писать в ARR значение больше текущего значения счетчика, или если запись в ARR буферизированна, тогда она происходит при апдейте и счетчик тогда нулевой. То же самое верно для прерывания, тогда счетчик только начинает считать и значение записываемое в ARR наверняка его больше.
Аватара пользователя
Ярослав555
Поставщик валерьянки для Кота
Сообщения: 2081
Зарегистрирован: Пт май 31, 2013 17:14:38
Откуда: Украина, Винница

Re: STM32 новичку в ARM что к чему

Сообщение Ярослав555 »

[uquote="pavell",url="/forum/viewtopic.php?p=3569865#p3569865"]Данные напрямую слались из АЦП в УАРТ? Я почему озадачился DMA, у меня данные идут с двух каналов и при пересылке напрямую тоже лагают. CRC он же только для контроля целостности полученного пакета, если же он изначально косячно сформирован то не поможет.[/uquote]
Да нет. Там СПИ, вычитка, контроль состояний, аварий и т.п. И только потом ЮАРТ.

Добавлено after 4 minutes 3 seconds:
[uquote="pavell",url="/forum/viewtopic.php?p=3569865#p3569865"]CRC он же только для контроля целостности полученного пакета, если же он изначально косячно сформирован то не поможет.[/uquote]
А как это можно "изначально косячно сформировать CRC"? Црц он и есть црц, процом прощитан и к посылке прикреплен. Если в приемнике не сошлось - отбрасываем пакет. Передеча исбыточная - 2-4 одинаковых пакета подряд. Если приемник пакет принял, то запоминает его номер и дальше такие же номера отбрасываем.

Добавлено after 4 minutes 12 seconds:
Кстати, для разделения пакетов я не использовал никаких таймаутов - данные идут сплошным потоком. ПК знает длину посылки и по шаблону ищет совпадение пакета и црц, двигается по 1му байту и убирает из буффера, пока не найдет пакет. Дальше получается автоматическая синхронизация - отрезаем по целому пакету, пока не случится сбой, потом опять по 1му байту и т.д.
Если тулить таймауты то в 38400 не укладывался.
Аватара пользователя
hosturik
Потрогал лапой паяльник
Сообщения: 354
Зарегистрирован: Чт июл 24, 2014 23:09:23
Откуда: Киев

Re: STM32 новичку в ARM что к чему

Сообщение hosturik »

[uquote="pavell",url="/forum/viewtopic.php?p=3569865#p3569865"]TIM2_CR_ARPE бит установлен?[/uquote]
И с ним и без него пробовал, разницы особо не заметил. Насколько я знаю это помогает от кривых имульсов при изменении частоты, у меня же несколько иная ситуация
[uquote="Reflector",url="/forum/viewtopic.php?p=3569890#p3569890"]для 32-х битного таймера это могут быть и минуты. Но все будет нормально если писать в ARR значение больше текущего значения счетчика[/uquote]
Кстати да, проблема проявляется когда я записываю в ARR меньшее значение чем там было. Причем проявляется не всегда.
Чем больше разница между текущим и новым (меньшим значениям) тем больше вероятность глюка.
Например было 20 000, стало 18 000 глюк будет очень редко, было 20 000, стало 3000, глюк будет почти наверняка.
Тупо срыв генерации или низкий или высокий уровень устанавливается на ножке МК.
Но таймер у меня 16 битный без делителя, на 48 МГц работает, частоту только с помощью регистра сравнения меняю, поэтому доситывать до переполнения будет быстро.
Здесь что то другое.
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: STM32 новичку в ARM что к чему

Сообщение Reflector »

[uquote="hosturik",url="/forum/viewtopic.php?p=3570153#p3570153"]Чем больше разница между текущим и новым (меньшим значениям) тем больше вероятность глюка.
Например было 20 000, стало 18 000 глюк будет очень редко, было 20 000, стало 3000, глюк будет почти наверняка.[/uquote]
Так правильно, если изменять ARR в произвольное время, то в первом случае глюк будет наблюдаться только когда счетчик больше 18K, т.е. с вероятностью 1/10. А во-втором случае все практически наоборот...
Но таймер у меня 16 битный без делителя, на 48 МГц работает, частоту только с помощью регистра сравнения меняю, поэтому доситывать до переполнения будет быстро.
Здесь что то другое.
Скорее не другое, а что-то еще :) Но решение уже озвучивали, включение CR1_ARPE должно помочь.

Кстати, что за мк? 48 MHz как бы намекают на F0, а там TIM2 32-х битный.
Аватара пользователя
pavell
Открыл глаза
Сообщения: 56
Зарегистрирован: Вт дек 29, 2015 11:33:49

Re: STM32 новичку в ARM что к чему

Сообщение pavell »

Что-то не срастается моя идея ADC->DMA->UART. Судя по отладчику данные бегают, а вот прерывания не обрабатываться. Может кто подскажет что не так?
Спойлер

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

#include "stm32f0xx.h"

uint16_t buff[100];


void DMA1_Channel1_IRQHandler(void){
	//empty	
}

void DMA1_Channel2_3_IRQHandler(void){
	//empty
}

void gpio_ini(){
	RCC->AHBENR |= RCC_AHBENR_GPIOBEN;
	GPIOB->MODER |= GPIO_MODER_MODER6_1 | GPIO_MODER_MODER0 | GPIO_MODER_MODER1;
	GPIOB->OTYPER &= ~GPIO_OTYPER_OT_6;
	GPIOB->PUPDR &= ~GPIO_PUPDR_PUPDR6_0;
	GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR6;
	GPIOB->AFR[0] &= ~GPIO_AFRL_AFRL6;	
}

void usart_ini(){
	RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
	USART1->BRR = SystemCoreClock/256000;
	USART1->CR3 = USART_CR3_DMAT;
	USART1->CR1 |= USART_CR1_TE; 
	USART1->CR1 |= USART_CR1_TCIE;
	USART1->CR1 |= USART_CR1_UE;
}

void adc_ini(){
	RCC->APB2ENR |= RCC_APB2ENR_ADCEN;
	ADC1->CHSELR |= ADC_CHSELR_CHSEL8 | ADC_CHSELR_CHSEL9;	
	ADC1->SMPR  |= ADC_SMPR_SMP_2 | ADC_SMPR_SMP_0; 			
	ADC1->CFGR2 |= ADC_CFGR2_CKMODE_1;	
	ADC1->CFGR1 &= ~ADC_CFGR1_SCANDIR;	
	ADC1->CFGR1 |= ADC_CFGR1_CONT;
	ADC1->CFGR1 &= ~ADC_CFGR1_RES_Msk;
	ADC1->CFGR1 |= ADC_CFGR1_DMACFG;
	ADC1->CFGR1 |= ADC_CFGR1_DMAEN;
	
	ADC1->CR |= ADC_CR_ADCAL;
		while(ADC1->CR & ADC_CR_ADCAL){
	}
	
	ADC1->CR |= ADC_CR_ADEN;
}

void dma_ini(){
	RCC->AHBENR |= RCC_AHBENR_DMAEN;
	
// DMA1 ADC->DMA init
	DMA1_Channel1->CPAR |= (uint32_t)&ADC1->DR;
	DMA1_Channel1->CMAR |= (uint32_t)&buff[0];
	DMA1_Channel1->CNDTR |= 100;
	DMA1_Channel1->CCR &= ~DMA_CCR_MEM2MEM_Msk;
	DMA1_Channel1->CCR &= ~DMA_CCR_DIR;	
	DMA1_Channel1->CCR &= ~DMA_CCR_PL_Msk;
	DMA1_Channel1->CCR |= DMA_CCR_MSIZE_0;
	DMA1_Channel1->CCR |= DMA_CCR_PSIZE_0;
	DMA1_Channel1->CCR |= DMA_CCR_MINC;
	DMA1_Channel1->CCR |= DMA_CCR_CIRC;
	DMA1_Channel1->CCR |= DMA_CCR_HTIE;
	DMA1_Channel1->CCR |= DMA_CCR_TCIE;
	DMA1_Channel1->CCR |= DMA_CCR_EN;
	NVIC_EnableIRQ(DMA1_Channel1_IRQn);
	NVIC_SetPriority(DMA1_Channel1_IRQn,2);

// DMA2 DMA->UART init
	DMA1_Channel2->CPAR |= (uint32_t)&USART1->TDR;
	DMA1_Channel2->CMAR |= (uint32_t)&buff[0];
	DMA1_Channel2->CNDTR |= 100;
	DMA1_Channel2->CCR &= ~DMA_CCR_MEM2MEM_Msk;
	DMA1_Channel2->CCR |= DMA_CCR_DIR;
	DMA1_Channel2->CCR &= ~DMA_CCR_PL_0;
	DMA1_Channel2->CCR &= ~DMA_CCR_MSIZE_Msk;
	DMA1_Channel2->CCR &= ~DMA_CCR_PSIZE_Msk;
	DMA1_Channel2->CCR |= DMA_CCR_MINC;
	DMA1_Channel2->CCR |= DMA_CCR_CIRC;
	DMA1_Channel2->CCR |= DMA_CCR_HTIE;
	DMA1_Channel2->CCR |= DMA_CCR_TCIE;
	DMA1_Channel2->CCR |= DMA_CCR_EN;
	NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
	NVIC_SetPriority(DMA1_Channel2_3_IRQn,1);	
}

int main(){
	void __enable_irq(void);
	NVIC->ISER[0] = 0x03<<7;
	
	dma_ini();
	gpio_ini();
	adc_ini();
	usart_ini();
	

	ADC1->CR |= ADC_CR_ADSTART;
	while(1){
		//empty
	}
	return 0;
}

Аватара пользователя
dosikus
Друг Кота
Сообщения: 3604
Зарегистрирован: Пн июл 28, 2008 22:12:01

Re: STM32 новичку в ARM что к чему

Сообщение dosikus »

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

DMA1_Channel1->CPAR |= (uint32_t)&ADC1->DR;
   DMA1_Channel1->CMAR |= (uint32_t)&buff[0];
   DMA1_Channel1->CNDTR |= 100;
Обычные ляпы?
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: STM32 новичку в ARM что к чему

Сообщение VladislavS »

Да ему "так наглядней" :)
Аватара пользователя
pavell
Открыл глаза
Сообщения: 56
Зарегистрирован: Вт дек 29, 2015 11:33:49

Re: STM32 новичку в ARM что к чему

Сообщение pavell »

[uquote="VladislavS",url="/forum/viewtopic.php?p=3574334#p3574334"]Да ему "так наглядней"[/uquote]
Не угадали, Владислав.
dosikus писал(а):Обычные ляпы?
Хуже, невнимательность.
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: STM32 новичку в ARM что к чему

Сообщение VladislavS »

[uquote="pavell",url="/forum/viewtopic.php?p=3574389#p3574389"]Не угадали, Владислав.[/uquote]Да тут и гадать не надо.
У того кто вот так &buff[0] берёт адрес массива и особенно автора вот этого

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

   DMA1_Channel1->CCR &= ~DMA_CCR_MEM2MEM_Msk;
   DMA1_Channel1->CCR &= ~DMA_CCR_DIR;   
   DMA1_Channel1->CCR &= ~DMA_CCR_PL_Msk;
   DMA1_Channel1->CCR |= DMA_CCR_MSIZE_0;
   DMA1_Channel1->CCR |= DMA_CCR_PSIZE_0;
   DMA1_Channel1->CCR |= DMA_CCR_MINC;
   DMA1_Channel1->CCR |= DMA_CCR_CIRC;
   DMA1_Channel1->CCR |= DMA_CCR_HTIE;
   DMA1_Channel1->CCR |= DMA_CCR_TCIE;
   DMA1_Channel1->CCR |= DMA_CCR_EN;
большие проблемы. :(
Ответить

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