Создание тонов в определенный промежуток времени с использованием программирования на C

Я использую язык C для PIC18F для создания тонов, которые воспроизводятся каждым из них в определенный промежуток времени. Я использовал ШИМ для создания тона. Но я не знаю, как создать интервалы. Вот моя попытка.

#pragma code                                    // 
void main (void)
{

 int i=0;
    // set internal oscillator to 1MHz  
    //OSCCON = 0b10110110;                    // IRCFx = 101
    //OSCTUNEbits.PLLEN = 0;                //PLL disabled

    TRISDbits.TRISD7 = 0;

    T2CON  = 0b00000101;                    //timer2 on
    PR2    = 240;
    CCPR1L = 0x78;
    CCP1CON= 0b01001100;



LATDbits.LATD7=0;
Delay1KTCYx(1000);

while(1);
}

3 ответа

Когда я занимаюсь встроенным программированием, я нахожу чрезвычайно полезным добавлять комментарии, поясняющие, что именно я имею в виду, когда я устанавливаю регистры конфигурации. Таким образом, мне не нужно возвращаться к таблицам данных, чтобы выяснить, что 0x01001010 делает, когда я пытаюсь получить код в следующий раз, когда я должен изменить его. (Просто убедитесь, что комментарии синхронизированы с изменениями).

Из того, что я могу декодировать, похоже, что у вас настроены ШИМ-регистры, но нет способа изменить частоту с заданными интервалами. Есть несколько способов сделать это, вот две идеи:

  • Вы можете прочитать таймер при запуске, добавить желаемый интервал, чтобы получить целевое время, и опрашивать таймер в цикле while. Когда таймер достигнет цели, установите новый рабочий цикл ШИМ и добавьте следующий интервал к целевому времени. Это будет работать нормально, пока вы не начнете делать другие вещи в фоновом цикле.
  • Вы можете установить счетчик timer0 в 0xFFFF-intervalи установите его для прерывания при опрокидывании. В ISR установите новый рабочий цикл ШИМ и сбросьте счетчик таймера 0 до следующего интервала.

Один из распространенных способов управления синхронизацией во встроенных процессах выглядит следующим образом:

int flag=0;
void main()
{
  setup_interrupt(); //schedule interrupt for desired time.
  while (1)
  {  
     if (flag)
     {  
        update_something();
        flag = 0;
     }
  }

Где же flag приготовься? В обработчике прерываний:

void InterruptHandler()
{
  flag = 1;
  acknowledge_interupt_reg = 0;
}

У вас есть все части в вашем примере, вам просто нужно собрать их в нужных местах. В твоем случае, update_something() обновил бы ШИМ. Логика будет выглядеть так: "Если он включен, выключите его; в противном случае включите его. Обновите тон (коэффициент заполнения), если это необходимо"

Не должно быть необходимости в дополнительных задержках или паузах в основном цикле while. Цель в том, чтобы он просто бегал снова и снова, ожидая, что что-то сделать. Если программе нужно делать что-то еще с другой скоростью, вы можете добавить еще один флаг, который срабатывает совершенно независимо, и синхронизация этих двух задач не будет мешать друг другу.

РЕДАКТИРОВАТЬ:
Теперь я смущен тем, что вы пытаетесь достичь. Вы хотите серию импульсов одного и того же тона (вкл-выкл-выкл)? Или вы хотите серию разных нот без пауз (do-re-me-fa -...)? Я предполагал последнее, но теперь я не уверен.


После просмотра вашего обновленного кода я не уверен, как именно настроена ваша система, поэтому я просто задам несколько вопросов, которые, я надеюсь, будут полезны.

  1. Работает ли ШИМ? Вы получаете начальный тон? Я предполагаю, что да.
  2. Есть ли на вашем оборудовании какой-то тактовый импульс, подключенный к выводу RA4/T0CKI? Если нет, то вам нужен режим T0, а не режим счетчика.
  3. Вызывается ли прерывание? Вы устанавливаете INT0IE, который включает внешнее прерывание, а не прерывание по таймеру
  4. Какой интервал вы хотите между обновлениями тонов? Прямо сейчас вы получаете 0xFFFF / (clock_freq/8) Вам нужно установить регистры TMR0H/L, если вы хотите что-то другое.
  5. Что на LATD7? и почему вы это очищаете? Вы говорите, что это позволяет выход ШИМ?
  6. Почему вызов Delay()? Сам таймер должен обеспечивать необходимую задержку. Кажется, есть разногласия по поводу того, как сделать выбор времени. Я расширю свой другой ответ
  7. Где вы пытаетесь изменить частоту ШИМ? Вам не нужно писать в PR2? Вам нужно будет дать ему другое значение для каждого другого тона.

Msgstr "Остановка сборки при первом сбое в соответствии с запросом."

Это просто говорит о том, что у вас есть какая-то синтаксическая ошибка, не показывая нам отчет об ошибке, мы не можем помочь.

В Windows вы можете использовать функцию Beep в kernel32:

    [DllImport("kernel32.dll")]
    private static extern bool Beep(int frequency, int duration);
Другие вопросы по тегам