Вы находитесь на странице: 1из 23

Министерство образования и науки Российской Федерации

Федеральное государственное бюджетное образовательное учреждение высшего


профессионального образования
Московский Авиационный Институт
(Национальный Исследовательский Университет)

Факультет “Cистем управления, информатики и электроэнергетики”

Кафедра №301 “Cистемы автоматического и интеллектуального управления”

Учебная группа 3В-402Б

Курсовой проект

по дисциплине “Микропроцессорные устройства систем управления”

на тему : “Разработка контроллера паяльной станции”

Выполнил студент: Федотов Н.А.

Руководитель: Можаев В.А.

Москва 2015
Расчетно-пояснительная записка
Техническое задание на проектирование
Исходные данные:

- контроллер предназначен для поддержания температуры паяльника в


заданных пределах;

- заданная температура устанавливается через клавиатуру;

- величина реальной температуры паяльника выводится на цифровой


дисплей;

- при подключении паяльника (мощность 50 Вт) к сети включается световая


индикация.

1
Эскизный проект
Описание алгоритма работы станции

При включении питания паяльника загорается дисплей. На дисплей


выводится значение ранее установленной температуры. После установления
значения нужной температуры начинается нагрев. На дисплей начинает
поступать значение реальной температуры. При достижении необходимого
значения микроконтроллер переходит в режим поддержания температуры в
пределах ∆t: при остывании паяльника до нижней границы ∆t включается
нагрев, при достижении верхней границы ∆t – отключается. При нажатии на
кнопку вверх/вниз производится увеличение/уменьшение значения
вводимой температуры. При этом на дисплее выводится это значение. Через
2 секунды после отпускания кнопки МК выводит на дисплее значение
реальной температуры и вновь переходит в рабочий режим. Введенное
значение температуры сохраняется в энергонезависимой памяти МК. При
отсутствии в выбранном МК энергонезависимой памяти используется
стандартное значение температуры, например, 380°C.

2
Принципиальная схема

3
Плата

4
Расчет и обоснование выбора элементов
Выбор компонентов проведен на основе имеющихся в продаже. Перед
выбором элементов было проведено исследование существующих паяльных
станций: как правило, они управляются 2-4 кнопками, выводят значения на
семисегментные, либо жидкокристаллические индикаторы и имеют разъем
для подключения паяльника – составного устройства из нагревателя и
чувствительного элемента. Диапазон температур обычно составляет от 100
до 500 °C. Максимальная мощность нагревательной части, как правило, не
превышает 80 Ватт.

Выбор компонентов начнем с чувствительного элемента. Для лучшего


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

1) Из имеющихся в продаже чувствительных элементов был выбран


терморезистор KTY84/130 с верхней границей измерения 300°С. Более того,
его стоимость сравнительно ниже других. Замена этого элемента на другой
подобный не приведет к каким-либо значительным изменениям
конструкции и ПО устройства (изменится лишь массив значений
контрольных точек температуры).

2)В качестве индикатора был выбран трехразрядный семисегментный


светодиодный индикатор BA56-12SRWA с общим анодом. Преимуществом
светодиодных индикаторов перед ЖК индикаторами является их яркость и
отсутствие необходимости внешней подсветки. Однако они имеют и
недостаток – большой потребляемый ток (порядка 50-100 мА на один
разряд). ЖК индикаторы потребляют меньше электроэнергии (порядка 1 мА

5
на разряд), но являются более хрупкими и требуют дополнительной
подсветки в условиях плохой освещенности.

В выбранном индикаторе катоды разных разрядов уже объединены между


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

3) Назову объединение блоков реверсивного счётчика, компаратора и


преобразователя из напряжения в число ядром устройства. В качестве ядра в
данном работе выступает микроконтроллер. Для реализации всех
необходимых функций был выбран микроконтроллер ATmega48PA-AU
фирмы Atmel из семейства AVR. Семейство AVR разделено на 3 подгруппы:
ATtiny, ATmega и Xmega. Другие МК не подходят для данной задачи по
различным параметрам , например, по количеству выводов. Обязательным
условием при подборе МК здесь является наличие в нем АЦП, т.к. без него
невозможно подключить чувствительный элемент. МК подгруппы Xmega
имеют избыточные для нашего случая характеристики (большое количество
выводов и периферийных интерфейсов, которые нами не используются и
высокая стоимость). Из подгруппы ATmega выбор пал на линейку ATmega 48-
88-168-328, благодаря следующим их свойствам : современность, наличие
АЦП, достаточное количество портов ввода-вывода, адекватная цена). МК
этой линейки являются полностью совместимыми и отличаются только
запасом оперативной и энергонезависимой памяти. По окончанию работ
оказалось, что код программы занимает всего 1184 байт, что составляет
много меньше половины от минимальной памяти в этой линейке.

Количество выводов : их должно быть не меньше 11 (8 на катоды


индикаторов и 3 на общие аноды разрядов, как минимум еще один для
исполнительного механизма (управляющего нагревателем) , 2 вывода порта
6
ввода для кнопок и 1 входа АЦП для чувствительного элемента. Итого : 15
выводов. Выбранный МК имеет 32 вывода.

Напряжение питания МК лежит в пределах от 4,5 до 5,5 В для стандартной


версии и в пределах от 1,8 В для версии с пониженным
электропотреблением. Опять же, в силу того, перед нами не стоит
требование экономии электроэнергии, рационально выбрать напряжение 5
В. В этом случае можно использовать любую из двух версий. Более того,
напряжение 5 В является стандартным и для него существует большое
количество готовых схем: различные блоки питания, USB-разъём и т. д.).

4) Устройство управления (исполнительное устройство) было решено


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

При выборе реле нужно учесть, что мощность бытового паяльника, как
правило, не превышает 100 Вт. Следовательно,
Pmax 100
I max= = =0,45[ A ] (1)
U 220

Выбранное реле способно коммутировать до 10 А при напряжении до 250


В. При этом напряжение, прикладываемое к катушке, равно 5 В. К тому же,
данное реле является самым дешёвым.

5) Семисегментный индикатор и реле нельзя подключать напрямую к МК,


т.к. они потребляют слишком большой ток: каждый сегмент индикатора
потребляет при достаточной для восприятия человеком яркости от 6 до 20
мА, т.е. от 48 до 160 мА на каждый сегмент при индикации на нём цифры «8»
с точкой (когда загораются все 8 сегментов). В замкнутом состоянии реле
потребляет ток 72,5 мА, а каждый контакт МК может отдать не более 40 мА.
Поэтому в цепь каждого анода и в цепь реле нужно поставить транзисторы
VT1-VT4. А в цепь базы каждого транзистора необходимо поставить
токоограничивающий резистор R10-R12 для уменьшения тока базы и
защиты от короткого замыкания. В цепях катодов также устанавливаем
8
токоограничивающие резисторы R1-R8: падение напряжения на каждом
светодиоде составляет 1,78 В, а напряжение питания МК равно 5 В. Кроме
того, АЦП выбранного МК способен различать напряжение в диапазоне от 0
до 1,1 В, что послужило причиной создания резистивного делителя на R14 и
R15. То есть делитель нужно рассчитать таким образом, чтобы при любых
значениях R14 в определённом диапазоне, на входе АЦП значение
напряжения не превышало 1,1 В. Данный расчёт приведён в отдельной
таблице.

Также в схему был включен разъём для внутрисхемного программирования


микроконтроллера Х1, что привело к необходимости добавить
подтягивающий резистор в цепь сброса (Reset): при отсутствии такой
подтяжки существует вероятность самопроизвольного сброса МК из-за
наводимых помех, а прямое подключение к питанию исключает
возможность программирования (в момент программирования на выводе
Reset произойдет короткое замыкание).

После проведения проверки, было установлено, что номинал внутреннего


резистора в цепи Reset составляет 47 кОм (по документации на
микроконтроллер – от 30 до 60 кОм).

В описании на индикатор указано, что падение напряжения на каждом


сегменте составляет 1,85 В (при проверке 1,78 В), а максимальный ток,
протекающий через каждый сегмент не должен превышать 30 мА. При
моделировании было установлено, что ток 30 мА дает чрезмерную яркость,
затрудняющую восприятие глазом. Путём ограничения величины этого тока
выяснилось, что оптимальная яркость достигается при токе 6-10 мА, = >

9
5−1,78
R1−8 min = = 322 [Ом] (2)
10∗10−3

5−1,78
R1−8 max = =536 [Ом] (3)
6∗10−3

Был выбран резистор 390 кОм, в таком случае ток каждого катода будет
равен
5−1,78
I= =0,0083=8,3[ мА ] (4)
390∗103

При индикации в любом из разрядов цифры 8 с точкой в цепи анода потечёт


ток

I =8,3∗8=66,4[ мА ] ( 5)

Соответственно, появились требования к транзисторам:

Imax = 66,4 мА (без запаса),

Umax Э-К = 5 В (без запаса)

Коэффициент усиления должен быть не меньше


66,4
hFE¿ 40 =1,66 (6)

В связи с этими параметрами были выбраны транзисторы BC857B со


следующими характеристиками: ток коллектора Ic=100 мА, напряжение
эмиттер-коллектор UCEO=45 В, минимальный коэффициент усиления
hFEmin=110, частота динамической индикации fT=100 МГц. Таким образом, для
пропускания тока в цепи эмиттер-коллектор, равного 66,4 мА, минимальный
необходимый ток базы:
I
I б=
h FEmin
=0,6 [ мА ] (7)

Значит, максимальный номинал резисторов будет рассчитываться по


формуле:
5
R9−12= −3
=8,333 [кОм ] (8)
0,6∗10

Мы воспользовались резисторами 4,7 кОм, следовательно, ток в цепях баз


транзисторов VT1-VT3:
10
5
I б= =0,001 А=1[ мА ] (9)
4,7∗10 3

а максимальный ток в цепях коллекторов транзисторов VT1-VT3:

I Cmax =I б∗hFEmin =0,001 А=1[ мА ] (10)


Резистор R13 и транзистор VT4 в цепи Reset рассчитываются аналогично и
выбираются такими же, чтобы избежать разброса номиналов.

6)Согласно техническому описанию, в каждом выводе любого порта


микроконтроллера установлен внутренний подтягивающий к питанию
резистор номиналом 20-50 кОм. В целях уточнения этого номинала была
проведена проверка. Проводилась она следующим образом: к выводу
микроконтроллера, к которому был подключен подтягивающий к питанию
резистор RPU, был подключен внешний резистор RPD, подтягивающий к
общему выводу. При этом в точке подключения с помощью мультиметра
контролировалось напряжение. Путём подбора резистора RPD было
достигнуто напряжение, равное половине питающего:
5
U = =2,5 [В]
2
(11)

что означало, что номиналы двух резисторов совпали. Этот номинал составил
50 кОм. Из этого вытекает требование к кнопкам: при замыкании на общий
провод через кнопку потечёт ток:
U 5
I max= =
R 50∗10 3
=0,0001 [ А ]=100 [ мкА ] (12)

11
а рабочее напряжение, прикладываемое к кнопкам, равно 5 В, отсюда были
выбраны кнопки 0695HIM-130G-G с рекомендуемым рабочим напряжением
не выше 12 В и рабочим током не более 0,05 А.

7)Конденсаторы C1 и C2 номиналом 0,1 мкФ, были выбраны исходя из


требований документации на МК. С1 служит для уменьшения
высокочастотных помех в цепи питания МК, а С2 – в схеме АЦП.

8)Диод VD2 выполняет гасящую функцию, т.е. защищает транзистор VT4 от


всплеска напряжения, который может поступить с катушки реле. Данный
диод 1N4007 выдерживает прямой ток 1 А и обратное напряжение 1000 В,
что многократно перекрывает наши технические требования.

9)VD1 – диод Шоттки 1N5818 защищает устройство от обратного включения.

Отличительным качеством диодов Шоттки от обычных диодов является


сравнительно малое падение напряжения на них. В данном случае оно
составляет 0,316 В.

12
Перечень элементов

Поз.
Наименование Кол-во Примечание
обозначение

C1…C2 Конденсатор керамический 0,1 мкФ 2

DD1 Микроконтроллер ATmega48PA-AU 1 *

HG1 Семисегментный индикатор BA56-12SRWA 1

К1 Электромагнитное реле 851H-1A-C 05VDC 1

R1…R8 Резистор 390 Ом 0,125 Вт 8

R9…R13 Резистор 4,7 кОм 0,125 Вт 5

R14 Терморезистор KTY84/130 1 **

R15 Резистор 100 Ом 0,125 Вт 1

S1…S2 Выключатель кнопочный 0695HIM-130G-G 2

VD1 Диод Шоттки 1N5818 1

VD2 Диод 1N4007 1

VT1…VT4 Транзистор BC857B 4

XP1 Разъем штыревой PLD6 1

* Требуется программирование ППЗУ.


Значения конфигурационных регистров установить следующими:

Fuse High Byte – 0xDF (1101 1111), Fuse Low Byte – 0xFF (1111 1111)

** монтаж проводом

13
Код программы на языке C
//--------------------------------------------------------------
------------
// Программа для контроллера нагревателя (паяльника, термоса и
т.п.)
// Микроконтроллер Atmega48p
// Тактовая частота 8 МГц
//--------------------------------------------------------------
------------

//--------------------------------------------------------------
------------------------------------------------
// Секция подключения заголовочных файлов (библиотек)
//--------------------------------------------------------------
------------------------------------------------
#include <avr/io.h> // для ввода-вывода
#include <avr/interrupt.h> // для прерываний
#include <util/delay.h> // для задержки
#include <avr/eeprom.h> // для работы с памятью EEPROM

//--------------------------------------------------------------
------------------------------------------------
// Секция настроек
//--------------------------------------------------------------
------------------------------------------------
#define LED_DELAY 4
#define MAX_TEMPERATURE 300
#define MIN_TEMPERATURE 100

#define DEC_TEMPERATURE(a) if ((a)>(MIN_TEMPERATURE)) ((a)--)


#define INC_TEMPERATURE(a) if ((a)<(MAX_TEMPERATURE)) ((a)++)

#define RELAY_ON() (PORTB &= ~(1<<2))


#define RELAY_OFF() (PORTB |= (1<<2))

#define BUTTON_INC_PRESSED (~PINC & (1<<0))


#define BUTTON_DEC_PRESSED (~PINC & (1<<2))
#define BUTTON_INC_RELEASED (PINC & (1<<0))
#define BUTTON_DEC_RELEASED (PINC & (1<<2))

#define STATE_NOT_PRESSED 0
#define STATE_SHORT_PRESS 1
#define STATE_LONG_PRESS 2

#define LED_A 7
#define LED_B 5
#define LED_C 4
#define LED_D 1
#define LED_E 0
#define LED_F 6
14
#define LED_G 3
#define LED_DP 2

#define DDR_LED DDRD


#define PORT_LED PORTD

#define DIG_HI 3
#define DIG_MD 4
#define DIG_LO 5

#define DDR_DIG DDRC


#define PORT_DIG PORTC

//#define COMMON_CATODE

//--------------------------------------------------------------
------------------------------------------------

#ifdef COMMON_CATODE

#define NUMBER_0 (uint8_t)((1<<LED_A)|(1<<LED_B)|(1<<LED_C)|


(1<<LED_D)|(1<<LED_E)|(1<<LED_F)|(0<<LED_G))
#define NUMBER_1 (uint8_t)((0<<LED_A)|(1<<LED_B)|(1<<LED_C)|
(0<<LED_D)|(0<<LED_E)|(0<<LED_F)|(0<<LED_G))
#define NUMBER_2 (uint8_t)((1<<LED_A)|(1<<LED_B)|(0<<LED_C)|
(1<<LED_D)|(1<<LED_E)|(0<<LED_F)|(1<<LED_G))
#define NUMBER_3 (uint8_t)((1<<LED_A)|(1<<LED_B)|(1<<LED_C)|
(1<<LED_D)|(0<<LED_E)|(0<<LED_F)|(1<<LED_G))
#define NUMBER_4 (uint8_t)((0<<LED_A)|(1<<LED_B)|(1<<LED_C)|
(0<<LED_D)|(0<<LED_E)|(1<<LED_F)|(1<<LED_G))
#define NUMBER_5 (uint8_t)((1<<LED_A)|(0<<LED_B)|(1<<LED_C)|
(1<<LED_D)|(0<<LED_E)|(1<<LED_F)|(1<<LED_G))
#define NUMBER_6 (uint8_t)((1<<LED_A)|(0<<LED_B)|(1<<LED_C)|
(1<<LED_D)|(1<<LED_E)|(1<<LED_F)|(1<<LED_G))
#define NUMBER_7 (uint8_t)((1<<LED_A)|(1<<LED_B)|(1<<LED_C)|
(0<<LED_D)|(0<<LED_E)|(0<<LED_F)|(0<<LED_G))
#define NUMBER_8 (uint8_t)((1<<LED_A)|(1<<LED_B)|(1<<LED_C)|
(1<<LED_D)|(1<<LED_E)|(1<<LED_F)|(1<<LED_G))
#define NUMBER_9 (uint8_t)((1<<LED_A)|(1<<LED_B)|(1<<LED_C)|
(1<<LED_D)|(0<<LED_E)|(1<<LED_F)|(1<<LED_G))

#else

#define NUMBER_0 (uint8_t)(~((1<<LED_A)|(1<<LED_B)|(1<<LED_C)|


(1<<LED_D)|(1<<LED_E)|(1<<LED_F)|(0<<LED_G)))
#define NUMBER_1 (uint8_t)(~((0<<LED_A)|(1<<LED_B)|(1<<LED_C)|
(0<<LED_D)|(0<<LED_E)|(0<<LED_F)|(0<<LED_G)))
#define NUMBER_2 (uint8_t)(~((1<<LED_A)|(1<<LED_B)|(0<<LED_C)|
(1<<LED_D)|(1<<LED_E)|(0<<LED_F)|(1<<LED_G)))
#define NUMBER_3 (uint8_t)(~((1<<LED_A)|(1<<LED_B)|(1<<LED_C)|
(1<<LED_D)|(0<<LED_E)|(0<<LED_F)|(1<<LED_G)))
#define NUMBER_4 (uint8_t)(~((0<<LED_A)|(1<<LED_B)|(1<<LED_C)|
(0<<LED_D)|(0<<LED_E)|(1<<LED_F)|(1<<LED_G)))
#define NUMBER_5 (uint8_t)(~((1<<LED_A)|(0<<LED_B)|(1<<LED_C)|
(1<<LED_D)|(0<<LED_E)|(1<<LED_F)|(1<<LED_G)))
#define NUMBER_6 (uint8_t)(~((1<<LED_A)|(0<<LED_B)|(1<<LED_C)|
(1<<LED_D)|(1<<LED_E)|(1<<LED_F)|(1<<LED_G)))
#define NUMBER_7 (uint8_t)(~((1<<LED_A)|(1<<LED_B)|(1<<LED_C)|
(0<<LED_D)|(0<<LED_E)|(0<<LED_F)|(0<<LED_G)))
#define NUMBER_8 (uint8_t)(~((1<<LED_A)|(1<<LED_B)|(1<<LED_C)|
15
(1<<LED_D)|(1<<LED_E)|(1<<LED_F)|(1<<LED_G)))
#define NUMBER_9 (uint8_t)(~((1<<LED_A)|(1<<LED_B)|(1<<LED_C)|
(1<<LED_D)|(0<<LED_E)|(1<<LED_F)|(1<<LED_G)))

#endif

//--------------------------------------------------------------
------------------------------------------------

// массив цифр для отображения


const uint8_t NUMBERS[] = { NUMBER_0, NUMBER_1, NUMBER_2, NUMBER_3, NUMBER_4,
NUMBER_5, NUMBER_6, NUMBER_7, NUMBER_8, NUMBER_9 };

// массив "температур"
const uint16_t TEMPS[] =
{ 778, 768, 759, 749, 740, 730, 721, 711, 702, 692,
683, 676, 669, 655, 648, 641, 633, 626, 618, 611,
603, 596, 588, 581, 574, 566, 560, 553, 546, 540,
533, 527, 521, 515, 509, 503, 497, 491, 485, 480,
474, 469, 464, 458, 453, 448, 440, 433, 426, 419,
412, 410, 408, 405, 403, 401, 397, 392, 388, 384,
379, 375, 371, 368, 364, 360, 356, 353, 349, 345,
342, 338, 335, 331, 328, 325, 321, 318, 315, 312,
309, 306, 303, 300, 297, 294, 291, 288, 286, 283,
280, 278, 275, 273, 271, 268, 265, 263, 260, 258,
255, 253, 251, 249, 246, 244, 242, 240, 238, 236,
234, 232, 230, 228, 226, 224, 220, 220, 218, 216,
214, 213, 211, 209, 207, 205, 204, 202, 201, 199,
197, 195, 194, 192, 191, 189, 201, 199, 198, 184,
182, 181, 180, 179, 177, 176, 175, 174, 173, 172,
171};

// Устанавливаемая температура
volatile uint16_t temperature_setup = 0;
// Устанавливаемая температура для работы с EEPROM
EEMEM uint16_t temperature_setup_eeprom;
// Измеряемая температура
volatile uint16_t temperature_real = 0;
// Состояние кнопок (не нажата/короткое нажатие/долгое нажатие)
volatile uint8_t buttons_state = STATE_NOT_PRESSED;
// Флаг нажатия кнопки
volatile uint8_t button_flag = 255;
// Флаг необходимости измерений
volatile uint8_t measure_fla = 0;

//--------------------------------------------------------------
------------------------------------------------
// функция инициализации (запись начальных значений в
необходимые регистры)
//--------------------------------------------------------------
------------------------------------------------
inline void init(void) {
// управление реле
PORTB |= (1<<2);
// управление реле
DDRB |= (1<<2);
// направление порта D на вывод
DDR_LED |= 0xFF;
// направление пинов 0,1,2 порта В на вывод - подключены аноды
индикатора через PNP-транзисторы
16
DDR_DIG |= (1<<DIG_HI)|(1<<DIG_MD)|(1<<DIG_LO);
// подаем питание на пины 0,1,2 порта В - гасим индикаторы
PORT_DIG |= (1<<DIG_HI)|(1<<DIG_MD)|(1<<DIG_LO);
// подтяжка питания к кнопкам
PORTC |= (1<<0)|(1<<2);
// подтяжка к внутреннему источнику питания
ADMUX = (1<<REFS1) | (1<<REFS0) | (1<<MUX0);
// Делитель таймера TIMER0 на 256
TCCR0B = (1<<CS02);
// Включение таймера TIMER0 по переполнению
TIMSK0 = (1<<TOIE0); }

//--------------------------------------------------------------
------------------------------------------------
// функция отображения на индикаторах трехзначного числа,
передаваемого в параметре temperature
//--------------------------------------------------------------
------------------------------------------------
inline static void show_number(uint16_t temperature, uint8_t
show_dp) {
// выводим сотни
PORT_LED = NUMBERS[temperature%1000/100];
// зажигаем старший разряд на индикаторе подаем 0 вольт
PORT_DIG &= ~(1<<DIG_HI);
_delay_ms(LED_DELAY);
// гасим старший разряд на индикаторе подаем 5 вольт
PORT_DIG |= (1<<DIG_HI);
// выводим десятки
PORT_LED = NUMBERS[temperature%100/10];
// зажигаем средний разряд на индикаторе
PORT_DIG &= ~(1<<DIG_MD);
_delay_ms(LED_DELAY);
// гасим средний разряд на индикаторе
PORT_DIG |= (1<<DIG_MD);
// выводим единицы
PORT_LED = NUMBERS[temperature%10];
// если было указано в параметре show_dp
if (show_dp)
// то зажигаем точку
PORT_LED &= ~(1<<LED_DP);
// зажигаем младший разряд на индикаторе
PORT_DIG &= ~(1<<DIG_LO);
_delay_ms(LED_DELAY);
// гасим младший разряд на индикаторе
PORT_DIG |= (1<<DIG_LO); }

//--------------------------------------------------------------
------------------------------------------------
// функция опроса кнопок
//--------------------------------------------------------------
------------------------------------------------
inline static void check_buttons(void) {
// защита от одновременного нажатия двух кнопок и последующая
задержка
if (BUTTON_INC_PRESSED && BUTTON_DEC_PRESSED) {
button_flag = 120;

17
return;
}
// обработка кнопки "больше"
if (BUTTON_INC_PRESSED && (button_flag < 60)) {
INC_TEMPERATURE(temperature_setup);
eeprom_write_word(&temperature_setup_eeprom,
temperature_setup);
button_flag = 120;
}
// обработка кнопки "меньше"
if (BUTTON_DEC_PRESSED && (button_flag < 60)) {
DEC_TEMPERATURE(temperature_setup);
eeprom_write_word(&temperature_setup_eeprom,
temperature_setup);
button_flag = 120;
}
}

//--------------------------------------------------------------
------------------------------------------------
// функция проверки температуры на попадание в границы диапазона
//--------------------------------------------------------------
------------------------------------------------
inline static void check_temperature(uint16_t* t) {
if (*t < MIN_TEMPERATURE) *t = MIN_TEMPERATURE;
if (*t > MAX_TEMPERATURE) *t = MAX_TEMPERATURE;
}

//--------------------------------------------------------------
------------------------------------------------
// функция измерения температуры
//--------------------------------------------------------------
------------------------------------------------
inline static void measure_temperature(uint16_t* t) {
ADCSRA = (1<<ADEN) | (1<<ADSC) | (1<<ADPS2) | (1<<ADPS1) |
(1<<ADPS0);

while ((~ADCSRA & (1<<ADIF)));

uint16_t v = ADCL;
v |= (ADCH << 8);

// v = (v*55)>>9; // напряжение на делителе напряжения в


сотых долях вольта
for (uint16_t i=1; i<=150; i++) {
*t = (i-1) * 2;
if (v > TEMPS[i]) {
break;
}
}
}

//--------------------------------------------------------------
------------------------------------------------
// функция обработки сравнения установленной и измеренной
температур
//--------------------------------------------------------------
18
------------------------------------------------
inline static void compare_temperature(void) {
if (temperature_real < temperature_setup) {
RELAY_ON();
}
else {
RELAY_OFF();
}
}

//--------------------------------------------------------------
------------------------------------------------
// функция обработки прерываний по таймеру TIMER0
//--------------------------------------------------------------
------------------------------------------------
ISR(TIMER0_OVF_vect) {
measure_flag--;
if (button_flag) button_flag--;
}

//--------------------------------------------------------------
------------------------------------------------
// начало работы программы (точка старта)
//--------------------------------------------------------------
------------------------------------------------
int main(void) {

init();
// инициализация

temperature_setup =
eeprom_read_word(&temperature_setup_eeprom);
check_temperature(&temperature_setup);

// разрешаем прерывания вообще


sei();
while (1) {
// если нужно измерить (флаг поднят)
if (measure_flag > 60) {
// измерение температуры
measure_temperature(&temperature_real);
// проверка температуры
check_temperature(&temperature_real);
measure_flag = 60;
}

// сравнение температур и управление реле


compare_temperature();
// показывать цифры
show_number(button_flag?temperature_setup:temperature_real,
button_flag);
// проверять кнопки
check_buttons();
}
}

19
Список использованных источников:

1)Гаврилин, Гуревич, Можаев, Шеленков. Микропроцессорные


средства систем управления.

2)Можаев В.А. Лекции по МПУ СУ.

3)Бусурин, Можаев, Шеленков. Микроэлектронные устройства


систем управления летательных аппаратов.
20
4)Техническая документация с сайта магазина радиоэлектронных
компонентов www.chipdip.ru.

Приложение

Сила тока на сегменте


Номинал Сила тока, мА
резистора, Ом
62 40
220 14
240 12
270 12
330 10
390 7,7

21
470 7,2
510 6,6
560 6

22

Вам также может понравиться