PORT vs PIN

Тема в разделе "Микроконтроллеры AVR", создана пользователем ostrov, 12 апр 2016.

  1. ostrov

    ostrov Гуру

    Из того что вряд ли понадобится, но интересно узнать. Странные результаты наблюдений обнаруживаются порой при изучении предельных возможностей МК. Например, измерял при помощи анализатора максимальную частоту с которой может переключаться пин на примере пина 13 Меги2560.

    Сперва при помощи конструкции их стандартных функций digitalWrite(13,!digitalRead(13));. Период получился ожидаемые примерно 14us, частота 35КГц. При использовании переменной (убрав чтение порта) результат улучшился почти вдвое: 8.4us.

    Далее при помощи вот такой нехитрой программки в цикле:
    Код (C++):
    PORTB = PINB ^ (1<<7);
    PORTB = PINB ^ (1<<7);
    PORTB = PINB ^ (1<<7);
    _delay_us(5);
    три раза подряд чтобы отличить разницу между потоком и итерацией. Вот тут начались странности. Внутри цикла переключалось не всегда! Примерно через раз. Пробовал сериями по 8, срабатывало 4 раза. Через итерацию цикла все срабатывает, с периодом 1us (без delay, разумеется), а подряд - пропуски. Вот, например, картина из 8 переключений:
    [​IMG]


    Затем я попробовал не совсем легальный способ:
    Код (C++):
    PORTB = PORTB ^ (1<<7);
    PORTB = PORTB ^ (1<<7);
    PORTB = PORTB ^ (1<<7);
    _delay_us(5);
    и вы знаете, все заработало очень четко, без сбоев внутри цикла. Период 0.18us, частота около 3МГц. Ни единого пропуска!
    [​IMG]

    Отсюда неожиданный, но логичный вопрос: информация о реальном состоянии пинов (как минимум находящихся в режиме вывода) находится таки в регистре PORT и передается в регистр PIN с некоторой задержкой? Или что? Пробовал смотреть двумя разными анализаторами, один из них на канал обещает 100МГц, результат един. При сомнении и желании перепроверить. подтвердить или опровергнуть этот факт может любой желающий.
     
    Последнее редактирование: 12 апр 2016
  2. AlexU

    AlexU Гуру

    Значение регистра PINB устанавливается в соответствии с уровнем пина минимум через один такт. А в соответствии с первым примером в этом такте производится чтение из регистра PINB, который хранит предыдущее состояние. Именно поэтому и происходит:
    Вот только скорее "не примерно", а точно через раз.
    Попробуйте следующий код:
    Код (C++):
    PORTB = PINB ^ (1<<7);
    asm ("nop");
    PORTB = PINB ^ (1<<7);
    asm ("nop");
    PORTB = PINB ^ (1<<7);
    asm ("nop");
    Что касается:
    С чего Вы взяли, что это не легальный способ в этом конкретном случае (переключение состояния пина)? В Вашем случае из вне на пин никаких сигналов не подаётся поэтому состояние пина можно узнать и по значению регистра PORTB.

    Есть ещё одна инересная фишка. Правда сам не проверял. Если верить документации, переключать состояние пина можно следующей командой:
    Код (C++):
    PINB = (1<<7);
    Т.е. каждый раз когда в PINB записывается единица в определённый бит, в регистре PORTB соответствующий бит меняет своё значение. Делать это можно только с одним битом одновременно.
     
    ostrov нравится это.
  3. Unixon

    Unixon Оракул Модератор

    Какой-то полудокументированный toggle-register :) На схеме порта есть, в тексте нет.
     
  4. AlexU

    AlexU Гуру

    Оф.документация на ATmega328:
     
  5. Unixon

    Unixon Оракул Модератор

    Блин, я реально слепой. :confused:
     
  6. ostrov

    ostrov Гуру

    А если нужно единичку туда поместить не зная что там?
     
  7. Airbus

    Airbus Радиохулиган Модератор

    И будет единичка-независимо от того что было
     
  8. ostrov

    ostrov Гуру

     
  9. AlexU

    AlexU Гуру

    Куда поместить?
    PINx -- это входной регистр, он показывает состояние пинов (которые обслуживает регистр PINx). В его биты можно поместить единички, если подать логические единицы на входы соответствующих пинов. Но программно записать скорее нельзя.
    PORTx -- выходной регистр. Так понимаю, Вы знаете, что будет, если в его биты записывать единички.
    То что я привёл про PINx -- это документированное, но скорее не стандартное использование регистра PINx, которое позволяет быстро менять состояние пина.
     
  10. ostrov

    ostrov Гуру

    Надо попробовать.
     
  11. ostrov

    ostrov Гуру

    Попробовал.
    Код (C++):
    PINB = (1<<7);
    Скорость срабатывания действительная увеличилась в 2,5 раза, частота поднялась с 3 до 8МГц. Я думал что 3МГц это уже предел для пина на этой конфигурации.

    [​IMG]

    Нефига себе blink...
     
    Последнее редактирование: 12 апр 2016
  12. ostrov

    ostrov Гуру

    Очень похоже, что это действительно предел для данного МК на данной тактовой частоте. Если верить моему простому осциллографу, сигнал между переключениями даже не успевает выйти на номинальное напряжение. Семь переключений:

    [​IMG]

    Восемь на другом простом осциллографе:

    [​IMG]
     
    Последнее редактирование: 14 апр 2016
  13. Unixon

    Unixon Оракул Модератор

    16МГц тактовая, 1 команда на такт, 8МГц на выходе. Как вы хотели это улучшить?
     
  14. Unixon

    Unixon Оракул Модератор

    Что за осциллограф, какая полоса пропускания канала и частота выборки?
     
  15. ostrov

    ostrov Гуру

    DSO 203, он же Quad. Параметры все на экране. На втором Hantek 6022BE. Для них это тоже предел, похоже.
     
  16. ostrov

    ostrov Гуру

    Улучшить уже некуда, про то и речь. Да и не нужно пока. Задача чисто теоретическая - выжать максимум возможно ли.
     
  17. ostrov

    ostrov Гуру

    Пожалуй максимально минимальный секундный blink для Меги на IDE (702 байта):

    Код (C++):
    void setup() {
      DDRB = 0xFF;
      TCCR1A = 0;
      TCCR1B = 0b00001101;
      OCR1A = 0x3D08;
      TIMSK1 = 0b0000110;
    }

    void loop() {
    }

    ISR(TIMER1_COMPA_vect) {
      PINB = (1 << 7);
    }
     
  18. AlexU

    AlexU Гуру

    На Arduino UNO rev.3 (оригинал) вот такая картинка получается:
    pind.jpeg
     
  19. Unixon

    Unixon Оракул Модератор

    Понятно. С этими двумя вы на такой частоте ничего лучше недосинуса и не увидите, нужен аппарат хотя бы на порядок быстрее, а лучше на 1.5-2.
     
  20. ostrov

    ostrov Гуру

    Пока я не дорос до 32битных МК, аппарат лучше не нужен. )