Функция tone()

arduino-logo

Описание функции tone в arduino

Генерирует прямоугольные импульсы заданной частоты и с 50-ти процентным заполнением (т.е. длительность импульса равна длительности паузы между импульсами). Если функция вызвана без параметра duration (длительности), то генерация будет продолжать до тех пор, пока не будет отменена функцией noTone.

50% заполнение сигнала функцией tone
На изображении видно, что длительность импульса равна паузе между двумя импульсами 415 микросекунд

Функцию tone нельзя вызвать одновременно на нескольких портах ввода/вывода.

Если во время выполения функции tone вызвать ее еще раз с тем же номером контакта платы, то произойдет изменение частоты сигнала, который был указан в последнем вызове функции.

Синтаксис

tone(pin, frequency) 
tone(pin, frequency, duration)

Параметры

  • pin — номер контакта платы Ардуино для запуска генерации частотного сигнала.
  • frequency — частота генерации сигнала в герцах (Гц).
  • duration — длительность генерации сигнала в миллисекундах (мс).

Что возвращает

Ничего

Пример функции tone в Arduino

#define BUZZER 2                    // Ввод/вывод, на котором висит бузер

void setup() {
  pinMode(BUZZER, OUTPUT);          // Настраиваем ввод/вывод на выход
  tone(BUZZER, 1200);               // Сгенерировать импульсный сигнал с частотой 1200 Гц (если подключен бузер, то он будет пищать)
  delay(2000);                      // Подождать 2 секунды
  noTone(BUZZER);                   // Остановить генерацию
}

void loop() {
  // Цикл генерирует поочередно частоты от 1 кГц до 4 кГц
  for(uint8_t i = 1; i < 5; i++) {
    tone(BUZZER, i * 1000, 2000);   // Сгенерировать сигнал с частотой i * 1000 и длительность 2000 милисекунд (2 секунды)
    delay(5000);                    // Подождать 5 секунд
  }
}

На гифке ниже можно посмотреть, как работает функция tone (правда без звука).

Код функции

(hardware/arduino/avr/cores/arduino/Tone.cpp 1.8.10)

void tone(uint8_t _pin, unsigned int frequency, unsigned long duration)
{
  uint8_t prescalarbits = 0b001;
  long toggle_count = 0;
  uint32_t ocr = 0;
  int8_t _timer;

  _timer = toneBegin(_pin);

  if (_timer >= 0)
  {
    pinMode(_pin, OUTPUT);
    
    if (_timer == 0 || _timer == 2)
    {
      ocr = F_CPU / frequency / 2 - 1;
      prescalarbits = 0b001;
      if (ocr > 255)
      {
        ocr = F_CPU / frequency / 2 / 8 - 1;
        prescalarbits = 0b010; 

        if (_timer == 2 && ocr > 255)
        {
          ocr = F_CPU / frequency / 2 / 32 - 1;
          prescalarbits = 0b011;
        }
        if (ocr > 255)
        {
          ocr = F_CPU / frequency / 2 / 64 - 1;
          prescalarbits = _timer == 0 ? 0b011 : 0b100;
          if (_timer == 2 && ocr > 255)
          {
            ocr = F_CPU / frequency / 2 / 128 - 1;
            prescalarbits = 0b101;
          }

          if (ocr > 255)
          {
            ocr = F_CPU / frequency / 2 / 256 - 1;
            prescalarbits = _timer == 0 ? 0b100 : 0b110;
            if (ocr > 255)
            {
              ocr = F_CPU / frequency / 2 / 1024 - 1;
              prescalarbits = _timer == 0 ? 0b101 : 0b111;
            }
          }
        }
      }

#if defined(TCCR0B)
      if (_timer == 0)
      {
        TCCR0B = (TCCR0B & 0b11111000) | prescalarbits;
      }
      else
#endif
#if defined(TCCR2B)
      {
        TCCR2B = (TCCR2B & 0b11111000) | prescalarbits;
      }
#else
      {
        // dummy place holder to make the above ifdefs work
      }
#endif
    }
    else
    {
      ocr = F_CPU / frequency / 2 - 1;
      prescalarbits = 0b001;
      if (ocr > 0xffff)
      {
        ocr = F_CPU / frequency / 2 / 64 - 1;
        prescalarbits = 0b011;
      }
      if (_timer == 1)
      {
#if defined(TCCR1B)
        TCCR1B = (TCCR1B & 0b11111000) | prescalarbits;
#endif
      }
#if defined(TCCR3B)
      else if (_timer == 3)
        TCCR3B = (TCCR3B & 0b11111000) | prescalarbits;
#endif
#if defined(TCCR4B)
      else if (_timer == 4)
        TCCR4B = (TCCR4B & 0b11111000) | prescalarbits;
#endif
#if defined(TCCR5B)
      else if (_timer == 5)
        TCCR5B = (TCCR5B & 0b11111000) | prescalarbits;
#endif

    }

    if (duration > 0)
    {
      toggle_count = 2 * frequency * duration / 1000;
    }
    else
    {
      toggle_count = -1;
    }

    switch (_timer)
    {

#if defined(OCR0A) && defined(TIMSK0) && defined(OCIE0A)
      case 0:
        OCR0A = ocr;
        timer0_toggle_count = toggle_count;
        bitWrite(TIMSK0, OCIE0A, 1);
        break;
#endif
      case 1:
#if defined(OCR1A) && defined(TIMSK1) && defined(OCIE1A)
        OCR1A = ocr;
        timer1_toggle_count = toggle_count;
        bitWrite(TIMSK1, OCIE1A, 1);
#elif defined(OCR1A) && defined(TIMSK) && defined(OCIE1A)
        // this combination is for at least the ATmega32
        OCR1A = ocr;
        timer1_toggle_count = toggle_count;
        bitWrite(TIMSK, OCIE1A, 1);
#endif
        break;

#if defined(OCR2A) && defined(TIMSK2) && defined(OCIE2A)
      case 2:
        OCR2A = ocr;
        timer2_toggle_count = toggle_count;
        bitWrite(TIMSK2, OCIE2A, 1);
        break;
#endif

#if defined(OCR3A) && defined(TIMSK3) && defined(OCIE3A)
      case 3:
        OCR3A = ocr;
        timer3_toggle_count = toggle_count;
        bitWrite(TIMSK3, OCIE3A, 1);
        break;
#endif

#if defined(OCR4A) && defined(TIMSK4) && defined(OCIE4A)
      case 4:
        OCR4A = ocr;
        timer4_toggle_count = toggle_count;
        bitWrite(TIMSK4, OCIE4A, 1);
        break;
#endif

#if defined(OCR5A) && defined(TIMSK5) && defined(OCIE5A)
      case 5:
        OCR5A = ocr;
        timer5_toggle_count = toggle_count;
        bitWrite(TIMSK5, OCIE5A, 1);
        break;
#endif
    }
  }
}

Загрузки

Где купить

0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest
0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии