Этюды для начинающих: blink и без delay, и без millis

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Ну от. Значить, gcc всёже лучше меня оптимизирует :) 

Green
Онлайн
Зарегистрирован: 01.10.2015

Оптимизация вообще последнее дело. Только в исключительных случаях.

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

ну это понятно, сдвинуть на десять разрядов за два такта совсем никак, хотя бы за десять )))

Bruzzer
Offline
Зарегистрирован: 17.03.2020

ua6em пишет:

ну это понятно, сдвинуть на десять разрядов за два такта совсем никак, хотя бы за десять )))

Меня переклинило потому что я предположил - т.к результат uint_8t то  вдруг он просто берет второй байт от long. Ну а то, что в байте не 10 бит, это мой мозг пропустил, в попытке обосновать 2 такта.

NikShel
Offline
Зарегистрирован: 21.01.2018

Уважаемый dimax !

Пытался сделать блинк из Вашего "Терминального" генератора

Немного переделал, т.к. мне очень надо, чтобы ещё была частота: 0 (без блинка).

Это я пытаюсь сделать индикацию режимов.  Задача простая

Частота: 0 - обычный режим;

Частота №1 - режим настройки  №1;

Частота №2 - режим настройки  №2.

Переключение режимов вручную (пока не задано новое значение).

Но пока у меня получилось, что блинк работает с нужной частотой примерно 1 сек. Переменная reqfreq почему-то обнуляется в конце void loop() , хотя я пытался сделать её глобальной переменной.

Подскажите, что не так!

[code]
volatile long reqfreq = 0; //<--N.Sh.
uint32_t ocr = OCR1A; // uint16_t divider = 1;  float freq;  //<--N.Sh.

void setup() {
  Serial.begin(9600);
  pinMode (9, OUTPUT); // выход генератора
  TCCR1A = 0; TCCR1B = 0;
}

void loop() {
  //  static uint32_t reqfreq = 0; //<-- dimax переменная запроса частоты
  uint16_t divider = 1;  float freq; // uint32_t ocr = OCR1A; <-- dimax
  if (Serial.available() > 0) {
    reqfreq = Serial.parseInt();

    if (reqfreq > F_CPU / 2) {
      return;
    }
    if (reqfreq == 0) {
      TCCR1A = 0; TCCR1B = 0;
      Serial.println("0 Hz");
      return;
    }  // <--N.Sh. / dimax--> if (reqfreq==0 || reqfreq>F_CPU/2) {return;}
    ocr = (F_CPU / reqfreq / 2 / divider);
    byte shifts[] = {3, 3, 2, 2};
    for (byte i = 0; i < 4; i++) {
      if (ocr > 65536) {
        divider <<= shifts[i];
        ocr = F_CPU / reqfreq / 2 / divider;
      }
      else {
        TCCR1B = (i + 1) | (1 << WGM12);   //Mode4 (CTC)
        break;
      }
    }
    OCR1A = ocr - 1; TCCR1A = 1 << COM1A0;
    freq = (float) F_CPU / 2 / (OCR1A + 1) / divider;
    if (freq < 10000) {
      Serial.print(freq, 1);
      Serial.println(" Hz ");
    }
    if (freq >= 10000) {
      Serial.print(freq / 1000, 3);
      Serial.println(" kHz");
    }
  }
  // Serial.println(reqfreq);
}

//Скетч использует 4430 байт (14%) памяти устройства. Всего доступно 30720 байт.
//Глобальные переменные используют 222 байт (10%) динамической памяти, оставляя 1826 байт для локальных переменных. Максимум: 2048 байт.
[/code]

 

venus
venus аватар
Offline
Зарегистрирован: 08.10.2019

volatile-то вам зачем? Serial.parseInt() у вас возвращает ноль не только если введена строка "0", но и если мусор считал.

uint32_t ocr = OCR1A; // uint16_t divider = 1;  float freq;  //<--N.Sh.

void setup() {
  Serial.begin(9600);
  pinMode (9, OUTPUT); // выход генератора
  TCCR1A = 0; TCCR1B = 0;
}

void loop() {
  static uint32_t reqfreq = 0; //<-- dimax переменная запроса частоты
  static char in[16];
  uint16_t divider = 1;  float freq; // uint32_t ocr = OCR1A; <-- dimax
  if (Serial.available() > 0 && Serial.readBytes(in, 15) > 0 && sscanf(in, "%lu", &reqfreq) == 1) {
    if (reqfreq > F_CPU / 2) {
      return;
    }
    if (reqfreq == 0) {
      TCCR1A = 0; TCCR1B = 0;
      Serial.println("0 Hz");
      return;
    }  // <--N.Sh. / dimax--> if (reqfreq==0 || reqfreq>F_CPU/2) {return;}
    ocr = (F_CPU / reqfreq / 2 / divider);
    byte shifts[] = {3, 3, 2, 2};
    for (byte i = 0; i < 4; i++) {
      if (ocr > 65536) {
        divider <<= shifts[i];
        ocr = F_CPU / reqfreq / 2 / divider;
      }
      else {
        TCCR1B = (i + 1) | (1 << WGM12);   //Mode4 (CTC)
        break;
      }
    }
    OCR1A = ocr - 1; TCCR1A = 1 << COM1A0;
    freq = (float) F_CPU / 2 / (OCR1A + 1) / divider;
    if (freq < 10000) {
      Serial.print(freq, 1);
      Serial.println(" Hz ");
    }
    if (freq >= 10000) {
      Serial.print(freq / 1000, 3);
      Serial.println(" kHz");
    }
  }
  // Serial.println(reqfreq);
}

//Скетч использует 4430 байт (14%) памяти устройства. Всего доступно 30720 байт.
//Глобальные переменные используют 222 байт (10%) динамической памяти, оставляя 1826 байт для локальных переменных. Максимум: 2048 байт.

 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

NikShel пишет:

 Переменная reqfreq почему-то обнуляется в конце void loop() , хотя я пытался сделать её глобальной переменной. Подскажите, что не так!

По виду всё так. Наверно из терминалки прилетает ноль. Если в ардуиновском мониторе смотрите, то выберете в настройке "Нет конца строки"

venus
venus аватар
Offline
Зарегистрирован: 08.10.2019

dimax пишет:
Наверно из терминалки прилетает ноль.

там что попало прилетает, функция parseint просто такая. замена на readbytes плюс sscanf решает вопрос. проверил.

NikShel
Offline
Зарегистрирован: 21.01.2018

в настройке "Нет конца строки"

Помогло, спасибо!

NikShel
Offline
Зарегистрирован: 21.01.2018

venus пишет:

dimax пишет:
Наверно из терминалки прилетает ноль.

там что попало прилетает, функция parseint просто такая. замена на readbytes плюс sscanf решает вопрос. проверил.

 readbytes плюс sscanf  - можно по-подробней. В справочниках не нашёл.

venus
venus аватар
Offline
Зарегистрирован: 08.10.2019

NikShel пишет:
readbytes плюс sscanf  - можно по-подробней. В справочниках не нашёл.

я же прицепил исправленный скетч в ответе на ваш вопрос. сравните со своим, там лишь пара строк отличается.

NikShel
Offline
Зарегистрирован: 21.01.2018

venus пишет:

 исправленный скетч в ответе на ваш вопрос. сравните со своим, там лишь пара строк отличается.

Я протестил: работает, спасибо!

NikShel
Offline
Зарегистрирован: 21.01.2018

Ну и вот он мой вариант Блинка:

#define D9_High TCCR1A = B11 << COM1A0; // 11 - установить пин_9 HIGH = off
#define D9_LOW TCCR1A = B10 << COM1A0; // 10 - установить пин_9 LOW = on
#define D9_F_1Hz TCCR1B = 12; OCR1A = 31249; TCCR1A = 1 << COM1A0; //  Frequency: 1Hz; 
#define D9_F_2Hz TCCR1B = 11; OCR1A = 62499;  TCCR1A = 1 << COM1A0; //  Frequency: 2Hz;

void setup() {
  Serial.begin(9600);
  pinMode (9, OUTPUT); // выход генератора
  TCCR1A = B10 << COM1A0;
}

void loop() {

  static uint32_t var = 0; //<-- dimax переменная запроса режима
  static char in[1];

  if (Serial.available() > 0 && Serial.readBytes(in, 1) > 0 && sscanf(in, "%lu", &var) == 1) { //  <-- venus
    Serial.println(var);
    switch (var) {
      case 0:
        D9_High //выполняется, когда var равно 0 - выкл
        break;
      case 1:
        D9_F_1Hz //выполняется, когда var равно 1
        break;
      case 2:
        D9_F_2Hz //выполняется когда  var равно 2
        break;
      default:
        D9_LOW // обычный режим

    }
  }
}

//Скетч использует 3836 байт (12%) памяти устройства. Всего доступно 30720 байт.
//Глобальные переменные используют 197 байт (9%) динамической памяти, оставляя 1851 байт для локальных переменных. Максимум: 2048 байт.

Спасибо, venus 

Спасибо, dimax 

Спасибо, ЕвгенийП !