2015-02-05 01:22:55 +03:00

91 lines
4.9 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

конфигурационный регистр АЦП: |!RDY|C1|C0|!O/C|S1|S0|G1|G0|
!RDY == 0 когда преобразование окончено (МК может послать NAK и считать данные); при записи в непрерывном режиме не учитывается
C1,C0 не задействованы
!O/C - режим преобразования (по умолчанию 1): 1-непрерывное, 0-одноразовое
S1,S0 - разрешение (по умолчанию 0): 00 - 12, 01 - 14, 10 - 16, 11 - 18 бит
G1,G0 - усиление (по умолчанию 0): 00 - 1, 01 - 2, 10 - 4, 11 - 8
Поддерживаемые скорости: 100кбит/с, 1400кбит/с и 3.4Мбит/с
Протокол: стартовый бит, данные (MSB first), стоповый бит
данные считываются при SCL==1, если SCL==1, а SDA меняется, это START(1->0) или STOP(0->1)
ноги: SCL - push/pull; SDA - open drain
в режиме чтения прервать передачу можно командами NAK/STOP
После стартового бита первый байт - адрес (4 бита - код устройства - 1101, 3 бита - адрес устройства/000 по даташиту/, 1 бит - R/!W)
в режиме записи (R/!W = 0) пишем конфигрегистр
в режиме чтения устройство посылает конфигрегистр и данные (1 байт == 8 бит данных + ACK бит, после адреса ACK инициируется
устройством, после данных - микроконтроллером)
в 18-битном режиме отсылаются 3 байта данных, следом 1 байт конфиг; первые 7 бит первого байта данных - MSB (знак операции, т.е. ноль),
LSB третьего байта - LSB данных
GENERAL CALL
Если первым байтом передать нули, то второй байт читают все устройства линии. Второй байт:
== 0x06 - сброс АЦП на настройки по умолчанию
== 0x08 - одноразовое преобразование
сигналы:
NOT BUSY (умолчательное состояние) - SDA=1, SCL=1
START DATA TRANSFER - SCL = 1, SDA = 1->0
STOP DATA TRANSFER - SCL = 1, SDA = 0->1
DATA VALID - данные не должны изменяться при SCL=1
Каждая передача данных начинается со START и кончается STOP
ACK: девятый такт SCL используется как ACK. Для прерывания чтения достаточно установить SDA=1 на этот бит
Этот бит можно проверять: если АЦП сдох, то будет 1 вместо 0
!!! на этот бит нужно отпустить ногу
После включения нужно инициализировать АЦП: 1 байт - start(0);1;1;0;1;0;0;0;0;ACK(1)
2 байт - 0;0;0;1;1;1;0;0;ACK(1)
не забываем проверять ACK: если он !=0, то АЦП сдох
далее - непрерывно читаем: 1 байт - start(0);1;1;0;1;0;0;0;1;ACK(1)
2-5 байты: 8 бит; ACK(0)
6 и последующие (пока тикает SCL и не установлен ACK/STOP): конфиг
чтение: читаем до тех пор, пока в конфиг-регистре RDY==1; затем прерываем (ACK=1,STOP) и инициализируем следующую порцию считывания
(можно читать 8 раз и усреднять)
прервать операцию чтения можно в любой момент, отправив бит STOP
ВОЛЬТМЕТР:
Вычисление.
В 18-битном режиме реально АЦП дает 17 бит (т.к. у нас однополярное напряжение без сдвига). Таким образом,
LSB=2.048V/2^{17}
коэффициент резисторного делителя kr (17.5 в идеальных условиях)
-> U = ADU*2.048*kr/2^{17}, где ADU - показания внешнего АЦП (по умолчанию коэффициент усиления = 1)
Следовательно, для вычисления напряжения в милливольтах (используем 32-битную целочисленную арифметику, т.к.
float не справится, а double и 64-битные целые sdcc не умеет) используем формулу
---> U = (ADU*K)>>17
K - коэффициент преобразования, по умолчанию K = 2048*17.5=35840, но при калибровке мы его можем поменять
Из-за того, что коэффициент K занимает 15-16 бит, может возникнуть ситуация переполнения, т.е.
нам нужно еще и хранить ADUmax - предельное значение, выдаваемое АЦП, которое еще можно обработать
это значение вычисляется так:
---> ADUmax = 0xffffffff/K (по умолчанию 119837)
"Умолчательное" ограничение дает нам предел измерений: 32.758В (естественно, в реальных условиях этот предел
варьируется как минимум на 5% из-за погрешности резисторов делителя)
Коэффициент K при калибровке вычисляется так:
---> K = Uref<<17/ADU = Const / ADU
Uref - опорное напряжение в милливольтах (жестко зафиксировано при компиляции)
Следовательно, Const можно вычислить на этапе компиляции, скажем, для Uref=12000мВ мы имеем
Const = 12000<<17 = 1572864000; для улучшения калибровки можно считать значение ADU 16 раз и усреднить
Служебный разъем имеет подключение к ноге 3 (PD6/UART1_RX), следовательно, используется для калибровки.
Вариантов калибровки 2 (причем, можно реализовать их одновременно):
1) при получении на PD6 логической 1 производится считывание результата, вычисление и запоминание констант
2) при получении данных по UART1 вольтметр воспринимает их в качестве множителя, вычисляет предельное значение и сохраняет константы
Во втором варианте можно пробежаться по всему диапазону (0..30В) и линейной аппроксимацией вычислить оптимальный коэффициент.
Режим отображени вычисленных данных прост:
- динамическая индикация на 5 позиций (т.е. нужно либо поочередно читать/показывать, либо делать это псевдоодновременно,
но ждать окончания преобразования, непрерывно читая, не стоит)
- после вычисления U в милливольтах нам надо отобразить это значение:
-- если U < 10000, т.е. используется 4 знакоместа, мы рисуем 4-значное число (дополняя спереди нулями), а десятичную точку ставим в четвертой позиции (digit2)
-- иначе рисуем на пяти знакоместах, просто выводя целое; десятичную точку опять же ставим в четвертой позиции (digit2)