Перейти к содержанию
    

Xenia

Модератор FTP
  • Постов

    4 822
  • Зарегистрирован

  • Победитель дней

    2

Весь контент Xenia


  1. Если у вас сохранился ioc-файл, а он у вас сохранился - "AD ADC.ioc", то ставьте последнюю (самую свежую) версию CubeMX, а уж она, согласно ioc-файлу, создаст нужное окружение - компилятор и Drivers (это так у нее исходники фирменных библиотек называются). И так, инсталлируем последнюю версию CubeMX (ныне это версия 6.11.0), запускаем AD ADC.ioc и видим это: Это означает, ваш проект был когда-то создан на версии CubeMX 6.6.1. Дальше надо нажать на кнопку Continue, чтобы проект был скомпилирован, как встарь. После чего начнется закачка из интернета сперва образа старой версии CubeMX, а затем библиотеки "stm32cube_fw_h7_v1100.zip" (по нынешним временам она уже устарела), поскольку именно так в вашем файле "AD ADC.ioc" прописано: ProjectManager.FirmwarePackage=STM32Cube FW_H7 V1.10.0 А дальше действуете по обстоятельствам - где попросит, соглашаетесь, но только не на миграцию! dimka76 прав, ранее скопилированный проект в вашем архиве уже есть - "AD ADC.elf".
  2. Виновата - килогерцы с мегагерцами спутала.
  3. Возможно, что я отстала от жизни :), но по моим представлениям 1000 SPS (а тем более 4000 SPS) не совместимо с требованием иметь разрешение в 20-24 разряда. Высокоразрядные АЦП, как правило, относятся к типу "сигма-дельта", чья высокая разрядность базирутся на принципе интегрирования входного сигнала на всем протяжении периода измерения. Именно благодаря такому усреднению удается уменьшить уровень шума и тем самым повысить число значащих бит в результате. Но по мере того, как мы увеличиваем частоту оцифровки данных, период измерения сокращается и эффект от усреднения всё меньше дает пользы. Оттого и разрешение с ростом частоты сэмплирования неизбежно уменьшается. Поэтому, на мой взгляд, при частоте сэмплирования свыше 1 МГц стоило бы использовать обычный SAR и смириться с разрядностью 16 бит.
  4. STM32F411 и I2C

    Через Transmit и Receive у меня тоже не получалось читать датчики, но для этой цели хорошо подошла функция: HAL_I2C_Mem_Read( &hi2c1, devAddress << 1, regAddress, 1, pData, 2, I2C_TIMEOUT10); куда сразу закладываем номер регистра данных - regAddress и адрес буфера на 2 байта, куда надо прочесть данные - pData. Т.е. всё делает одна эта функция. В вашем случае это будет выглядеть так: HAL_I2C_Mem_Read( &hi2c1, I2C_ACL_ADRESS << 1, rgMgnAdress, 1, &rgMgnData, 2, I2C_TIMEOUT10); Внимание! в качестве rgMgnAdress следует класть число (в вашем случае 0x4F), а не адрес памяти, где оно лежит! Вероятно в этом ваша ошибка. HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout);
  5. Это у меня восприятие такое - заменить плату или прошивку кажется мне легким делом (особенно, если прошивку сама писала, а плата и драйвер не интегрированы в одно целое). Тогда как что-то делать с железом кажется мне непосильным трудом, а предложение добавить "синхронизирующий вал" вгоняет в ужас 🙂.
  6. Золотые слова :). Судя по картинке, двигатели там относительно маломощные (на вид Nema17), а для таких есть дешевые драйверы на ток до 2А. У меня, например, стоят A4988 на каждый двигатель (у меня их 4 штуки). Лот из 5-ти штук на Aliexpress за $1 когда-то покупала. Ныне, когда 3D-принтеры широко распространены, драйверы для них достать очень легко.
  7. А чем это плохо? Или вы, когда в следующий раз станок включите, ожидаете, что шаговый двигатель останется на том же шаге, на котором вы его в прошлый раз выключили? А если при включении станка вы свой двигатель позиционируете, гоняя до ближайшего концевого выключателя, то вам должно быть безразлично, в каком положении остался двигатель в прошлый раз. Почему бы тогда вам ни поставить второй концевой выключатель, а этот раз на максимум?
  8. Вместо пинга я пользуюсь программой NMAP (https://nmap.org), которой сканирую всю сетку. К сожалению, при подключении моей платы к роутеру новый IP-узел не появляется.
  9. Все равно не работает... А может быть DHCP не надо отключать? Пусть роутер присвоит свой IP - тогда уж сеть у компьютера и платы с гарантией будет одинаковой, раз уж они в один и тот же роутер воткнуты. Или это плохая идея? P.S. И вообще для меня было бы большим облегчением увидеть своими глазами исходники рабочего проекта, написанного на HAL (CubeMХ) в конфигурации "DP83848+RMII". Без RTOS. В репозитории (\Repository\STM32Cube_FW_F4_V1.28.0\Projects\) уже искала, но там только под MII есть примеры, тогда как у меня на плате DP83848 кормит отдельный генератор на 50 МГц (именно генератор, а не резонатор). А раз так то я вынуждена режим RMII использовать. Это было бы для меня наиболее эффективной помощью, т.к. у меня не хватает наглости просить участников нашей конференции, чтобы они искали ошибки в моем программном коде.
  10. Из ваших объяснений не поняла, в каком месте надо выставить IP и какой. Но больше всего я боюсь, что, перенастроив ПК на связь с платой, я лишусь интернета. На эту мысль меня наводит тот факт, что на ПК DHCP у меня включен, а на плате выключен. Именно такой совет мне был дан: А пока DHCP на вкладке CubeMX не выключишь, статический IP адрес он ввести не дает. Вот оно как у меня: Тогда как в настройках ПК ситуация выглядит так:
  11. Однако не заработало оно у меня... Однако я задам вопрос не о возможных причинах этого (тем более, что их может быть очень много), а о том, как этот пинг проверять. Пока что я просто соединила пач-кордом Ethernet-гнездо на плате с Ethernet-гнездом на материнской плате компьютера. Результат таков: компьютер крутит колесико (у меня Win7) в поисках интернет-сети, но так ее и не находит. Оно и понятно, т.к. моя плата предоставить выход в интернет не может. А поскольку сети компьютер не находит, то я и не могу поглядеть , какие TCP/IP-адреса в ней есть. Сперва я подумала, что в программе у меня ошибка и поэтому вместо самодельно-запрограммированной платы поставила другую плату (иной конструкции), где какая-то заводская прошивка для Ethernet уже была. Но результат получила точно такой же. От этого и закралась у меня мысль, что может быть я платный Ethernet неправильно проверяю? Вдруг компьютер надо как-то иначе настраивать, чтобы он такую плату в своем окружении увидел?
  12. Покупала себе под шаговые двигатели вот такую плату: https://aliexpress.ru/item/1005004770273121.html на ней STM32G407 стоит. А раньше использовала MKS-GEN V1.4 на контроллере ATmega2560. Обе платы рассчитаны на управление шаговыми двигателями на 3D-принтере. До тока 2А хватает наплатных драйверов, а при больших токах надо использовать внешние. Код прошивки брала оттуда же - https://github.com/MarlinFirmware/Marlin/ но перед компиляцией вносила в него свои поправки. Оно так и положено, поскольку 3D-принтеры у всех разные.
  13. Что-то стоит 🙂 . Согласилась. Впрочем решение своей проблемы я кажется нашла - это именно та функция, что стояла внутри while'ов. Она достаточно надежно определяет, когда шина I2C лишается подтяжки: __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) Причем работает она максимально быстро, т.к. представляет собой дефайн, который при флаге I2C_FLAG_BUSY тождественен проверке бита: SR2.BUSY например, так: if ((I2C1->SR2 & I2C_SR2_BUSY) != 0) { читать и писать нельзя, зависнет! } Уже испытала: при обеих подтяжках (SCL и SDA) SR2.BUSY = 0, а если хотя бы от одной из них оторвать подтяжку, то SR2.BUSY > 0. Правда после возвращения подтяжки на место, в ноль она возвращаться не хочет, но после "взбадривания" на ноль возвращается.
  14. Потому что в данном случае "зависание" является не каким-то событием, наступление которого можно отследить трассировкой, а похоже, что является бесконечным циклом, по которому можно ходить трассировщиком бесконечно долго. Но есть и короткие циклы типа: while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); из которых не выходит никогда. И таких мест в этом файле 19 штук. Вот что нашел поиск по команде find: ---------- STM32F1XX_HAL_I2C.C while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == RESET); while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == RESET); while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); while (__HAL_I2C_GET_FLAG(hi2c, Flag) == Status) while (__HAL_I2C_GET_FLAG(hi2c, Flag) == RESET) while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXE) == RESET) while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == RESET) while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == RESET) while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == RESET)
  15. Именно так и сделала - заменила I2C-ключи на управляемые уровнем, вот такие: https://wiki.iarduino.ru/page/silovoy-klyuch-trema-modul/ Но такого рода исправление касается только "критического блока", где переключение клапанов происходит часто (потому и вероятность сбоя там выше). Однако есть там один датчик, который только по I2C способен работать. И если он вызовет зависание контроллера, то и "критическому блоку" тоже каюк, т.к. контроллер у них один и тот же.
  16. Про это я читала раньше, но суть этой заметки в целом сводится к детализации реализации совета, который сама компания ST дала в Errara ("STM32F10xx8 and STM32F10xxB silicon limitations"). На мой взгляд этот способ плохой, т.к. он занимает много времени и срабатывает не всегда. По этому поводу я уже проводила собственные исследования и изобрела лучший способ :), который работает более надежно и к тому же гораздо более простой. Однако в той статье описана борьба с другой проблемой - той, когда статус BUSY выдается ошибочно, в то время как с подтяжками на линиях I2C всё в порядке. Т.е. это отнюдь не моя проблема, поскольку там на операциях чтения и передачи контроллер не зависает, а честно выдает ошибку HAL_BUSY. Поэтому в том случае действительно возможен алгоритм, основанный на принятии мер , "взбадривающих" I2C, после того, как транзакция окончилась неудачей. Тогда как у меня проблема иная - неудачная транзакция приводит к зависанию с последующим ресетом по WаtchDog. Т.е. мне нечего лечить, т.к. наступает полный пипец. К этому стоит добавить, что мой контроллер по I2C-шине управляет силовыми ключами, вот такими (на ток 10А): https://wiki.iarduino.ru/page/power-key-4n-i2c-datasheet/ А те, в свою очередь, переключают клапана на линиях, по которым перекачиваются "агрессивные" жидкости. Это, так называемый, "градиент низкого давления", когда клапаны поочередно пропускают жидкость из двух бутылей/ёмкостей, выдерживая нужное время для каждой фазы, для того, чтобы после смесителя получилась нужная концентрация. Абстрактный пример: качаем 4 секунды спирт из первой бутыли, а потом 6 секунд - воду из второй бутыли. И так в бесконечном цикле. В результате после смесителя получаем 40%-ный (по объему) спирт. И это должно надежно работать даже ночью. А теперь представим, что мой контроллер, который не только управляет клапанами, но и контролирует результат их работы по расходомеру, внезапно завис? Я со всеми неожиданностями знаю способы борьбы, но зависание контроллера это кранты.
  17. Отладчик есть, но с моей стороны выглядело целесообразнее не изобретать велосипед, а задать вопрос на форуме, поскольку речь идет о проблеме не в моей программе, а в программном продукте CubeMX, которым пользуется очень много народа. Т.е. расценила, что не я первая, кто использует I2C через Куб, а потому надеялась, что эта проблема кем-то уже была замечена, и от нее найдено противоядие. Тогда как ваш совет из рода "найди место ошибки сама и сама же ее исправь" не кажется мне полезным.
  18. Когда проблемы с ответами и запросами началась, уже поздно махать кулаками, т.к. имя этой проблеме - зависание. А после эксгумации по ватчдогу уже неясно, что случилось и в каком месте. СлабО мне ту ошибку в Кубе сыскать, тем более когда на одних регистрах пользоваться I2C я не умею. Пыталась обновлять кубовые драйверы, т.к. после моей версии 1.8.0 уже вышли версии 1.8.3, 1.8.4 и 1.8.5. Причем в каждой из них в файле stm32f1xx_hal_i2c.c были подвижки (на 5 килобайт файл раздулся). Разбираться в нем - голову сломать. Однако замена драйвера I2C на последнюю версию ситуацию не изменило - по-прежнему провисание.
  19. Согласна с вами ... наполовину 🙂, действительно проверка в режиме gpio в режиме pulldown должна определить наличие внешней подтяжки. Причем проверка в режиме pullup для этой цели не требуется. Одно только плохо - для такого рода теста пришлось бы постоянно отключать I2C и переходить в режим обычного GPIO_MODE_INPUT, а после проведения теста вновь инициировать режим I2C. Это было бы не страшно, если делать этот тест только перед началом работы, но сильно обременительно, если обрыв линии возможен в процессе работы (сильно замедлило бы как чтение, так и запись по шине). Тем более что при переходе из режима I2C в GPIO и обратно требуется выдерживать какие-то таймауты. Тем не менее существует функция: HAL_StatusTypeDef HAL_I2C_IsDeviceReady(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout) которая не виснет при отсутствии подтяжек и при разрыве I2C-шины, возвращая значение HAL_BUSY. И этот ответ, по-видимому, правильный, т.к. низкий уровень шины действительно следует рассматривать так признак ее занятости. Между тем, эта функция не выходит из режима I2C, а стало быть принципиально возможно определить низкий уровень I2C-шины, не прибегая к переходу в режим GPIO_MODE_INPUT. Спрашивается, как этой функция это удается? Я уже лазила в сорцы. Там для HAL_I2C_IsDeviceReady довольно запутанный код, однако выяснила, что информацию она берет через функцию __HAL_I2C_GET_FLAG(...), которая определена как дефайн: #define __HAL_I2C_GET_FLAG(__HANDLE__, __FLAG__) ((((uint8_t)((__FLAG__) >> 16U)) == 0x01U) ? \ (((((__HANDLE__)->Instance->SR1) & ((__FLAG__) & I2C_FLAG_MASK)) == ((__FLAG__) & I2C_FLAG_MASK)) ? SET : RESET) : \ (((((__HANDLE__)->Instance->SR2) & ((__FLAG__) & I2C_FLAG_MASK)) == ((__FLAG__) & I2C_FLAG_MASK)) ? SET : RESET)) Глубоко не разбираясь в коде, здесь уже видно, что информация вытягивается из флагов регистров SR1 и SR1. Отсюда и следующий вопрос - какие флаги для моей цели годятся? Описание всех флагов, содержащихся в этих регистрах, я уже смотрела, но почти ничего не поняла. Наиболее перспективными (по названию) мне показались флаги (комментарий к ним чужой): SR1->TIMEOUT (Timeout or Tlow error) — возникает если линия SCL прижата к земле. Для master 10mS, для slave 25mS. SR2->BUSY(Bus busy) — флаг занятости. В моих интересах провести тест, не покидая режима I2C, тем более что проверка флага - очень быстрая процедура, которую я могла бы с случае успеха такого теста проводить перед каждой транзакцией, не теряя в скорости передачи. Можно ли что-то подсказать мне по этому поводу? Этот флаг тоже смотрела, но ясности у меня не прибавилось. Вот что про него написано: SR1->ARLO (Arbitration lost (master mode) ) — устанавливается при потере арбитража. Для сброса нужно записать 0. На его фоне флаги SR1->TIMEOUT и SR2->BUSY выглядят в моих глазах более перспективными.
  20. У меня возник еще один животрепещущий вопрос. Контроллер (у меня это STM32F103C8T6) намертво виснет (оживает только по WatchDog'у) при выполнении функций: HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout); HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout); когда линии SDA и SCL не подтянуты к питанию, вне зависимости от того, какой задаешь Timeout. Т.е. зависает на этой процедуре и по Timeout'у из нее не выходит. Я отлично понимаю, что случай, когда линии I2C не потянуты к питанию резисторами - аномальная ситуация, в которой нельзя требовать от шины нормальной работы. Однако мне сильно хочется, чтобы обрыв в шины (а резисторы подтяжки находятся на слейве, т.к. этот контролер не умеет такую подтяжку создавать сам, а на плате она не предусмотрена) не приводил к зависанию, чтобы контроллер мог бы выдать по этому поводу вразумительное сообщение об ошибке. Типа: "Шина I2C оборвана". Уже пробовала определять уровень на пинах SDA и SCL, но получаю результат такой, что оба пина имеют высокий потенциал, как и должно быть. Вопрос: есть ли какой-то способ проверить наличие подтяжки на линиях SDA и SCL, а еще лучше сделать так, чтобы контролер при операциях чтения и записи по шине I2C не зависал, если на ней нет подтяжки?
  21. Сообщаю для своих: 🙂 На FTP в директории /pub/DSP/TI - Code Composer Studio/ есть вcе версии CCS (сама долгое время их собирала).
  22. STM32F405 или STM32F407 легко эту частоту вытянет, если, конечно, меандр нужен правильный со скважностью 50%. У этих чипов тактовая частота до168 МГц, а если ее понизить до 128 МГц, то будет в самый раз для меандра на 64 МГц. Я сама недавно на Aliexpress вот такую плату заказала и уже почтой ее получила: https://aliexpress.ru/item/1005004064401634.html 1000 руб без доставки, конечно, дороговато, то не слишком, если нужно для дела.
  23. SWD - распиновка

    Как же я его выломаю, если там монтаж печатный? Могу просто ничего к нему не присоединять, если для прошивки он не нужен. А стабилизатор на этой плате есть, а точнее - LDO, которое из 5V делает 3.3V для питания контроллера, т.к. сам модуль питается от внешнего источника 5V. Возможно, что этот разъем был сделан в расчете не на J-Link, а на ST-Link.
  24. SWD - распиновка

    Российский SWD? Дело было так. Купила я себе (для проекта) отечественное изделие (на нем так и написано "RUSSIA") - силовой ключ под управлением контроллера STM32F030F4 и решила его перепрограммировать под свою специфическую задачу. Однако столкнулась с трудностью прошивки из-за того, что у этого модуля SWD-разъем (а точнее - только дырочки вместо него) размером 3x2 пина (итого пинов 6), а расстояния между ними малы - 1.27 мм. В начале рассчитывала спаять переходник с этого SWD на стандартный разъем J-TAG (10x2 пинов) по схеме, найденной мной в интернете: Но поскольку нумерации пинов на том разъеме не было, то решила прозвоном определить, где у этого разъема земля. Оказалось, что не с краю, а в середине! После этого стала прозванивать всё остальное и вот что выяснила: Распиновка этого SWD оказалась совершенно не той, что на схеме из интернета. Мой вопрос: кто-нибудь встречался с такой распиновкой? И как мне его теперь к J-Link'у подключать? (BOOT0 у этого контроллера в землю впаян, а SWO нет совсем)
×
×
  • Создать...