mirror of
https://github.com/IoTManagerProject/IoTManager.git
synced 2026-03-26 22:22:16 +03:00
Исправление ошибки компиляции
This commit is contained in:
134
lib/iarduino_RTC/src/iarduino_RTC.cpp
Normal file
134
lib/iarduino_RTC/src/iarduino_RTC.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
#include "iarduino_RTC.h"
|
||||
|
||||
// Вывод даты и времени
|
||||
char* iarduino_RTC::gettime(String i){char j[i.length()+1]; i.toCharArray(j, i.length()); j[i.length()]=0; return gettime(j);}
|
||||
char* iarduino_RTC::gettime(const char* i){
|
||||
uint8_t j, k, n; bool f; // Объявляем локальные переменные
|
||||
if(valRequest > millis()){valRequest=0;} // Избавляемся от переполнения millis()
|
||||
// Получаем текущее время:
|
||||
if(valPeriod == 0) {funcReadTime();}else // Если минимальный период опроса модуля == 0 минут, то получаем время из регистров модуля, иначе ...
|
||||
if(valRequest == 0 || (valPeriod+valRequest <= millis())) {funcReadTime();}else // Если время последнего опроса модуля превысило минимальный период опроса модуля, то получаем время из регистров модуля, иначе ...
|
||||
{funcCalculationTime();} // Получаем время без обращения к модулю (время рассчитывая исходя из millis и valRequest)
|
||||
funcSetMoreTime(); // Преобразуем переменные не читаемые из модуля
|
||||
// Вычисляем размер блока памяти под строку с ответом:
|
||||
n=strlen(i)+1; // Определяем размер равный введённой строке (i) + 1 символ конца строки
|
||||
for(j=0; j<strlen(i); j++) { // Проходим по символам полученной строки
|
||||
for(k=0; k<strlen(charInput); k++) { // Проходим по служебным символам строки charInput
|
||||
if (i[j]==charInput[k]) { // Если символы обеих строк совпали, то ...
|
||||
if(k>0){n++;} if(k>9){n++;} if(k>11){n++;} // Увеличиваем размер (n) в соостветствии со значениём найденного служебного символа
|
||||
}}}
|
||||
// Выделяем блок памяти под строку с ответом:
|
||||
free(charReturn); // Освобождаем ранее созданный блок памяти
|
||||
charReturn = (char*) malloc(n); // Выделяем новый блок памяти размером n байт
|
||||
// Заполняем выделенный блок памяти:
|
||||
n=0; // Определяем позицию в блоке памяти для следующего подставляемого значения
|
||||
for(j=0; j<strlen(i); j++) { // Проходим по символам полученной строки
|
||||
if(i[j]==charInput[0] /* w */ ) {funcFillChar( weekday ,0,n,7); n+=1;}else // Подставляем день недели от 0 до 6 (один знак: 0-воскресенье, 6-суббота)
|
||||
if(i[j]==charInput[1] /* a */ ) {funcFillChar( midday*2 ,2,n,8); n+=2;}else // Подставляем полдень am или pm (два знака, в нижнем регистре)
|
||||
if(i[j]==charInput[2] /* A */ ) {funcFillChar((midday+2)*2 ,2,n,8); n+=2;}else // Подставляем полдень AM или PM (два знака, в верхнем регистре)
|
||||
if(i[j]==charInput[3] /* d */ ) {funcFillChar( day ,1,n,4); n+=2;}else // Подставляем день месяца от 01 до 31 (два знака)
|
||||
if(i[j]==charInput[4] /* h */ ) {funcFillChar( hours ,1,n,3); n+=2;}else // Подставляем часы от 01 до 12 (два знака)
|
||||
if(i[j]==charInput[5] /* H */ ) {funcFillChar( Hours ,1,n,3); n+=2;}else // Подставляем часы от 00 до 23 (два знака)
|
||||
if(i[j]==charInput[6] /* i */ ) {funcFillChar( minutes ,1,n,2); n+=2;}else // Подставляем минуты от 00 до 59 (два знака)
|
||||
if(i[j]==charInput[7] /* m */ ) {funcFillChar( month ,1,n,5); n+=2;}else // Подставляем месяц от 01 до 12 (два знака)
|
||||
if(i[j]==charInput[8] /* s */ ) {funcFillChar( seconds ,1,n,1); n+=2;}else // Подставляем секунды от 00 до 59 (два знака)
|
||||
if(i[j]==charInput[9] /* y */ ) {funcFillChar( year ,1,n,6); n+=2;}else // Подставляем год от 00 до 99 (два знака)
|
||||
if(i[j]==charInput[10] /* M */ ) {funcFillChar((month+6)*3 ,3,n,5); n+=3;}else // Подставляем имя месяца от Jan до Dec (три знака: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)
|
||||
if(i[j]==charInput[11] /* D */ ) {funcFillChar( weekday*3 ,3,n,7); n+=3;}else // Подставляем имя деня недели от Mon до Sun (три знака: Mon Tue Wed Thu Fri Sat Sun)
|
||||
if(i[j]==charInput[12] /* Y */ ) {funcFillChar( year ,4,n,6); n+=4;}else // Подставляем год от 2000 до 2099 (четыре знака)
|
||||
{charReturn[n]=i[j]; n+=1;} // Если символ полученной строки не совпал со служебными, то подставляем его в блок памяти как есть, без изменений
|
||||
} charReturn[n]='\0'; return charReturn; // Устанавливаем символ конца строки и возвращаем указатель на блок памяти с результатом
|
||||
}
|
||||
|
||||
// Заполняем значением определённую позицию блока памяти:
|
||||
void iarduino_RTC::funcFillChar(uint8_t i, uint8_t j, uint8_t n, uint8_t k){ // (данные, тип данных, позиция для вставки, мигание)
|
||||
bool f=valBlink==k; if((millis()%valFrequency)<(valFrequency/2)){f=false;} // Устанавливаем флаг мигания, если значение valBlink равно значению параметра k
|
||||
switch (j){
|
||||
/* 1 знак */ case 0: if(i>6 ){i=6; } charReturn[n]=f?32:i+48; break;
|
||||
/* 2 знака */ case 1: if(i>99){i=99;} charReturn[n]=f?32:i/10+48; charReturn[n+1]=f?32:i%10+48; break;
|
||||
/* AM / PM */ case 2: if(i>6 ){i=6; } charReturn[n]=f?32:charMidday[i]; charReturn[n+1]=f?32:charMidday[i+1]; break;
|
||||
/* дн / мес */ case 3: if(i>54){i=54;} charReturn[n]=f?32:charDayMon[i]; charReturn[n+1]=f?32:charDayMon[i+1]; charReturn[n+2]=f?32:charDayMon[i+2]; break;
|
||||
/* 4 знака */ case 4: if(i>99){i=99;} charReturn[n]=f?32:(valCentury-1)/10+48; charReturn[n+1]=f?32:(valCentury-1)%10+48; charReturn[n+2]=f?32:i/10+48; charReturn[n+3]=f?32:i%10+48; break;
|
||||
}
|
||||
}
|
||||
|
||||
// Установка даты и времени
|
||||
void iarduino_RTC::settime(int i1, int i2, int i3, int i4, int i5, int i6, int i7){ // (сек, мин, час, день, мес, год, день_недели)
|
||||
funcWriteTime(i1, i2, i3, i4, i5, i6, i7); // Записываем дату и время в регистры модуля
|
||||
funcReadTime(); // Читаем дату и время из регистров модуля
|
||||
funcSetMoreTime(); // Корректируем переменные не читаемые из модуля (hours, midday)
|
||||
}
|
||||
|
||||
// Установка даты и времени от начала эпохи Unix
|
||||
void iarduino_RTC::settimeUnix(uint32_t i){ // (сек)
|
||||
uint32_t j; uint8_t k; bool f=true; // Объявляем временные переменные.
|
||||
seconds = i % 60; // Получаем текущее значение секунд. (остаток от деления секунд прошедших с начала эпохи Unix на количество секунд в минуте)
|
||||
i = (i-seconds) / 60; // Получаем количество минут прошедших с начала эпохи Unix.
|
||||
minutes = i % 60; // Получаем текущее значение минут. (остаток от деления минут прошедших с начала эпохи Unix на количество минут в часе)
|
||||
i = (i-minutes) / 60; // Получаем количество часов прошедших с начала эпохи Unix.
|
||||
Hours = i % 24; // Получаем текущее значение часов. (остаток от деления часов прошедших с начала эпохи Unix на количество часов в дне)
|
||||
i = (i-Hours) / 24; // Получаем количество дней прошедших с начала эпохи Unix.
|
||||
j = 0; while((((j+1)*365)+((j+2)/4))<=i){j++;} // Получаем количество лет прошедших с начала эпохи Unix.
|
||||
weekday = (i+4) % 7; // Получаем текущий день недели. (0-воскресенье, 1-понедельник, ... , 6-суббота)
|
||||
i = i - (j*365) - ((j+1)/4); // Получаем количество дней прошедших в текущем году.
|
||||
valCentury = ((1970+j)/100)+1; // Получаем текущий век.
|
||||
year = (1970+j)%100; // Получаем две последние цифры текущего года.
|
||||
k = ((1970+j)%4)==0?29:28; // Получаем количество дней в феврале текущего года.
|
||||
month = 0; while(f){month++; j=month; j=(((j+1)%2)^(j<8))?31:(j==2?k:30); if(i>=j){i-=j;}else{f=false;}}
|
||||
day = i+1; // Получаем текущий день.
|
||||
// Устанавливаем время:
|
||||
settime(seconds, minutes, Hours, day, month, year, weekday);
|
||||
}
|
||||
|
||||
// Чтение даты и времени в переменные из регистров модуля:
|
||||
void iarduino_RTC::funcReadTime(void){ // (без параметров)
|
||||
seconds = arrCalculationTime[0] = funcConvertCodeToNum(objClass -> funcReadTimeIndex(0)); // Получаем секунды
|
||||
minutes = arrCalculationTime[1] = funcConvertCodeToNum(objClass -> funcReadTimeIndex(1)); // Получаем минуты
|
||||
Hours = arrCalculationTime[2] = funcConvertCodeToNum(objClass -> funcReadTimeIndex(2)); // Получаем часы
|
||||
day = arrCalculationTime[3] = funcConvertCodeToNum(objClass -> funcReadTimeIndex(3)); // Получаем день
|
||||
month = arrCalculationTime[4] = funcConvertCodeToNum(objClass -> funcReadTimeIndex(4)); // Получаем месяц
|
||||
year = arrCalculationTime[5] = funcConvertCodeToNum(objClass -> funcReadTimeIndex(5)); // Получаем год
|
||||
weekday = arrCalculationTime[6] = funcConvertCodeToNum(objClass -> funcReadTimeIndex(6))-1; // Получаем день недели (в регистре значение от 1 до 7, а в переменной от 0 до 6)
|
||||
Unix = funcCalculationUnix(); // Получаем количество секунд (прошедших с начала эпохи Unix)
|
||||
valRequest = millis(); // Сохраняем время данного запроса
|
||||
}
|
||||
|
||||
// Запись даты и времени в регистры модуля:
|
||||
void iarduino_RTC::funcWriteTime(int i1, int i2, int i3, int i4, int i5, int i6, int i7){ //
|
||||
if(i1<=60 && i1>=0){objClass -> funcWriteTimeIndex(0, funcConvertNumToCode(i1 ));} // Сохраняем секунды
|
||||
if(i2<=60 && i2>=0){objClass -> funcWriteTimeIndex(1, funcConvertNumToCode(i2 ));} // Сохраняем минуты
|
||||
if(i3<=23 && i3>=0){objClass -> funcWriteTimeIndex(2, funcConvertNumToCode(i3 ));} // Сохраняем часы
|
||||
if(i4<=31 && i4>=1){objClass -> funcWriteTimeIndex(3, funcConvertNumToCode(i4 ));} // Сохраняем день
|
||||
if(i5<=12 && i5>=1){objClass -> funcWriteTimeIndex(4, funcConvertNumToCode(i5 ));} // Сохраняем месяц
|
||||
if(i6<=99 && i6>=0){objClass -> funcWriteTimeIndex(5, funcConvertNumToCode(i6 ));} // Сохраняем год
|
||||
if(i7<= 6 && i7>=0){objClass -> funcWriteTimeIndex(6, funcConvertNumToCode(i7+1));} // Сохраняем день недели (в регистре значение от 1 до 7, а в переменной от 0 до 6)
|
||||
}
|
||||
|
||||
// Расчёт времени без обращения к модулю:
|
||||
void iarduino_RTC::funcCalculationTime(void){ // (без параметров)
|
||||
uint32_t i=(millis()-valRequest)/1000; // Определяем количество секунд (прошедших после последнего обращения к модулю)
|
||||
uint8_t j=30 + ( (arrCalculationTime[4] + (arrCalculationTime[4]>7?1:0)) % 2 ); // Определяем количество дней в месяце (31, 30, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
|
||||
if(arrCalculationTime[4]==2){j=28+((((uint16_t)valCentury-1)*100+arrCalculationTime[5])%4?0:1);}// Если текущий месяц - февраль, то меняем на ... (31, 28/29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
|
||||
i+=arrCalculationTime[0]; seconds = i%60; i/=60; // Добавляем к прошедним секундам (i) посление прочитанные секунды (arrCalculationTime[0]), результатом будет остаток, а значение i превращаем в минуты
|
||||
i+=arrCalculationTime[1]; minutes = i%60; i/=60; // Добавляем к прошедним минутам (i) посление прочитанные минуты (arrCalculationTime[1]), результатом будет остаток, а значение i превращаем в часы
|
||||
i+=arrCalculationTime[2]; Hours = i%24; i/=24; // Добавляем к прошедним часам (i) посление прочитанные часы (arrCalculationTime[2]), результатом будет остаток, а значение i превращаем в дни
|
||||
weekday = arrCalculationTime[6]+i; if(weekday>6){weekday=0;} // День недели увеличится на (i) от прочитанного дня недели (arrCalculationTime[6])
|
||||
i+=arrCalculationTime[3]; day = i%(j+1); i/=(j+1); day+=i; // Добавляем к прошедним дням (i) посление прочитанные дни (arrCalculationTime[3]), результатом будет остаток, а значение i превращаем в месяцы
|
||||
i+=arrCalculationTime[4]; month = i%13; i/=13; month+=i; // Добавляем к прошедним месяцам (i) посление прочитанные месяцы (arrCalculationTime[4]), результатом будет остаток, а значение i превращаем в годы
|
||||
i+=arrCalculationTime[5]; year = i%100; // Добавляем к прошедним годам (i) посление прочитанные годы (arrCalculationTime[5]), результатом будет остаток, а значение i превращаем в дни
|
||||
Unix = funcCalculationUnix(); // Получаем количество секунд прошедших с начала эпохи Unix
|
||||
}
|
||||
|
||||
// Расчёт количества cекунд прошедших с начала эпохи Unix:
|
||||
uint32_t iarduino_RTC::funcCalculationUnix(void){ // (без параметров)
|
||||
uint32_t i; // Объявляем переменную для хранения результата. (рассчёты производятся из значений переменных: seconds, minutes, Hours, day, month, year и valCentury).
|
||||
uint32_t j = (uint32_t)(valCentury-1) * 100 + year; // Определяем текущий год с учётом века. (valCentury - век, year - последние два знака текущего года).
|
||||
i = j - 1970; // Определяем количество прошедших лет (с 01.01.1970 г.)
|
||||
i = i * 365 + ((i+1)/4); // Определяем количество дней в прошедших годах ((i+1)/4) - количество прошедших високосных лет (без учёта текущего года).
|
||||
i += (month-1)*30 + ( (month + (month<9?0:1) )/2 ); // Добавляем количество дней в прошедших месяцах ((month+(month<9?0:1))/2) - количество прошедших месяцев текущего года, содержащих 31 день.
|
||||
i -= month>2? (j%4==0?1:2) : 0; // Вычитаем 1 или 2 дня из февраля текущего года ((month>2) - если февраль уже прошел, j%4==0 - если текущий год високосный)
|
||||
i += day-1; // Добавляем количество прошедших дней этого месяца
|
||||
i *= 86400; // Получаем количество секунд прошедших дней
|
||||
i += (uint32_t)Hours * 3600 + (uint32_t)minutes * 60 + seconds; // Добавляем количество секунд текущего дня
|
||||
return i; // Возвращаем результат
|
||||
}
|
||||
107
lib/iarduino_RTC/src/iarduino_RTC.h
Normal file
107
lib/iarduino_RTC/src/iarduino_RTC.h
Normal file
@@ -0,0 +1,107 @@
|
||||
// Библиотека для работы с часами реального времени: (на чипе DS1302) https://iarduino.ru/shop/Expansion-payments/rtc-modul-ds1302.html
|
||||
// (на чипе DS1307) https://iarduino.ru/shop/Expansion-payments/kroshechnye-rtc-modul-realnogo-vremeni.html
|
||||
// https://iarduino.ru/shop/Expansion-payments/chasy-realnogo-vremeni-rtc-trema-modul.html
|
||||
// (на чипе DS3231) https://iarduino.ru/shop/Expansion-payments/chasy-realnogo-vremeni-ds3231.html
|
||||
// https://iarduino.ru/shop/Expansion-payments/chasy-realnogo-vremeni-rtc-trema-modul-v2-0.html
|
||||
// (на чипе RX8025)
|
||||
// Версия: 2.0.0
|
||||
// Последнюю версию библиотеки Вы можете скачать по ссылке: https://iarduino.ru/file/235.html
|
||||
// Подробное описание функции бибилиотеки доступно по ссылке: https://wiki.iarduino.ru/page/chasy-realnogo-vremeni-rtc-trema-modul/
|
||||
// Библиотека является собственностью интернет магазина iarduino.ru и может свободно использоваться и распространяться!
|
||||
// При публикации устройств или скетчей с использованием данной библиотеки, как целиком, так и её частей,
|
||||
// в том числе и в некоммерческих целях, просим Вас опубликовать ссылку: https://iarduino.ru
|
||||
// Автор библиотеки: Панькин Павел
|
||||
// Если у Вас возникли технические вопросы, напишите нам: shop@iarduino.ru
|
||||
|
||||
#ifndef iarduino_RTC_h //
|
||||
#define iarduino_RTC_h //
|
||||
//
|
||||
#define RTC_UNDEFINED 0 // Модуль часов реального времени не определён
|
||||
//
|
||||
#if defined(ARDUINO) && (ARDUINO >= 100) //
|
||||
#include <Arduino.h> //
|
||||
#else //
|
||||
#include <WProgram.h> //
|
||||
#endif //
|
||||
//
|
||||
#include "memorysaver.h" // Подключаем файл «хранитель памяти» (внутри файла есть комментарий поясняющий как сэкономить мапять)
|
||||
//
|
||||
class iarduino_RTC_BASE{ // Объявляем полиморфный класс
|
||||
public: //
|
||||
virtual void begin (void); // Объявляем функцию инициализации модуля (без параметров)
|
||||
virtual uint8_t funcReadTimeIndex (uint8_t); // Объявляем функцию чтения 1 значения из регистров даты и времени (0-секунды / 1-минуты / 2-часы / 3-день / 4-месяц / 5-год / 6-день недели)
|
||||
virtual void funcWriteTimeIndex (uint8_t, uint8_t); // Объявляем функцию записи 1 значения в регистры даты и времени (0-секунды / 1-минуты / 2-часы / 3-день / 4-месяц / 5-год / 6-день недели, значение)
|
||||
}; //
|
||||
//
|
||||
#include "iarduino_RTC_DS1302.h" // Подключаем файл iarduino_RTC_DS1302.h
|
||||
#include "iarduino_RTC_DS1307.h" // Подключаем файл iarduino_RTC_DS1307.h
|
||||
#include "iarduino_RTC_DS3231.h" // Подключаем файл iarduino_RTC_DS3231.h
|
||||
#include "iarduino_RTC_RX8025.h" // Подключаем файл iarduino_RTC_RX8025.h
|
||||
//
|
||||
class iarduino_RTC{ //
|
||||
public: //
|
||||
/** Конструктор класса **/ //
|
||||
iarduino_RTC(uint8_t i, uint8_t j=SS, uint8_t k=SCK, uint8_t n=MOSI){ // Конструктор основного класса (название [, вывод SS/RST [, вывод SCK/CLK [, вывод MOSI/DAT]]])
|
||||
switch(i){ // Тип выбранного модуля
|
||||
#ifdef RTC_ENABLE_DS1302 //
|
||||
case RTC_DS1302: objClass = new iarduino_RTC_DS1302(j,k,n); break; // Если используется модуль на базе чипа DS1302, то присваеиваем указателю objClass ссылку на новый объект производного класса iarduino_RTC_DS1302 переопределяя на него все виртуальные функции полиморфного класса iarduino_RTC_BASE
|
||||
#endif //
|
||||
#ifdef RTC_ENABLE_DS1307 //
|
||||
case RTC_DS1307: objClass = new iarduino_RTC_DS1307; break; // Если используется модуль на базе чипа DS1307, то присваеиваем указателю objClass ссылку на новый объект производного класса iarduino_RTC_DS1307 переопределяя на него все виртуальные функции полиморфного класса iarduino_RTC_BASE
|
||||
#endif //
|
||||
#ifdef RTC_ENABLE_DS3231 //
|
||||
case RTC_DS3231: objClass = new iarduino_RTC_DS3231; break; // Если используется модуль на базе чипа DS3231, то присваеиваем указателю objClass ссылку на новый объект производного класса iarduino_RTC_DS3231 переопределяя на него все виртуальные функции полиморфного класса iarduino_RTC_BASE
|
||||
#endif //
|
||||
#ifdef RTC_ENABLE_RX8025 //
|
||||
case RTC_RX8025: objClass = new iarduino_RTC_RX8025; break; // Если используется модуль на базе чипа RX8025, то присваеиваем указателю objClass ссылку на новый объект производного класса iarduino_RTC_RX8025 переопределяя на него все виртуальные функции полиморфного класса iarduino_RTC_BASE
|
||||
#endif //
|
||||
} //
|
||||
} //
|
||||
/** Пользовательские функции **/ //
|
||||
void begin (void) {objClass -> begin(); gettime();} // Определяем функцию инициализации модуля (без параметров)
|
||||
void period (uint8_t i) {valPeriod=i; valPeriod*=60000;} // Определяем функцию задания минимального периода обращения к модулю (i = период в минутах)
|
||||
void blinktime (uint8_t i, float j=1) {valBlink=i; valFrequency=uint32_t(1000/j);} // Определяем функцию позволяющую мигать одним из параметров времени (i = 0-нет / 1-сек / 2-мин / 3-час / 4-день / 5-мес / 6-год / 7-день_недели / 8-полдень , j = частота мигания в Гц)
|
||||
void gettime (void) {gettime("");} // Определяем функцию получения даты и времени из переменных (без параметров)
|
||||
char* gettime (String); // Объявляем функцию «дублёр» получения даты и времени из переменных (строка с параметрами)
|
||||
char* gettime (const char*); // Объявляем функцию получения даты и времени ввиде строки (строка с параметрами)
|
||||
void settime (int, int=-1, int=-1, int=-1, int=-1, int=-1, int=-1); // Объявляем функцию установки даты и времени (сек, мин, час, день, мес, год, день_недели)
|
||||
uint32_t gettimeUnix (void) {gettime(""); return Unix;} // Определяем функцию получения cекунд прошедших с начала эпохи Unix (без параметров)
|
||||
void settimeUnix (uint32_t); // Объявляем функцию установки cекунд прошедших с начала эпохи Unix (сек)
|
||||
//
|
||||
/** Переменные доступные для пользователя **/ //
|
||||
uint8_t seconds = 0; // Секунды 0-59
|
||||
uint8_t minutes = 0; // Минуты 0-59
|
||||
uint8_t hours = 1; // Часы 1-12
|
||||
uint8_t Hours = 0; // Часы 0-23
|
||||
uint8_t midday = 0; // Полдень 0-1 (0-am, 1-pm)
|
||||
uint8_t day = 1; // День месяца 1-31
|
||||
uint8_t weekday = 0; // День недели 0-6 (0-воскресенье, 1-понедельник, ... , 6-суббота)
|
||||
uint8_t month = 1; // Месяц 1-12
|
||||
uint8_t year = 0; // Год 0-99 (без учёта века)
|
||||
uint32_t Unix = 0; // Секунды прошедшие с начала эпохи Unix (01.01.1970 00:00:00 GMT)
|
||||
//
|
||||
/** Внутренние переменные **/ //
|
||||
iarduino_RTC_BASE* objClass; // Объявляем указатель на объект полиморфного класса (функции данного класса будут переопределены, т.к. указателю будет присвоена ссылка на производный класс)
|
||||
char* charReturn = (char*) malloc(1); // Определяем указатель на символьную область памяти в 1 байт (указатель будет ссылаться на строку вывода времени)
|
||||
const char* charInput = "waAdhHimsyMDY"; // Определяем константу-строку с символами требующими замены (данные символы заменяются функцией gettime на значение времени)
|
||||
const char* charMidday = "ampmAMPM"; // Определяем константу-строку для вывода полудня (am / pm / AM / PM)
|
||||
const char* charDayMon = "SunMonTueWedThuFriSatJanFebMarAprMayJunJulAugSepOctNovDec"; // Определяем константу-строку для вывода дня недели или месяца (Mon ... Sun / Jan ... Dec)
|
||||
uint8_t arrCalculationTime[7]; // Объявляем массив для рассчёта времени без обращения к модулю (для хранения последних, прочитанных из модуля, значений даты и времени)
|
||||
uint8_t valBlink = 0; // Определяем параметр времени, который должен мигать (1-сек / 2-мин / 3-час / 4-день / 5-мес / 6-год / 7-день_недели / 8-полдень)
|
||||
uint32_t valFrequency = 1000; // Определяем частоту мигания параметра времени для функции blinktime (по умолчанию 1 Гц)
|
||||
uint8_t valCentury = 21; // Определяем переменную для хранения текущего века (по умолчанию 21 век)
|
||||
uint16_t valPeriod = 0; // Определяем минимальный период опроса модуля (в минутах, от 00 до 255)
|
||||
uint32_t valRequest = 0; // Определяем время последнего чтения регистров времени
|
||||
private: //
|
||||
/** Внутренние функции **/ //
|
||||
void funcReadTime (void); // Объявляем функцию чтения даты и времени из регистров модуля (без параметров)
|
||||
void funcWriteTime (int, int, int, int, int, int, int); // Объявляем функцию записи даты и времени в регистры модуля (без параметров)
|
||||
uint8_t funcConvertCodeToNum (uint8_t i) {return (i >> 4)*10 + (i & 0x0F);} // Определяем функцию преобразования двоично-десятичного кода в число (код)
|
||||
uint8_t funcConvertNumToCode (uint8_t i) {return ((i/10) << 4) + (i%10);} // Определяем функцию преобразования числа в двоично-десятичный код (число)
|
||||
void funcSetMoreTime (void){hours=(Hours%12)?(Hours%12):12; midday=(Hours<12)?0:1;} // Корректировка переменных не читаемых из модуля (без параметров)
|
||||
void funcCalculationTime (void); // Объявляем функцию расчёта времени без обращения к модулю (без параметров)
|
||||
uint32_t funcCalculationUnix (void); // Объявляем функцию расчёта cекунд прошедших с начала эпохи Unix (без параметров)
|
||||
void funcFillChar (uint8_t, uint8_t, uint8_t, uint8_t); // Объявляем функцию заполнения строки вывода времени (данные, тип данных, позиция для вставки, мигание)
|
||||
}; //
|
||||
//
|
||||
#endif //
|
||||
67
lib/iarduino_RTC/src/iarduino_RTC_DS1302.h
Normal file
67
lib/iarduino_RTC/src/iarduino_RTC_DS1302.h
Normal file
@@ -0,0 +1,67 @@
|
||||
#ifndef iarduino_RTC_DS1302_h //
|
||||
#define iarduino_RTC_DS1302_h //
|
||||
#define RTC_DS1302 1 // Модуль часов реального времени с протоколом передачи данных SI3, памятью 040x8 (31 байт которой доступны для хранения данных пользователя)
|
||||
//
|
||||
class iarduino_RTC_DS1302: public iarduino_RTC_BASE{ //
|
||||
public: //
|
||||
/** Конструктор класса **/ //
|
||||
iarduino_RTC_DS1302(uint8_t i=SS, uint8_t j=SCK, uint8_t k=MOSI){pinRES=i; pinCLK=j; pinDAT=k;} // (вывод RST, вывод CLK, вывод DAT)
|
||||
/** функции доступные пользователю **/ //
|
||||
// Инициализация модуля: //
|
||||
void begin(void){ // (без параметров)
|
||||
// Инициализация работы с трехпроводной шиной: //
|
||||
funcBegin(); // (без параметров)
|
||||
// Установка флагов управления и состояния модуля: //
|
||||
varI=funcReadReg(0x81); if( varI & 0b10000000){funcWriteReg(0x81, (varI&~0b10000000));} // (если установлен 7 бит в 129 регистре, то сбрасываем его - запускаем генератор)
|
||||
varI=funcReadReg(0x85); if( varI & 0b10000000){funcWriteReg(0x85, (varI&~0b10000000));} // (если установлен 7 бит в 133 регистре, то сбрасываем его - переводим модуль в 24 часовой режим)
|
||||
varI=funcReadReg(0x8F); if( varI & 0b10000000){funcWriteReg(0x8F, (varI&~0b10000000));} // (если установлен 7 бит в 143 регистре, то сбрасываем его - разрешаем запись в регистры модуля)
|
||||
} //
|
||||
//
|
||||
// Чтение одного значения из регистров даты и времени модуля: //
|
||||
uint8_t funcReadTimeIndex(uint8_t i){ // (i = 0-секунды / 1-минуты / 2-часы / 3-день / 4-месяц / 5-год / 6-день недели)
|
||||
delay(1); return funcReadReg(arrTimeRegAddr[i]) & arrTimeRegMack[i]; //
|
||||
} //
|
||||
//
|
||||
// Запись одного значения в регистры даты и времени модуля: //
|
||||
void funcWriteTimeIndex(uint8_t i, uint8_t j){ // (i = 0-секунды / 1-минуты / 2-часы / 3-день / 4-месяц / 5-год / 6-день недели, j = значение)
|
||||
varI=funcReadTimeIndex(i); // Читаем данные из регистра i
|
||||
j |= ~arrTimeRegMack[i] & varI; // Устанавливаем биты значения j по маске arrTimeRegMack[i] в прочитанные из регистра i
|
||||
j &= arrTimeRegMack[i] | varI; // Сбрасываем биты значения j по маске arrTimeRegMack[i] в прочитанные из регистра i
|
||||
funcWriteReg(arrTimeRegAddr[i], j); // Сохраняем значение j в регистр arrTimeRegAddr[i]
|
||||
} //
|
||||
//
|
||||
private: //
|
||||
/** Внутренние переменные **/ //
|
||||
uint8_t pinRES = 0; // Определяем переменную для хранения номера вывода RST трехпроводной шины
|
||||
uint8_t pinCLK = 0; // Определяем переменную для хранения номера вывода CLK трехпроводной шины
|
||||
uint8_t pinDAT = 0; // Определяем переменную для хранения номера вывода DAT трехпроводной шины
|
||||
uint8_t arrTimeRegAddr[7] = {0x81,0x83,0x85,0x87,0x89,0x8D,0x8B}; // Определяем массив с адресами регистров чтения даты и времени (сек, мин, час, день, месяц, год, день недели)
|
||||
uint8_t arrTimeRegMack[7] = {0x7F,0x7F,0x3F,0x3F,0x1F,0xFF,0x07}; // Определяем маскировочный массив для регистров даты и времени (при чтении/записи, нужно совершить побитовое «и»)
|
||||
uint8_t busRate = 10; // Скорость передачи данных трехпроводной шине в кГц (до 255 кГц)
|
||||
uint8_t varI; //
|
||||
//
|
||||
/** Внутренние функции **/ //
|
||||
// Функция чтения данных из регистра модуля: //
|
||||
uint8_t funcReadReg(uint8_t i){ // Определяем функцию читения данных из регистра модуля (аргумент: адрес_регистра)
|
||||
varI=1; // Предустанавливаем переменную varI в значение 1, чтоб не вывести: 45 апреля 255 часов 127 минут и 200 секунд
|
||||
digitalWrite (pinRES, 1); // Устанавливаем линию RES в активное состояние
|
||||
funcWriteByte (i); // Отправляем адрес регистра
|
||||
varI=funcReadByte (true); // Читаем байт из регистра с учётом предустановленного бита
|
||||
digitalWrite (pinRES, 0); // Устанавливаем линию RES в неактивное состояние
|
||||
return varI; // Возвращаем значение переменной varI
|
||||
} //
|
||||
// Функция записи данных в регистр модуля: //
|
||||
void funcWriteReg(uint8_t i, uint8_t j){ // Определяем функцию записи данных в регистр модуля (аргументы: адрес_регистра, байт_данных)
|
||||
digitalWrite (pinRES, 1); // Устанавливаем линию RES в активное состояние
|
||||
funcWriteByte (i-1); // Отправляем адрес регистра (при чтении указывается адрес-1)
|
||||
funcWriteByte (j); // Отправляем байт данных
|
||||
digitalWrite (pinRES, 0); // Устанавливаем линию RES в неактивное состояние
|
||||
} //
|
||||
//
|
||||
/** функции для работы с трехпроводной шиной **/ //
|
||||
void funcWriteByte (uint8_t j) /* Передача одного байта (байт для передачи) */ {uint8_t i=0, n=500/busRate+1; pinMode(pinDAT, OUTPUT); while(i>=0 && i<8){digitalWrite(pinDAT, (j & _BV(i))); delayMicroseconds(n); digitalWrite(pinCLK, 1); delayMicroseconds(n); digitalWrite(pinCLK, 0); i++;} pinMode(pinDAT, INPUT);}
|
||||
uint8_t funcReadByte (bool j) /* Получение одного байта (флаг чтения предустановленного бита с линии DAT) */ {uint8_t i=0, k=0, n=500/busRate+1; pinMode(pinDAT, INPUT); if(j){if(digitalRead(pinDAT)){k |= _BV(i);} i++;} while(i>=0 && i<8){digitalWrite(pinCLK, 1); delayMicroseconds(n); digitalWrite(pinCLK, 0); delayMicroseconds(n); if(digitalRead(pinDAT)){k |= _BV(i);} i++;} return k;}
|
||||
void funcBegin (void) /* Подготовка выводов шины (без параметров) */ {pinMode(pinRES, OUTPUT); pinMode(pinCLK, OUTPUT); pinMode(pinDAT, INPUT); digitalWrite(pinCLK, 0); digitalWrite(pinRES, 0);}
|
||||
}; //
|
||||
//
|
||||
#endif //
|
||||
42
lib/iarduino_RTC/src/iarduino_RTC_DS1307.h
Normal file
42
lib/iarduino_RTC/src/iarduino_RTC_DS1307.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#ifndef iarduino_RTC_DS1307_h //
|
||||
#define iarduino_RTC_DS1307_h //
|
||||
#define RTC_DS1307 2 // Модуль часов реального времени с протоколом передачи данных I2C, памятью 064x8 (56 байт которой доступны для хранения данных пользователя)
|
||||
#include "iarduino_RTC_I2C.h" // Подключаем файл iarduino_RTC_I2C.h - для работы с шиной I2C
|
||||
//
|
||||
class iarduino_RTC_DS1307: public iarduino_RTC_BASE{ //
|
||||
public: //
|
||||
/** функции доступные пользователю **/ //
|
||||
// Инициализация модуля: //
|
||||
void begin(void){ // (без параметров)
|
||||
// Инициализация работы с шиной I2C: //
|
||||
objI2C.begin(100); // (скорость шины в кГц)
|
||||
// Установка флагов управления и состояния модуля: //
|
||||
varI=objI2C.readByte(valAddress, 0x00); if( varI & 0b10000000 ){objI2C.writeByte(valAddress, 0x00, (varI&~0b10000000) );} // (если установлен 7 бит в 0 регистре, то сбрасываем его - запускаем генератор)
|
||||
varI=objI2C.readByte(valAddress, 0x02); if( varI & 0b01000000 ){objI2C.writeByte(valAddress, 0x02, (varI&~0b01000000) );} // (если установлен 6 бит в 2 регистре, то сбрасываем его - переводим модуль в 24 часовой режим)
|
||||
varI=objI2C.readByte(valAddress, 0x07); if((varI & 0b00000011) || !(varI & 0b00010000)){objI2C.writeByte(valAddress, 0x07, (varI&~0b00000011)|0b00010000 );} // (если установлены 1 и 0 биты или сброшен 4 бит в 7 регистре, то сбрасываем 1 с 0 битами, а 4 устанавливаем - выводим меандр с частотой 1 Гц на выводе SQW/OUT модуля)
|
||||
} //
|
||||
//
|
||||
// Чтение одного значения из регистров даты и времени модуля: //
|
||||
uint8_t funcReadTimeIndex(uint8_t i){ // (i = 0-секунды / 1-минуты / 2-часы / 3-день / 4-месяц / 5-год / 6-день недели)
|
||||
delay(1); //
|
||||
return objI2C.readByte(valAddress, arrTimeRegAddr[i]) & arrTimeRegMack[i]; //
|
||||
} //
|
||||
//
|
||||
// Запись одного значения в регистры даты и времени модуля: //
|
||||
void funcWriteTimeIndex(uint8_t i, uint8_t j){ // (i = 0-секунды / 1-минуты / 2-часы / 3-день / 4-месяц / 5-год / 6-день недели, j = значение)
|
||||
varI=funcReadTimeIndex(i); // Читаем данные из регистра i
|
||||
j |= ~arrTimeRegMack[i] & varI; // Устанавливаем биты значения j по маске arrTimeRegMack[i] в прочитанные из регистра i
|
||||
j &= arrTimeRegMack[i] | varI; // Сбрасываем биты значения j по маске arrTimeRegMack[i] в прочитанные из регистра i
|
||||
objI2C.writeByte(valAddress, arrTimeRegAddr[i], j); // Сохраняем значение j в регистр arrTimeRegAddr[i]
|
||||
} //
|
||||
//
|
||||
private: //
|
||||
/** Внутренние переменные **/ //
|
||||
iarduino_I2C objI2C; // Создаём объект для работы с шиной I2C
|
||||
uint8_t valAddress = 0x68; // Адрес модуля на шине I2C
|
||||
uint8_t arrTimeRegAddr[7] = {0x00,0x01,0x02,0x04,0x05,0x06,0x03}; // Определяем массив с адресами регистров даты и времени (сек, мин, час, день, месяц, год, день недели)
|
||||
uint8_t arrTimeRegMack[7] = {0x7F,0x7F,0x3F,0x3F,0x1F,0xFF,0x07}; // Определяем маскировочный массив для регистров даты и времени (при чтении/записи, нужно совершить побитовое «и»)
|
||||
uint8_t varI; //
|
||||
}; //
|
||||
//
|
||||
#endif //
|
||||
42
lib/iarduino_RTC/src/iarduino_RTC_DS3231.h
Normal file
42
lib/iarduino_RTC/src/iarduino_RTC_DS3231.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#ifndef iarduino_RTC_DS3231_h //
|
||||
#define iarduino_RTC_DS3231_h //
|
||||
#define RTC_DS3231 3 // Модуль часов реального времени с протоколом передачи данных I2C, памятью 019x8, температурной компенсацией, двумя будильниками и встроенным кварцевым резонатором
|
||||
#include "iarduino_RTC_I2C.h" // Подключаем файл iarduino_RTC_I2C.h - для работы с шиной I2C
|
||||
//
|
||||
class iarduino_RTC_DS3231: public iarduino_RTC_BASE{ //
|
||||
public: //
|
||||
/** функции доступные пользователю **/ //
|
||||
// Инициализация модуля: //
|
||||
void begin(void){ // (без параметров)
|
||||
// Инициализация работы с шиной I2C: //
|
||||
objI2C.begin(100); // (скорость шины в кГц)
|
||||
// Установка флагов управления и состояния модуля: //
|
||||
varI=objI2C.readByte(valAddress, 0x02); if( varI & 0b01000000 ){objI2C.writeByte(valAddress, 0x02, (varI&~0b01000000) );} // (если установлен 6 бит в 2 регистре, то сбрасываем его - переводим модуль в 24 часовой режим)
|
||||
varI=objI2C.readByte(valAddress, 0x0E); if( varI & 0b11011111 ){objI2C.writeByte(valAddress, 0x0E, (varI&~0b11011111) );} // (если установлены 7,6,4,3,2,1 и 0 биты в 14 регистре, то сбрасываем их - разрешаем генератору работать от батарейки, запрещаем выводу SQW работать от батарейки, выводим меандр с частотой 1Гц на вывод SQW, переводим вывод INT/SQW в режим SQW, запрещаем прерывания будильников)
|
||||
varI=objI2C.readByte(valAddress, 0x0F); if((varI & 0b10000011) || !(varI & 0b00001000)){objI2C.writeByte(valAddress, 0x0F, (varI&~0b10000011)|0b00001000 );} // (если установлены 7,1 и 0 биты или сброшен 3 бит в 15 регистре, то сбрасываем 7,1 и 0 биты, а 3 устанавливаем - сбрасываем флаг остановки генератора, разрешаем меандр с частотой 32768Гц на выводе 32kHz, сбрасываем флаги будильников)
|
||||
} //
|
||||
//
|
||||
// Чтение одного значения из регистров даты и времени модуля: //
|
||||
uint8_t funcReadTimeIndex(uint8_t i){ // (i = 0-секунды / 1-минуты / 2-часы / 3-день / 4-месяц / 5-год / 6-день недели)
|
||||
delay(1); //
|
||||
return objI2C.readByte(valAddress, arrTimeRegAddr[i]) & arrTimeRegMack[i]; //
|
||||
} //
|
||||
//
|
||||
// Запись одного значения в регистры даты и времени модуля: //
|
||||
void funcWriteTimeIndex(uint8_t i, uint8_t j){ // (i = 0-секунды / 1-минуты / 2-часы / 3-день / 4-месяц / 5-год / 6-день недели, j = значение)
|
||||
varI=funcReadTimeIndex(i); // Читаем данные из регистра i
|
||||
j |= ~arrTimeRegMack[i] & varI; // Устанавливаем биты значения j по маске arrTimeRegMack[i] в прочитанные из регистра i
|
||||
j &= arrTimeRegMack[i] | varI; // Сбрасываем биты значения j по маске arrTimeRegMack[i] в прочитанные из регистра i
|
||||
objI2C.writeByte(valAddress, arrTimeRegAddr[i], j); // Сохраняем значение j в регистр arrTimeRegAddr[i]
|
||||
} //
|
||||
//
|
||||
private: //
|
||||
/** Внутренние переменные **/ //
|
||||
iarduino_I2C objI2C; // Создаём объект для работы с шиной I2C
|
||||
uint8_t valAddress = 0x68; // Адрес модуля на шине I2C
|
||||
uint8_t arrTimeRegAddr[7] = {0x00,0x01,0x02,0x04,0x05,0x06,0x03}; // Определяем массив с адресами регистров даты и времени (сек, мин, час, день, месяц, год, день недели)
|
||||
uint8_t arrTimeRegMack[7] = {0x7F,0x7F,0x3F,0x3F,0x1F,0xFF,0x07}; // Определяем маскировочный массив для регистров даты и времени (при чтении/записи, нужно совершить побитовое «и»)
|
||||
uint8_t varI; //
|
||||
}; //
|
||||
//
|
||||
#endif //
|
||||
461
lib/iarduino_RTC/src/iarduino_RTC_I2C.h
Normal file
461
lib/iarduino_RTC/src/iarduino_RTC_I2C.h
Normal file
@@ -0,0 +1,461 @@
|
||||
#ifndef iarduino_I2C_h // Разрешаем включить данный код в скетч, только если он не был включён ранее
|
||||
#define iarduino_I2C_h // Запрещаем повторное включение данного кода в скетч
|
||||
//
|
||||
// Определяем тип реализации шины I2C: //
|
||||
#define iarduino_I2C_SW // Объявляем константу iarduino_I2C_SW - Возможна программная реализация шины I2C.
|
||||
#if (!defined(pin_SW_SDA) || !defined(pin_SW_SCL)) // Если выводы не определены пользователем, то ...
|
||||
#undef iarduino_I2C_SW // Отменяем объявление константы iarduino_I2C_SW - Программная реализация шины I2C не возможна (так как выводы не указаны).
|
||||
#if defined(ESP8266) || defined(ESP32) // Если используются указанные платы, то ...
|
||||
#include <Wire.h> // Подключаем библиотеку Wire.
|
||||
#define pin_SW_SDA 255 // № вывода SDA не определён
|
||||
#define pin_SW_SCL 255 // № вывода SCL не определён
|
||||
#define iarduino_I2C_TW // Объявляем константу iarduino_I2C_TW - Будет использована аппаратная реализация шины I2C под управлением библиотеки Wire.
|
||||
#elif defined(TwoWire_h) // Проверяем не подключена ли библиотека Wire.
|
||||
#define pin_SW_SDA 255 // № вывода SDA не определён
|
||||
#define pin_SW_SCL 255 // № вывода SCL не определён
|
||||
#define iarduino_I2C_TW // Объявляем константу iarduino_I2C_TW - Будет использована аппаратная реализация шины I2C под управлением библиотеки Wire.
|
||||
#elif (defined(SDA) && defined(SCL)) // Определяем выводы для шины I2C
|
||||
#define pin_SW_SDA SDA // № вывода SDA = SDA
|
||||
#define pin_SW_SCL SCL // № вывода SCL = SCL
|
||||
#define iarduino_I2C_HW // Объявляем константу iarduino_I2C_HW - Будет использована аппаратная реализация шины I2C.
|
||||
#elif (defined(PIN_WIRE_SDA) && defined(PIN_WIRE_SCL)) // Определяем выводы для шины I2C
|
||||
#define pin_SW_SDA PIN_WIRE_SDA // № вывода SDA = PIN_WIRE_SDA
|
||||
#define pin_SW_SCL PIN_WIRE_SCL // № вывода SCL = PIN_WIRE_SCL
|
||||
#define iarduino_I2C_HW // Объявляем константу iarduino_I2C_HW - Будет использована аппаратная реализация шины I2C.
|
||||
#elif (defined(SDA1) && defined(SCL1)) // Определяем выводы для шины I2C-1
|
||||
#define pin_SW_SDA SDA1 // № вывода SDA = SDA1
|
||||
#define pin_SW_SCL SCL1 // № вывода SCL = SCL1
|
||||
#define iarduino_I2C_HW_1 // Объявляем константу iarduino_I2C_HW_1 - Будет использована аппаратная реализация шины I2C-1.
|
||||
#else // Если выводы определить не удалось, то ...
|
||||
#define pin_SW_SDA 255 // № вывода SDA не определён - Аппаратная реализация шины I2C не возможна.
|
||||
#define pin_SW_SCL 255 // № вывода SCL не определён - Аппаратная реализация шины I2C не возможна.
|
||||
#endif //
|
||||
#endif //
|
||||
//
|
||||
class iarduino_I2C_BASE{ // Определяем полиморфный класс
|
||||
public: // Доступные методы и функции:
|
||||
// ОСНОВНЫЕ ФУНКЦИИ: (поддерживаются библиотекой Wire) //
|
||||
virtual void begin (uint32_t); // Объявляем функцию указания скорости шины I2C. Аргументы: скорость в кГц.
|
||||
virtual uint8_t readByte (uint8_t, uint8_t ); // Объявляем функцию чтения байта данных из регистра модуля. Аргументы: адрес_модуля, адрес_регистра. (адрес регистра указывает модулю, данные какого регистра требуется отправить мастеру)
|
||||
virtual bool writeByte (uint8_t, uint8_t, uint8_t); // Объявляем функцию записи байта данных в регистр модуля. Аргументы: адрес_модуля, адрес_регистра, байт_данных. (адрес регистра указывает модулю, в какой регистр требуется сохранить данные)
|
||||
virtual uint8_t readByte (uint8_t ); // Объявляем функцию чтения байта данных из модуля. Аргументы: адрес_модуля (функция отличается тем, что она не отправляет модулю адрес регистра)
|
||||
virtual bool writeByte (uint8_t, uint8_t); // Объявляем функцию записи байта данных в модуль. Аргументы: адрес_модуля, байт_данных. (функция отличается тем, что она не отправляет модулю адрес регистра)
|
||||
virtual bool readBytes (uint8_t, uint8_t, uint8_t*, uint8_t); // Объявляем функцию чтения байтов данных из регистров модуля. Аргументы: адрес_модуля, адрес_первого_регистра, указатель_на_массив, количество_байт. (адрес первого регистра указывает модулю, с какого регистра требуется начать передачу данных мастеру)
|
||||
virtual bool writeBytes (uint8_t, uint8_t, uint8_t*, uint8_t); // Объявляем функцию записи байтов данных в регистры модуля. Аргументы: адрес_модуля, адрес_первого_регистра, указатель_на_массив, количество_байт. (адрес первого регистра указывает модулю, начиная с какого регистра требуется сохранять данные)
|
||||
virtual bool readBytes (uint8_t, uint8_t*, uint8_t); // Объявляем функцию чтения байтов данных из модуля. Аргументы: адрес_модуля, указатель_на_массив, количество_байт. (функция отличается тем, что она не отправляет модулю адрес первого регистра, а начинает цикл чтения сразу после отправки адреса модуля.)
|
||||
virtual bool writeBytes (uint8_t, uint8_t*, uint8_t); // Объявляем функцию записи байтов данных в модуль. Аргументы: адрес_модуля, указатель_на_массив, количество_байт. (функция отличается тем, что после отправки адреса модуля она сразу начинает цикл отправки данных, без передачи адреса первого регистра.)
|
||||
// ДОПОЛНИТЕЛЬНЫЕ ФУНКЦИИ: (поддерживаются библиотекой Wire) //
|
||||
virtual uint8_t getType (void); // Объявляем функцию получения типа реализации шины I2C. Аргументы: отсутствуют.
|
||||
virtual bool checkAddress(uint8_t); // Объявляем функцию поиска модуля на шине I2C. Аргументы: адрес_модуля.
|
||||
// ФУНКЦИИ НИЖНЕГО УРОВНЯ: (не поддерживаются библиотекой Wire) //
|
||||
virtual bool start (void); // Объявляем функцию установки состояния START. Аргументы: отсутствуют.
|
||||
virtual bool reStart (void); // Объявляем функцию установки состояния RESTART. Аргументы: отсутствуют.
|
||||
virtual void stop (void); // Объявляем функцию установки состояния STOP. Аргументы: отсутствуют.
|
||||
virtual bool sendID (uint8_t, bool); // Объявляем функцию передачи адреса модуля. Аргументы: ID-адрес модуля, бит RW (0-запись, 1-чтение).
|
||||
virtual bool setByte (uint8_t); // Объявляем функцию передачи байта данных. Аргументы: байт для передачи.
|
||||
virtual uint8_t getByte (bool); // Объявляем функцию получения байта данных. Аргументы: бит подтверждения ACK/NACK
|
||||
private: //
|
||||
virtual bool setSCL (bool); // Объявляем функцию установки уровня на линии SCL. Аргументы: логический уровень.
|
||||
virtual void setSDA (bool); // Объявляем функцию установки уровня на линии SDA. Аргументы: логический уровень.
|
||||
virtual bool getSDA (void); // Объявляем функцию чтения уровня с линии SDA. Аргументы: отсутствуют.
|
||||
}; //
|
||||
//
|
||||
class iarduino_I2C: public iarduino_I2C_BASE{ // Определяем производный класс
|
||||
public: // Доступные методы и функции:
|
||||
//
|
||||
/** ОСНОВНЫЕ ФУНКЦИИ: **/ //
|
||||
//
|
||||
// Функция подготовки шины I2C: // Определяем функцию подготовки шины I2C.
|
||||
void begin(uint32_t speed){ // Аргумент: скорость шины в кГц.
|
||||
// _ _ _ _______ _ _ _ //
|
||||
// SCL: _?_?_/ OUTPUT //
|
||||
// _ _ _ _ _____ _ _ _ //
|
||||
// SDA: _?_?_ _/ OUTPUT //
|
||||
// //
|
||||
#if defined(iarduino_I2C_TW) //
|
||||
// Если используется шина I2C под управлением библиотеки Wire: //
|
||||
Wire.setClock(speed*1000L); // Устанавливаем скорость передачи данных по шине I2C.
|
||||
Wire.begin(); // Инициируем работу на шине I2C в качестве мастера.
|
||||
#elif defined(iarduino_I2C_HW) //
|
||||
// Если используется аппаратная шина I2C: //
|
||||
pinMode(pin_SDA, INPUT ); digitalWrite(pin_SDA, HIGH); // Определяем вывод pin_SDA как вход и подтягиваем его к Vcc.
|
||||
pinMode(pin_SCL, INPUT ); digitalWrite(pin_SCL, HIGH); // Определяем вывод pin_SCL как вход и подтягиваем его к Vcc.
|
||||
TWBR=((F_CPU/(speed*1000L))-16)/2; // Определяем значение регистра скорости связи TWBR: speed = F_CPU / (16 + 2 * TWBR * 4^TWPS). Значит TWBR = (F_CPU/speed - 16) / (2 * 4^TWPS), но так как биты предделителя TWPS мы далее сбросим в 0, то формула упростится до: TWBR = (F_CPU/speed - 16) / 2. Так как speed указана в кГц, а F_CPU в Гц, то умножаем speed на 1000.
|
||||
if(TWBR<10){TWBR=10;} // Если значение регистра скорости TWBR стало меньше 10 (параметр speed > 400 кГ) то оставляем значение этого регистра равным 10 иначе шина будет работать нестабильно.
|
||||
TWSR&=(~(_BV(TWPS1)|_BV(TWPS0))); // Определяем значение регистра статуса TWSR: оставляем все его биты не тронутыми, кроме двух битов предделитея TWPS сбрасывая их в 0.
|
||||
#elif defined(iarduino_I2C_SW) //
|
||||
// Если используется программная шина I2C: //
|
||||
port_SDA = digitalPinToPort (pin_SDA); // Определяем номер порта для вывода pin_SDA.
|
||||
port_SCL = digitalPinToPort (pin_SCL); // Определяем номер порта для вывода pin_SCL.
|
||||
mask_SDA = digitalPinToBitMask (pin_SDA); // Определяем маску для вывода pin_SDA. в переменной mask_SDA будет установлен только тот бит который соответствует позиции бита управления выводом pin_SDA.
|
||||
mask_SCL = digitalPinToBitMask (pin_SCL); // Определяем маску для вывода pin_SCL. в переменной mask_SCL будет установлен только тот бит который соответствует позиции бита управления выводом pin_SCL.
|
||||
mod_SDA = portModeRegister (port_SDA); // Определяем указатель на адрес регистра конфигурации направления работы выводов порта port_SDA.
|
||||
mod_SCL = portModeRegister (port_SCL); // Определяем указатель на адрес регистра конфигурации направления работы выводов порта port_SCL.
|
||||
inp_SDA = portInputRegister (port_SDA); // Определяем указатель на адрес регистра входных значений для управления портом port_SDA.
|
||||
inp_SCL = portInputRegister (port_SCL); // Определяем указатель на адрес регистра входных значений для управления портом port_SCL.
|
||||
out_SDA = portOutputRegister (port_SDA); // Определяем указатель на адрес регистра выходных значений для управления портом port_SDA.
|
||||
out_SCL = portOutputRegister (port_SCL); // Определяем указатель на адрес регистра выходных значений для управления портом port_SCL.
|
||||
setSCL(1); // Переводим вывод SCL в режим входа с подтяжкой к Vcc
|
||||
setSDA(1); // Переводим вывод SDA в режим входа с подтяжкой к Vcc
|
||||
#endif //
|
||||
} //
|
||||
//
|
||||
// Функция чтения одного байта из регистра модуля: //
|
||||
uint8_t readByte(uint8_t adr, uint8_t reg){ // Определяем функцию чтения одного байта данных из регистра модуля (аргументы: адрес_модуля, адрес_регистра)
|
||||
uint8_t i=0; readBytes(adr, reg, &i, 1); return i; // Объявляем переменную i и указываем её ссылку для получения 1 байта из регистра reg модуля с адресом adr
|
||||
} //
|
||||
//
|
||||
// Функция чтения одного байта из модуля: //
|
||||
uint8_t readByte(uint8_t adr){ // Определяем функцию чтения одного байта данных из регистра модуля (аргументы: адрес_модуля)
|
||||
uint8_t i=0; readBytes(adr, &i, 1); return i; // Объявляем переменную i и указываем её ссылку для получения 1 байта из модуля с адресом adr
|
||||
} //
|
||||
//
|
||||
// Функция записи одного байта в регистр модуля: //
|
||||
bool writeByte(uint8_t adr, uint8_t reg, uint8_t data){ // Определяем функцию записи одного байта данных в регистр модуля (аргументы: адрес_модуля, адрес_регистра, байт_данных)
|
||||
return writeBytes(adr, reg, &data, 1); // Запысываем 1 байт по ссылке на переменную data в регистр reg модуля с адресом adr
|
||||
} //
|
||||
//
|
||||
// Функция записи одного байта в модуль: //
|
||||
bool writeByte(uint8_t adr, uint8_t data){ // Определяем функцию записи одного байта данных в регистр модуля (аргументы: адрес_модуля, байт_данных)
|
||||
return writeBytes(adr, &data, 1); // Запысываем 1 байт по ссылке на переменную data в модуль с адресом adr
|
||||
} //
|
||||
//
|
||||
// Функция пакетного чтения нескольких байт данных из регистров модуля: //
|
||||
bool readBytes(uint8_t adr, uint8_t reg, uint8_t *data, uint8_t sum){ // Определяем функцию пакетного чтения нескольких байт данных из регистров модуля (аргументы: адрес_модуля, адрес_первого_регистра, указатель_на_массив, количество_байт)
|
||||
#if defined(iarduino_I2C_TW) //
|
||||
// Если используется шина I2C под управлением библиотеки Wire: //
|
||||
uint8_t i=0; // Предустанавливаем переменную i в значение 0 - это ответ по умолчанию.
|
||||
Wire.beginTransmission(adr); // Инициируем передачу данных по шине I2C к устройству с адресом adr и битом RW=0 => запись. При этом сама передача не начнётся.
|
||||
Wire.write(reg); // Определяем значение первого байта (reg - адреса регистра) который будет отправлен после байта адреса. Функция write() поместит указанный байт в буфер для передачи.
|
||||
i=Wire.endTransmission(false); if(i){return 0;} // Выполняем инициированную ранее передачу данных (без установки состояния STOP). Функция endTransmission() возвращает: 0-передача успешна / 1 - переполнен буфер для передачи / 2 - получен NACK при передаче адреса / 3 - получен NACK при передаче данных / 4 - другая ошибка.
|
||||
if(!Wire.requestFrom( adr, sum )) {return i;} // Читаем (запрашиваем) sum байт данных от устройства с адресом adr и битом RW=1 => чтение. Функция requestFrom() возвращает количество реально принятых байтов. Так как предыдущая функция не установила состояние STOP, то состояние START данной функции будет расценено как RESTART.
|
||||
while(Wire.available() && i<sum){data[i]=Wire.read(); i++;} // Читаем sum принятых байт из буфера для полученных данных в массив по указателю data.
|
||||
while(Wire.available()){Wire.read();}return i==sum; // Если в буфере для полученных данных есть еще принятые байты, то чистим буфер. Возвращаем true если удалось прочитать sum байт.
|
||||
#else //
|
||||
// Если шина управляется функциями нижнего уровня данного класса: //
|
||||
uint8_t i=0; // Предустанавливаем переменную i в значение 0 - это результат записи.
|
||||
if ( start () ) { i=1; // Если на шине I2C установилось состояние START, то ...
|
||||
if ( sendID (adr,0) ) { i=2; // Если модуль ответил ACK на получение адреса устройства adr с битом RW=0 (запись), то ...
|
||||
if ( setByte (reg) ) { i=3; // Если модуль ответил ACK на получение адреса регистра i, то ...
|
||||
if ( reStart () ) { i=4; // Если на шине I2C установилось состояние RESTART, то ...
|
||||
if ( sendID (adr,1) ) { i=5; // Если модуль ответил ACK на получение адреса устройства adr с битом RW=1 (чтение), то ...
|
||||
while(sum>0){ *data=getByte(sum>1); // Получаем по одному байту из очередного регистра за каждый проход цикла while. Прочитанный байт записываются по указателю data. Аргумент функции getByte имеет значение true на всех проходах цикла кроме последнего
|
||||
data++; sum--; // Увеличиваем адрес указателя data, и уменьшаем сумму прочитанных байт sum.
|
||||
#if defined(iarduino_I2C_HW) // Проверить корректность чтения каждого байта можно только на аппаратном уровне
|
||||
if (sum) { if(TWSR&0xF8!=0x50) { i=0;}} // Если после чтения очередного байта пакета значение регистра состояния шины I2C Arduino TWSR с маской 0xF8 не равно 0x50 значит произошла ошибка при чтении
|
||||
else { if(TWSR&0xF8!=0x58) { i=0;}} // Если после чтения последного байта пакета значение регистра состояния шины I2C Arduino TWSR с маской 0xF8 не равно 0x58 значит произошла ошибка при чтении
|
||||
#endif //
|
||||
}}}}}} stop (); return i==5; // Отправляем команду STOP и возвращаем результат успешности чтения
|
||||
#endif //
|
||||
} //
|
||||
//
|
||||
// Функция пакетного чтения нескольких байт данных из модуля: //
|
||||
bool readBytes(uint8_t adr, uint8_t *data, uint8_t sum){ // Определяем функцию пакетного чтения нескольких байт данных из модуля (аргументы: адрес_модуля, указатель_на_массив, количество_байт)
|
||||
#if defined(iarduino_I2C_TW) //
|
||||
// Если используется шина I2C под управлением библиотеки Wire: //
|
||||
uint8_t i=0; // Предустанавливаем переменную i в значение 0 - это ответ по умолчанию.
|
||||
if(!Wire.requestFrom( adr, sum )) {return i;} // Читаем (запрашиваем) sum байт данных от устройства с адресом adr и битом RW=1 => чтение. Функция requestFrom() возвращает количество реально принятых байтов.
|
||||
while(Wire.available() && i<sum){data[i]=Wire.read(); i++;} // Читаем sum принятых байт из буфера для полученных данных в массив по указателю data.
|
||||
while(Wire.available()){Wire.read();}return i==sum; // Если в буфере для полученных данных есть еще принятые байты, то чистим буфер. Возвращаем true если удалось прочитать sum байт.
|
||||
#else //
|
||||
// Если шина управляется функциями нижнего уровня данного класса: //
|
||||
uint8_t i=0; // Предустанавливаем переменную i в значение 0 - это результат записи.
|
||||
if ( start () ) { i=1; // Если на шине I2C установилось состояние START, то ...
|
||||
if ( sendID (adr,1) ) { i=2; // Если модуль ответил ACK на получение адреса устройства adr с битом RW=1 (чтение), то ...
|
||||
while(sum>0){ *data=getByte(sum>1); // Получаем по одному байту из очередного регистра за каждый проход цикла while. Прочитанный байт записываются по указателю data. Аргумент функции getByte имеет значение true на всех проходах цикла кроме последнего
|
||||
data++; sum--; // Увеличиваем адрес указателя data, и уменьшаем сумму прочитанных байт sum.
|
||||
#if defined(iarduino_I2C_HW) // Проверить корректность чтения каждого байта можно только на аппаратном уровне
|
||||
if (sum) { if(TWSR&0xF8!=0x50) { i=0;}} // Если после чтения очередного байта пакета значение регистра состояния шины I2C Arduino TWSR с маской 0xF8 не равно 0x50 значит произошла ошибка при чтении
|
||||
else { if(TWSR&0xF8!=0x58) { i=0;}} // Если после чтения последного байта пакета значение регистра состояния шины I2C Arduino TWSR с маской 0xF8 не равно 0x58 значит произошла ошибка при чтении
|
||||
#endif //
|
||||
}}} stop (); return i==2; // Отправляем команду STOP и возвращаем результат успешности чтения
|
||||
#endif //
|
||||
} //
|
||||
//
|
||||
// Функция пакетной записи нескольких байт данных в регистр модуля: //
|
||||
bool writeBytes(uint8_t adr, uint8_t reg, uint8_t *data, uint8_t sum){ // Определяем функцию пакетной записи нескольких байт данных в регистры модуля (аргументы: адрес_модуля, адрес_первого_регистра, указатель_на_массив, количество_байт)
|
||||
#if defined(iarduino_I2C_TW) //
|
||||
// Если используется шина I2C под управлением библиотеки Wire: //
|
||||
uint8_t i=0; // Предустанавливаем переменную i в значение 0 - это результат записи
|
||||
Wire.beginTransmission(adr); // Инициируем передачу данных по шине I2C к устройству с адресом adr и битом RW=0 => запись. При этом сама передача не начнётся.
|
||||
Wire.write(reg); // Определяем значение первого байта (reg - адреса регистра) который будет отправлен после байта адреса. Функция write() поместит указанный байт в буфер для передачи.
|
||||
Wire.write(data, sum); // Определяем значения следующих байт (data - массив данных) который будет отправлен после байта регистра. Функция write() поместит sum элементов массива data в буфер для передачи.
|
||||
i = Wire.endTransmission(); return i==0; // Выполняем инициированную ранее передачу данных. Функция endTransmission() возвращает: 0-передача успешна / 1 - переполнен буфер для передачи / 2 - получен NACK при передаче адреса / 3 - получен NACK при передаче данных / 4 - другая ошибка. В качестве параметра функция endTransmission() может принимать флаг установки стсояния STOP - по умолчанию true.
|
||||
#else //
|
||||
// Если шина управляется функциями нижнего уровня данного класса: //
|
||||
uint8_t i=0; // Предустанавливаем переменную i в значение 0 - это результат записи
|
||||
if ( start () ) { i=1; // Если на шине I2C установилось состояние START, то ...
|
||||
if ( sendID (adr,0) ) { i=2; // Если модуль ответил ACK на получение адреса устройства adr с битом RW=0 (запись), то ...
|
||||
if ( setByte (reg) ) { i=3; // Если модуль ответил ACK на получение адреса регистра reg, то ...
|
||||
while(sum>0){if(!setByte(*data )) { i=0;} // Передаём один байт из массива по указателю data в очередной регистр за каждый проход цикла while. Увеличиваем адрес указателя data, и уменьшаем сумму переданных байт sum.
|
||||
data++; sum--; // Увеличиваем адрес указателя data, и уменьшаем сумму переданных байт sum.
|
||||
}}}} stop (); return i==3; // Отправляем команду STOP и возвращаем результат записи.
|
||||
#endif //
|
||||
} //
|
||||
//
|
||||
// Функция пакетной записи нескольких байт данных в модуль: //
|
||||
bool writeBytes(uint8_t adr, uint8_t *data, uint8_t sum){ // Определяем функцию пакетной записи нескольких байт данных в модуль (аргументы: адрес_модуля, указатель_на_массив, количество_байт)
|
||||
#if defined(iarduino_I2C_TW) //
|
||||
// Если используется шина I2C под управлением библиотеки Wire: //
|
||||
uint8_t i=0; // Предустанавливаем переменную i в значение 0 - это результат записи
|
||||
Wire.beginTransmission(adr); // Инициируем передачу данных по шине I2C к устройству с адресом adr и битом RW=0 => запись. При этом сама передача не начнётся.
|
||||
Wire.write(data, sum); // Указываем массив данных который будет отправлен после байта адреса. Функция write() поместит sum элементов массива data в буфер для передачи.
|
||||
i = Wire.endTransmission(); return i==0; // Выполняем инициированную ранее передачу данных. Функция endTransmission() возвращает: 0-передача успешна / 1 - переполнен буфер для передачи / 2 - получен NACK при передаче адреса / 3 - получен NACK при передаче данных / 4 - другая ошибка. В качестве параметра функция endTransmission() может принимать флаг установки стсояния STOP - по умолчанию true.
|
||||
#else //
|
||||
// Если шина управляется функциями нижнего уровня данного класса: //
|
||||
uint8_t i=0; // Предустанавливаем переменную i в значение 0 - это результат записи
|
||||
if ( start () ) { i=1; // Если на шине I2C установилось состояние START, то ...
|
||||
if ( sendID (adr,0) ) { i=2; // Если модуль ответил ACK на получение адреса устройства adr с битом RW=0 (запись), то ...
|
||||
while(sum>0){if(!setByte(*data )) { i=0;} // Передаём один байт из массива по указателю data в очередной регистр за каждый проход цикла while. Увеличиваем адрес указателя data, и уменьшаем сумму переданных байт sum.
|
||||
data++; sum--; // Увеличиваем адрес указателя data, и уменьшаем сумму переданных байт sum.
|
||||
}}} stop (); return i==2; // Отправляем команду STOP и возвращаем результат записи.
|
||||
#endif //
|
||||
} //
|
||||
//
|
||||
/** ДОПОЛНИТЕЛЬНЫЕ ФУНКЦИИ: **/ //
|
||||
//
|
||||
// Функция получения типа реализации шины I2C: // Определяем функцию получения типа шины Ш2С.
|
||||
uint8_t getType(void){ // Аргументы: отсутсвуют.
|
||||
#if defined(iarduino_I2C_TW) //
|
||||
return 4; // Используется аппаратная реализация шины I2C под управлением библиотеки Wire.
|
||||
#elif defined(iarduino_I2C_HW) //
|
||||
return 3; // Используется аппаратная реализация шины I2C.
|
||||
#elif defined(iarduino_I2C_HW_1) //
|
||||
return 2; // Используется аппаратная реализация шины I2C-1.
|
||||
#elif defined(iarduino_I2C_SW) //
|
||||
return 1; // Используется программная реализация шины I2C.
|
||||
#else //
|
||||
return 0; // Тип реализации шины I2C не определён.
|
||||
#endif //
|
||||
} //
|
||||
//
|
||||
// Функция проверки наличия ведомого по его адресу: //
|
||||
bool checkAddress(uint8_t adr){ // Определяем функцию записи одного байта данных в регистр модуля (аргументы: адрес_регистра, байт_данных)
|
||||
#if defined(iarduino_I2C_TW) //
|
||||
// Если используется шина I2C под управлением библиотеки Wire: //
|
||||
uint8_t i=0; // Предустанавливаем переменную i в значение 0 - это результат проверки.
|
||||
Wire.beginTransmission(adr); // Инициируем передачу данных по шине I2C к устройству с адресом adr и битом RW=0 => запись. При этом сама передача не начнётся.
|
||||
i=Wire.endTransmission(); return i==0; // Выполняем инициированную ранее передачу но без данных (отправится только START, байт адреса, STOP). Функция endTransmission() возвращает: 0-передача успешна / 1 - переполнен буфер для передачи / 2 - получен NACK при передаче адреса / 3 - получен NACK при передаче данных / 4 - другая ошибка. В качестве параметра функция endTransmission() может принимать флаг установки стсояния STOP - по умолчанию true.
|
||||
#else //
|
||||
// Если шина управляется функциями нижнего уровня данного класса: //
|
||||
uint8_t i=0; // Предустанавливаем переменную i в значение 0 - это результат записи.
|
||||
if ( start () ) { i=1; // Если на шине I2C установилось состояние START, то ...
|
||||
if ( sendID (adr,0) ) { i=2; // Если модуль ответил ACK на получение адреса устройства adr с битом RW=0 (запись), то ...
|
||||
}} stop (); return i==2; // Отправляем команду STOP и возвращаем результат записи.
|
||||
#endif //
|
||||
} //
|
||||
//
|
||||
/** ФУНКЦИИ НИЖНЕГО УРОВНЯ: **/ //
|
||||
//
|
||||
// Функция нижнего уровня - установка состояния START: // Определяем функцию установки состояния START.
|
||||
bool start(void){ // Аргументы: отсутствуют.
|
||||
// _ _ _ _____:___ _ _ _ //
|
||||
// SCL: : \___ _ _ _ _ _/ //
|
||||
// _ _ _ _____: _ _ _ _ _ _ // Спад логического уровня на линии SDA с «1» в «0», при наличии уровня логической «1» на линии SCL
|
||||
// SDA: :\______ _ _/_ _ _ _ _ _ //
|
||||
// //
|
||||
#if defined(iarduino_I2C_HW) //
|
||||
// Если используется аппаратная шина I2C: //
|
||||
uint16_t i=60000L; // Определяем счётчик указывая максимальное количество циклов для ожидания установки состояния start.
|
||||
TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWSTA); // Определяем значение регистра управления TWCR: устанавливаем биты TWINT (флаг прерывания), TWEN (бит разрешения работы шины), TWSTA (бит условия START).
|
||||
while((!(TWCR & _BV(TWINT))) && i){i--;} // Ждём сброса флага прерывания TWINT в регистре управления TWCR, но не дольше чем i циклов.
|
||||
if((TWSR & 0xF8)==0x08){return true;} // Проверяем значение регистра статуса TWSR: если его значение с маской 0xF8 равно 0x08, значит состояние START установилось на шине I2C.
|
||||
return false; // Если предыдущая строка не вернула true, значит состояние START не установилось на шине I2C, возвращаем false.
|
||||
#elif defined(iarduino_I2C_SW) //
|
||||
// Если используется программная шина I2C: //
|
||||
bool i= setSCL(1); // Устанавливаем «1» на линии SCL. Если ведомый удерживает линию SCL прижатой, то функция ждёт освобождения линии и, если не дождётся, то возвращает false.
|
||||
setSDA(0); // Устанавливаем «0» на линии SDA
|
||||
setSCL(0); // Устанавливаем «0» на линии SCL
|
||||
return i; // Если счетчик i не дошел до 0 при ожидании «1» на линии SCL, то вернётся true.
|
||||
#else //
|
||||
// Если тип шины I2C не поддерживается или не определён: //
|
||||
return false; // Возвращаем false.
|
||||
#endif //
|
||||
} //
|
||||
//
|
||||
// Функция нижнего уровня - установка состояния RESTART: // Определяем функцию установки состояния RESTART.
|
||||
bool reStart(void){ // Аргументы: отсутствуют.
|
||||
// _ _ _ ___:___ _ _ _ //
|
||||
// SCL: \_ _ _ _ / : \___ _ _ _ _ _/ //
|
||||
// _ _ _ _ _ ________: _ _ _ _ _ _ // Спад логического уровня на линии SDA с «1» в «0», при наличии уровня логической «1» на линии SCL
|
||||
// SDA: _ _ _ _ _/ :\______ _ _/_ _ _ _ _ _ // Сигнал рестрат аналогичен сигналу старт и отличается лишь тем, что ему не предшествует сигнал STOP
|
||||
// //
|
||||
#if defined(iarduino_I2C_HW) //
|
||||
// Если используется аппаратная шина I2C: //
|
||||
uint16_t i=60000L; // Определяем счётчик указывая максимальное количество циклов для ожидания установки состояния RESTART.
|
||||
TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWSTA); // Определяем значение регистра управления TWCR: устанавливаем биты TWINT (флаг прерывания), TWEN (бит разрешения работы шины), TWSTA (бит условия START).
|
||||
while((!(TWCR & _BV(TWINT))) && i){i--;} // Ждём сброса флага прерывания TWINT в регистре управления TWCR, но не дольше чем i циклов.
|
||||
if((TWSR & 0xF8)==0x10){return true;} // Проверяем значение регистра статуса TWSR: если его значение с маской 0xF8 равно 0x10, значит состояние RESTART установилось на шине I2C.
|
||||
return false; // Если предыдущая строка не вернула true, значит состояние RESTART не установилось на шине I2C, возвращаем false.
|
||||
#elif defined(iarduino_I2C_SW) //
|
||||
// Если используется программная шина I2C: //
|
||||
return start(); // Программная реализация состояния RESTART идентична программной реализации состояния START.
|
||||
#else //
|
||||
// Если тип шины I2C не поддерживается или не определён: //
|
||||
return false; // Возвращаем false.
|
||||
#endif //
|
||||
} //
|
||||
//
|
||||
// Функция нижнего уровня - установка состояния STOP: // Определяем функцию установки состояния STOP.
|
||||
void stop(void){ // Аргументы: отсутствуют.
|
||||
// _ _ _ ___:____ _ _ _ //
|
||||
// SCL: \_ _ _ _/ : //
|
||||
// _ _ _ _ _ :____ _ _ _ // Подъём логического уровня на линии SDA с «0» в «1», при наличии уровня логической «1» на линии SCL
|
||||
// SDA: _ _ _ _ _\______/: //
|
||||
// //
|
||||
#if defined(iarduino_I2C_HW) //
|
||||
// Если используется аппаратная шина I2C: //
|
||||
uint16_t i=60000L; // Определяем счётчик указывая максимальное количество циклов для ожидания установки состояния STOP
|
||||
TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWSTO); // Определяем значение регистра управления TWCR: устанавливаем биты TWINT (флаг прерывания), TWEN (бит разрешения работы шины), TWSTO (бит условия STOP).
|
||||
while((!(TWCR & _BV(TWSTO))) && i){i--;} // Ждём сброса бита условия стоп TWSTO в регистре управления TWCR, но не дольше чем i циклов
|
||||
// if((TWSR & 0xF8)==0xA0){return true;} // Проверяем значение регистра статуса TWSR: если его значение с маской 0xF8 равно 0xA0, значит состояние STOP установилось на шине I2C.
|
||||
delayMicroseconds(20); // Данная функция не возвращает результат, но в любом случае делаем задержку меджу завершением текущего пакета и возможным началом следующего
|
||||
#elif defined(iarduino_I2C_SW) //
|
||||
// Если используется программная шина I2C: //
|
||||
setSDA(0); // Устанавливаем «0» на линии SDA
|
||||
setSCL(1); // Устанавливаем «1» на линии SCL. Если ведомый удерживает линию SCL прижатой, то функция ждёт освобождения линии и, если не дождётся, то возвращает false.
|
||||
setSDA(1); // Устанавливаем «1» на линии SDA
|
||||
#endif //
|
||||
} //
|
||||
//
|
||||
// Функция нижнего уровня - передача первого байта АДРЕС+RW: // Определяем функцию передачи первого байта после cигнала START. Это байт адреса модуля с битом RW
|
||||
bool sendID(uint8_t adr, bool rw){ // Аргументы: ID-адрес модуля, бит RW (0-запись, 1-чтение)
|
||||
// 1 2 3 4 5 6 7 8 9 //
|
||||
// SCL: _ _ _ _____/\_/\_/\_/\_/\_/\_/\_/\__/\_____ _ _ _ //
|
||||
// ________________________ // Передача 7-битного адреса и 1 бита RW. На 9 тактирубщем импульсе модуль отвечает ACK («0» - «я сдесь»), или NACK («1» - «нет»)
|
||||
// SDA: _ _ _ ___/________ADDRESS_______RW>----____ _ _ _ //
|
||||
// вход //
|
||||
#if defined(iarduino_I2C_HW) //
|
||||
// Если используется аппаратная шина I2C: //
|
||||
uint16_t i=60000L; // Определяем счётчик указывая максимальное количество циклов для ожидания получения подтверждения от ведомого ввиде бита ACK.
|
||||
TWDR = (adr<<1)+rw; // Определяем значение регистра данных TWDR: записываем в него адрес adr сдвигая его на 1 бит влево, при этом младший бит (освободившийся) займёт бит RW (0-запись / 1-чтение)
|
||||
TWCR = _BV(TWINT) | _BV(TWEN); // Определяем значение регистра управления TWCR: устанавливаем биты TWINT (флаг прерывания) и TWEN (бит разрешения работы шины).
|
||||
while((!(TWCR & _BV(TWINT))) && i){i--;} // Ждём сброса флага прерывания TWINT в регистре управления TWCR, но не дольше чем i циклов
|
||||
if((TWSR & 0xF8)==0x40 && rw){return true;} // Проверяем значение регистра статуса TWSR: если его значение с маской 0xF8 равно 0x40, значит ведомый опознал свой адрес с битом RW=1 и отправил бит подтверждения ACK (в противном случае значение регистра TWSR будет равно 0x48).
|
||||
if((TWSR & 0xF8)==0x18 && !rw){return true;} // Проверяем значение регистра статуса TWSR: если его значение с маской 0xF8 равно 0x18, значит ведомый опознал свой адрес с битом RW=0 и отправил бит подтверждения ACK (в противном случае значение регистра TWSR будет равно 0x20).
|
||||
return false; // Если предыдущая строка не вернула true, значит на шине нет ведомых у сказанным адресом, возвращаем false.
|
||||
#elif defined(iarduino_I2C_SW) //
|
||||
// Если используется программная шина I2C: //
|
||||
bool i=true; // Определяем флаг возвращаемый данной функцией.
|
||||
uint8_t j=7; // Определяем счётчик количества переданных бит адреса.
|
||||
while(j){ j--; // Передаём 7 бит адреса adr в цикле
|
||||
setSDA(adr & bit(j)); // Устанавливаем очередной бит адреса на линии SDA
|
||||
if(!setSCL(1) ) {i=false;} // Устанавливаем «1» на линии SCL (Фронт тактирующего импульса). Если ведомый удерживает линию SCL прижатой, то функция ждёт освобождения линии и, если не дождётся, то возвращает false.
|
||||
setSCL(0); // Устанавливаем «0» на линии SCL (Спад тактирубщего импульса)
|
||||
} setSDA(rw); // Устанавливаем бит RW на линии SDA
|
||||
if(!setSCL(1) ) {i=false;} // Устанавливаем «1» на линии SCL (Фронт тактирующего импульса). Если ведомый удерживает линию SCL прижатой, то функция ждёт освобождения линии и, если не дождётся, то возвращает false.
|
||||
setSCL(0); // Устанавливаем «0» на линии SCL (Спад тактирубщего импульса)
|
||||
setSDA(1); // Переводим вывод SDA в режим входа с подтяжкой к Vcc
|
||||
if(!setSCL(1) ) {i=false;} // Устанавливаем «1» на линии SCL (Фронт тактирующего импульса). Если ведомый удерживает линию SCL прижатой, то функция ждёт освобождения линии и, если не дождётся, то возвращает false.
|
||||
if( getSDA( ) ) {i=false;} // Если на линии SDA установлена «1» значит ведомый ответил NACK
|
||||
setSCL(0); // Устанавливаем «0» на линии SCL (Спад тактирубщего импульса)
|
||||
return i; // Если линия SCL была занята или модуль ответил NACK, то вернётся false.
|
||||
#else //
|
||||
// Если тип шины I2C не поддерживается или не определён: //
|
||||
return false; // Возвращаем false
|
||||
#endif //
|
||||
} //
|
||||
//
|
||||
// Функция нижнего уровня - передача одного байта данных: // Определяем функцию передачи одного байта (в любом месте между байтом адреса с битом RW=0 и сигналом STOP).
|
||||
bool setByte(uint8_t data){ // Аргумент: байт для передачи.
|
||||
// 1 2 3 4 5 6 7 8 9 //
|
||||
// SCL: _ _ _ _____/\_/\_/\_/\_/\_/\_/\_/\__/\_____ _ _ _ //
|
||||
// ________________________ // Передача 1 байта, каждый бит читается модулем по фронту тактирубщих импульсов. На 9 тактирубщем импульсе модуль отвечает ACK («0» - «принял»), или NACK («1» - «нет»)
|
||||
// SDA: _ _ _ ___/__________DATA__________>----____ _ _ _ //
|
||||
// вход //
|
||||
#if defined(iarduino_I2C_HW) //
|
||||
// Если используется аппаратная шина I2C: //
|
||||
uint16_t i=60000L; // Определяем счётчик указывая максимальное количество циклов для ожидания получения подтверждения от ведомого ввиде бита ACK.
|
||||
TWDR = data; // Определяем значение регистра данных TWDR: записываем в него байт для передачи по шине I2C.
|
||||
TWCR = _BV(TWINT) | _BV(TWEN); // Определяем значение регистра управления TWCR: устанавливаем биты TWINT (флаг прерывания) и TWEN (бит разрешения работы шины).
|
||||
while((!(TWCR & _BV(TWINT))) && i){i--;} // Ждём сброса флага прерывания TWINT в регистре управления TWCR, но не дольше чем i циклов
|
||||
if((TWSR & 0xF8)==0x28){return true;} // Проверяем значение регистра статуса TWSR: если его значение с маской 0xF8 равно 0x28, значит ведомый отправил бит подтверждения приёма данных ACK (в противном случае значение регистра TWSR будет равно 0x30).
|
||||
return false; // Если предыдущая строка не вернула true, значит ведомый не принял отправленный ему байт, возвращаем false.
|
||||
#elif defined(iarduino_I2C_SW) //
|
||||
// Если используется программная шина I2C: //
|
||||
bool i=true; // Определяем флаг возвращаемый данной функцией.
|
||||
uint8_t j=8; // Определяем счётчик количества переданных байт.
|
||||
while(j){ j--; // Передаём 8 бит байта data в цикле
|
||||
setSDA(data & bit(j)); // Устанавливаем очередной бит байта на линии SDA
|
||||
if(!setSCL(1) ) {i=false;} // Устанавливаем «1» на линии SCL (Фронт тактирующего импульса). Если ведомый удерживает линию SCL прижатой, то функция ждёт освобождения линии и, если не дождётся, то возвращает false.
|
||||
setSCL(0); // Устанавливаем «0» на линии SCL (Спад тактирубщего импульса)
|
||||
} setSDA(1); // Переводим вывод SDA в режим входа с подтяжкой к Vcc
|
||||
if(!setSCL(1) ) {i=false;} // Устанавливаем «1» на линии SCL (Фронт тактирующего импульса). Если ведомый удерживает линию SCL прижатой, то функция ждёт освобождения линии и, если не дождётся, то возвращает false.
|
||||
if( getSDA( ) ) {i=false;} // Если на линии SDA установлена «1» значит ведомый ответил NACK
|
||||
setSCL(0); // Устанавливаем «0» на линии SCL (Спад тактирубщего импульса)
|
||||
return i; // Если счетчик i не дошел до 0 и не был сброшен в 0 при получении NACK, то вернётся true.
|
||||
#else //
|
||||
// Если тип шины I2C не поддерживается или не определён: //
|
||||
return false; // Возвращаем false
|
||||
#endif //
|
||||
} //
|
||||
//
|
||||
// Функция нижнего уровня - получение одного байта данных: // Определяем функцию получения одного байта (в любом месте между байтом адреса с битом RW=1 и сигналом STOP).
|
||||
uint8_t getByte(bool ack){ // Аргумент: бит подтверждения ACK/NACK
|
||||
// 1 2 3 4 5 6 7 8 9 //
|
||||
// SCL: _ _ _ _____/\_/\_/\_/\_/\_/\_/\_/\__/\_____ _ _ _ //
|
||||
// __ // Получение 1 байта, каждый бит читается мастером по фронту тактирубщих импульсов. На 9 тактирубщем импульсе мастер отвечает ACK («0» - «давай еще»), или NACK («1» - «хватит»)
|
||||
// SDA: _ _ _ ___/----------DATA-----------<__\____ _ _ _ //
|
||||
// вход выход //
|
||||
#if defined(iarduino_I2C_HW) //
|
||||
// Если используется аппаратная шина I2C: //
|
||||
uint16_t i=60000L; // Определяем счётчик указывая максимальное количество циклов для ожидания.
|
||||
TWCR = _BV(TWINT) | _BV(TWEN) | ack<<TWEA; // Определяем значение регистра управления TWCR: устанавливаем биты TWINT (флаг прерывания) и TWEN (бит разрешения работы шины), а бит TWEA (бит разрешения подтверждения) устанавливаем только если мы собираемся отправить ведомому бит подтверждения получения данных ACK.
|
||||
while((!(TWCR & _BV(TWINT))) && i){i--;} // Ждём сброса флага прерывания TWINT в регистре управления TWCR, но не дольше чем i циклов
|
||||
if((TWSR & 0xF8)==0x50 && ack){return TWDR;} // Проверяем значение регистра статуса TWSR: если его значение с маской 0xF8 равно 0x50, значит данные приняты и сохранены в регистре TWDR, а ведомому отправлен бит ACK.
|
||||
if((TWSR & 0xF8)==0x58 && !ack){return TWDR;} // Проверяем значение регистра статуса TWSR: если его значение с маской 0xF8 равно 0x58, значит данные приняты и сохранены в регистре TWDR, а ведомому отправлен бит NACK.
|
||||
return 0; // Если предыдущая строка не вернула принятый байт из регистра данных TWDR, значит мы не приняли байт, возвращаем 0.
|
||||
#elif defined(iarduino_I2C_SW) //
|
||||
// Если используется программная шина I2C: //
|
||||
bool i=true; // Определяем флаг возвращаемый данной функцией.
|
||||
uint8_t j=8; // Определяем счётчик количества полученных битов байта.
|
||||
uint8_t k=0; // Объявляем переменную для хранения прочитанного байта данных.
|
||||
setSDA(1); // Переводим вывод SDA в режим входа с подтяжкой к Vcc
|
||||
while(j){ j--; // Получаем 8 бит байта в цикле
|
||||
if(!setSCL(1) ) {i=false;} // Устанавливаем «1» на линии SCL (Фронт тактирующего импульса). Если ведомый удерживает линию SCL прижатой, то функция ждёт освобождения линии и, если не дождётся, то возвращает false.
|
||||
if( getSDA( ) ) { k |= (1<<j); } // Заполняем биты байта k в соотсетствии с уровнем на линии SDA
|
||||
setSCL(0); // Устанавливаем «0» на линии SCL (Спад тактирубщего импульса)
|
||||
} setSDA(!ack); // Устанавливаем бит «ACK/NACK» на линии SDA (ACK-прижимаем, NACK-отпускаем)
|
||||
if(!setSCL(1) ) {i=false;} // Устанавливаем «1» на линии SCL (Фронт тактирующего импульса). Если ведомый удерживает линию SCL прижатой, то функция ждёт освобождения линии и, если не дождётся, то возвращает false.
|
||||
setSCL(0); // Устанавливаем «0» на линии SCL (Спад тактирубщего импульса)
|
||||
return i?k:0; // Если во время ожидания поднятия логического уровня на линии SCL, cчётчик i не дошел до 0, то функция вернёт байт из переменной k.
|
||||
#else //
|
||||
// Если тип шины I2C не поддерживается или не определён: //
|
||||
return 0; // Возвращаем false
|
||||
#endif //
|
||||
} //
|
||||
//
|
||||
private: //
|
||||
uint8_t pin_SDA = pin_SW_SDA; // Определяем вывод pin_SDA.
|
||||
uint8_t pin_SCL = pin_SW_SCL; // Определяем вывод pin_SCL.
|
||||
uint8_t port_SDA; // Объявляем переменную для хранения номера порта вывода pin_SDA.
|
||||
uint8_t port_SCL; // Объявляем переменную для хранения номера порта вывода pin_SCL.
|
||||
uint8_t mask_SDA; // Объявляем переменную для хранения позиции бита управления выводом pin_SDA.
|
||||
uint8_t mask_SCL; // Объявляем переменную для хранения позиции бита управления выводом pin_SCL.
|
||||
volatile uint8_t *mod_SDA; // Объявляем указатель на регистр направления работы выводов порта port_SDA.
|
||||
volatile uint8_t *mod_SCL; // Объявляем указатель на регистр направления работы выводов порта port_SCL.
|
||||
volatile uint8_t *inp_SDA; // Объявляем указатель на регистр входных значений порта port_SDA.
|
||||
volatile uint8_t *inp_SCL; // Объявляем указатель на регистр входных значений порта port_SCL.
|
||||
volatile uint8_t *out_SDA; // Объявляем указатель на регистр выходных значений порта port_SDA.
|
||||
volatile uint8_t *out_SCL; // Объявляем указатель на регистр выходных значений порта port_SCL.
|
||||
//
|
||||
// функция установки уровня на линии SCL: // Определяем функцию установки уровня на линии SCL.
|
||||
bool setSCL(bool f){ // Аргумент: логический уровень.
|
||||
uint16_t i=60000L; // Определяем счётчик ожидания освобождения линии SCL.
|
||||
if(!f) {*mod_SCL |= mask_SCL; *out_SCL &= ~mask_SCL;} // Устанавливаем «0» на линии SCL (Спад тактирубщего импульса) pinMode(pin_SCL, OUTPUT); digitalWrite(pin_SCL, LOW );
|
||||
else {*mod_SCL &= ~mask_SCL; *out_SCL |= mask_SCL; // Устанавливаем «1» на линии SCL (Фронт тактирующего импульса) pinMode(pin_SCL, INPUT ); digitalWrite(pin_SCL, HIGH);
|
||||
while((*inp_SCL & mask_SCL)==0 && i){i--;} } // Ждём поднятия логического уровня на линии SCL while(digitalRead(pin_SCL)==0 && i){ цикл выполняется пока на линии 0 или пока i не сброситя d 0}
|
||||
return i; //
|
||||
} //
|
||||
//
|
||||
// Функция установки уровня на линии SDA: // Определяем функцию установки уровня на линии SDA.
|
||||
void setSDA(bool f){ // Аргумент: логический уровень.
|
||||
if(!f) {*mod_SDA |= mask_SDA; *out_SDA &= ~mask_SDA;} // Устанавливаем «0» на линии SDA (если бит RW=«0») pinMode(pin_SDA, OUTPUT); digitalWrite(pin_SDA, LOW );
|
||||
else {*mod_SDA &= ~mask_SDA; *out_SDA |= mask_SDA;} // Устанавливаем «1» на линии SDA (если бит RW=«1») pinMode(pin_SDA, INPUT ); digitalWrite(pin_SDA, HIGH );
|
||||
} //
|
||||
//
|
||||
// Функция чтения уровня с линии SDA: // Определяем функцию чтения уровня с линии SDA. Перед чтением необходимо вызвать функцию setSDA(1) которая переведёт вывод SDA в режим входа
|
||||
bool getSDA(void){ return (*inp_SDA & mask_SDA); } // Аргументы: отсутсвуют. digitalRead(pin_SDA);
|
||||
}; //
|
||||
//
|
||||
#endif //
|
||||
43
lib/iarduino_RTC/src/iarduino_RTC_RX8025.h
Normal file
43
lib/iarduino_RTC/src/iarduino_RTC_RX8025.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef iarduino_RTC_RX8025_h //
|
||||
#define iarduino_RTC_RX8025_h //
|
||||
#define RTC_RX8025 4 // Модуль часов реального времени с протоколом передачи данных I2C, памятью 016x8, температурной компенсацией, двумя будильниками и встроенным кварцевым резонатором
|
||||
#include "iarduino_RTC_I2C.h" // Подключаем файл iarduino_RTC_I2C.h - для работы с шиной I2C
|
||||
//
|
||||
class iarduino_RTC_RX8025: public iarduino_RTC_BASE{ //
|
||||
public: //
|
||||
/** функции доступные пользователю **/ //
|
||||
// Инициализация модуля: //
|
||||
void begin(void){ // (без параметров)
|
||||
// Инициализация работы с шиной I2C: //
|
||||
objI2C.begin(100); // (скорость шины в кГц)
|
||||
// Установка флагов управления и состояния модуля: //
|
||||
delay(10); objI2C.writeByte(valAddress, 0x0F, 0xA0); // Записываем байт 0xA0 (10100000) в регистр 0x0F (Control-2): VDSL=1 пороговое напряжение 1.3В, VDET=0 перезапуск определения падения мощности, /XST=1 перезапуск определения остановки колебаний, PON=0 перезапуск сброса при вкл питания, 0, CTFG=0 сброс периодического прерывания, WAFG=0 и DAFG=0 сброс прерываний будильников Alarm_D и Alarm_W
|
||||
delay(10); objI2C.writeByte(valAddress, 0x0E, 0x20); // Записываем байт 0x20 (00100000) в регистр 0x0E (Control-1): WALE=0 и DALE=0 отключение будильников Alarm_W и Alarm_D, /12,24=1 переключение в 24-часовой формат, 00, CT2-0=000 отключение периодического прерывания.
|
||||
} //
|
||||
//
|
||||
// Чтение одного значения из регистров даты и времени модуля: //
|
||||
uint8_t funcReadTimeIndex(uint8_t i){ // (i = 0-секунды / 1-минуты / 2-часы / 3-день / 4-месяц / 5-год / 6-день недели)
|
||||
delay(1); //
|
||||
varI = objI2C.readByte(valAddress, arrTimeRegAddr[i]) & arrTimeRegMack[i]; // Читаем байт из регистра arrTimeRegAddr[i] с маской arrTimeRegMack[i] в переменную varI.
|
||||
if(i==6){for(uint8_t j=1;j<8;j++){if(varI&bit(j-1)){return j;}} return 1;} // Если запрошен день недели, то возвращаем позицию (1...7) установленного бита в байте varI.
|
||||
// if( i==6 ){ varI++; } // Если чип считает день недели как написано в datasheet, то раскомментируйте данную строку и закомментируйте предыдущую.
|
||||
return varI; //
|
||||
} //
|
||||
//
|
||||
// Запись одного значения в регистры даты и времени модуля: //
|
||||
void funcWriteTimeIndex(uint8_t i, uint8_t j){ // (i = 0-секунды / 1-минуты / 2-часы / 3-день / 4-месяц / 5-год / 6-день недели, j = значение)
|
||||
if( i==6 ){ if( (j==0)||(j>7) ){ j=1; } j=bit(j-1); } // Устанавливаем один бит в переменной j;
|
||||
// if( i==6 ){j--;} // Если чип считает день недели как написано в datasheet, то раскомментируйте данную строку и закомментируйте предыдущую.
|
||||
objI2C.writeByte(valAddress, arrTimeRegAddr[i], j&arrTimeRegMack[i]); // Сохраняем значение j в регистр arrTimeRegAddr[i] с маской arrTimeRegMack[i].
|
||||
} //
|
||||
//
|
||||
private: //
|
||||
/** Внутренние переменные **/ //
|
||||
iarduino_I2C objI2C; // Создаём объект для работы с шиной I2C
|
||||
uint8_t valAddress = 0x32; // Адрес модуля на шине I2C
|
||||
uint8_t arrTimeRegAddr[7] = {0x00,0x01,0x02,0x04,0x05,0x06,0x03}; // Определяем массив с адресами регистров даты и времени (сек, мин, час, день, месяц, год, день недели)
|
||||
uint8_t arrTimeRegMack[7] = {0x7F,0x7F,0x3F,0x3F,0x1F,0xFF,0x7F}; // Определяем маскировочный массив для регистров даты и времени (при чтении/записи, нужно совершить побитовое «и»)
|
||||
uint8_t varI; //
|
||||
}; //
|
||||
//
|
||||
#endif //
|
||||
9
lib/iarduino_RTC/src/memorysaver.h
Normal file
9
lib/iarduino_RTC/src/memorysaver.h
Normal file
@@ -0,0 +1,9 @@
|
||||
// Файл: «ХРАНИТЕЛЬ ПАМЯТИ»
|
||||
|
||||
// Если закомментировать строки с названиями тех модулей которые не используются в Вашем устройстве, можно освободить около 50 байт флеш-памяти.
|
||||
// Если закомментировать строку с названием используемого модуля, компилятор выдаст ошибку.
|
||||
|
||||
#define RTC_ENABLE_DS1302 1 // Модуль часов реального времени (RTC) на базе чипа DS1302, с протоколом передачи данных SI3, памятью 040x8 (31 байт которой доступны для хранения данных пользователя).
|
||||
#define RTC_ENABLE_DS1307 1 // Модуль часов реального времени (RTC) на базе чипа DS1307, с протоколом передачи данных I2C, памятью 064x8 (56 байт которой доступны для хранения данных пользователя).
|
||||
#define RTC_ENABLE_DS3231 1 // Модуль часов реального времени (RTC) на базе чипа DS3231, с протоколом передачи данных I2C, памятью 019x8, температурной компенсацией, двумя будильниками и встроенным кварцевым резонатором.
|
||||
#define RTC_ENABLE_RX8025 1 // Модуль часов реального времени (RTC) на базе чипа RX8025, с протоколом передачи данных I2C, памятью 016x8, температурной компенсацией, двумя будильниками и встроенным кварцевым резонатором.
|
||||
Reference in New Issue
Block a user