считать и использовать. При этом главный цикл крутится по своим делам и
не парится, зная, что свежие значение всегда его ждут.
В самом прерывании активно используется работа с масками. Для того,
чтобы сменить номер канала. Номер канала лежит в последних трех битах
регистра ADMUX и может иметь значение от 0 до 7 (000 и 111
соотвествтенно). И нам надо в каждом вызове увеличивать значение канала,
перебирая их по очереди. Просто так икрементировать ADMUX нельзя, т.к.
кроме номера канала там лежат еще и быти управления АЦП, выравнивания
и опорного напряжения — они могут сбиться. Приходится изощряться с
масками, чтобы их не задеть.
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
ADC_OK: PUSHF
PUSH ZL
PUSH ZH
PUSH R17
IN R16,ADMUX ; Берем ADMUX
ANDI R16,0x07 ; Маской отрезаем лишние биты.
Получаем номер канала
; С которого было снято измерение.
MOV R17,R16 ; Cохранили копию номера канала
LDI ZL,low(ADCCH) ; Берем адрес начала массива с будущими
данными.
LDI ZH,High(ADCCH)
ADD ZL,R16 ; Прибавляем к адресу наш номер канала.
; Если было переполнение, то будет флаг
С
CLR R16 ; Флаг важен, а значение в R16 уже нет.
Но нам нужен ноль
; Возьмем и сделаем его из R16.
ADC ZH,R16 ; Сложим флаг возможного переполнения
с ZH
; Т.о. у нас получается в Z = адрес
(ADCCH+номер канала)
; И значения из разных каналов ложатся в
разные переменные массива
; с адресом базы ADCCH
IN R16,ADCL ; Младшее значение нам не надо. Но
считать его нужно.