Настраиваем выводы микроконтроллера ATmega8 и управляем светодиодами
Подключение светодиодов
Используем пять выводов порта D: PD0, PD1, PD2, PD3 и PD4. Каждый светодиод подключается к отдельному выводу микроконтроллера через токоограничивающий резистор.
Регистр DDRx
В микроконтроллерах AVR направление работы выводов задаётся регистрами DDRx.
Если соответствующий бит регистра DDR установлен в логическую 1, вывод работает как выход. Если записан логический 0, вывод работает как вход.
Например, для настройки вывода PB0 на выход можно записать:
DDRB = 0b00000001;
В нашей программе на выход настраиваются сразу пять выводов порта D:
DDRD = 0b00011111;
Регистр PORTx
После настройки вывода на выход логический уровень задаётся через регистр PORTx.
Например, установить логическую 1 на выводе PB0 можно записью:
PORTB = 0b00000001;
Но на практике удобнее изменять только нужный бит, не затрагивая остальные выводы порта.
Установить логическую 1:
PORTB |= (1 << PB0);
Установить логический 0:
PORTB &= ~(1 << PB0);
Генератор псевдослучайных чисел
Для изменения задержки будем использовать функцию rand() .
Функция находится в стандартной библиотеке stdlib.h и генерирует псевдослучайное число.
Для нашей учебной задачи этого вполне достаточно: полученное значение будем использовать при формировании задержки между переключениями светодиодов.
Основная программа
Сначала подключаем необходимые заголовочные файлы, выполняем инициализацию выводов, после чего в бесконечном цикле вызываем функцию последовательного переключения светодиодов.
#include <avr/io.h>
#include "led.h"
#include <stdlib.h>
#define F_CPU 1000000UL
unsigned int k;
void init(void);
void delay(unsigned int y);
void miganie(unsigned int t);
int main(void)
{
init();
while (1)
{
k = 1000 * (unsigned int)rand();
miganie(k);
}
}
void init(void)
{
/* PD0-PD4 работают как выходы */
DDRD = 0b00011111;
/* На PD0-PD4 устанавливаем логический 0 */
PORTD = 0b00000000;
}
void delay(unsigned int y)
{
unsigned int i = 0;
unsigned int w = 0;
for (w = 0; w <= 4; w++)
{
for (i = 0; i <= y; i++)
{
;
}
}
}
void miganie(unsigned int t)
{
HL1_on;
HL2_off;
HL3_off;
HL4_off;
HL5_off;
delay(t);
HL1_off;
HL2_on;
HL3_off;
HL4_off;
HL5_off;
delay(t);
HL1_off;
HL2_off;
HL3_on;
HL4_off;
HL5_off;
delay(t);
HL1_off;
HL2_off;
HL3_off;
HL4_on;
HL5_off;
delay(t);
HL1_off;
HL2_off;
HL3_off;
HL4_off;
HL5_on;
delay(t);
}
Заголовочный файл led.h
Чтобы основной файл программы оставался более читаемым, операции включения и выключения светодиодов вынесем в отдельный заголовочный файл led.h.
Для каждого светодиода создаём два макроса: включение и выключение.
#ifndef LED_H_ #define LED_H_ /* Светодиод HL1 */ #define HL1_on PORTD |= (1 << PD0) #define HL1_off PORTD &= ~(1 << PD0) /* Светодиод HL2 */ #define HL2_on PORTD |= (1 << PD1) #define HL2_off PORTD &= ~(1 << PD1) /* Светодиод HL3 */ #define HL3_on PORTD |= (1 << PD2) #define HL3_off PORTD &= ~(1 << PD2) /* Светодиод HL4 */ #define HL4_on PORTD |= (1 << PD3) #define HL4_off PORTD &= ~(1 << PD3) /* Светодиод HL5 */ #define HL5_on PORTD |= (1 << PD4) #define HL5_off PORTD &= ~(1 << PD4) #endif /* LED_H_ */