Синтез двухчастотного сигнала с помощью ШИМ |
![]() |
Добавил(а) microsin |
Этот пример кода генерирует на ножке 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 для измерения и подсчета импульсов. |