Этот пример кода генерирует на ножке OC1A (PD5) микроконтроллера ATmega32A сигнал ТРЦ с помощью режима быстрого ШИМ (Fast PWM Mode).
[pwm.h]
Константами TRC420_8_MAIN и TRC420_8_MOD задаются основная частота и частота модуляции ТРЦ. Таблица SinusTable сгенерирована с помощью утилиты sinus-table-generator, см. архив [7].
#pragma once
#include
#include
// Для ATmega32A используется кварц на 20 МГц. Для надежного
// запуска генерации на плате AVR-USB-MEGA16 [5] следует выпаять
// конденсаторы C3 и C4.
#define F_CPU 20000000
// Частота ШИМ в режиме Fast PWM, Гц:
#define PWM_FREQ 5000
#define PWM_TOP (F_CPU/PWM_FREQ)
#define TRC_OVERMODULATION (1.29)
#define TRC420_8_MAIN 420
#define TRC420_8_MOD 8
extern const signed char SinusTable [256];
void FastPWMstart(void);
[pwm.c]
В модуле pwm.c находится обработчик прерывания таймера 1 и подпрограмма запуска ШИМ FastPWMstart:
#include "pwm.h"
float phaseincHi = 256.0*(float)TRC420_8_MAIN/PWM_FREQ;
float phaseincLo = 256.0*(float)TRC420_8_MOD/PWM_FREQ;
float phaseHi = 0;
float phaseLo = 0;
float ScaleCoef;
// Настраивает для ATmega32A таймер TIMER1 в режиме
// Fast PWM Mode с генерацией ШИМ на ножке OC1A (PD5).
void FastPWMstart (void)
{
//ScaleCoef = 6.8231441;
ScaleCoef = ((float)PWM_TOP/2)/((float)128 * (1 + TRC_OVERMODULATION));
//Считать счетчик будет до ICR1:
ICR1 = PWM_TOP;
//Сравниваемая величина для меандра:
OCR1A = PWM_TOP/2;
// Очистка уровня OC1A/OC1B (установка выхода в лог. 0)
// при Compare Match, тактовая частота равна F_CPU
// (настроено опциями компилятора на 20 МГц):
TCCR1A = (1 << COM1A1)|(1 << WGM11);
TCCR1B = (1 << WGM13)|(1 << WGM12)|(1 << CS10);
//Настройка ножки OC1A как выход:
DDRD |= (1 << PWM_OUT);
//Разрешить прерывание для TIMER1_OVF_vect:
TIMSK = (1 << TOIE1);
}
// Обработчик прерывания таймера 1. Прерывание переполнения происходит,
// когда счетчик достигает предела счета TOP (в нашем случае ICR1).
ISR(TIMER1_OVF_vect)
{
static u16 OCRnext = 0;
s16 uc, um, uam;
OCR1A = OCRnext;
uc = SinusTable [(u8)phaseHi];
um = SinusTable [(u8)phaseLo];
uam = ScaleCoef * uc * (1 + TRC_OVERMODULATION * ((float)um/127));
phaseHi = phaseHi + phaseincHi;
if (phaseHi >= 256)
{
phaseHi = phaseHi - 256;
}
phaseLo = phaseLo + phaseincLo;
if (phaseLo >= 256)
{
phaseLo = phaseLo - 256;
}
//Возможный диапазон от 0 до PWM_TOP:
OCRnext = PWM_TOP/2 + uam;
}
void pwmstop (void)
{
TCCR1B = 0;
}
[main.c]
Тело основной программы, где запускается генерация:
#include "pwm.h"
void main (void)
{
FastPWMstart();
sei();
while(1)
{
}
}
[Фильтр для сигнала ШИМ]
Поскольку ШИМ работала на 5 кГц, то для получения качественного сигнала ТРЦ был спроектирован фильтр Чебышева 6-го порядка с полосой пропускания 2 кГц и частой среза 5 кГц при подавлении -60 дБ. Фильтр был синтезирован с помощью онлайн-утилиты Filter Design от компании Texas Instruments [6].
В качестве операционного усилителя лучше всего подошел счетверенный OP482G.
Сигнал ТРЦ на экране осциллографа:
[Ссылки]
1. Использование 16-bit Timer/Counter1 для измерения и подсчета импульсов. 2. AVR130: настройка и использование таймеров AVR. 3. Таймеры-счетчики ATmega2560. 4. ATmega32: 16-битный таймер/счетчик 1. 5. Макетная плата AVR-USB-MEGA16. 6. Filter Design Tool site:ti.com. 7. 201209031346trc-gen-avr.zip. 8. ATmega16 - PWM с помощью T/C0, T/C1, T/C2. |