3

我为 PIC18F 使用 C 语言来产生音调,使它们中的每一个都以特定的时间间隔播放。我使用 PWM 来产生音调。但我不知道如何创建间隔。这是我的尝试。

#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);
}
4

3 回答 3

6

当我进行嵌入式编程时,我发现添加注释非常有用,可以准确解释我在设置配置寄存器时的意图。这样,当我下次必须更改代码时,我就不必返回数据表来弄清楚0x01001010当我试图摸索代码时会发生什么。(请确保评论与更改保持同步)。

从我可以解码的内容来看,您似乎已经设置了 PWM 寄存器,但无法以所需的时间间隔更改频率。有几种方法可以做到,这里有2个想法:

  • 您可以在启动时读取计时器,添加所需的间隔以获得目标时间,并在 while 循环中轮询计时器。当计时器达到目标时,设置新的 PWM 占空比,并将下一个间隔添加到目标时间。这将正常工作,直到您需要开始在后台循环中执行其他操作。
  • 您可以将 timer0 的计数设置为0xFFFF-interval,并将其设置为在翻转时中断。在 ISR 中,设置新的 PWM 占空比,并将 timer0 计数复位到下一个间隔。

在嵌入式进程中控制时序的一种常见方法如下所示:

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()将更新 PWM。逻辑看起来像:“如果它打开,将其关闭;否则打开它。如果需要,更新音调(占空比)”

在主 while 循环中应该不需要额外的延迟或暂停。目标是它一遍又一遍地运行,等待某事做。如果程序需要以不同的速率做其他事情,你可以再加一个标志,这个标志完全独立触发,两个任务的时间不会相互干扰。

于 2009-03-02T18:33:27.193 回答
0

EDIT:
I'm now confused about what you are trying to accomplish. Do you want a series of pulses of the same tone (on-off-on-off)? Or do you want a series of different notes without pauses (do-re-me-fa-...)? I had been assuming the latter, but now I'm not sure.


After seeing your updated code, I'm not sure exactly how your system is configured, so I'm just going to ask some questions I hope are helpful.

  1. Is the PWM part working? Do you get the initial tone? I'm assuming yes.
  2. Does your hardware have some sort of clock pulse hooked up to the RA4/T0CKI pin? If not, you need T0 to be clock mode, not counter mode.
  3. Is the interrupt being called? You are setting INT0IE, which enables the external interrupt, not the timer interrupt
  4. What interval do you want between tone updates? Right now, you are getting 0xFFFF / (clock_freq/8) You need to set the TMR0H/L registers if you want something different.
  5. What's on LATD7? and why are you clearing it? Are you saying it enables PWM output?
  6. Why the call to Delay()? The timer itself should be providing the needed delay. There seems to be a disconnect about how to do timing. I'll expand my other answer
  7. Where are you trying to change the PWM frequency? Don't you need to write to PR2? You will need to give it a different value for every different tone.

"Halting build on first failure as requested."

This just says you have some syntax error, without showing us the error report, we can't really help.

于 2009-03-04T18:42:46.980 回答
-2

在 Windows 中,您可以使用 kernel32 中的 Beep 功能:

    [DllImport("kernel32.dll")]
    private static extern bool Beep(int frequency, int duration);
于 2009-03-02T18:08:17.627 回答