Если программа Ардуино строится по традиционному принципу – последовательное выполнение программных блоков, то время выполнений операций с шиной 1-Wire не имеет большого значения. Одна, две, десять миллисекунд. Какая разница, если все происходит в цикле, например, 1 сек.
В случае с параллельным выполнением задач программы часто необходимо знать время выполнения таких сложных и критичных ко времени функций.
При разработке Ардуино контроллера элемента Пельтье я вынужден был реализовывать параллельное выполнение нескольких задач с разными временными циклами.
Остро встали вопросы:
- Сколько времени выделять на управление датчиками температуры DS18B20?
Как организовывать обмен данными по 1-Wire шине?
Пришлось определить время выполнения функций класса OneWire. Я сделал это двумя способами:
- Посчитал теоретически, исходя из временных требований к операциям на шине 1-Wire.
Измерил специальной программой. Я писал о ней в этой теме.
Для измерения времени выполнения функций библиотеки OneWire я подкорректировал программу, добавил библиотеку и объявление класса OneWire.
Код: Выделить всё
// определение времени выполнения функций OneWire
#include <OneWire.h>
OneWire sensD (16); // датчик подключен к выводу 16 (A2)
unsigned int timerValue; // значение таймера
byte bufData[9]; // буфер данных
void setup() {
Serial.begin(9600); // инициализируем порт
// установки таймера 1
TCCR1A = 0;
TCCR1B = 0;
}
void loop() {
noInterrupts(); // запрет прерываний
TCNT1H = 0; // сброс таймера
TCNT1L = 0;
TCCR1B = 1; // разрешение работы таймера
// ---------- исследуемый программный блок ---------
// sensD.reset(); // сброс шины
// sensD.write(0xCC, 1); // пропуск ROM
// sensD.write(0x44, 1); // инициализация измерения
// sensD.reset(); // сброс шины
// sensD.write(0xCC, 1); // пропуск ROM
// sensD.write(0xBE, 1); // команда чтения памяти датчика
// sensD.read_bytes(bufData, 9); // чтение памяти датчика, 9 байтов
// bufData[0]= sensDs.read(); // чтение памяти датчика, 9 байтов
// if ( OneWire::crc8(bufData, 8) == bufData[8] ) { bufData[8]=0; } // проверка CRC
// else bufData[8]=1;
// -------------------------------------------------
TCCR1B = 0; // остановка таймера
timerValue = (unsigned int)TCNT1L | ((unsigned int)TCNT1H << 8); // чтение таймера
interrupts(); // разрешение прерываний
// вывод на компьютер
Serial.print( (float)(timerValue - 2) * 0.0625);
Serial.println(" mks");
delay(500);
}
По очереди открывал от комментариев функции и получал время выполнения. Результаты я свел в таблицу.
Функция | Назначение | Расчетное время | Измеренное время |
reset() | Инициализация обмена | 960 мкс | 966 мкс |
write() | Запись байта | 480 - 960 мкс | 548 мкс |
read() | Чтение байта | 480 - 960 мкс | 522 мкс |
read_bytes() | Чтение блока байтов (9байтов) | 4320 - 8640 мкс | 4700 мкс |
crc8 | Вычисление контрольной суммы | - | 7,3 мкс |
Получается, что последовательность самой простой инициализации измерения датчика DS18B20 требует 2063 мкс.
Код: Выделить всё
sensD.reset(); // сброс
sensD.write(0xCC, 1); // пропуск ROM
sensD.write(0x44, 1); // инициализация измерения
А на чтение температуры из датчика DS18B20 и проверку контрольной суммы требуется 6,8 мс.
Код: Выделить всё
sensD.reset(); // сброс
sensD.write(0xCC, POWER_MODE); // пропуск ROM
sensD.write(0xBE, POWER_MODE); // команда чтения памяти датчика
sensD.read_bytes(bufData, 9); // чтение памяти датчика, 9 байтов
if ( OneWire::crc8(bufData, 8) == bufData[8] ) { // проверка CRC