Внешнее тактование attiny85

Тема в разделе "Микроконтроллеры AVR", создана пользователем DrProg, 29 сен 2015.

  1. DrProg

    DrProg Вечный нерд

    delay вообще не пользуюсь кроме случаев, когда нужно действительно тупо подождать пару секунд. А вообще интересную тему затронули, попробую завтра сделать shiftIn через PORTA и сравню fps.
     
    ИгорьК нравится это.
  2. Megakoteyka

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

    Попробуйте, только замеры делайте на большом количестве вызовов, как я выше писал - точнее измерения будут.
     
  3. Tomasina

    Tomasina Сушитель лампочек Модератор

    DrProg нравится это.
  4. DrProg

    DrProg Вечный нерд

    Провел вот такой простой эксперимент:

    Код (C++):
    unsigned long timerM;

    void setup() {
      // put your setup code here, to run once:
      pinMode(13, OUTPUT);
      Serial.begin(9600);
    }

    void loop() {
      // put your main code here, to run repeatedly:
      timerM = millis();
      for (long i = 0; i < 500000; i++) {
        digitalWrite(13, HIGH);
        digitalWrite(13, LOW);
      }
      Serial.print("digitalWrite: ");
      Serial.println(millis() - timerM);

      timerM = millis();
      for (long i = 0; i < 500000; i++) {
        PBdigWH(5);
        PBdigWL(5);
      }
      Serial.print("PBbigW: ");
      Serial.println(millis() - timerM);


    }

    void PBdigWH(byte NB) {
      PORTB |= 1 << NB;
    }

    void PBdigWL(byte NB) {
      PORTB &= ~(1 << NB);
    }
    Разница составила не 1000 раз (как в статье выше) и не в 100 и даже не в 10. Примерно в 2 раза быстрее. Что я делаю не так?

    PS: а вот на матрице 8х8 при работе с tiny85 разница заметна на глаз, нет дрожания совсем даже на 1МГц, жаль fps через Serial не посмотреть так просто.
     
    Последнее редактирование: 30 сен 2015
    ИгорьК нравится это.
  5. ИгорьК

    ИгорьК Гуру

    Что сразу видно:
    Код (C++):
    inline void PBdigWH(byte NB) {
      PORTB |= 1 << NB;
    }

    inline void PBdigWL(byte NB) {
      PORTB &= ~(1 << NB);
    }
     
    AlexU нравится это.
  6. DrProg

    DrProg Вечный нерд

    Может быть сама организация цикла съедает большую часть времени? Надо еще поискать.
     
    ИгорьК нравится это.
  7. AlexU

    AlexU Гуру

    В этом эксперименте в функции loop() Вы используете вывод в последовательный порт (Serial.print/ln). Запись в последовательный порт замедляет работу всего скетча, почти то же самое, что вызывать функцию delay().
    Если правильно понял исходники (HardwareSerial.cpp), то при передаче последовательности байт 'Serial.print("digitalWrite: ");' скетч остановиться пока все байты не передадутся. А при скорости 9600 бит/с, для передачи 14 байт потребуется ~12 мсек. Вот из-за этого и разница маленькая.
     
  8. DrProg

    DrProg Вечный нерд

    Не уверен что это так, тем более что пустой цикл вообще никакой задержки не вызывает. Думаю, что передача в порт никак не задерживает цикл, а отображает секундомер когда тот заканчивает работу.
     
    ИгорьК нравится это.
  9. geher

    geher Гуру

    Serial.print реально замедляет работу программы, но он не ждет, пока все байты передадутся. А если чего-то ждет, то только записи этих байт в буфер порта.
    Если слишком быстро гнать данные в порт, то они просто начинают теряться из-за переполнения буфера. По крайней мере у меня на меге так получилось. Пришлось паузу между передачами небольших блоков вставлять, чтобы блоки доходили без потерь.
     
  10. AlexU

    AlexU Гуру

    Попробуйте вместо кода:
    Код (C++):
      timerM = millis();
      for (long i = 0; i < 500000; i++) {
        digitalWrite(13, HIGH);
        digitalWrite(13, LOW);
      }
      Serial.print("digitalWrite: ");
      Serial.println(millis() - timerM);
    использовать:
    Код (C++):
      timerM = millis();
      for (long i = 0; i < 500000; i++) {
        digitalWrite(13, HIGH);
        digitalWrite(13, LOW);
      }
      timerM = millis() - timerM;
      Serial.print("digitalWrite: ");
      Serial.println(timerM);
    И во втором замере тоже.
    Также можно вместо millis() ппопробовать micros().
     
  11. DrProg

    DrProg Вечный нерд

    Простите, в чем разница? Переполнение буфера не наступает и в том и другом случае, ибо в цикле он не участвует. Вот inline реально ускоряет процесс, спасибо ИгорюК, хоть он и пробивается иной раз из игнора, несмотря на то, что inline достаточно не секретная опция. В итоге, общими усилиями, с увеличением частоты и обращению к ноге напрямую поучили ускорение раз в 100-150, о чем и говорил Мегакотейка, за что ему отдельное спасибо. Tiny85 начала тянуть такие задачи, которые ранее считались мною превыше этих замечательных козявок.

    ПыСы: чуть позже выложу функции и таблицу соответствия ног битам портов Уно, Меги и Про Мини для тех кто интересуется, но пока не достиг. Для Тинек ноги прозрачнее, но вопросов больше по другой части.
     
    Последнее редактирование: 1 окт 2015
    ИгорьК нравится это.
  12. AlexU

    AlexU Гуру

    Разница в том, что замер времени происходит до отправки данных в последовательный порт. Вы же в эксперименте вычисляете разницу после передачи строки в порт из-за чего в разницу вносится погрешность.
    Код (C++):
    timerM = millis() - timerM;  // вычисляем затраченное время
    Serial.print("digitalWrite: ");  // пишем в порт
    Serial.println(timerM);
    И действительно, ИгорьК обратил внимание на то, на что нужно было обратить внимание сразу. В Вашем эксперименте процессорное время, затраченное на вызов функций, будет сопоставимо, если не больше, с процессорным временем, затраченным на тело функций. А inline встроит тело функций вместо их вызовов.

    Вы в основном правы, я не совсем точно выразил свои мысли. Описанная мной ситуация произойдет при полностью заполненном буфере.
     
  13. Airbus

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

    А ещё можно reset задействовать будет +1 нога!
    Немного не понял зачем для таймера обратного отсчёта повышать скорость в 8 раз?Это типа как крутить двигатель до 5000 об/мин и всё равно ехать со скоростью 40 км/час на 1 передаче?
     
  14. DrProg

    DrProg Вечный нерд

    А вам жалко 7 мегагерц что ли? Да хотя бы не мерцает и уже хорошо. Плюс задел на будущее, когда на 85ых повешаются задачки поважнее и посложнее, пригодится разгонять.
     
    ИгорьК нравится это.
  15. Airbus

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

    Если честно не вижу связь между тактовой частотой и мерцанием.Уже на 50 Гц.Тем более на 1МГЦ Как старый радиолюбитель мерцание могу объяснить невысокой нагрузочной способностью выводов микроконтроллера (любого!)Если поставить ключи на транзисторах на общие Аноды/Катоды как пишут в умных книжках то и мерцания не будет и риска спалить порты-тоже.А вот для считывания+передачи данных "разгон" как раз самое оно.Хотя судя из моего скромного опыта общения с AVR 4МГЦ (4 миллиона операций в секунду)хватает для любых задач.
     
  16. DrProg

    DrProg Вечный нерд

    Связь прямая. И 1МГц на такте это примерно 10Гц на 4х знаковом индикаторе, что очень заметно и не очень приятно глазу. На 8МГц мерцание почти не заметно, при прямом обращении к портам и вовсе пропадает. Разница есть.
     
    Последнее редактирование: 8 окт 2015
    ИгорьК нравится это.