Простейший программатор для atmega8

Исходный код программы на языке С (Си) с пояснениями

Программа для рассматриваемой схемы подключения оптопары к микроконтроллеру AVR ATmega8 представлена следующим фрагментом кода на языке С (Си). Комментарии к коду программу поясняют принцип работы отдельных команд.

C++

#include <avr/io.h> // заголовок чтобы задействовать контроль данных на контактах
#define F_CPU 1000000UL // задание тактовой частоты микроконтроллера
#include <util/delay.h> // заголовок чтобы задействовать функции задержки в программе
int main(void)
{
DDRD = 0x00; // установка portd на ввод данных
DDRB = 0xFF; // установка PORTB на вывод данных
while(1)
{
if (bit_is_set(PIND,0)) // если кнопка нажата
{
PORTB^=1<<0; // переключаем логический уровень на контакте pin0 PORTB
_delay_ms(200); // задержка 200ms
_delay_ms(200);
}
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

#include <avr/io.h> // заголовок чтобы задействовать контроль данных на контактах
#define F_CPU 1000000UL // задание тактовой частоты микроконтроллера          
#include <util/delay.h> // заголовок чтобы задействовать функции задержки в программе

intmain(void)

{

DDRD=0x00;// установка portd на ввод данных

DDRB=0xFF;// установка PORTB на вывод данных

while(1)

{

if(bit_is_set(PIND,))// если кнопка нажата

{

PORTB^=1<<;// переключаем логический уровень на контакте pin0 PORTB    

_delay_ms(200);// задержка 200ms

_delay_ms(200);

}

}

}

Тестер микросхем

Опубликовано вт, 09/05/2017 — 15:45 пользователем trol

Устройство предназначено для тестирования логических микросхем, операционных усилителей, оптопар, и некоторых других элементов.
Из логических микросхем поддерживаются отечественные (серии 155, 555, 1531, 1533, 176, 561, 1561, 1564, 580, 589 и др.) и импортные
(74ххх, 40ххx, 45xxx) ИМС ТТЛ и КМОП. Меню и результаты проверки отображаются на цветном дисплее 128х128.
Так же тестер умеет проверять микросхемы DRAM, SRAM, считывать EPROM и показывать, есть ли в них записанные данные.
Кроме того, прибор можно использовать при отладке различных цифровых устройств как интерфейс с 40 каналами ввода-вывода управляемыми по USB.

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

Программное обеспечение написано на Java и является кроссплатформенным (Windows, Linux, MacOS X).

Исходный код программы на языке С (Си) с пояснениями

Программа для рассматриваемой схемы представлена следующим фрагментом кода на языке С (Си). Комментарии к коду программу поясняют принцип работы отдельных команд.

C++

#include <avr/io.h> // заголовок чтобы разрешить контроль данных на контактах
#define F_CPU 1000000 // установка тактовой частоты микроконтроллера
#include <util/delay.h> // заголовок чтобы задействовать функции задержки в программе

int check();
volatile int alarm = 0;
volatile int chec = 0;

int main(void)
{
DDRD = 0;//устанавливаем PORTD на ввод данных
DDRC = 0;// устанавливаем PORTС на ввод данных
DDRB = 0xFF;// устанавливаем PORTB на вывод данных
while(1)
{
if ((bit_is_clear(PIND,0)))
{
alarm=1;// после срабатывания датчика устанавливаем бит ALARM
}
if (bit_is_clear(PINC,4))
{
if (bit_is_clear(PINC,2))
{
if (bit_is_clear(PINC,1))
{
if ((bit_is_set(PINC,0))&&(bit_is_set(PINC,3)))
{
_delay_ms(220);
check();
// если нажаты только кнопки 5,3 и 2, то выход из цикла
}
}
}
}
if (alarm==1) //если бит ALARM установлен
{
PORTB |=(1<<PINB0); // включаем светодиод
PORTB &=~(1<<PINB1); // включаем звонок
}
if (alarm==0) // если бит ALARM не установлен
{
PORTB |=(1<<PINB1);//выключаем светодиод
PORTB &=~(1<<PINB0); //выключаем звонок
}
}
}
int check()
{
if (bit_is_clear(PINC,4))
{
if (bit_is_clear(PINC,2))
{
if (bit_is_clear(PINC,1))
{
if ((bit_is_set(PINC,0))&&(bit_is_set(PINC,3)))
{
if (chec==1)
{
alarm=0;
// если кнопки все еще нажаты по истечении 5 сек, то сбрасываем бит ALARM
}
if (chec==0)
{
for (int i=0;i<15;i++)
{
_delay_ms(220);
// проверяем сброшены ли биты по истечении 5 секунд
}
chec=1;
check();
}
}
else
{
chec=0;
}
}
}
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

#include <avr/io.h> // заголовок чтобы разрешить контроль данных на контактах
#define F_CPU 1000000 // установка тактовой частоты микроконтроллера
#include <util/delay.h> // заголовок чтобы задействовать функции задержки в программе
 

intcheck();

volatileintalarm=;

volatileintchec=;

intmain(void)

{

DDRD=;//устанавливаем PORTD на ввод данных

DDRC=;// устанавливаем PORTС на ввод данных

DDRB=0xFF;// устанавливаем PORTB на вывод данных

while(1)

{

if((bit_is_clear(PIND,)))

{

alarm=1;// после срабатывания датчика устанавливаем бит ALARM

}

if(bit_is_clear(PINC,4))

{

if(bit_is_clear(PINC,2))

{

if(bit_is_clear(PINC,1))

{

if((bit_is_set(PINC,))&&(bit_is_set(PINC,3)))

{

_delay_ms(220);

check();

// если нажаты только кнопки 5,3 и 2, то выход из цикла
}
}
}
}

if(alarm==1)//если бит ALARM установлен

{

PORTB|=(1<<PINB0);// включаем светодиод

PORTB&=~(1<<PINB1);// включаем звонок

}

if(alarm==)// если бит ALARM не установлен

{

PORTB|=(1<<PINB1);//выключаем светодиод

PORTB&=~(1<<PINB0);//выключаем звонок

}

}
}

intcheck()

{

if(bit_is_clear(PINC,4))

{

if(bit_is_clear(PINC,2))

{

if(bit_is_clear(PINC,1))

{

if((bit_is_set(PINC,))&&(bit_is_set(PINC,3)))

{

if(chec==1)

{

alarm=;

// если кнопки все еще нажаты по истечении 5 сек, то сбрасываем бит  ALARM
}

if(chec==)

{

for(inti=;i<15;i++)

{

_delay_ms(220);

//  проверяем сброшены ли биты по истечении 5 секунд
}

chec=1;

check();

}
}
else
{

chec=;

}
}
}
}
}

Работа схемы

Схема устройства приведена на следующем рисунке.

Вращать ось сервомотора на 180 градусов и потом обратно до 0 градусов с определенной задержкой мы будем с помощью широтно-импульсной модуляции (ШИМ, от англ. PWM – Pulse Width Modulation), присутствующей в микроконтроллере ATmega8. Чтобы повернуть ось сервомотора влево до конца нам нужна ШИМ с длительностью 1/18, а чтобы повернуть ось сервомотора от крайнего правого до крайнего левого положения, нам потребуется ШИМ с длительностью 2/18.

Датчик огня и микроконтроллер находятся в режиме контроля за обстановкой (есть ли огонь или нет) непрерывно. В случае появления огня эта ситуация обнаруживается датчиком огня, который формирует импульс высокого уровня на своем выходе. Этот импульс обнаруживается микроконтроллером, который производит включение сигнализации Сигнализация может быть выключена нажатием кнопки, присутствующей в схеме.

В микроконтроллере ATmega8 три ШИМ (PWM) канала могут быть задействованы на трех его контактах. На этих контактах мы можем использовать только выход ШИМ. Поскольку мы решили использовать PWM1 мы должны использовать ШИМ сигнал с контакта OC1 (PORTB 2-й контакт). Как показано на представленной схеме, мы соединяем сервомотор с контактом OC1A. В микроконтроллере ATmega8 из трех ШИМ каналов два 8-битные и один 16-битный. Мы в нашем примере будем использовать 16-битный канал.

В микроконтроллерах ATmega есть два способа генерации ШИМ:

  1. Фазовая (правильная) ШИМ.
  2. Быстрая ШИМ.

Мы будем использовать более простой способ – быстрый метод формирования ШИМ.

Сначала необходимо выбрать частоту ШИМ, которая будет зависеть от используемого приложения (применения). Мы выберем частоту 1 МГц без использования коэффициента деления предделителя. Коэффициент деления предделителя используется для того, чтобы получить нужную нам частоту. К примеру, если у нас частота кварцевого резонатора равна 8 МГц, то с использованием коэффициента деления предделителя, равного 8, мы можем получить нужную нам частоту 1 МГц. Коэффициент деления предделителя выбирается исходя из необходимой нам частоты. Если мы хотим получить больший период следования импульсов (то есть частота должна быть меньше), то нам следует использовать больший коэффициент деления предделителя.

Теперь чтобы получить частоту импульсов ШИМ 50 Гц мы должны установить соответствующие биты в регистре TCCR1B микроконтроллера. Состав битов данного регистра представлен на следующем рисунке.

CS10, CS11, CS12 (желтый, YELLOW) – задают коэффициент деления предделителя счетного регистра таймера/счетчика. Таблица для установки данных битов представлена на следующем рисунке.

Таким образом, чтобы задать коэффициент деления предделителя равный 1 необходимо установить бит CS10 в 1, а биты CS11 и CS12 – в 0.

RED (красный, WGM10-WGM13) – задают режим генерации ШИМ. Как следует из нижеприведенной таблицы для получения быстрой ШИМ мы должны WGM11, WGM12 и WGM12 установить в 1.

Теперь мы знаем, что ШИМ – это сигнал с различными интервалами ON и OFF сигнала (различными продолжительностями включения). Для получения различных продолжительностей включения (отношение длительности импульса к периоду повторения) нам необходимо выбрать значение между 0 и 255 (от 0 до 2^8 поскольку мы используем 8 битную ШИМ). Допустим мы выбрали значение 180, это значит что счетчик начинает счет от 0 и когда он достигает значения 180, то отклик на выходе может быть приведен в действие (запустится триггер). Этот триггер может быть инвертирующим и неинвертирующим, соответственно можно получить инвертированный и неинвертированный ШИМ-сигнал. То есть выход ШИМ можно сконфигурировать таким образом, чтобы счет шел либо в прямом направлении (прямой счет), либо в обратном направлении (обратный счет). Этот выбор производится с помощью установки битов COM1A0 и COM1A1 (выделены зеленым цветом на рисунке выше).

Как следует из приведенной таблицы для необходимых нам параметров (сигнал сравнивается с граничным значением отсечки при нарастании, инвертированный ШИМ сигнал) нам необходимо установить COM1A0=1; COM1A1=1.

За установку того самого значения, которое задает различные продолжительности включения (отношение длительности импульса к периоду повторения), в микроконтроллере ATmega8 отвечает байт OCR1A (Output Compare Register 1A) – в нем сохраняется нужное нам значение от 0 до 255. Пример выбранного нами режима ШИМ (с инвертированием) показан на рисунке ниже. Таким образом, если мы запишем в OCR1A=180, то микроконтроллер будет изменять уровень сигнала на выходе когда счетчик досчитает до 180 (начиная с 0).

OCR1A должен быть 19999-600 для 180 градусов и 19999-2400 для 0 градусов.

How to install

Boards Manager Installation

This installation method requires Arduino IDE version 1.6.4 or greater.

  • Open the Arduino IDE.

  • Open the File > Preferences menu item.

  • Enter the following URL in Additional Boards Manager URLs:

  • Open the Tools > Board > Boards Manager… menu item.

  • Wait for the platform indexes to finish downloading.

  • Scroll down until you see the MiniCore entry and click on it.

  • Click Install.

  • After installation is complete close the Boards Manager window.

  • Note: If you plan to use the *PB series, you need the latest version of the Arduino toolchain. This toolchain is available through IDE 1.8.6 or newer. Here’s how you install/enable the toolchain:

    • Open the Tools > Board > Boards Manager… menu item.
    • Wait for the platform indexes to finish downloading.
    • The top is named Arduino AVR boards. Click on this item.
    • Make sure the latest version is installed and selected
    • Close the Boards Manager window.

Manual Installation

Click on the «Download ZIP» button in the upper right corner. Exctract the ZIP file, and move the extracted folder to the location «~/Documents/Arduino/hardware». Create the «hardware» folder if it doesn’t exist.
Open Arduino IDE, and a new category in the boards menu called «MiniCore» will show up.

Схема первая

С помощью этого программатора можно прошивать практически любой AVR-контроллер от ATMEL, надо только свериться с распиновкой микросхемы.

СОМ-разъем на схеме — это «мама».

На всякий случай привожу разводку печатной платы для атмеги8 (скачать), хотя такую примитивную схему проще нарисовать от руки. Плату перед печатью нужно отзеркалить.

Файл печатной платы открывать с помощью популярной программы Sprint Layout (если она у вас еще не установлена, то качайте 5-ую версию или лучше сразу 6-ую).

Как понятно из схемы, для сборки программатора потребуется ничтожно малое количество деталек:

Вместо КТ315 я воткнул SMD-транзистор BFR93A, которые у меня остались после сборки микромощных радиомикрофонов.

А вот весь программатор в сборе:

Питание (+5В) я решил брать с USB-порта.

Если у вас новый микроконтроллер (и до этого никто не пытался его прошивать), то кварц с сопутствующими конденсаторами можно не ставить. Работа без кварцевого резонатора возможна благодаря тому, что камень с завода идет с битом на встроенный генератор и схема, соответственно, тактуется от него.

Если же ваша микросхема б/у-шная, то без внешнего кварца она может и не запуститься. Тогда лучше ставьте кварц на 4 МГц, а конденсаторы лучше на 33 пФ.

Как видите, я кварц с конденсаторами не ставил, но на всякий случай предусмотрел под них места на плате.

Заливать прошивку лучше всего с помощью программы PonyProg (скачать).

Прошивка с помощью PonyProg

Заходим в меню Setup -> Calibration -> Yes. Должно появиться окошко «Calibration OK».

Далее Setup -> Interface Setup. Выбираем «SI Prog API» и нужный порт, внизу нажимаем «Probe», должно появиться окно «Test OK». Далее выбираем микроконтроллер «Device -> AVR micro ATmega8».

Теперь втыкаем микроконтроллер в панельку программатора, и подаем питание 5 вольт (можно, например, от отдельного источника питания или порта ЮСБ). Затем жмем Command -> Read All.

После чтения появляется окно «Read successful». Если все ок, то выбираем файл с нужной прошивкой для заливки: File -> Open Device File. Жмем «Открыть».

Теперь жмем Command -> Security and Configuration Bits и выставляем фьюзы, какие нужно.

Тщательно все проверяем и жмем «OK». Далее нажимаем Command -> Write All -> Yes. Идет прошивка и проверка. По окончании проверки появляется окно «Write Successful».

Вот и все, МК прошит и готов к использованию!

Имейте в виду, что при прошивке с помощью других программ (не PonyProg) биты могут быть инверсными! Тогда их надо выставлять с точностью до наоборот. Определить это можно, считав фьюзы и посмотрев на галку «SPIEN».

Автомат световых эффектов на микроконтроллере ATtiny13A-SU

Рейтинг:   / 5

Подробности
Категория: схемы на ATtiny
Опубликовано: 12.12.2018 14:00
Просмотров: 2863

Ю. Мартынюк, п. Затобольск, Казахстан Выпускаемые сегодня промышленностью новогодние гирлянды укомплектованы, как правило, автоматическими переключателями, реализующими различные световые эффекты, но некоторые потребительские характеристики этих переключателей неудовлетворительны. Частота переключения гирлянд в большинстве случаев выше желаемой, нередки выходы из строя тиристоров или даже интегральной микросхемы, Поэтому самостоятельное конструирование автоматов световых эффектов всё ещё остаётся актуальным.

Обозначения индексов микроконтроллеров

После обозначения базовой версии и серии микроконтроллера, через дефис идет индекс, указывающий вариант исполнения микроконтроллера.Индекс состоит из 1-2 цифр, которые означают максимальную частоту, на которой микроконтроллер может стабильно работать при нормальном для него напряжении питания, и из 1-3 букв, которые обозначают вариант корпуса, температурный диапазон работы, и особенности изготовления.Первая буква (или две буквы) после частоты обозначает тип корпуса:P — корпус DIP (PDIP)A — корпус TQFPM — корпус MLFTS — корпус SOT-23 (ATtiny4/5/9/10)J — корпус PLCCA — корпус UDFN/USONC — корпус CBGACK — корпус LGAS — корпус EIAJ SOICSS — узкий корпус JEDEC SOICT — корпус TSOPX — корпус TSSOP

Следующая буква означает температурный диапазон и особенности изготовления:C — коммерческий температурный диапазон (0 °C — 70 °C)A — температурный диапазон −20 °C — +85 °C, с использованием бессвинцового припояI — индустриальный температурный диапазон (-40 °C — +85 °C)U — индустриальный температурный диапазон (-40 °C — +85 °C), с использованием бессвинцового припояH — индустриальный температурный диапазон (-40 °C — +85 °C), с использованием NiPdAuN — расширенный температурный диапазон (-40 °C — +105 °C), с использованием бессвинцового припояF — расширенный температурный диапазон (-40 °C — +125 °C)Z — автомобильный температурный диапазон (-40 °C — +125 °C)D — расширенный автомобильный температурный диапазон (-40 °C — +150 °C)
Еще в самом конце может быть буква R, которая означает, что микроконтроллеры упакованы в ленты для автоматизированных систем сборки

К примеру:ATmega8L-8AU — максимальная частота — 8 мегагерц, корпус — TQFP, индустриальный температурный диапазон (-40 °C — +85 °C), с использованием бессвинцового припояATmega8-16PN — максимальная частота — 16 мегагерц, корпус — PDIP, расширенный температурный диапазон (-40 °C — +105 °C), с использованием бессвинцового припоя

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

Линейка микроконтроллеров ATmegaЛинейка микроконтроллеров ATtiny

Маркировка микроконтроллеров AVR ATmega и ATtinyМаркировка микроконтроллеров AVR семейства ATmega и ATtiny, базовые версии и версии микроконтроллеров, индекс микроконтроллеров
Published by: Мир микроконтроллеров

Date Published: 04/27/2015

Исходный код программы на языке C (Си) с пояснениями

Программа для рассматриваемой схемы представлена следующим фрагментом кода на языке C (Си). Комментарии к коду программу поясняют принцип работы отдельных команд.

Программа на передающей стороне

C++

#include <avr/io.h>
//заголовок чтобы разрешить контроль данных на контактах
#define F_CPU 1000000UL
//задание тактовой частоты микроконтроллера
#include <util/delay.h>
//заголовок чтобы задействовать функции задержки в программе

int main(void)
{
DDRD |= 1 << PIND1;//контакт 1 portD устанавливаем на вывод данных
DDRD &= ~(1 << PIND0);//контакт 0 portD устанавливаем на ввод данных
PORTD |= 1 << PIND0;

int UBBRValue = 25;// установка бодовой скорости

//записываем это значение в верхнюю часть регистра (8 бит из 11)
UBRRH = (unsigned char) (UBBRValue >> 8);

// записываем оставшуюся часть регистра
UBRRL = (unsigned char) UBBRValue;

// задействуем передатчик и приемник
UCSRB = (1 << RXEN) | (1 << TXEN);

//устанавливаем 2 стоповых бита и 8-битную длину передаваемого символа
UCSRC = (1 << USBS) | (3 << UCSZ0);

while (1)
{
if (bit_is_clear(PINC,0))// если кнопка нажата
{

while (! (UCSRA & (1 << UDRE)) );
{
UDR = 0b11110000;//когда передатчик готов посылаем 8 бит данных
}

_delay_ms(220);
}
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

#include <avr/io.h>
//заголовок чтобы разрешить контроль данных на контактах
#define F_CPU 1000000UL
//задание тактовой частоты микроконтроллера
#include <util/delay.h>
//заголовок чтобы задействовать функции задержки в программе

intmain(void)

{

DDRD|=1<<PIND1;//контакт 1 portD устанавливаем на вывод данных

DDRD&=~(1<<PIND0);//контакт 0 portD устанавливаем на ввод данных

PORTD|=1<<PIND0;

intUBBRValue=25;// установка бодовой скорости

//записываем это значение в верхнюю часть регистра  (8 бит из 11)  

UBRRH=(unsignedchar)(UBBRValue>>8);

// записываем оставшуюся часть регистра

UBRRL=(unsignedchar)UBBRValue;

// задействуем передатчик и приемник  

UCSRB=(1<<RXEN)|(1<<TXEN);

//устанавливаем 2 стоповых бита и 8-битную длину передаваемого символа                    

UCSRC=(1<<USBS)|(3<<UCSZ0);

while(1)

{

if(bit_is_clear(PINC,))// если кнопка нажата

{

while(!(UCSRA&(1<<UDRE)));

{

UDR=0b11110000;//когда передатчик готов посылаем 8 бит данных

}

_delay_ms(220);

}

}

}

Программа на приемной стороне

C++

#include <avr/io.h>
#define F_CPU 1000000UL
#include <util/delay.h>
int main(void)
{
DDRD |= (1 << PIND0);//устанавливаем контакт 0 PORTD на ввод данных
DDRC=0xFF;//устанавливаем PORTC на вывод данных

int UBRR_Value = 25; // скорость 2400 бод/с
UBRRH = (unsigned char) (UBRR_Value >> 8);
UBRRL = (unsigned char) UBRR_Value;
UCSRB = (1 << RXEN) | (1 << TXEN);
UCSRC = (1 << USBS) | (3 << UCSZ0);

unsigned char receiveData;
while (1)
{
while (! (UCSRA & (1 << RXC)) );

receiveData = UDR;
if (receiveData == 0b11110000)
{
PORTC ^= (1 << PINC0);
_delay_ms(220);
}
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

#include <avr/io.h>
#define F_CPU 1000000UL
#include <util/delay.h>

intmain(void)

{

DDRD|=(1<<PIND0);//устанавливаем контакт 0 PORTD на ввод данных

DDRC=0xFF;//устанавливаем PORTC на вывод данных

intUBRR_Value=25;// скорость 2400 бод/с

UBRRH=(unsignedchar)(UBRR_Value>>8);

UBRRL=(unsignedchar)UBRR_Value;

UCSRB=(1<<RXEN)|(1<<TXEN);

UCSRC=(1<<USBS)|(3<<UCSZ0);

unsignedcharreceiveData;

while(1)

{

while(!(UCSRA&(1<<RXC)));

receiveData=UDR;

if(receiveData==0b11110000)

{

PORTC^=(1<<PINC0);

_delay_ms(220);

}

}

}

Работа схемы

Схема устройства приведена на следующем рисунке.

Прежде чем двигаться дальше, рассмотрим принципы работы оптопары. Внутренняя схема оптопары приведена на следующем рисунке.

Контакты PINA и PINC подсоединяются к источнику. Контакты PINB, PINC, PINE подсоединяются к нагрузке.

Из представленного рисунка видно, что оптопара состоит из светодиода на стороне источника и фототранзистора на стороне нагрузки. Система заключена в замкнутый корпус, что увеличивает эффективность работы фототранзистора.

Когда от источника поступает сигнал на светодиод оптопары он испускает свет и фототранзистор, расположенный рядом со светодиодом, срабатывает и приводит в исполнение подсоединенную к его выходам цепь. Таким образом, управляющий сигнал от микроконтроллера преобразуется в свет, который заставляет сработать фототранзистор и тем самым подать необходимый сигнал в управляемую нагрузку (в представленной схеме нагрузкой является светодиод, но в общем случае подобным образом можно управлять и электродвигателем).

Эквивалентную электрическую схему оптопары можно изобразить следующим образом.

Исходный код программы на языке С (Си)

Программа для передающей части

C++

#include <io.h>
#include <delay.h>
void main(void)
{
DDRB=(0<<DDB7) | (0<<DDB6) | (0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=0
PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);
// инициализация Port C
// Function: Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
DDRC=(1<<DDC6) | (1<<DDC5) | (1<<DDC4) | (1<<DDC3) | (1<<DDC2) | (1<<DDC1) | (1<<DDC0);
// State: Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTC=(0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (0<<PORTC1) | (0<<PORTC0);
// инициализация Port D
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
DDRD=(1<<DDD7) | (1<<DDD6) | (1<<DDD5) | (1<<DDD4) | (1<<DDD3) | (1<<DDD2) | (1<<DDD1) | (1<<DDD0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);
while (1)
{
if(PINB.0 == 1) {
PORTD = 0x10;
}
if(PINB.0 == 0) {
PORTD = 0x20;
}
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

#include <io.h>
#include <delay.h>

voidmain(void)

{

DDRB=(<<DDB7)|(<<DDB6)|(<<DDB5)|(<<DDB4)|(<<DDB3)|(<<DDB2)|(<<DDB1)|(<<DDB0);

// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=0

PORTB=(<<PORTB7)|(<<PORTB6)|(<<PORTB5)|(<<PORTB4)|(<<PORTB3)|(<<PORTB2)|(<<PORTB1)|(<<PORTB0);

// инициализация Port C
// Function: Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In

DDRC=(1<<DDC6)|(1<<DDC5)|(1<<DDC4)|(1<<DDC3)|(1<<DDC2)|(1<<DDC1)|(1<<DDC0);

// State: Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T

PORTC=(<<PORTC6)|(<<PORTC5)|(<<PORTC4)|(<<PORTC3)|(<<PORTC2)|(<<PORTC1)|(<<PORTC0);

// инициализация Port D
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In

DDRD=(1<<DDD7)|(1<<DDD6)|(1<<DDD5)|(1<<DDD4)|(1<<DDD3)|(1<<DDD2)|(1<<DDD1)|(1<<DDD0);

// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T

PORTD=(<<PORTD7)|(<<PORTD6)|(<<PORTD5)|(<<PORTD4)|(<<PORTD3)|(<<PORTD2)|(<<PORTD1)|(<<PORTD0);

while(1)

{

if(PINB.==1){

PORTD=0x10;

}

if(PINB.==){

PORTD=0x20;

}

}

}

Программа для приемной части

C++

#include <io.h>
#include <delay.h>
// объявляем глобальные переменные
unsigned char byte = 0;
unsigned char lightON = 0;//статус света
int LED_status = 0;
void main(void)
{
// инициализация Port B
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=Out Bit0=Out
DDRB=(0<<DDB7) | (0<<DDB6) | (0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (1<<DDB0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=0 Bit0=0
PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);
// инициализация Port D
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
DDRD=(0<<DDD7) | (0<<DDD6) | (0<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (0<<DDD0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);
while (1)
{
byte = PIND;
if(PIND.7==0 && PIND.6==0 && PIND.5==0 && PIND.4==1 && LED_status==0)
{
PORTB.0 = ~PORTB.0;
delay_ms(1000);
}
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

#include <io.h>
#include <delay.h>
// объявляем глобальные переменные

unsignedcharbyte=;

unsignedcharlightON=;//статус света

intLED_status=;

voidmain(void)

{
// инициализация Port B
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=Out Bit0=Out

DDRB=(<<DDB7)|(<<DDB6)|(<<DDB5)|(<<DDB4)|(<<DDB3)|(<<DDB2)|(<<DDB1)|(1<<DDB0);

// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=0 Bit0=0

PORTB=(<<PORTB7)|(<<PORTB6)|(<<PORTB5)|(<<PORTB4)|(<<PORTB3)|(<<PORTB2)|(<<PORTB1)|(<<PORTB0);

// инициализация Port D
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In

DDRD=(<<DDD7)|(<<DDD6)|(<<DDD5)|(<<DDD4)|(<<DDD3)|(<<DDD2)|(<<DDD1)|(<<DDD0);

// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T

PORTD=(<<PORTD7)|(<<PORTD6)|(<<PORTD5)|(<<PORTD4)|(<<PORTD3)|(<<PORTD2)|(<<PORTD1)|(<<PORTD0);

while(1)

{

byte=PIND;

if(PIND.7==&&PIND.6==&&PIND.5==&&PIND.4==1&&LED_status==)

{

PORTB.=~PORTB.;

delay_ms(1000);

}

}

}

Программирование

Итак, что же даёт нам ядро помимо выбора настроек МК? Можно программировать МК всё теми же командами, что и раньше! Мигать светодиодами через digitalWrite, измерять напряжение через analogRead и прочее прочее. Давайте напишем классический Blink:

void setup() {
  pinMode(PB3, OUTPUT);
}

void loop() {
  digitalWrite(PB3, HIGH);
  delay(500);
  digitalWrite(PB3, LOW);
  delay(500);
}

PB3 – это номер пина, прямо как на распиновке.

Всё! Осталось загрузить прошивку. Для этого нажимаем Скетч/Загрузить через программатор:

Я подключил светодиод через резистор на 220 Ом и он мигает два раза в секунду, всё как написано.

Что следует помнить при работе с тиньками: у них мало памяти, а все вот эти Ардуино-функции являются кошмаром индуса и занимают очень много места в памяти. Если тини85 ещё как-то переживёт такие издевательства и сможет уместить в себе вполне интересный проект из Ардуино-функций, то в тини13 уже сложно уместить что-то серьёзное. Напомню: всего 64 байта оперативной памяти и 1 кб флэша! Для перехода на 13-ые тиньки рекомендуется научиться работать с МК напрямую, при помощи даташита и регистров.

Я думаю вы поняли, что в целом работа с голыми МК не особо то и отличается от работы с обычной платой Arduino, и теперь можно переходить к сложным самоделкам на базе своей платы, в центре которой будет стоять микроконтроллер. Давайте поделюсь парой советов по минимальной обвязке.

Устройства ввода-вывода МК

МК AVR имеют развитую периферию:

  • До 86 многофункциональных, двунаправленных GPIO линий ввода-вывода, объединённых в 8-битные порты ввода-вывода. В зависимости от программно-задаваемой конфигурации регистров, могут независимо друг от друга работать в режиме «сильного» драйвера, выдающего или принимающего (на «землю») ток до 40 мА, что достаточно для подключения светодиодных индикаторов. Любой из выводов портов может быть сконфигурирован на «ввод» либо в свободном состоянии, либо с использованием встроенного подтягивающего (на плюс) резистора.
  • До 3 внешних источников прерываний (по фронту, срезу, или уровню) и до 32 по изменению уровня на входе.
  • В качестве источника тактовых импульсов может быть выбран:
    • керамический или кварцевый резонатор (не у всех моделей);
    • внешний тактовый сигнал;
    • калиброванный внутренний RC-генератор (частота 1, 2, 4, 8 МГц, а также, для некоторых моделей ATtiny — 4,8, 6.4, 9.6 МГц и 128 кГц).
  • Внутренняя флеш-память команд до 256 KБ (не менее 10 000 циклов перезаписи).
  • Отладка программ осуществляется с помощью интерфейсов JTAG или debugWIRE

    сигналы JTAG (TMS, TDI, TDO, и TCK) мультиплексированы на порт ввода-вывода. Режим работы — JTAG или порт — задаётся соответствующим битом в регистре fuses. МК AVR поставляются с включённым интерфейсом JTAG.

    :

  • Внутренняя память данных EEPROM до 4 КБ (ATmega/ATxmega)/512 байт (ATtiny) (до 100 000 циклов перезаписи).
  • Внутренняя память SRAM до 32 KБ (ATxmega)/16 Кб (ATmega)/1 Кб (ATtiny) c временем доступа 2 такта.
  • Внешняя память объёмом до 64 КБ (ATmega8515, ATmega162, ATmega640, ATmega641, ATmega1280, ATmega1281, ATmega2560, ATmega256).
  • Таймеры c разрядностью 8, 16 бит.
  • ШИМ-модулятор (PWM) 8-, 9-, 10-, 16-битный.
  • Аналоговые компараторы.
  • АЦП (ADC) с дифференциальными входами, разрядность 8 (ATtiny)/10 (ATtiny/ATmega)/12 (ATxmega) бит:
    • программируемый коэффициент усиления перед АЦП 1, 10 и 200 (в дифференциальном режиме);
    • в качестве опорного напряжения могут выступать: напряжение питания, внешнее напряжение, или внутреннее некалиброванное опорное напряжение около 2,56 В (для моделей, имеющих минимальное напряжение питания от 2,7 В и выше) либо 1,1 В (с минимальным напряжением питания 1,8 В).
  • Различные последовательные интерфейсы, включая:
    • двухпроводной интерфейс TWI, совместимый с I²C;
    • универсальный синхронно/асинхронный приёмопередатчик UART/USART;
    • синхронный последовательный порт Serial Peripheral Interface (SPI).
  • USB серия AT90USBxxxx.
  • CAN серия AT90CANxxx.
  • LCD серии ATmega169 и ATmega329.
  • Датчики температуры ATtiny25, ATtiny45, ATtiny85.
  • Почти все (за исключением некоторых ранних моделей ATtiny, у которых перепрограммирование идёт по особому интерфейсу) поддерживают внутрисхемное программирование (ISP) через последовательный интерфейс SPI. Многие микроконтроллеры поддерживают альтернативное последовательное или параллельное программирование с использованием высокого напряжения, для случаев, если fuse-регистры были настроены так, что обычное программирование стало недоступно.
  • Поддержка самопрограммирования, при котором основная программа может изменить часть своего кода.
  • Поддержка загрузки основной программы с помощью защищённой от перезаписи подпрограммы (bootloader). Код основной программы обычно принимается через один из портов микроконтроллера с использованием одного из стандартных протоколов.
  • Ряд режимов пониженного энергопотребления.

Примечание: не все периферийные устройства могут быть включены программно. Некоторые из них предварительно должны быть активированы битами в регистрах Fuses, которые могут быть изменены только программатором.

Оцените статью
Рейтинг автора
5
Материал подготовил
Андрей Измаилов
Наш эксперт
Написано статей
116
Добавить комментарий