0

I am trying to get PWM output from PB7 pin with timer0 on Atmega2560 with no luck. It should generate tone for the connected repro.My PWM settings are:

DDRB    = 0b11100000;
PORTB   = 0b00000000;

OCR0A = 0x04;
TCCR0A = (0 << COM0A1) | (1 << COM0A0) | (1 << WGM01) | (0 << WGM00);
TCCR0B = (0 << WGM02) | (0 << CS02) | (0 << CS01) | (0 << CS00);

and then I have this function, which should generate the sound:

void SoundOutput(unsigned int uintTone)
{
    if (uintTone != 0)
    {
        LED_2(1);
        OCR0A = uintTone;

        TCCR0B |= (1 << CS02) | (1 << CS01) | (1 << CS00);
    }
    else
    {
        TCCR0B &= ~((1 << CS02) | (1 << CS01) | (1 << CS00));
    }
}

but nothing happens when i call it with tone parameter. Can you please help me?

LPs
  • 16,045
  • 8
  • 30
  • 61
Radim Sejk
  • 5
  • 1
  • 5
  • 1
    I think it's this line which are setting the source: `TCCR0B |= (1 << CS02) | (1 << CS01) | (1 << CS00);`. If all three are set it means: **External clock source on T0 pin. Clock on rising edge**. If you don't have an external clock source on **T0** just set `CS00` to get for example the CPU frequency as source without any prescaler. – Andre Kampling Jun 06 '17 at 09:18
  • This works, I have output on the PB7 now, but the frequency is too high now. when I call the SoundOutput(400), I can se on O-scope period of 12.5us, which is too high for tone generating. – Radim Sejk Jun 06 '17 at 10:15
  • Yes because the CPU Frequency of the 2560 is 16MHz. So the period of your tone signal will be: `t = (1/f_CPU) * uintTone / 2`. Do you want the parameter `uintTone` to be the resulting frequency? I will post it later as I have time as an answer. – Andre Kampling Jun 06 '17 at 10:26
  • "Do you want the parameter `uintTone` to be the resulting frequency?" Yes, that would be great, But I have 11059200Hz externa crystal instead of 16MHz. – Radim Sejk Jun 06 '17 at 11:09

1 Answers1

1

Based on your comments, you are using ~12MHz clock as the input to your timer, and from your code, you are using 8 bit timer 0 in CTC mode with OCR0A as your top. You have OC0A set to toggle on a compare match.

According to the 2560 datasheet, the frequency of your timer is given by:

F_CLK/(2*(1 + OCR0A)) | F_CLK ~= 12MHz

This is an 8 bit timer, so that means that your minimum frequency that your PWM can generate is given by:

12e6/(2*(1 + 255)) ~= 20KHz

You simply aren't going to be able to generate an audible tone with that configuration unless you slow down the clock you are using for your timer or use a timer that can count higher.

1) Use a 16 bit counter (i.e. timer1). That will give you a min frequency of ~90Hz and a max frequency of ~6MHz, which should give you plenty of range to generate tones:

/* WGM BITS = 0100: CTC Mode */
/* COMA BITS = 01: Toggle OC1A on compare match */
/* CS BITS = 111: External clock source on rising edge */

TCCR1A = (0 << COM1A1) | (1 << COM1A0) | (0 << WGM01) | (0 << WGM00);
TCCR1B = (1 << WGM12) | (1 << WGM13) | (1 << CS02) | (1 << CS01) | (1 << CS00);

2) Use the internal clock source as the timer clock instead of an external source. Unless you changed fuse bits or you are changing it in the code somewhere, the clock will be 1MHz. Prescaling the clock by 8 gives you a frequency range of ~250Hz - ~60KHz.

/* WGM BITS = 010: CTC Mode */
/* COMA BITS = 01: Toggle OC1A on compare match */
/* CS BITS = 010: Prescale the internal clock by 8 */

TCCR0A = (0 << COM0A1) | (1 << COM0A0) | (1 << WGM01) | (0 << WGM00);
TCCR0B = (0 << WGM02) | (0 << CS02) | (1 << CS01) | (0 << CS00);
  • Yes! I have used the second solution and it works great. Thank you very much :) – Radim Sejk Jun 07 '17 at 06:00
  • No problem: Here's a link to some more reference information about how to use a PWM: http://allaboutavr.com/index.php/2017/05/13/chapter-5-timers-and-pwm-pulse-width-modulation/ – rlphillipsiii Jun 07 '17 at 17:31
  • Well, my joy was a little bit preliminary. I can generate sound now, but the frequencies are odd. I need to output exact frequencies out of the speaker, but I am able to output (measured with Agilent frequency counter) frequencies in range of 230KHz (`OCR0A = 2`) and 2.69 KHz (`OCR0A = 255`) and 0Hz with `OCR0A = 0` or `OCR0A = 1` – Radim Sejk Jun 08 '17 at 12:42
  • What exactly are you measuring? The calculations I gave you were for the frequency of the PWM not the sound you would generate. – rlphillipsiii Jun 08 '17 at 19:30
  • I am measuring frequency on the speaker. I need to generate sounds between165Hz and 680Hz. – Radim Sejk Jun 09 '17 at 05:53
  • Slow down your timer more i.e. `TCCR0B = (0 << WGM02) | (0 << CS02) | (1 << CS01) | (1 << CS00);` – rlphillipsiii Jun 09 '17 at 07:16