RadioRadar - Радиоэлектроника, даташиты, схемы

https://www.radioradar.net/radiofan/measuring_technics/barometer_thermometer_cr2477_part_2.html

Барометр-термометр с питанием от литиевого элемента CR2477 (часть 2)

Теперь по поводу "бага" при программировании ЖКИ RDN0007-PAN-#00. Этот ЖКИ - усовершенствованная версия более старых ЖКИ TI8148 и TIC55. У этих ЖКИ общий контроллер (драйвер) - ML1001. Эти ЖКИ имеют восемь знакомест, каждое из которых состоит из семи сегментов цифры, сегмента десятичной точки и сегмента "галочки" ("^"), т. е. всего из девяти сегментов. Таким образом, общее число сегментов ЖКИ равно 8x9 = 72. Каждый сегмент кодируется определённым битом, откуда следует, что для заполнения всего ЖКИ требуется передать 72 бита. Так вот, в справочном листке ML1001 указано, что для заполнения всего ЖКИ требуется передать 72 информационных бита и ещё восемь пустых битов, чтобы их общее число было равно 80. На таком принципе работают ЖКИ TI8148 и TIC55. В отличие от этих ЖКИ, в RDN0007-PAN-#00 требуется передать не 80, а 72 бита, т. е. ровно столько, сколько их требуется для всех его знакомест (по девять бит каждое), иначе все знакоместа сдвигаются влево, при этом информация первого знакоместа пропадает, а информация последнего знакоместа становится копией предпоследнего. В этом и состоит "баг". Здесь необходимо добавить, что вначале передаётся бит точки, затем бит "галочки" и далее - семь битов сегментов цифры. Передача битов знакомест осуществляется задом наперёд или, другими словами, последние переданные девять бит соответствуют первому (левому) знакоместу на ЖКИ, если точки и "галочки" располагаются снизу.

При программировании чтения по SPI из BMP280 автор также обнаружил "баг". Он состоит в том, что при чтении идентификационного номера (ID) и калибровочных коэффициентов используется стандартная процедура чтения по SPI, а при чтении данных АЦП эта процедура даёт неадекватные значения. Для объяснения этого эффекта и снятия этого "бага" сделаем некоторое отступление по поводу стандартных протоколов чтения и записи по SPI.

Для того чтобы записать байт по SPI, требуется записать его в регистр SPI0DAT, дождаться установки бита (флага) окончания передачи (SPI0CN0_ SPIF) и сбросить этот бит. Эта стандартная процедура (подпрограмма) приведена в табл. 2.

Таблица 2

При чтении байта по SPI требуется записать в SPI0DAT ничего не значащий фиктивный (подставной - dummy) байт (например, 0xff), дождаться установки флага sPl0CN0_sPlF и сбросить его. Результат чтения будет в регистре SPI0DAT. Подпрограмма чтения по SPI приведена в табл. 3.

Таблица 3

Возвращаясь к прерванной последовательности изложения, следует пояснить, что сама процедура чтения из области памяти BMP280 состоит в том, что вначале требуется записать байт адреса, откуда необходимо получить информацию вышеприведённой подпрограммой записи, а затем - прочитать эту информацию вышеприведённой подпрограммой чтения. Причём, если требуется прочитать несколько (два и более) подряд расположенных байтов или, другими словами, массив байтов (многократное чтение - multiple byte read), нет необходимости перед чтением каждого байта указывать его адрес. Достаточно записать адрес первого элемента массива и далее просто читать подряд столько раз, сколько элементов в массиве. Другими словами, перед чтением каждого следующего байта происходит автоматическое инкрементирование адреса.

Например, для чтения первого двухбайтного калибровочного коэффициента температуры (в справочном листке он обозначен как dig_T1), расположенного по адресам 0x88 (старший байт) и 0x89 (младший байт), необходимо вначале записать адрес старшего байта (0x88), а затем произвести двукратное чтение. В этом случае такая процедура чтения работает правильно, и к ней никаких претензий нет.

Иное дело, если требуется прочитать данные АЦП. Эти данные для давления (ADC_P) и температуры (ADC_T) расположены в памяти BMP280 также подряд, начиная с адреса 0xF7 (старший байт данных давления - press_msb). Причём каждое показание АЦП содержится в трёх байтах. Например, данные ADC_P расположены по адресам 0xF7 (старший байт), 0xF8 (средний байт - press_lsb) и 0xF9 (младший байт - press_xlsb). Далее идут данные ADC_T. Таким образом, два показания занимают 2x3 = 6 байт. Если требуется прочитать подряд все шесть байтов, то, применив вышеприведённую процедуру многократного чтения, вначале следует записать в BMP280 адрес первого элемента этого массива, т. е. 0xF7, а затем осуществить шестикратное чтение. Однако в этом случае получится полная белиберда. В чём же здесь дело? Как выяснил автор, при записи адреса 0xF7 вышеприведённой подпрограммой записи байта и последующего чтения байта вышеприведённой подпрограммой чтения будет произведена операция чтения не с адреса 0xF7, а со следующего адреса - 0xF8. Другими словами, после записи адреса 0xF7 в регистр SPI0DAT сразу же запишется содержимое 0xF7, а при последующем чтении после записи фиктивного байта в SPI0DAT запишется содержимое уже следующего байта, т. е. после записи адреса происходит его авто-матическое инкрементирование, и, таким образом, содержимое регистра 0xF7 теряется.

Решение этой проблемы можно осуществить двумя способами. Первый способ - после выполнения подпрограммы записи адреса 0xF7 сразу же прочитать содержимое SPI0DAT (это и будет содержимое адреса 0xF7), а затем уже осуществить чтение подпрограммой чтения, в результате чего получим содержимое адреса 0xF8, и далее прочитать остальные байты стандартным образом.

Таблица 4

Второй способ состоит в том, что вначале следует записать подпрограммой записи не адрес 0xF7, а адрес на единицу меньше, т. е. адрес 0xF6, а затем уже прочитать все шесть байтов. Оба способа, как выяснилось, работают, однако второй, по мнению автора, более предпочтителен, поскольку он позволяет воспользоваться стандартными подпрограммами чтения и записи по SPI. В табл. 4 приведён фрагмент основной программы, где показано, как это сделать. Во-первых, вначале следует установить совмещение (объединение) четырёхбайтного числа (uint32_t dw) с массивом из четырёх однобайтных чисел (uint8_t b[3]) с четырьмя элементами b[0], b[1], b[2] и b[3]. Это совмещение требуется, чтобы, с одной стороны, иметь возможность работы с четырёхбайтным числом (ADC_P) для расчётов давления по формулам, приведённым в справочном листке с учётом калибровочных коэффициентов, с другой - производить однобайтное чтение по интерфейсу SPI, а он, как известно, однобайтный. Такое совмещение приводит к тому, что массив из четырёх однобайтных чисел b[3] и одно четырёхбайтное число dw перераспределяют одно и то же место в памяти. Другими словами, массив b[3] строго определяет число dw, и, наоборот, dw строго определяет массив b[3].

Таблица 5

В табл. 5 приведён фрагмент основной программы, в котором осуществляется чтение, начиная с адреса 0xF6 (BMP280_REG_PRESS_MSB - 1), т. е. на единицу меньше адреса старше-го байта давления, поскольку в начале программы установлена директива #define BMP280_REG_PRESS_MSB 0xF7. Самый старший элемент массива (ret.b[3]) не используется, поэтому он должен быть обнулён.

Таким образом, прочитав все три байта, можно получить правильные данные АЦП (adc_P) из числа ret.dw. Остальные три байта для температуры читаются аналогично.

Продолжение следует

Автор: А. Кузьминов, г. Москва