ШИМ Atmega2560 на PB7

Я пытаюсь получить выход ШИМ с вывода PB7 с таймером 0 на Atmega2560, но безуспешно. Он должен генерировать тон для подключенного репродукции. Мои настройки ШИМ:

DDRB    = 0b11100000;
PORTB   = 0b00000000;

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

а затем у меня есть эта функция, которая должна генерировать звук:

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

но ничего не происходит, когда я вызываю его с параметром тона. Не могли бы вы мне помочь?


person Radim Sejk    schedule 06.06.2017    source источник
comment
Я думаю, что эта строка устанавливает источник: TCCR0B |= (1 << CS02) | (1 << CS01) | (1 << CS00);. Если все три установлены, это означает: Внешний источник синхронизации на выводе T0. Часы на переднем фронте. Если у вас нет внешнего источника синхронизации на T0, просто установите CS00, чтобы получить, например, частоту ЦП в качестве источника без какого-либо предварительного делителя.   -  person Andre Kampling    schedule 06.06.2017
comment
Это работает, теперь у меня есть выход на PB7, но частота слишком высока. когда я вызываю SoundOutput(400), я вижу период O-scope 12,5 мкс, что слишком велико для генерации тона.   -  person Radim Sejk    schedule 06.06.2017
comment
Да, потому что частота процессора 2560 составляет 16 МГц. Таким образом, период вашего тонального сигнала будет: t = (1/f_CPU) * uintTone / 2. Вы хотите, чтобы параметр uintTone был результирующей частотой? Я опубликую его позже, когда у меня будет время в качестве ответа.   -  person Andre Kampling    schedule 06.06.2017
comment
Вы хотите, чтобы параметр uintTone был результирующей частотой? Да, было бы здорово, Но у меня кварц экстерна 11059200Гц вместо 16МГц.   -  person Radim Sejk    schedule 06.06.2017


Ответы (1)


Основываясь на ваших комментариях, вы используете часы ~ 12 МГц в качестве входных данных для своего таймера, а из вашего кода вы используете 8-битный таймер 0 в режиме CTC с OCR0A в качестве верхней части. У вас есть OC0A, настроенный на включение сравнения совпадений.

Согласно техническому описанию 2560, частота вашего таймера определяется следующим образом:

F_CLK/(2*(1 + OCR0A)) | F_CLK ~= 12 МГц

Это 8-битный таймер, так что это означает, что ваша минимальная частота, которую может генерировать ваш ШИМ, определяется как:

12e6/(2*(1 + 255)) ~= 20 кГц

Вы просто не сможете генерировать звуковой сигнал с этой конфигурацией, если только вы не замедлите часы, которые используете для своего таймера, или не используете таймер, который может считать больше.

1) Используйте 16-битный счетчик (например, таймер 1). Это даст вам минимальную частоту ~ 90 Гц и максимальную частоту ~ 6 МГц, что должно дать вам достаточный диапазон для генерации тонов:

/* 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) Используйте внутренний источник часов в качестве часов таймера вместо внешнего источника. Если вы не изменили фьюз-биты или не изменили их где-то в коде, тактовая частота будет 1 МГц. Предварительное масштабирование часов на 8 дает вам частотный диапазон от ~ 250 Гц до ~ 60 кГц.

/* 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);
person rlphillipsiii    schedule 06.06.2017
comment
Да! Я использовал второе решение, и оно прекрасно работает. Большое Вам спасибо :) - person Radim Sejk; 07.06.2017
comment
Нет проблем: Вот ссылка на дополнительную справочную информацию о том, как использовать ШИМ: allaboutavr.com/index.php/2017/05/13/ - person rlphillipsiii; 07.06.2017
comment
Ну, моя радость была немного предварительной. Теперь я могу генерировать звук, но частоты странные. Мне нужно вывести точные частоты из динамика, но я могу выводить (измеренные частотомером Agilent) частоты в диапазоне 230 кГц (OCR0A = 2) и 2,69 кГц (OCR0A = 255) и 0 Гц с OCR0A = 0 или OCR0A = 1 - person Radim Sejk; 08.06.2017
comment
Что именно вы измеряете? Расчеты, которые я дал вам, были для частоты ШИМ, а не для звука, который вы будете генерировать. - person rlphillipsiii; 08.06.2017
comment
Измеряю частоту на динамике. Мне нужно генерировать звуки между 165 Гц и 680 Гц. - person Radim Sejk; 09.06.2017
comment
Замедлите свой таймер больше, т.е. TCCR0B = (0 << WGM02) | (0 << CS02) | (1 << CS01) | (1 << CS00); - person rlphillipsiii; 09.06.2017