Зміст

Примеры программ для микроконтроллеров AVR

8 светодиодов

Эта программа реализует “бегущий огонь” из 8-ми светодиодов, подключенных к порту “A” микроконтроллера. В данном случае использовался внешний тактовый генератор с частотой 11.0592 МГц. Переключаться между использованием внешнего и внутреннего генератора можно при помощи FUSE-битов.

led_blink.c
//#define F_CPU 1000000UL     // Тактовая частота 1МГц
#define F_CPU 11059200UL      // Тактовая частота 11.0592 МГц
 
#include <inttypes.h>
#include <avr/io.h>
#include <util/delay.h>
 
int main()                     // Главная функция программы
{
 
    DDRA = 0b11111111;         // Установка всех ножек порта "A" в режим вывода
    //DDRC = 0b11111111;       // Установка всех ножек порта "C" в режим вывода
 
    while (1)                  // Бесконечный цикл
    {
 
        PORTA = 0b00000001;    // Включение светодиода №1
        _delay_ms(500);        // Пауза в 500мс
        PORTA = 0b00000010;    // Включение светодиода №2
        _delay_ms(100);        // Пауза в 100мс
        PORTA = 0b00000100;    // И так далее
        _delay_ms(100);
        PORTA = 0b00001000;
        _delay_ms(100);
        PORTA = 0b00010000;
        _delay_ms(100);
        PORTA = 0b00100000;
        _delay_ms(100);
        PORTA = 0b01000000;
        _delay_ms(100);
        PORTA = 0b10000000;
        _delay_ms(100);
    }
}

АЦП и 8 светодиодов

Эта программа периодически считывает напряжение с АЦП (первая ножка порта “A”) и выдаёт уровень, последовательно зажигая линейку из 8-ми светодиодов (ножки порта “C”).

adc-leds.c
#define F_CPU 11059200UL      // Тактовая частота 11.0592 MHz
 
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
 
 
volatile uint16_t adcval;     // Значение, считываемое с АЦП
 
 
 
ISR(ADC_vect)                 // Обработчик прерывания АЦП
{
  adcval = ADCW;
}
 
int main()                    // Главная функция
{
 
    uint16_t digits = 0;
    int i;
 
    // Включаем АЦП и устанавливаем частоту дискретизации = F_CPU / 128
    ADCSRA = _BV(ADEN) | _BV(ADPS1) | _BV(ADPS0) | _BV(ADPS2);
 
 
    sei();                    // Разрешаем прерывания
 
    DDRA = 0b00000000;        // Устанавливаем все ножки порта "A" на ввод
    DDRC = 0b11111111;        // станавливаем все ножки порта "C" на вывод
 
    PORTC = 0b00000000;
 
 
    ADCSRA |= _BV(ADIE);      // Разрешаем прерывания АЦП
    // Выбираем первую ножку (№0) для считывания напряжения АЦП
    ADMUX  &= ~_BV(MUX0) & ~_BV(MUX1) & ~_BV(MUX2) & ~_BV(MUX3) & ~_BV(MUX4);
 
    // Выбор внутреннего напряжения 1.22В для считывания АЦП
    //ADMUX  &= ~_BV(MUX0) ;
    //ADMUX  |= _BV(MUX1) | _BV(MUX2) | _BV(MUX3) | _BV(MUX4);
 
    ADMUX  |= _BV(REFS0) | _BV(REFS1); // Внутреннее опорное напряжение 2.56В
    ADCSRA |= _BV(ADATE);     // Разрешаем автозапуск
    // Выбираем "Free running mode"
    SFIOR  &= ~_BV(ADTS0) & ~_BV(ADTS1) & ~_BV(ADTS2);
 
    ADCSRA |= _BV(ADSC);      // Запуск первого преобразования
 
 
    while (1)                 // Бесконечный цикл
    {
 
 
        //ADCSRA |= _BV(ADSC);  // Запуск преобразования
 
        // Вычисляем количество светодиодов, которые нужно
        // зажечь при данном напряжении
        digits = 0b00000000;
        for (i=0; i< (adcval+1) / 128; i++)
        {
            digits = (digits << 1) +1;
        }
 
        /*
        if      (adcval >= 1023) digits = 0b11111111;
        else if (adcval >= 895)  digits = 0b01111111;
        else if (adcval >= 767)  digits = 0b00111111;
        else if (adcval >= 639)  digits = 0b00011111;
        else if (adcval >= 511)  digits = 0b00001111;
        else if (adcval >= 383)  digits = 0b00000111;
        else if (adcval >= 255)  digits = 0b00000011;
        else if (adcval >= 127)  digits = 0b00000001;
        else digits = 0b00000000;
        */
 
        PORTC = digits;       // Зажигаем нужные светодиоды
    }
}

I2C / TWI

http://www.nongnu.org/avr-libc/user-manual/group__twi__demo.html