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

LAS9891

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

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

  • Посещение

Репутация

0 Обычный

Информация о LAS9891

  • Звание
    Местный
    Местный

Посетители профиля

3 705 просмотров профиля
  1. Другой оценки мне не стоит ожидать. Предложите свой код, в котором не будет пропусков, а я проверю. Где найти достойный пример, если даже в STM работают говнокодеры? На свежую голову (или что там вместо головы у говнокодеров) нашёл косяк. Теперь не ловлю пропуски в обоих вариантах, но надеюсь, что выложат неговнокодовый пример того, как надо делать.
  2. Сделал специальный дебуговый проект. В нём делаю минимальную инициализацию для настройки тактирования, пинов, таймера 1. По завершении инициализации проект висит в while(1){;}. На 4 канала таймера 1 подаю одинаковые пачки импульсов. Вот в таком варианте обработчика прерываний: стабильно ловлю пропуски в канале 3. Даже если в обработчике ставлю обработку канала 3 в самое начало, всё равно ловлю пропуски в канале 3. В остальных поймать не получилось. Вот в таком варианте обработчика прерываний: пропусков поймать не удалось.
  3. Переписал согласно ЦУ: Получилось так: Работает плюс/минус также. Заметная разница только в том, что раньше чаще пропуски были на канале 3. Сейчас ещё не удалось поймать пропуск на канале 3. Вот так случилось на канале 2: Розовый - дрыг ногой при каждом валидном прерывании на канале 2. Голубой - вид исходной посылки. НА НЕСИНХРОННОСТЬ СИГНАЛОВ ВО ВРЕМЕНИ НЕ СМОТРИМ. Это сигналы с разных каналов. На все каналы приходят одинаковые посылки. Голубой сигнал тут просто для того, чтобы видеть, как должна выглядеть правильная посылка. (Лень было провода перепаивать).
  4. А эта несколько? TIMER_INTF(TIMER1) &= ~TIMER_INTF_CH0IF; TIMER_INTF_CH0IF - это макрос одного бита! Согласен, что код будет не оптимальным по количеству операций, и так делать нерационально, и я не буду так делать. Но как эта запись изменит другие биты кроме одного? В язык Си внесли изменения, в которых операция "&" стала работать по другому? Пусть биты, отличные от TIMER_INTF_CH0IF, хоть обизменяются, макрос от этого не поменяется, и он установит в 0 только свой один бит! Скажите уже, что мне надо читать Страуструпа.
  5. Надо делать так: 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 работают дураки, да и во всех остальных производителях.
  6. Я, конечно, ссу против ветра, но при записи будет изменён только один нужный бит. Для этого и придуманы макросы чуть ли не на каждый бит. Например ~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. Вещи это все очевидные. Понятные априори даже без объяснений.
  7. Хорош теории, вот свежий говнокод: 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. } //------------------------------------------------------------------------------//
  8. Первый об этом написал Сергей Борщ. Потом это же написал я. Вы - третий. Это я уже понял, достаточно. Что на счёт этого: Ну ок. А тут пишут в п.9: Тут получается напрямую в регистре смотреть? Или опять сначала прочитать в значение в переменную и уже в переменной смотреть значение?
  9. Вот это: Это ответ на это? Ну ок. А тут пишут в п.9: Тут получается напрямую в регистре смотреть? Или опять сначала прочитать в значение в переменную и уже в переменной смотреть значение?
  10. Как я ИХ мог очистить, если я чищу только один бит, а запись единиц " Writing 1 has no effect on the bit value". Ладно, проехали про это. Мне про это рассказали. Тогда какая разница где проверять значение в регистре процессора или в переменной, которую я создам специально для этого? Только для того чтобы не делать чтение в регистровую переменную несколько раз? Тогда как тут делать: Нужно проверить регистр таймера, очистить его и опять проверить. Тогда нужно дважды читать значение регистра таймера в специальную переменную а не в процессорную? Разница то какая?
  11. 🤣 Получается: TIMER_INTF(TIMER1) &= (~TIMER_INTF_CH0IF); // Происходит: чтение, модификация, запись. TIMER_INTF(TIMER1) = ~TIMER_INTF_CH0IF; // Происходит: запись. Разница в количестве совершаемых операций и, соответственно, в скорости, а далее следствие из этого: Вот теперь прям по полочкам. Теперь понятно, зачем для каждого регистра смотреть abbreviations for registers, которые для GD появились только в User Manual Revision 2.6. Зачем было так долго объяснять мне, что я читать не умею? Вы ответили в одном предложении! Но его пришлось пассатижами вытаскивать из Вас. Мне тоже не комплиментов отсыпали, но что уж поделать, это русскоязычный форум. Не обижайтесь, свет ваших нимбов ослепляет и документации не видно. Теперь, благодаря Сергей Борщ, стало понятнее. Да по разному. Напрямую нигде. Должен сам догадаться и понять, что даже в STM работают говнокодеры. Теперь чуть-чуть понял. А что вот тут как: Ну ок. А тут пишут в п.9: Тут получается напрямую в регистре смотреть? Или опять сначала прочитать в значение в переменную и уже в переменной смотреть значение?
  12. Тут пишут, что флаг надо смотреть не прямо в регистре, а через переменную: Ну ок. А тут пишут в п.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 раз сработает неправильно из-за того, что флаг почистил не так.
  13. Киньте ссылку где будет написано "не делай так, потому что случится вот это", а не "не делай так, разве непонятно почему, ну ты и дебил, сам не можешь понять, значит эта задача тебе не по плечу". Если бы я каждый раз слушал философов, которые говорили такое, то можно было не начинать жить.
  14. Вам стоило написать в STM и рассказать им какие они там все говнокодеры: Попробуйте дать ссылку на документ от STM, или хотя бы на чью-то статью, где было бы напечатано выражение "так делать нельзя". Аргумент "я так решил" - это не аргумент. Я не говорю, что Вы не правы. Я хочу узнать, почему Вы сделали такие выводы? Я согласен делать так как Вы говорите, но мне нужно знать, почему нужно делать именно так. Вы проводили самостоятельные эксперименты? Переписывали код на ассемблере и сравнивали результаты? Кучи примеров написано в стиле говнокода, наверно потому, что Ваша истина им менее доступна, чем говнокодовые примеры. Написали бы статью, и каждого тыкали носом в неё. Или это развлечение такое, говнокодерам сообщать, что они говнокодеры?
×
×
  • Создать...