#include #include #include volatile uint8_t sine_value; // Значение из таблицы от 0 до 255 сгенерированная синусоида static uint16_t sine_index = 0; // Переменная размерности таблицы const uint8_t PROGMEM sine_table[1024] = { // Полный период синусоиды 1024 значения для 54Гц чем больше таблица тем меньше частота Гц 128, 127, 126, 125, 124, 124, 123, 122, 121, 120, 120, 119, 118, 117, 117, 116, 115, 114, 114, 113, 112, 111, 110, 110, 109, 108, 107, 107, 106, 105, 104, 103, 103, 102, 101, 100, 100, 99, 98, 97, 97, 96, 95, 94, 94, 93, 92, 91, 91, 90, 89, 88, 88, 87, 86, 85, 85, 84, 83, 83, 82, 81, 80, 80, 79, 78, 77, 77, 76, 75, 75, 74, 73, 72, 72, 71, 70, 70, 69, 68, 68, 67, 66, 66, 65, 64, 64, 63, 62, 62, 61, 60, 60, 59, 58, 58, 57, 56, 56, 55, 54, 54, 53, 52, 52, 51, 51, 50, 49, 49, 48, 48, 47, 46, 46, 45, 45, 44, 43, 43, 42, 42, 41, 40, 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, 34, 34, 33, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 21, 20, 20, 19, 19, 19, 18, 18, 17, 17, 17, 16, 16, 15, 15, 15, 14, 14, 14, 13, 13, 13, 12, 12, 12, 11, 11, 11, 10, 10, 10, 10, 9, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16, 17, 17, 17, 18, 18, 19, 19, 19, 20, 20, 21, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 36, 36, 37, 37, 38, 38, 39, 39, 40, 40, 41, 42, 42, 43, 43, 44, 45, 45, 46, 46, 47, 48, 48, 49, 49, 50, 51, 51, 52, 52, 53, 54, 54, 55, 56, 56, 57, 58, 58, 59, 60, 60, 61, 62, 62, 63, 64, 64, 65, 66, 66, 67, 68, 68, 69, 70, 70, 71, 72, 72, 73, 74, 75, 75, 76, 77, 77, 78, 79, 80, 80, 81, 82, 83, 83, 84, 85, 85, 86, 87, 88, 88, 89, 90, 91, 91, 92, 93, 94, 94, 95, 96, 97, 97, 98, 99, 100, 100, 101, 102, 103, 103, 104, 105, 106, 107, 107, 108, 109, 110, 110, 111, 112, 113, 114, 114, 115, 116, 117, 117, 118, 119, 120, 120, 121, 122, 123, 124, 124, 125, 126, 127, 127, 128, 129, 130, 131, 131, 132, 133, 134, 135, 135, 136, 137, 138, 138, 139, 140, 141, 141, 142, 143, 144, 145, 145, 146, 147, 148, 148, 149, 150, 151, 152, 152, 153, 154, 155, 155, 156, 157, 158, 158, 159, 160, 161, 161, 162, 163, 164, 164, 165, 166, 167, 167, 168, 169, 170, 170, 171, 172, 172, 173, 174, 175, 175, 176, 177, 178, 178, 179, 180, 180, 181, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 189, 189, 190, 191, 191, 192, 193, 193, 194, 195, 195, 196, 197, 197, 198, 199, 199, 200, 201, 201, 202, 203, 203, 204, 204, 205, 206, 206, 207, 207, 208, 209, 209, 210, 210, 211, 212, 212, 213, 213, 214, 215, 215, 216, 216, 217, 217, 218, 218, 219, 219, 220, 221, 221, 222, 222, 223, 223, 224, 224, 225, 225, 226, 226, 227, 227, 228, 228, 229, 229, 230, 230, 230, 231, 231, 232, 232, 233, 233, 234, 234, 234, 235, 235, 236, 236, 236, 237, 237, 238, 238, 238, 239, 239, 240, 240, 240, 241, 241, 241, 242, 242, 242, 243, 243, 243, 244, 244, 244, 245, 245, 245, 245, 246, 246, 246, 247, 247, 247, 247, 248, 248, 248, 248, 249, 249, 249, 249, 249, 250, 250, 250, 250, 251, 251, 251, 251, 251, 251, 252, 252, 252, 252, 252, 252, 252, 253, 253, 253, 253, 253, 253, 253, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 255, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 253, 253, 253, 253, 253, 253, 253, 252, 252, 252, 252, 252, 252, 252, 251, 251, 251, 251, 251, 251, 250, 250, 250, 250, 249, 249, 249, 249, 249, 248, 248, 248, 248, 247, 247, 247, 247, 246, 246, 246, 245, 245, 245, 245, 244, 244, 244, 243, 243, 243, 242, 242, 242, 241, 241, 241, 240, 240, 240, 239, 239, 238, 238, 238, 237, 237, 236, 236, 236, 235, 235, 234, 234, 234, 233, 233, 232, 232, 231, 231, 230, 230, 230, 229, 229, 228, 228, 227, 227, 226, 226, 225, 225, 224, 224, 223, 223, 222, 222, 221, 221, 220, 219, 219, 218, 218, 217, 217, 216, 216, 215, 215, 214, 213, 213, 212, 212, 211, 210, 210, 209, 209, 208, 207, 207, 206, 206, 205, 204, 204, 203, 203, 202, 201, 201, 200, 199, 199, 198, 197, 197, 196, 195, 195, 194, 193, 193, 192, 191, 191, 190, 189, 189, 188, 187, 187, 186, 185, 185, 184, 183, 183, 182, 181, 180, 180, 179, 178, 178, 177, 176, 175, 175, 174, 173, 172, 172, 171, 170, 170, 169, 168, 167, 167, 166, 165, 164, 164, 163, 162, 161, 161, 160, 159, 158, 158, 157, 156, 155, 155, 154, 153, 152, 152, 151, 150, 149, 148, 148, 147, 146, 145, 145, 144, 143, 142, 141, 141, 140, 139, 138, 138, 137, 136, 135, 135, 134, 133, 132, 131, 131, 130, 129, 128 }; int main(void) { // инициалицация параметров контроллера для Fast PWM и АЦП cli(); // Выключить прерывания DDRB &= ~(1 << PB5); // Настройка пина PB5 как вход для АЦП DDRB &= ~(1 << PB2);DDRB &= ~(1 << PB3);DDRB &= ~(1 << PB4); // Настройка пинов как входов ADMUX = (0 << REFS0) | // Опорное напряжение от источника VCC, bit 7 (0 << REFS1) | // Опорное напряжение от источника VCC, bit 6 (1 << ADLAR) | // результат сдвигаем влево, ADLAR bit5 (0 << REFS2) | // Опорное напряжение от источника VCC, bit 4 (0 << MUX3) | // Включение входа (PB5) для ADC0, MUX bit 3 (0 << MUX2) | // Включение входа (PB5) для ADC0, MUX bit 2 (0 << MUX1) | // Включение входа (PB5) для ADC0, MUX bit 1 (0 << MUX0); // Включение входа (PB5) для ADC0, MUX bit 0 ADCSRA = (1 << ADEN) | // Включаем ADC (1 << ADATE) | // Включаем ADC Auto Trigger без этого значения не работает обратная связь (1 << ADPS2) | // Настройка преобразователя Коэффициент деления 2, bit 2 (1 << ADPS1) | // Настройка преобразователя Коэффициент деления 2, bit 1 (1 << ADPS0); // Настройка преобразователя Коэффициент деления 2, bit 0 ADCSRB = (0 << ADTS2) | (0 << ADTS1) | (0 << ADTS0); // Free Running mode for Auto Trigger DDRB |= (1 << PB0); // PB0 (OC0A) Выход шим DDRB |= (1 << PB1); // PB1 (OC0B) Выход шим TCCR0A |= (1 << WGM01) | (1 << WGM00); // Режим Fast PWM mode TCCR0A |= (1 << COM0A1) | (0 << COM0A0); // Прямой ШИМ для OC0A (PB0) TCCR0A |= (1 << COM0B1) | (1 << COM0B0); // Инвертированный ШИМ для OC0B (PB1) TCCR0B = (0 << WGM02) | (0 << CS02) | (0 << CS01) | (1 << CS00); // Prescaler 1 для скорости ~54Гц при таблице 1024 значений, при F_CPU 16000000 шим 62500 гЦ TIMSK |= (1 << TOIE0); // Включить прерывание для таймера ADCSRA |= (1 << ADIE); // Включить прерывание для АЦП OCR0A = 0; OCR0B = 0; // Начальное значение выходов sei(); // Прерывания while (1) { } } ISR(TIMER0_OVF_vect) { // Прерывание по таймеру sine_index++; // счетаем от 0 до 1024 if (sine_index >= 1024) { //Если равно 1024 sine_index = 0; // То сбрасываем переменную в ноль и считаем сначала } sine_value = pgm_read_byte(&sine_table[sine_index]); // Читаем значение из таблицы ПОСЛЕ инкремента ADCSRA |= (1 << ADSC);// включаем преобразования АЦП } ISR(ADC_vect) { uint8_t modulation_amplitude; // Результат модуляции синуса АЦП (0-255) uint8_t final_ocr_val_for_leg; // Конечное значение для OCR активного плеча uint8_t adc_modulation_factor = 255 - ADCH; //Обратная связь uint32_t product = (uint32_t)sine_value * adc_modulation_factor; // Преобразование значения синусоиды с учетом обратной связи modulation_amplitude = (uint8_t)((product + (product >> 8)) >> 8); // Деление на 255 быстрый метод const uint8_t MAX_PWM_DUTY_PUSH_PULL = 230; // максимальное рабочее значение ШИМ uint32_t scaled_product = (uint32_t)modulation_amplitude * MAX_PWM_DUTY_PUSH_PULL; // Маштабирование рабочего цикла ШИМ к мин и макс final_ocr_val_for_leg = (uint8_t)((scaled_product + (scaled_product >> 8)) >> 8); // Деление на 255 быстрый метод const uint8_t MIN_PWM_DUTY = 25; // минимальное рабочее значение ШИМ if (final_ocr_val_for_leg < MIN_PWM_DUTY ) { // исключение отрицательного значения и не ниже MIN_PWM_DUTY final_ocr_val_for_leg = MIN_PWM_DUTY; } OCR0A = final_ocr_val_for_leg; // вывод шим сигнала на выход PB0 прямой 62.500 кГц с модуляцией синусоидой 54Гц OCR0B = final_ocr_val_for_leg; // вывод шим сигнала на выход PB1 инверсия 62.500 кГц с модуляцией синусоидой 54Гц }