/
Interrupt.cpp
103 lines (86 loc) · 6.07 KB
/
Interrupt.cpp
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
//******************************** Пояснение ******************************//
// Данный пример для Atmega32u4.
//******************************* /Пояснение ******************************//
//******************************* Библиотеки ******************************//
#include "Arduino.h"
#include "Interrupt.h"
//******************************* /Библиотеки *****************************//
// Маска для 7 пина, PE6.
#define PIN_PORTE_MASK B01000000
// Переменная в которой храним последнее значение порта E.
volatile uint8_t lastValuePortE = 0;
/// <summary>
/// Настройка внешнего прерывания 6.
/// </summary>
void SetupExtInterrupt6()
{
// EIMSK (External Interrupt Mask Register) - регистр разрешающий внешние прерывания.
// INTn (External Interrupt Request) - биты которые разрешают внешние прерывания INTn. Когда бит INTn и бит I регистра SREG установлены в 1 - внешние прерывания на пине INTn разрешены.
// Очищаем регистр разрешающий внешние прерывания.
EIMSK |= (0 << INT6);
// EICRA (External Interrupt Control Register A) - регистр управления внешними прерываниями А.
// EICRB (External Interrupt Control Register B) - регистр управления внешними прерываниями B.
// ISCn0, ISCn1 (External Interrupt Sense Control Bits) - биты события, в результате которых будет сгенерировано прерывание INTn.
// ISCn0 = 0, ISCn1 = 0 низкий уровень на входе INTn.
// ISCn0 = 0, ISCn1 = 1 любое изменение уровня на входе INTn.
// ISCn0 = 1, ISCn1 = 0 по спадающему сигналу на входе INTn.
// ISCn0 = 1, ISCn1 = 1 по возрастающему сигналу на входе INTn.
EICRB |= (1 << ISC60) | (1 << ISC61);
// EIFR (External Interrupt Flag Register) - регистр флагов внешних прерываний.
// Очищаем регистр флагов внешних прерываний.
EIFR = (1 << INTF6);
// EIMSK (External Interrupt Mask Register) - регистр разрешающий внешние прерывания.
// INTn (External Interrupt Request) - биты которые разрешают внешние прерывания INTn. Когда бит INTn и бит I регистра SREG установлены в 1 - внешние прерывания на пине INTn разрешены.
// Разрешаем внешнее прерывание на INT6.
EIMSK |= (1 << INT6);
}
/// <summary>
/// Настройка прерывания по изменению состояния группы выводов 0.
/// </summary>
void SetupPortInterrupt0()
{
// PCICR (Pin Change Interrupt Enable) - регистр разрешающий прерывания по изменению состояния группы выводов.
// PCIEn - биты которые разрешают прерывания по изменению состояния группы выводов. Когда бит PCIEn и бит I регистра SREG установлены в 1 - прерывания по изменению состояния на группе выводов PCIEn разрешены.
// Очищаем регистр разрещающий прерывания по изменению состояния группы выводов.
PCICR |= (0 << PCIE0);
// PCMSKn (Pin Change Mask Register) - регистр включающий выводы конкретной группы портов на прерываний по изменению состояния.
PCMSK0 |= (1 << PCINT7) | (0 << PCINT6) | (0 << PCINT5) | (0 << PCINT4) | (0 << PCINT3) | (0 << PCINT2) | (0 << PCINT1) | (0 << PCINT0);
// PCIFR (Pin Change Interrupt Flag Register) - регистр флагов прерываний по изменению состояния группы выводов. Указывает от какой группы поступило прерывание.
// Очищаем регистр флагов прерываний по изменению состояния группы выводов.
PCIFR = (1 << PCIF0);
// PCICR (Pin Change Interrupt Enable) - регистр разрешающий прерывания по изменению состояния группы выводов.
// PCIEn - биты которые разрешают прерывания по изменению состояния группы выводов. Когда бит PCIEn и бит I регистра SREG установлены в 1 - прерывания по изменению состояния на группе выводов PCIEn разрешены.
PCICR |= (1 << PCIE0);
}
/// <summary>
/// Внешнее прерывание 6.
/// </summary>
ISR(INT6_vect)
{
}
/// <summary>
/// Прерывание по изменению состояния группы выводов 0.
/// </summary>
ISR(PCINT0_vect)
{
// Получаем измененные биты порта E.
uint8_t changedBits = PINE & PIN_PORTE_MASK ^ lastValuePortE;
// Сохраняем последнее значение порта E.
lastValuePortE = PINE;
// Пины к которым подключено прерывание по изменению состояния группы выводов, изменились.
if (changedBits)
{
// Проверяем изменилось состояние пина 7.
if (changedBits & (1 << PE6))
{
if (PINE & (1 << PE6))
{
// Состояние вывода изменилось с низкого уровня на высокий.
}
else
{
// Состояние вывода изменилось с высокого уровня на низкий.
}
}
}
}