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

Я использую язык 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 ]

6 голосов
/ 02 марта 2009

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

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

  • Вы можете прочитать таймер при запуске, добавить желаемый интервал, чтобы получить целевое время, и опрашивать таймер в цикле while. Когда таймер достигнет цели, установите новый рабочий цикл ШИМ и добавьте следующий интервал к целевому времени. Это будет работать нормально, пока вам не нужно будет заняться другими вещами в фоновом цикле.
  • Вы можете установить счетчик таймера 0 на 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. Цель в том, чтобы он просто бегал снова и снова, ожидая, что что-то сделать. Если программе нужно сделать что-то еще с другой скоростью, вы можете добавить еще один флаг, который срабатывает совершенно независимо, и синхронизация этих двух задач не будет мешать друг другу.

0 голосов
/ 04 марта 2009

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


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

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

«Прекращение сборки при первом сбое по запросу».

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

0 голосов
/ 02 марта 2009

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

    [DllImport("kernel32.dll")]
    private static extern bool Beep(int frequency, int duration);
...