Jump to content

    

ToR_TDA

Свой
  • Content Count

    279
  • Joined

  • Last visited

Community Reputation

0 Обычный

About ToR_TDA

  • Rank
    Местный

Контакты

  • Сайт
    Array
  • ICQ
    Array

Информация

  • Город
    Array

Recent Profile Visitors

1525 profile views
  1. Возможно для этого придуманы IDE, что бы не лезть в Datasheet каждый раз. 2 Такта memory access time при fHCLK > 48MHz Не принципиально, аналогично остановке АЦП. После обнаружения события в буфере необходимо сделать еще N отсчетов АЦП, затем остановить. Процессору должен по итогам работы достаться массив данных из 256 элементов, с событием располагающемся в районе 128 элемента. Вот пример оцифровки со скоростью 1МГц в буфер через ПДП, а затем медленная передача на ПК через SWO
  2. Спасибо всем отписавшимся jcxz, MrBearManul, Baser мне понадобиться время что бы все это обдумать. Да, похоже получается обработка в прерывании будет лучше. На тот момент я думал, что через ПДП это можно сделать быстрее, но все верно, получается асинхронный счет сэмплов, а это глупость. Абсолютно верно. Не обязательно фронт, в идеале любой настраиваемый триггер. Про неспешный анализ после остановки АЦП совершенно верно. Хотел произвольный триггер, не только фронт/спад. Да, читать данные данные в циклическом буфере для поиска определенных состояний. Да, регистр DMA1_Channel1->CNDTR, действительно содержит информацию о оставшемся количестве слов до заполнения циклического буфера (если я ничего не попутал), но получается придется читать его асинхронно, а это плохо. ISR от DMA. скорость выборки из флеша 1 такт, не? Да, ничего лишнего только АЦП, кольцевой буфер, блок триггера, и команда на остановку АЦП. В общем, задача очень похожа на то как работают цифровые осциллографы. То есть поиск события в буфере, после события дополняем буфер на еще N отсчетов, а далее стоп и медленно обрабатываем. В идеале я хотел бы получать буфер на 256 точек, в котором посередине было бы мое событие. Да, похоже что так. Я понял, согласен. 32 такта на чтение из регистра АЦП, сохранения в кольцевой буфер, инкремент указателя, проверка пары условий с чтением из буфера и при совпадении остановка АЦП. Думаете не заморачиваться?
  3. Почему? 1uS это не так и мало это целых 56 тактов при 56МГц. Остановка АЦП может быть и через CMSIS, это не столь важно, мой вопрос от этого не меняется. Я уже понял, что нужно разобраться с регистром DMA_CNDTR1, но пока я не понял, какие именно данные мне в нем ожидать при циклическом заполнении буфера длиной 256 слов. У меня МК 32F103С8T6, но я думаю эти принципы должны распространятся по крайней мере на все 100-е МК. Да, есть событие по окончанию преобразования группы каналов АЦП, можно вызвать по нему прерывание, но я лишь хочу знать текущее положение потока DMA в буфере, например чтобы сделать такое условие: ADC1->CR2 |= ADC_CR2_SWSTART; uint8_t adc_buf_pos; if (adc_buf[adc_buf_pos-127] > 1000 && adc_buf[adc_buf_pos -128] < 1000 && adc_buf_pos == 255) { ADC1->CR2 &= ~ADC_CR2_SWSTART; } Где adc_buf_pos это суть вопроса Неправильно наверху написал, скорее так: ADC1->CR2 |= ADC_CR2_SWSTART; // старт АЦП uint8_t adc_buf_pos; while(1) { if (adc_buf[128] > 1000 && adc_buf[127] < 1000) { while(adc_buf_pos<255) { adc_buf_pos = ???; } ADC1->CR2 &= ~ADC_CR2_SWSTART; // Стоп АЦП // обработка статического массива } ADC1->CR2 |= ADC_CR2_SWSTART; // перезапуск АЦП }
  4. АЦП создает новое данное раз в 1uS, мне бы хотелось иметь глобальную переменную, обновляющуюся раз в 1uS и несущую в себе информацию о адресе в буфере adc_buf[256] по которому была произведена последняя передача ПДП. Пример события: while (1) { if (adc_buf[128] > 1000 && adc_buf[127] < 1000) { HAL_ADC_Stop_DMA(&hadc1); } }
  5. АЦП в режиме continuous mode сам себя перезапускает, по готовности АЦП отрабатывает ПДП. Да, я останавливаю работу АЦП и тем останавливается ПДП, вопрос только на какой был последний переданный элемент массива adc_buf[256]; Да, как это получать максимально просто и правильно?
  6. Нет, это не проблема, просто я хочу по некоторому событию в структуре данных буфера АЦП делать остановку DMA и дальше работать со статичным массивом, но одна из вещей которая мне нужна это знание на каком элементе ДМА было остановлено. Если я правильно понял в этом регистре будет храниться число оставшихся данных для передачи. И в circular mode, для моего случает когда буфер дойдет до 0, произойдет перезагрузка на 255? Этот регистр декрементируется да?
  7. Здравствуйте форумчане! МК - STM32F103. Сохраняю данные с АЦП в циклический буфер с передачей по DMA, все работает ок, ниже примерный код с HAL, инициализация не показана, но это не суть, вопрос такой: я хочу иметь возможность в любой момент времени узнать адрес или номер элемента массива adc_buf в который произойдет очередное сохранение (или последний куда сохранение было сделано). То есть указатель бегающий вместе со DMA. Один из вариантов, который я продумывал было инкремент некоторой переменной в прерывании по готовности передачи DMA, но есть ли нормальный (лучший) способ это делать, ведь этот указатель уже должен быть частью DMA, мне лишь надо его читать. #define ADC_BUF_LEN 256 ADC_HandleTypeDef hadc1; uint16_t adc_buf[ADC_BUF_LEN]; ADC_HandleTypeDef hadc1; HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buf, ADC_BUF_LEN); while (1) { }
  8. Так как у меня нет отдельной информации о переполнении АЦП, я назначу обе крайние точки 32767 и -32768 как "out of range".
  9. Каюсь, не всю программу выложил. Это связано было со способом приема данных с АЦП через 2 отдельных байта MSB и LSB. int16_t current; char sign; div_t fracDigit; char Str_Buffer[20]; int8_t MSB = 0x83; uint8_t LSB = 0x00; //например -32000 current = abs (MSB << 8 | LSB); if (MSB >= 0) sign = ' '; else sign = '-'; fracDigit = div(current/10,1000); sprintf(Str_Buffer, "I= %1c%1d.%03d A", sign, fracDigit.quot, fracDigit.rem);
  10. Да я тоже только узналhttps://ru.cppreference.com/w/cpp/numeric/math/div Понял, при -32768 на выходе будет -0.000 Из того что я понял будет только одна проблемная точка это -32768.
  11. Не не не, если уж сказали то договаривайте, вот код который работает сейчас: int16_t current; char sign; div_t fracDigit; if (current >= 0) sign = ' '; else sign = '-'; fracDigit = div(current/10, 1000); sprintf(Str_Buffer, "I= %1c%1d.%03d A", sign, fracDigit.quot, fracDigit.rem); В какой момент происходит проблема? И почему я не вижу ее по показаниям?
  12. Если честно то не очень понял. Есть некоторое АЦП которое отдает мне данные так: При этом коду 0x0000 соответствует ток 0А. В какой момент происходит неправильная смена знака?
  13. Да, я проверил все в железе на всем диапазоне несколько раз. Форматирование работает корректно.
  14. Но идея то правильная Я не из тех кто выбивает от людей на форуме готовый исполняемый код, мне нужна была лишь подсказка. И теперь все работает как нужно, еще раз спасибо всем за ответы.
  15. О, огромная благодарность все так просто, я был слеп когда смотрел на форматы sprintf Спасибо! Переписал это так: int16_t current; char sign; div_t fracDigit; if (current >= 0) sign = ' '; else sign = '-'; fracDigit = div(current/10, 1000); sprintf(Str_Buffer, "I= %1c%1d.%03d A", sign, fracDigit.quot, fracDigit.rem); Именно поэтому я и написал в раздел "В помощь начинающему" на форуме. Спасибо, идея аналогична первому ответу и в данной задаче сверх-оптимизация не требуется. Возможно кому-то и проще.