使用C编程以一定的时间间隔产生音调

发布于 2024-07-14 19:48:22 字数 553 浏览 8 评论 0原文

我使用 C 语言为 PIC18F 生成音调,以便每个音调以特定的时间间隔播放。 我使用 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);
}

Im using C language for a PIC18F to produce tones such that each of them plays at certain time-interval. I used PWM to produce a tone. But I don't know how to create the intervals. Here is my attempt.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

七婞 2024-07-21 19:48:23

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

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

  • 您可以在启动时读取计时器,添加所需的间隔以获取目标时间,并在 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 循环中不需要额外的延迟或暂停。 目标是它一遍又一遍地运行,等待执行某些操作。 如果程序需要以不同的速率做其他事情,可以添加另一个标志,该标志完全独立触发,两个任务的时间不会互相干扰。

When I'm doing embedded programming, I find it extremely useful to add comments explaining exactly what I'm intending when I'm set configuration registers. That way I don't have to go back to the data sheets to figure out what 0x01001010 does when I'm trying to grok the code the next time I have to change it. (Just be sure to keep the comments in sync with the changes).

From what I can decode, it looks like you've got the PWM registers set up, but no way to change the frequency at your desired intervals. There are a few ways to do it, here are 2 ideas:

  • You could read a timer on startup, add the desired interval to get a target time, and poll the timer in the while loop. When the timer hits the target, set a new PWM duty cycle, and add the next interval to your target time. This will work fine, until you need to start doing other things in the background loop.
  • You could set timer0's count to 0xFFFF-interval, and set it to interrupt on rollover. In the ISR, set the new PWM duty cycle, and reset timer0 count to the next interval.

One common way of controlling timing in embedded processes looks like this:

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

Where does flag get set? In the interrupt handler:

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

You've got all the pieces in your example, you just need to put them together in the right places. In your case, update_something() would update the PWM. The logic would look like: "If it's on, turn it off; else turn it on. Update the tone (duty cycle) if desired"

There should be no need for additional delays or pauses in the main while loop. The goal is that it just runs over and over again, waiting for something to do. If the program needs to do something else at a different rate, you can add another flag, which is triggered completely independently, and the timing of the two tasks won't interfere with each other.

勿忘初心 2024-07-21 19:48:23

编辑:
我现在对你想要实现的目标感到困惑。 您想要一系列相同音调的脉冲(开-关-开-关)吗? 或者您想要一系列没有停顿的不同音符(do-re-me-fa-...)? 我一直假设是后者,但现在我不确定。


看到您更新的代码后,我不确定您的系统是如何配置的,所以我只想问一些问题,希望对您有所帮助。

  1. PWM部分工作正常吗? 你听懂初始音了吗? 我假设是的。
  2. 您的硬件是否有某种时钟脉冲连接到 RA4/T0CKI 引脚? 如果不是,则需要T0为时钟模式,而不是计数器模式。
  3. 中断正在被调用吗? 您正在设置 INT0IE,它启用外部中断,而不是定时器中断
  4. 您希望音调更新之间的间隔是多少? 现在,您得到 0xFFFF / (clock_freq/8) 如果您想要不同的东西,您需要设置 TMR0H/L 寄存器。
  5. LATD7 上有什么? 你为什么要清除它? 你是说它启用了 PWM 输出吗?
  6. 为什么要调用 Delay()? 计时器本身应该提供所需的延迟。 关于如何进行计时似乎存在脱节。 我将扩展我的其他答案
  7. 你想在哪里改变 PWM 频率? 不需要写信给PR2吗? 您需要为每种不同的音调赋予不同的值。

“根据要求在第一次失败时停止构建。”

这只是说您有一些语法错误,没有向我们显示错误报告,我们无法真正提供帮助。

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.

不离久伴 2024-07-21 19:48:23

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

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

In Windows you can use the Beep function in kernel32:

    [DllImport("kernel32.dll")]
    private static extern bool Beep(int frequency, int duration);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文