INT 21h

Hi, I am Vladimir Smagin, sysadmin. Telegram Email

Bit Angle Modulation (BAM) – аналог ШИМ (PWM)

№ 3772 В разделах: Программирование Электроника от October 31st, 2011,

Прошляпил я как-то параметры купленного микроконтроллера AtTiny461. Думал там 6 шимов, а оказалось 3 + 3 инверсных выхода. Но ZiB подсказал клевый выход – сделать программный ШИМ. Этот МК работает на частоте 20 МГц, поэтому можно сделать все 12 необходимых мне ШИМов всего лишь на 1 чипе.

Принцип оказался проще некуда. Допустим, нам надо светить светодиодом с яркостью 00110010b (50d). В этом байте 8 бит. Проход начинаем с самого левого бита до самого правого. Длительность задержки таймера зависит от текущей позиции обрабатываемого бита. На самом левом задержка должна быть 128 тактов, на самом правом 1, т.е. мы делим задержку предыдущего бита на 2 и полученную задержку применяем к текущему биту. Знаю, сразу не вкурили. Сейчас объясню:

  1. программа запустилась, установилась самая первая задержка OCR = 128, таймер запустился
  2. сработал таймер
  3. берем самый левый бит. если он 0, то зажигаем диодик, если 1, то гасим. устанавливаем задержку таймера OCR = OCR / 2
  4. сделали инкремент переменной с текущей позицией обрабатываемого бита, делаем сдвиг всех битов влево
  5. проверили не являлся ли обработанный бит последним
  6. если бит последний, сбрасываем счетчик позиций и берем значение в служебную переменную из переменной с яркостью светодиода
  7. конец работы обработчика таймера
  8. переход к шагу 2


Прежде всего нужно инициализировать таймер:

void init_timer()
{
    TCCR1A = (0 << WGM10) | (0 << WGM11);
    TCCR1B = (0 << CS12) | (1 << CS11) | (1 << CS10) | (1 << WGM12) | (0 << WGM13);
    OCR1A = 128;
    TIMSK |= _BV(OCIE1A);
    sei();
}

Обработчик таймера должен выглядеть примерно так:

static volatile uint8_t arr_value = 128,
                led_value = 0,
                led_value_bit = 0;

ISR(TIMER1_COMPA_vect)
{
    // изменение задержки
    OCR1A = (uint16_t) arr_value;
    arr_value = arr_value / 2;

    // проверяем первый бит яркости
    if (led_value & 0x80)
        LED_PORT &= ~LED_BIT;   // 0 - выкл диод
    else
        LED_PORT |= LED_BIT;    // 1 - вкл диод

    led_value <<= 1;            // сдвиг значения яркости на бит влево 
    led_value_bit++;            // запоминаем текущий бит

    // если посмотрели все 8 битов, то сбрасываемся и берем значение яркости заново
    if (led_value_bit > 7) {
        led_value = led_brightness;
        led_value_bit = 0;
        arr_value = 128;
    }
}

А теперь основная программа

#include <avr/io.h>
#include <avr/delay.h>
#include <avr/interrupt.h>
#include <inttypes.h>

#define LED_PORT    PORTB
#define LED_DDR        DDRB
#define LED_BIT        (1<<PB4)
#define LED_GREEN    (1<<PB3)

void main()
{
    LED_DDR |= LED_BIT | LED_GREEN;
    init_timer();

    while (1) {
        _delay_ms(20);
        LED_PORT ^= LED_GREEN;  // моргаю зеленым. так, для красоты.
        led_brightness = 1;
        led_value = led_brightness;     // делаем копию для прерывания

        /*
        //медленно изменяем яркость туда-сюда
        if (led_direction > 0) { led_brightness++; } else { led_brightness--; } 
        if (led_brightness == 255) led_direction = 0; 
        if (led_brightness == 0) led_direction = 1; 
        */
    }
    return 0;
}

В конце бесконечного цикла есть закомментированный кусок кода. Чтобы светодиод медленно разгорался и гаснул, раскомментируйте его, а строку с led_brightness = 1; вообще уберите.

2 комментариев »

2 responses to “Bit Angle Modulation (BAM) – аналог ШИМ (PWM)”

  1. Hammer says:

    А как же печально известный переход 0x7f 0x80? Когда получается то слишком длинный 0, то слишком длинная 1 и, как следствие, мерцание.

  2. 21h says:

    ну мерцает, да. только программно исправлять такие недостатки.

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

Leave a Reply

Your email address will not be published. Required fields are marked *

*

Комментарии

  • 21h: нене ) без меня )
  • Серегй: Не совсем грабить)) если грабить можно и без рации, есть...
  • 21h: магазин грабить собрались? ) не, тут я не помощник ;)
  • Серегй: А что бы мне поймать чужую волну, что мне для этого нужно...
  • 21h: слушать никто не запрещает. нет закона, который запрещает...
  • Серегй: Я хотел узнать могу ли я просто прийти с данной рацией baofeng...
  • 21h: У меня есть только эти 2. По другим ничего не знаю. В интернете...

© Vladimir Smagin, 2005-2017. Копирование материалов без разрешения запрещено.
Яндекс.Метрика