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

Кто любит RISC в жизни, заходим, не стесняемся.
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

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

Сообщение WiseLord »

А не может ли здесь произойти так, что CurrentChannel поменялся с 1 на 2, а EOSEQ флаг остался равен 0 (не успел, например, выставиться)?

Соотвественно, сброс индекса в 0 не происходит на этой итерации, происходит ещё одна, когда данные пишутся в ADC_array[2], по сути, портя память.

Ну и сдвиг каналов происходит при этом.

Я бы в этом коде не стал надеятся на то, что ADC_ISR_EOSEQ будет в нужном состоянии, как только будет прочитан последний канал в последовательности. Вещи-то по сути не связанные.
Аватара пользователя
do-vitas
Потрогал лапой паяльник
Сообщения: 363
Зарегистрирован: Вс мар 03, 2019 08:18:34
Откуда: Волгоград

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

Сообщение do-vitas »

Да так все и происходит. Только как это обыграть не пойму. У ф0 серии нет режекционных коналов..
Аватара пользователя
КРАМ
Друг Кота
Сообщения: 25121
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

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

Сообщение КРАМ »

[uquote="do-vitas",url="/forum/viewtopic.php?p=4464499#p4464499"]нет режекционных коналов..[/uquote]
Инжектированных.
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

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

Сообщение WiseLord »

Ну, как минимум, сброс счётчика каналов сделать самостоятельным и независящим от флагов:

Может, как-то так:

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

while ((ADC1->ISR & ADC_ISR_EOC) == 0) /* wait end of conversion */
{
/* For robust implementation, add here time-out management */
}

if ((ADC1->ISR & ADC_ISR_EOC) != 0)         /* checks EOC has triggered the IT */
{
    ADC_array[CurrentChannel] = ADC1->DR;   /* reads data and clears EOC flag */
    CurrentChannel++;                       /* increments the index on ADC_array */
    
    if (CurrentChannel >= 2) {
        CurrentChannel = 0; /* reinitialize the CurrentChannel */
        out_adc = ADC_array[0];in_adc = ADC_array[1];
    }
}

if ((ADC1->ISR & ADC_ISR_EOSEQ) != 0)       /* checks EOSEQ has triggered the IT */
{
    ADC1->ISR |= ADC_ISR_EOSEQ;             /* clears the pending bit */
}
a797945
Мучитель микросхем
Сообщения: 446
Зарегистрирован: Вс ноя 01, 2015 09:15:16
Откуда: 69.Ржев

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

Сообщение a797945 »

будем полагать, что не знаем какой канал сейчас оцифровывается, поэтому считав DR проверяем EOSEQ - если 1 то это последний в очереди. и я полагаю, что в последующем это все таки массив (с чередованием каналов) - иначе зачем массив, это просто две переменные.
Аватара пользователя
do-vitas
Потрогал лапой паяльник
Сообщения: 363
Зарегистрирован: Вс мар 03, 2019 08:18:34
Откуда: Волгоград

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

Сообщение do-vitas »

a797945, да в том и проблема, что как писал WiseLord, тот самый EOSEQ то взлетает а то нет. я конечно решил проблему при помощи костыля: каждый раз перед запуском преобразования, меняю значение регистра ADC1->CFGR1 |= ADC_CFGR1_SCANDIR что меняет направление сканирования каналов ацп, но осадчик остался, а если больше 2-х каналов...
a797945
Мучитель микросхем
Сообщения: 446
Зарегистрирован: Вс ноя 01, 2015 09:15:16
Откуда: 69.Ржев

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

Сообщение a797945 »

выстраивайте ожидание:
1 снимаем флаг EOSEQ, если был
2 ждем когда EOSEQ=1 - текущая очередь заканчивается,
3 снимаем флаги EOSEQ, EOC ,
4 ждем EOC первого из новой очереди
...

да и очередь лучше как-то так задавать (не через |=)
ADC1->CHSELR = ADC_CHSELR_CHSEL2 | ADC_CHSELR_CHSEL5;
Аватара пользователя
do-vitas
Потрогал лапой паяльник
Сообщения: 363
Зарегистрирован: Вс мар 03, 2019 08:18:34
Откуда: Волгоград

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

Сообщение do-vitas »

[uquote="a797945",url="/forum/viewtopic.php?p=4464619#p4464619"]выстраивайте ожидание:

да и очередь лучше как-то так задавать (не через |=)
ADC1->CHSELR = ADC_CHSELR_CHSEL2 | ADC_CHSELR_CHSEL5;[/uquote]
нет разницы какой тут порядок, он идут по порядку, а ADC_CFGR1_SCANDIR определят только напряжение от большего к меньшему либо наоборот.
a797945
Мучитель микросхем
Сообщения: 446
Зарегистрирован: Вс ноя 01, 2015 09:15:16
Откуда: 69.Ржев

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

Сообщение a797945 »

а если посмотреть, действительно EOSEQ пропадает ?

ADC_array[128]=0;

ADC1->ISR |=ADC_ISR_EOC | ADC_ISR_EOSEQ;
for (int i; i<128; i++){

while ((ADC1->ISR & ADC_ISR_EOC) == 0) {}
ADC1->ISR |=ADC_ISR_EOC;

if (ADC1->ISR & ADC_ISR_EOSEQ) {
ADC1->ISR |= ADC_ISR_EOSEQ;
ADC_array = 1;}
else {ADC_array = 0;}
}
если в очереди 2 канала - в массиве ожидается зебра (0,1,0, ...) без пропусков
отредактировал, тороплюсь куда-то.
engine66
Родился
Сообщения: 4
Зарегистрирован: Вт авг 29, 2023 13:45:38

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

Сообщение engine66 »

Здравствуйте!
Вопрос по STM32F103C8
Хочу настроить ADC следующим образом" 8 каналов - медленные (датчики давления, температуры и т. п.) и два канала для оцифровки звука.
Представился такой вариант: Двойным преобразованием ADC1 и ADC2 c DMA с регулярных каналов заполнять массив датчиков 4Х2 непрерывно без прерываний вообще. Считывать их в свободное время. Плюс для оцифровки звука два инжектированных канала, также двойным преобразованием ADC1 и ADC2, периодически запускать по таймеру и считывать результат в прерывании от ADC по завершению преобразования. Можно так сконфигурировать Blue Pill? Или есть другие варианты попроще?
engine66
Родился
Сообщения: 4
Зарегистрирован: Вт авг 29, 2023 13:45:38

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

Сообщение engine66 »

Частота дискретизации звука (приём тональных сигналов) выбрана 14080. Получается 852 такта ADC между прерываниями таймера для старта преобразования ижектированных каналов. Если sampling time выставить максимальным 239,5, то в этот промежуток укладываются три преобразования - один инжектированный (два канала) и два регулярных (четыре канала). Вроде проблем нет.
Аватара пользователя
КРАМ
Друг Кота
Сообщения: 25121
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

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

Сообщение КРАМ »

[uquote="engine66",url="/forum/viewtopic.php?p=4470649#p4470649"]Представился такой вариант: Двойным преобразованием ADC1 и ADC2 c DMA с регулярных каналов заполнять массив датчиков 4Х2 непрерывно без прерываний вообще. Считывать их в свободное время. Плюс для оцифровки звука два инжектированных канала, также двойным преобразованием ADC1 и ADC2[/uquote]
Все поставлено с ног на голову... :facepalm:
Под ДМА должен работать звук, а не датчики. А датчики можно считывать в прерываниях. Они медленные и потому редкие.
Только вот возник вопрос. А куда потом этот звук?
engine66
Родился
Сообщения: 4
Зарегистрирован: Вт авг 29, 2023 13:45:38

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

Сообщение engine66 »

КРАМу
Спасибо за отклик. Звук не под DMA так как планируются некоторые вычисления после приёма каждого сэмпла. это будут команды тональными сигналами, по полсекунды длиной. Думаю использовать синхронное детектирование, для простоты и кажется минимум ресурсов понадобится на вычисления.
А датчики под DMA для того же, чтобы минимум ресурсов на них тратить. Как-то так.

Добавлено after 13 minutes 58 seconds:
То есть процесс будет выглядеть примерно так: Сканируются два оегулярных преобразования и складываются куда надо под ДМА без прерываний, затем как только начинается третье регулярное преобразование, оно прерывается инжектированным преобразованием, данные которого извлекаются через прерывание. После окончания инжектированного преобразования, сканируются третье и четвёртое регулярные преобразования, а как только вновь начинается первое, оно прерывается на инжектированное преобразование и так дальше.
Аватара пользователя
КРАМ
Друг Кота
Сообщения: 25121
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

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

Сообщение КРАМ »

[uquote="engine66",url="/forum/viewtopic.php?p=4471168#p4471168"]Звук не под DMA так как планируются некоторые вычисления после приёма каждого сэмпла. это будут команды тональными сигналами, по полсекунды длиной.[/uquote]
Так и принимайте окнами. Тональные сигналы - это классический ДПФ приемник. Окно приема должно иметь длину рассчитанную из полосы пропускания фильтров. В зависимости от оконной функции оно будет немного больше чем величина обратная полосе фильтра. Скажем, для полосы в 100 Гц окно потребуется примерно 12...15 мс. При частоте дискретизации, например, 8 кГц количество отсчетов в одном окне составит примерно 128. Захватили окно - сделали N-канальный ДПФ - обнаружили сигнал - приняли решение. За полсекунды можно накопить аж 32 окна и получить 32 скалярных значения фильтров. Ну и зачем вам обрабатывать каждый отсчет? :dont_know:
Скажу больше. У АРМов прерывания - полный тормоз. Вы получите на каждом отсчете кучу потерянного времени на вход-сохранение контекста-восстановление контекста-выход... Оно вам зачем?
engine66
Родился
Сообщения: 4
Зарегистрирован: Вт авг 29, 2023 13:45:38

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

Сообщение engine66 »

КРАМу
Вот так вот обрубили полёт моей фантазии )
ОК, выберу какое-нибудь классическое решение.
Аватара пользователя
КРАМ
Друг Кота
Сообщения: 25121
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

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

Сообщение КРАМ »

Обращайтесь, если что...
:)
a797945
Мучитель микросхем
Сообщения: 446
Зарегистрирован: Вс ноя 01, 2015 09:15:16
Откуда: 69.Ржев

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

Сообщение a797945 »

если интересует тон - зачем АЦП ?
Аватара пользователя
КРАМ
Друг Кота
Сообщения: 25121
Зарегистрирован: Чт янв 10, 2008 22:01:02
Откуда: Московская область, Фрязино

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

Сообщение КРАМ »

Ну наверное потому, что детектировть DTMF с помощью АЦП проще, чем городить разного рода суррогаты, рискуя получить всякий бред при помехах.
Аватара пользователя
Эйлер Леонард
Встал на лапы
Сообщения: 104
Зарегистрирован: Пн ноя 04, 2019 09:58:29
Откуда: г. Нижний Тагил Свердл. обл.

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

Сообщение Эйлер Леонард »

Добрый день. Решил на досуге заняться портированием драйвера АЦП ADS1256, который написан для STM32 (С) на 8-и битную архитектуру ATmega(С++14). Но вот оказия - в STM32 не петрю. А драйверок то хороший, полнофункциональный - есть все, что надо и ни чета Ардуиновским библиотекам. Вопрос мой конечно немного глуповатый: Регистр данный в SPI на STM32 тридцатидвухбитный? У мег 8-битный. И для передачи/приема чисел более 8-и бит на AVR-ках их передают кусочками по 8 бит, а потом уже склеивают в одно число. Для АЦП ADS1256 необходимы определенные тайминги при общении с МК по SPI. Напр. отправил 8 бит - перекур в несколько тактов(или микросекунд). Вот по этому и вкрались сомнения по необходимости таймингов после отправки каждого байта.
Регистр данный в SPI на STM32 тридцатидвухбитный?
это для мег
Спойлер

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

#define NOP __asm__ __volatile__ ("nop");
inline static uint32_t transfer24(uint32_t data) {
	union {
		uint32_t val;
		struct { uint8_t lsb, mid, msb; };
	} in, out;
	
	in.val = data;
	
	if(SPCR & bit(DORD)){ // прямой порядок отправки
		
		SPDR = in.lsb; // младший
		NOP;
		while(!( SPSR & bit(SPIF) )){}; //wait
		out.lsb = SPDR;

		SPDR = in.mid; // средний
		NOP;
		while(!( SPSR & bit(SPIF) )){}; //wait
		out.mid = SPDR;

		SPDR = in.msb; // старший
		NOP;
		while(!( SPSR & bit(SPIF) )){}; //wait
		out.msb = SPDR;
		
		} else { // обратный порядок отправки
		
		SPDR = in.msb; // старший
		NOP;
		while(!( SPSR & bit(SPIF) )){}; //wait
		out.msb = SPDR;

		SPDR = in.mid; // средний
		NOP;
		while(!( SPSR & bit(SPIF) )){}; //wait
		out.mid = SPDR;
		
		SPDR = in.lsb; // младший
		NOP;
		while(!( SPSR & bit(SPIF) )){}; //wait
		out.lsb = SPDR;
		
	}
	
	return (out.val);

}
Аватара пользователя
asvhmao
Друг Кота
Сообщения: 3716
Зарегистрирован: Чт мар 07, 2013 20:39:17
Откуда: Краснодар

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

Сообщение asvhmao »

Камень stm32f103cb
В ардуинке попался код настройки таймера TIM1 с первым каналом. Хотел поиграть со всеми четырьмя каналами, с инверсией и выравниванию по центру. Три канала работают, четвёртый не хотит, CHxN тоже молчит.
Где накосячил, пока не разобрался :dont_know:
Опыта с регистрами всего пару дней.

Изображение
Спойлер

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

#include "flprogUtilites.h"
int16_t Timperiod;
int16_t PWM_1;
int16_t PWM_2;
int16_t PWM_3;
int16_t PWM_4;
int16_t Fr;
bool Q;
#define RCC_BASE 0x40021000
#define RCC_APB2ENR ((volatile uint32_t *)(RCC_BASE+0x18))
#define GPIOA_BASE 0x40010800
#define GPIOA_CRH ((volatile uint32_t *)(GPIOA_BASE+0x04))
#define GPIOB_BASE 0x40010C00
#define GPIOB_CRH ((volatile uint32_t *)(GPIOB_BASE+0x04))
#define TIM1_BASE 0x40012C00
#define TIM1_CNT ((volatile uint32_t *)(TIM1_BASE+0x24))
#define TIM1_CR1 ((volatile uint32_t *)(TIM1_BASE+0x00))
#define TIM1_CCMR1 ((volatile uint32_t *)(TIM1_BASE+0x18))
#define TIM1_CCMR2 ((volatile uint32_t *)(TIM1_BASE+0x1C))
#define TIM1_CCER ((volatile uint32_t *)(TIM1_BASE+0x20))
#define TIM1_PSC ((volatile uint32_t *)(TIM1_BASE+0x28))
#define TIM1_ARR ((volatile uint32_t *)(TIM1_BASE+0x2C))
#define TIM1_CCR1 ((volatile uint32_t *)(TIM1_BASE+0x34))
#define TIM1_CCR2 ((volatile uint32_t *)(TIM1_BASE+0x38))
#define TIM1_CCR3 ((volatile uint32_t *)(TIM1_BASE+0x3C))
#define TIM1_CCR4 ((volatile uint32_t *)(TIM1_BASE+0x40))
#define TIM1_BDTR ((volatile uint32_t *)(TIM1_BASE+0x44))
uint16_t test= 0;
uint16_t PWMcontrol= 0;
#define TIM1_CCER ((volatile uint32_t *)(TIM1_BASE+0x20))
#define TIM1_PSC ((volatile uint32_t *)(TIM1_BASE+0x28))
#define TIM1_ARR ((volatile uint32_t *)(TIM1_BASE+0x2C))
#define TIM1_CCR1 ((volatile uint32_t *)(TIM1_BASE+0x34))
#define TIM1_CCR2 ((volatile uint32_t *)(TIM1_BASE+0x38))
#define TIM1_CCR3 ((volatile uint32_t *)(TIM1_BASE+0x3C))
#define TIM1_CCR4 ((volatile uint32_t *)(TIM1_BASE+0x40))
#define TIM1_BDTR ((volatile uint32_t *)(TIM1_BASE+0x44))
int16_t _gtv2;
void setup()
{
    *RCC_APB2ENR |= 0x00000805;
    *GPIOA_CRH &= 0xFFFF0000;
    *GPIOA_CRH |= 0x0000BBBB;
    *GPIOB_CRH &= 0x000FFFFF;
    *GPIOB_CRH |= 0xBBB00000;
    *TIM1_ARR = Timperiod;
    *TIM1_CCMR1 = 0x00006868;
    *TIM1_CCMR2 = 0x00006868;
    *TIM1_CCER = 0x00001557;
    *TIM1_PSC = 72;
    *TIM1_BDTR = 0x00008000;
    *TIM1_CR1 = 0x00000061;
    *TIM1_CCR1 = 0x5;
    *TIM1_CCR2 = 0x5;
    *TIM1_CCR3 = 0x5;
    *TIM1_CCR4 = 0x5;
}
void loop()
{
    //Плата:1
    Timperiod = 255;
    PWM_1 = (255)-((map((_gtv2), (0), (4095), (0), (255))));
    PWM_2 = (map((_gtv2), (0), (4095), (0), (128)));
    PWM_3 = (map((_gtv2), (0), (4095), (0), (255)));
    PWM_4 = (map((_gtv2), (0), (4095), (0), (255)));
    *TIM1_ARR = Timperiod;
    PWMcontrol = PWM_1;
    PWMcontrol = constrain(PWM_1,0,Timperiod);
    *TIM1_CCR1 = PWMcontrol;
    PWMcontrol = PWM_2;
    PWMcontrol = constrain(PWM_2,0,Timperiod);
    *TIM1_CCR2 = PWMcontrol;
    PWMcontrol = PWM_3;
    PWMcontrol = constrain(PWM_3,0,Timperiod);
    *TIM1_CCR3 = PWMcontrol;
    PWMcontrol = PWM_4;
    PWMcontrol = constrain(PWM_4,0,Timperiod);
    *TIM1_CCR4 = PWMcontrol;
    // test= *TIM1_CNT;
// Fr=test;
    //   if (test >=PWMcontrol)
     //   {Q=false;}
     //   else 
//    {Q=true;}
    _gtv2 =  (analogRead (197));
}
„Выживает не самый сильный и не самый умный, а тот, кто лучше всех приспосабливается к изменениям.“
— Чарлз Дарвин
Ответить

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