Кто любит RISC в жизни, заходим, не стесняемся.
Ответить

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

Пт авг 18, 2023 23:38:19

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

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

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

Я бы в этом коде не стал надеятся на то, что ADC_ISR_EOSEQ будет в нужном состоянии, как только будет прочитан последний канал в последовательности. Вещи-то по сути не связанные.

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

Сб авг 19, 2023 06:24:09

Да так все и происходит. Только как это обыграть не пойму. У ф0 серии нет режекционных коналов..

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

Сб авг 19, 2023 09:59:18

нет режекционных коналов..

Инжектированных.

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

Сб авг 19, 2023 10:59:22

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

Может, как-то так:
Код:
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 */
}

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

Сб авг 19, 2023 11:25:24

будем полагать, что не знаем какой канал сейчас оцифровывается, поэтому считав DR проверяем EOSEQ - если 1 то это последний в очереди. и я полагаю, что в последующем это все таки массив (с чередованием каналов) - иначе зачем массив, это просто две переменные.

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

Сб авг 19, 2023 12:46:31

a797945, да в том и проблема, что как писал WiseLord, тот самый EOSEQ то взлетает а то нет. я конечно решил проблему при помощи костыля: каждый раз перед запуском преобразования, меняю значение регистра ADC1->CFGR1 |= ADC_CFGR1_SCANDIR что меняет направление сканирования каналов ацп, но осадчик остался, а если больше 2-х каналов...

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

Сб авг 19, 2023 13:49:26

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

да и очередь лучше как-то так задавать (не через |=)
ADC1->CHSELR = ADC_CHSELR_CHSEL2 | ADC_CHSELR_CHSEL5;

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

Сб авг 19, 2023 14:07:41

выстраивайте ожидание:

да и очередь лучше как-то так задавать (не через |=)
ADC1->CHSELR = ADC_CHSELR_CHSEL2 | ADC_CHSELR_CHSEL5;

нет разницы какой тут порядок, он идут по порядку, а ADC_CFGR1_SCANDIR определят только напряжение от большего к меньшему либо наоборот.

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

Сб авг 19, 2023 16:36:16

а если посмотреть, действительно 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[i] = 1;}
else {ADC_array[i] = 0;}
}
если в очереди 2 канала - в массиве ожидается зебра (0,1,0, ...) без пропусков
отредактировал, тороплюсь куда-то.

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

Чт авг 31, 2023 09:45:38

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

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

Пт сен 01, 2023 09:31:47

Частота дискретизации звука (приём тональных сигналов) выбрана 14080. Получается 852 такта ADC между прерываниями таймера для старта преобразования ижектированных каналов. Если sampling time выставить максимальным 239,5, то в этот промежуток укладываются три преобразования - один инжектированный (два канала) и два регулярных (четыре канала). Вроде проблем нет.

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

Пт сен 01, 2023 09:53:57

Представился такой вариант: Двойным преобразованием ADC1 и ADC2 c DMA с регулярных каналов заполнять массив датчиков 4Х2 непрерывно без прерываний вообще. Считывать их в свободное время. Плюс для оцифровки звука два инжектированных канала, также двойным преобразованием ADC1 и ADC2

Все поставлено с ног на голову... :facepalm:
Под ДМА должен работать звук, а не датчики. А датчики можно считывать в прерываниях. Они медленные и потому редкие.
Только вот возник вопрос. А куда потом этот звук?

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

Пт сен 01, 2023 10:25:19

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

Добавлено after 13 minutes 58 seconds:
То есть процесс будет выглядеть примерно так: Сканируются два оегулярных преобразования и складываются куда надо под ДМА без прерываний, затем как только начинается третье регулярное преобразование, оно прерывается инжектированным преобразованием, данные которого извлекаются через прерывание. После окончания инжектированного преобразования, сканируются третье и четвёртое регулярные преобразования, а как только вновь начинается первое, оно прерывается на инжектированное преобразование и так дальше.

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

Пт сен 01, 2023 10:46:56

Звук не под DMA так как планируются некоторые вычисления после приёма каждого сэмпла. это будут команды тональными сигналами, по полсекунды длиной.

Так и принимайте окнами. Тональные сигналы - это классический ДПФ приемник. Окно приема должно иметь длину рассчитанную из полосы пропускания фильтров. В зависимости от оконной функции оно будет немного больше чем величина обратная полосе фильтра. Скажем, для полосы в 100 Гц окно потребуется примерно 12...15 мс. При частоте дискретизации, например, 8 кГц количество отсчетов в одном окне составит примерно 128. Захватили окно - сделали N-канальный ДПФ - обнаружили сигнал - приняли решение. За полсекунды можно накопить аж 32 окна и получить 32 скалярных значения фильтров. Ну и зачем вам обрабатывать каждый отсчет? :dont_know:
Скажу больше. У АРМов прерывания - полный тормоз. Вы получите на каждом отсчете кучу потерянного времени на вход-сохранение контекста-восстановление контекста-выход... Оно вам зачем?

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

Пт сен 01, 2023 14:57:23

КРАМу
Вот так вот обрубили полёт моей фантазии )
ОК, выберу какое-нибудь классическое решение.

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

Пт сен 01, 2023 14:58:45

Обращайтесь, если что...
:)

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

Пт сен 01, 2023 17:53:06

если интересует тон - зачем АЦП ?

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

Пт сен 01, 2023 17:56:30

Ну наверное потому, что детектировть DTMF с помощью АЦП проще, чем городить разного рода суррогаты, рискуя получить всякий бред при помехах.

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

Вс окт 08, 2023 13:39:05

Добрый день. Решил на досуге заняться портированием драйвера АЦП 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);

}

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

Ср апр 24, 2024 03:06:14

Камень 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));
}
Ответить