3

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);
}
AShelly
  • 34,686
  • 15
  • 91
  • 152

3 Answers3

6

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.

AShelly
  • 34,686
  • 15
  • 91
  • 152
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.

AShelly
  • 34,686
  • 15
  • 91
  • 152
-2

In Windows you can use the Beep function in kernel32:

    [DllImport("kernel32.dll")]
    private static extern bool Beep(int frequency, int duration);
Jason S
  • 184,598
  • 164
  • 608
  • 970
Jeff Kotula
  • 2,114
  • 12
  • 16