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

LAS9891

Участник
  • Постов

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

  • Посещение

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


  1. Да пожалуйста: Это схема отсюда: um1079-discovery-kits-with-stm32l152rct6-and-stm32l152rbt6-mcus-stmicroelectronics.pdf Сломал именно такую отладочную плату. При подключении через ST-Link Utility, программатор определяется, целевой контроллер определяется, но длится это не долго, секунд 10 и снова "Connection to device is lost: check power supply and debug connection." Всё точно также как и в шапке темы. Прошивку ST-Link можно даже обновить через ST-Link Utility, всё проходит успешно. Ничего не изменилось, программатор был подключен, контроллер работал в отладке несколько дней, когда понадобилось посмотреть ход выполнения программы в Debug-е, Keil сказал что отладка не возможна. Вышел из отладки, смотрю ST-Link, а он "вышел из чата".
  2. Последние два экземпляра погибли при отладке оборудования в распределительном шкафу, где рядом установлены автоматы 220V и другое высоковольтное оборудование. Но опять погибли не совсем, а так же как и первый.
  3. Проблема усугубилась. Первый заболевший экземпляр попробовали вылечить заменой контроллера STM. Контроллер заменили, прошивку зашили, результат - без изменений. Решили оставить его в покое. Взяли новый экземпляр. Через какое-то время с новым экземпляром случилось тоже самое. В связи с этим прошу помощи:
  4. Другой оценки мне не стоит ожидать. Предложите свой код, в котором не будет пропусков, а я проверю. Где найти достойный пример, если даже в STM работают говнокодеры? На свежую голову (или что там вместо головы у говнокодеров) нашёл косяк. Теперь не ловлю пропуски в обоих вариантах, но надеюсь, что выложат неговнокодовый пример того, как надо делать.
  5. Сделал специальный дебуговый проект. В нём делаю минимальную инициализацию для настройки тактирования, пинов, таймера 1. По завершении инициализации проект висит в while(1){;}. На 4 канала таймера 1 подаю одинаковые пачки импульсов. Вот в таком варианте обработчика прерываний: стабильно ловлю пропуски в канале 3. Даже если в обработчике ставлю обработку канала 3 в самое начало, всё равно ловлю пропуски в канале 3. В остальных поймать не получилось. Вот в таком варианте обработчика прерываний: пропусков поймать не удалось.
  6. Переписал согласно ЦУ: Получилось так: Работает плюс/минус также. Заметная разница только в том, что раньше чаще пропуски были на канале 3. Сейчас ещё не удалось поймать пропуск на канале 3. Вот так случилось на канале 2: Розовый - дрыг ногой при каждом валидном прерывании на канале 2. Голубой - вид исходной посылки. НА НЕСИНХРОННОСТЬ СИГНАЛОВ ВО ВРЕМЕНИ НЕ СМОТРИМ. Это сигналы с разных каналов. На все каналы приходят одинаковые посылки. Голубой сигнал тут просто для того, чтобы видеть, как должна выглядеть правильная посылка. (Лень было провода перепаивать).
  7. А эта несколько? TIMER_INTF(TIMER1) &= ~TIMER_INTF_CH0IF; TIMER_INTF_CH0IF - это макрос одного бита! Согласен, что код будет не оптимальным по количеству операций, и так делать нерационально, и я не буду так делать. Но как эта запись изменит другие биты кроме одного? В язык Си внесли изменения, в которых операция "&" стала работать по другому? Пусть биты, отличные от TIMER_INTF_CH0IF, хоть обизменяются, макрос от этого не поменяется, и он установит в 0 только свой один бит! Скажите уже, что мне надо читать Страуструпа.
  8. Надо делать так: uint32_t regval = TIMER_INTF(TIMER1); //---If channel 0 capture/compare interrupt flag is set---// if (regval & TIMER_INTF_CH0IF) // If channel 0 capture/compare interrupt flag is set {;} Или так: //---If channel 0 capture/compare interrupt flag is set---// if (TIMER_INTF(TIMER1) & TIMER_INTF_CH0IF) // If channel 0 capture/compare interrupt flag is set {;} Т.е. вот эта конструкция: TIMER_INTF(TIMER1) = ~TIMER_INTF_CH0IF; Установит в 0 не один бит? P.S.: как-то всё ещё не верится что в STM работают дураки, да и во всех остальных производителях.
  9. Я, конечно, ссу против ветра, но при записи будет изменён только один нужный бит. Для этого и придуманы макросы чуть ли не на каждый бит. Например ~TIMER_INTF_CH0IF, это в двоичной системе число 11111111111111111111111111111101, и когда будет запись в TIMER_INTF(TIMER1) запишется только 0 в бит номер 1, потому что "Software can read as well as clear this bit by writing 0. Writing 1 has no effect on the bit value". Чтобы изменить два бита нужно, например, записать 11111111111111111111111101111101. Вещи это все очевидные. Понятные априори даже без объяснений.
  10. Хорош теории, вот свежий говнокод: void TIMER1_Exception_Handling (void) { //---Variables---// uint8_t ch = 0; // Переменная определяет номер канала. uint32_t regval = TIMER_INTF(TIMER1); uint32_t polarity = TIMER_CHCTL2(TIMER1); EdgeEnum edge = FALLING; GPIO_PinState NewPinState = GPIO_PIN_RESET; static GPIO_PinState OldPinState = GPIO_PIN_RESET; GPIO_PinState LoopCondition = GPIO_PIN_RESET; //---------------// //---If channel 0 capture/compare interrupt flag is set---// if (regval & TIMER_INTF_CH0IF) // If channel 0 capture/compare interrupt flag is set. { ch = 0; // Выбор номера канала. polarity = (polarity & TIMER_CHCTL2_CH0P); //---Input capture event--------------------------------------------------------------// if (polarity) // Если было настроено прерывание на срез... { edge = RISING; LoopCondition = GPIO_PIN_RESET; } else // Если было настроено прерывание на фронт... { edge = FALLING; LoopCondition = GPIO_PIN_SET; } do { EdgeChanging(TIMER1, ch, edge); edge = !edge; LoopCondition = !LoopCondition; do { TIMER_INTF(TIMER1) = ~TIMER_INTF_CH0IF; // Clear capture/compare interrupt flag. NewPinState = GPIO_GetPinState(DALI_RX_Connect[0].port, DALI_RX_Connect[0].pin); } while(TIMER_INTF(TIMER1) & TIMER_INTF_CH0IF); } while(NewPinState == LoopCondition); if (NewPinState == OldPinState) return; else { OldPinState = NewPinState; //И выполняете все полезные действия, которые нужно сделать по фронту или спаду } } } //...// void EdgeChanging (uint32_t timer, uint8_t channel, EdgeEnum edge) { uint32_t TIMER_CHCTL2_CHxP = (TIMER_CHCTL2_CH0P << (channel * 4)); uint32_t temp = TIMER_CHCTL2(timer); if (edge == FALLING) temp = (temp | TIMER_CHCTL2_CHxP); else temp = (temp & TIMER_CHCTL2_CHxP); TIMER_CHCTL2(timer) = temp; // Change channel x capture/compare function polarity. } //------------------------------------------------------------------------------//
  11. Первый об этом написал Сергей Борщ. Потом это же написал я. Вы - третий. Это я уже понял, достаточно. Что на счёт этого: Ну ок. А тут пишут в п.9: Тут получается напрямую в регистре смотреть? Или опять сначала прочитать в значение в переменную и уже в переменной смотреть значение?
  12. Вот это: Это ответ на это? Ну ок. А тут пишут в п.9: Тут получается напрямую в регистре смотреть? Или опять сначала прочитать в значение в переменную и уже в переменной смотреть значение?
  13. Как я ИХ мог очистить, если я чищу только один бит, а запись единиц " Writing 1 has no effect on the bit value". Ладно, проехали про это. Мне про это рассказали. Тогда какая разница где проверять значение в регистре процессора или в переменной, которую я создам специально для этого? Только для того чтобы не делать чтение в регистровую переменную несколько раз? Тогда как тут делать: Нужно проверить регистр таймера, очистить его и опять проверить. Тогда нужно дважды читать значение регистра таймера в специальную переменную а не в процессорную? Разница то какая?
  14. 🤣 Получается: TIMER_INTF(TIMER1) &= (~TIMER_INTF_CH0IF); // Происходит: чтение, модификация, запись. TIMER_INTF(TIMER1) = ~TIMER_INTF_CH0IF; // Происходит: запись. Разница в количестве совершаемых операций и, соответственно, в скорости, а далее следствие из этого: Вот теперь прям по полочкам. Теперь понятно, зачем для каждого регистра смотреть abbreviations for registers, которые для GD появились только в User Manual Revision 2.6. Зачем было так долго объяснять мне, что я читать не умею? Вы ответили в одном предложении! Но его пришлось пассатижами вытаскивать из Вас. Мне тоже не комплиментов отсыпали, но что уж поделать, это русскоязычный форум. Не обижайтесь, свет ваших нимбов ослепляет и документации не видно. Теперь, благодаря Сергей Борщ, стало понятнее. Да по разному. Напрямую нигде. Должен сам догадаться и понять, что даже в STM работают говнокодеры. Теперь чуть-чуть понял. А что вот тут как: Ну ок. А тут пишут в п.9: Тут получается напрямую в регистре смотреть? Или опять сначала прочитать в значение в переменную и уже в переменной смотреть значение?
  15. Тут пишут, что флаг надо смотреть не прямо в регистре, а через переменную: Ну ок. А тут пишут в п.9: Тут получается напрямую в регистре смотреть? Или опять сначала прочитать в значение в переменную и уже в переменной смотреть значение? И вообще, вот все небожители пишут, что чистить флаг надо только так: TIMER_INTF(TIMER1) = ~TIMER_INTF_CH0IF; По причине того что: "Software can read as well as clear this bit by writing 0. Writing 1 has no effect on the bit value". Где в этой фразе написано, что нельзя сделать так: TIMER_INTF(TIMER1) &= (~TIMER_INTF_CH0IF); Написано же "Writing 1 has no effect on the bit value". Нет эффекта, а не "нельзя". Что произойдёт, если написать как в варианте 2: 1. Прочитается значение регистра; 2. Значение TIMER_INTF_CH0IF будет побитно инвертировано, лог. 0 будет только на месте нужного бита, остальные лог. 1. 3. С прочитанным значением и с побитно инвертированным значением TIMER_INTF_CH0IF будет сделано побитовое &, т.е. лог. 0 будет там где надо. 4. В TIMER_INTF(TIMER1) запишется высчитанное значение. Ок, лог. 1 писать смысла нет, согласен, смысла нет, но не запрещено! И нужный бит сбросится нулём. Чё у всех так радикально печёт от этого? Код сработает по другому? Почему в примерах от STM так пишут и у них не печёт? Согласен, вот так: TIMER_INTF(TIMER1) = ~TIMER_INTF_CH0IF писать логичнее, а так: TIMER_INTF(TIMER1) &= (~TIMER_INTF_CH0IF) пишут, потому что лень проверять свойства каждого регистра, запись просто универсальнее. Но от этого они что отработают по разному? Где это написано? Судя по тому что, мне упорно объясняют, что я долбоёб, я должен как-то сам понять, что 1000 раз мой код сработает как я думаю, но в 1001 раз сработает неправильно из-за того, что флаг почистил не так.
  16. Киньте ссылку где будет написано "не делай так, потому что случится вот это", а не "не делай так, разве непонятно почему, ну ты и дебил, сам не можешь понять, значит эта задача тебе не по плечу". Если бы я каждый раз слушал философов, которые говорили такое, то можно было не начинать жить.
  17. Вам стоило написать в STM и рассказать им какие они там все говнокодеры: Попробуйте дать ссылку на документ от STM, или хотя бы на чью-то статью, где было бы напечатано выражение "так делать нельзя". Аргумент "я так решил" - это не аргумент. Я не говорю, что Вы не правы. Я хочу узнать, почему Вы сделали такие выводы? Я согласен делать так как Вы говорите, но мне нужно знать, почему нужно делать именно так. Вы проводили самостоятельные эксперименты? Переписывали код на ассемблере и сравнивали результаты? Кучи примеров написано в стиле говнокода, наверно потому, что Ваша истина им менее доступна, чем говнокодовые примеры. Написали бы статью, и каждого тыкали носом в неё. Или это развлечение такое, говнокодерам сообщать, что они говнокодеры?
  18. В п.2 я бы очистил флаг через &=. В п.4 я бы проверил наличие флага опять через &=. и т.д. Как одного? В алгоритме вы читаете INTF несколько раз в разное время (в п.4 можно зациклиться и читать много раз). ну чтож, продолжим традицию
  19. Как оптимально изменить значение бита CH0P в регистре TIMERx_CHCTL2? И почему это будет оптимально? Это Вы лично проверяли в отладке в ассемблере? Я бы обязательно это сделал через &= и |=. Я лично не знаю ни одного программиста, кто придрался бы к этому. Вокруг меня одни говнокодеры. Если Вы объясните, то лично обойду всех, до кого смогу дотянуться и расскажу им, и говнокода в мире станет меньше.
  20. Благодарю за труд. Даже я понял. Единственный момент тут, я ещё не придумал, как в этом алгоритме обрабатывать значения регистра захвата. Получается если возникло "дребезговое" прерывание, мне всё равно нужно хранить значение захвата, а учесть его только когда случится прям "трушное" прерывание. При этом "дребезговых" может быть куча, и всю кучу значений нужно хранить до прихода "трушного".
  21. Тут многим очевидно, и многим видно, что код - говнокод. Жду первого, кто расскажет очевидное для всех, кроме меня, решение. Типа надо было поймать пропуск прерывания и измерить длительность обработки предыдущего прерывания?
  22. Такой момент хер поймаешь. Это не подтверждает пропуски?
  23. Просто картинка сделана когда пропусков прерываний не было. Пропуски возникают не при каждой передаче. Вы просили измерить длительность обработки прерывания, а не поймать осциллограмму с длительностью обработки во время пропуска фронта/среза.
  24. Жёлтый - источник сигнала. Голубой - пин микроконтроллера -> вход канала 3 в Timer1. Розовый - пин микроконтроллера. Пин настроен на выход и меняет своё значение в начале обработчика прерывания и в конце. Вот картинки крупнее: Длительность импульса и, я полагаю, время обработки прерывания составляет 1,6857 us.
×
×
  • Создать...