Удалить 'OLED-I2C/I2C.h'

This commit is contained in:
Максим Шумилов 2023-05-25 13:24:51 +00:00
parent 979a66a221
commit ca1230d713

View File

@ -1,189 +0,0 @@
#ifndef I2C_h
#define I2C_h
// этот символ необходим для совместимости с Wire.h. его значение является максимумом для параметра uint8_t используемого в оригинальной библиотеке.
#define BUFFER_LENGTH 255
class I2CLIB {
public:
void begin(void); // инициализация шины
void setClock(uint32_t clock); // ручная установка частоты шины 31-900 kHz (в герцах)
void beginTransmission(uint8_t address); // открыть соединение (для записи данных)
uint8_t endTransmission(bool stop); // закрыть соединение , произвести stop или restart (по умолчанию - stop)
uint8_t endTransmission(void); // закрыть соединение , произвести stop
size_t write(uint8_t data); // отправить в шину байт данных , отправка производится сразу , формат - byte "unsigned char"
uint8_t requestFrom(uint8_t address , uint8_t length , bool stop); //открыть соединение и запросить данные от устройства, отпустить или удержать шину
uint8_t requestFrom(uint8_t address , uint8_t length); //открыть соединение и запросить данные от устройства, отпустить шину
uint8_t read(void); // прочитать байт , БУФЕРА НЕТ!!! , читайте сразу все запрошенные байты , stop или restart после чтения последнего байта, настраивается в requestFrom
uint8_t available(void); // вернет количество оставшихся для чтения байт
// функции добавлены для совместимости с Wire API
inline void beginTransmission(int address){beginTransmission((uint8_t)address);}
uint8_t requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop);
uint8_t requestFrom(uint8_t address, uint8_t quantity, uint32_t iaddress, uint8_t isize, uint8_t sendStop);
uint8_t requestFrom(int address, int quantity);
uint8_t requestFrom(int address, int quantity, int sendStop);
size_t write(const uint8_t *buffer, size_t size);
inline size_t write(unsigned long n) { return write((uint8_t)n); }
inline size_t write(long n) { return write((uint8_t)n); }
inline size_t write(unsigned int n) { return write((uint8_t)n); }
inline size_t write(int n) { return write((uint8_t)n); }
private:
uint8_t _requested_bytes = 0; // переменная хранит количество запрошенных и непрочитанных байт
bool _address_nack = false; // Флаг для отслеживания ошибки при передаче адреса
bool _data_nack = false; // Флаг для отслеживания ошибки при передаче данных
bool _stop_after_request = true; // stop или restart после чтения последнего байта
void start(void); // сервисная функция с нее начинается любая работа с шиной
void stop(void); // сервисная функция ей заканчивается работа с шиной
};
extern I2CLIB Wire;
void setPinMode(uint8_t pin, uint8_t mode) {
if (mode == INPUT) {
DDRD &= ~(1 << pin); // устанавливаем вход
} else {
DDRD |= (1 << pin); // устанавливаем выход
}
}
void I2CLIB::begin()
{ // Инициализация шины в роли master
setPinMode(SDA, INPUT_PULLUP); // Подтяжка шины
setPinMode(SCL, INPUT_PULLUP); // Подтяжка шины
TWBR = 72; // Стандартная скорость - 100kHz
TWSR = 0; // Делитель - /1 , статус - 0;
}
void I2CLIB::setClock(uint32_t clock)
{ // Функция установки частоты шины 31-900 kHz (в герцах)
TWBR = (((long)F_CPU / clock) - 16) / 2; // Расчет baudrate - регистра
}
void I2CLIB::beginTransmission(uint8_t address)
{ // Начать передачу (для записи данных)
I2CLIB::start(); // Старт
I2CLIB::write(address << 1); // Отправка slave - устройству адреса с битом "write"
}
uint8_t I2CLIB::endTransmission(void)
{ // Завершить передачу и отпустить шину
return I2CLIB::endTransmission(true);
}
uint8_t I2CLIB::endTransmission(bool stop)
{ // Завершить передачу (после записи данных)
if (stop) I2CLIB::stop(); // Если задано stop или аргумент пуст - отпустить шину
else I2CLIB::start(); // Иначе - restart (другой master на шине не сможет влезть между сообщениями)
if (_address_nack) { // Если нет ответа при передаче адреса
_address_nack = false; // Обнуляем оба флага
_data_nack = false; // Обнуляем оба флага
return 2; // Возвращаем '2'
} if (_data_nack) { // Если нет ответа при передаче данных
_address_nack = false; // Обнуляем оба флага
_data_nack = false; // Обнуляем оба флага
return 3; // Возвращаем '2'
} return 0; // Если все ОК - возвращаем '0'
}
size_t I2CLIB::write(uint8_t data)
{ // Прямая отправка байта на шину
TWDR = data; // Записать данные в data - регистр
TWCR = _BV(TWEN) | _BV(TWINT); // Запустить передачу
while (!(TWCR & _BV(TWINT))); // Дождаться окончания
uint8_t _bus_status = TWSR & 0xF8; // Чтение статуса шины
if(_bus_status == 0x20) _address_nack = true; // SLA + W + NACK ? - нет ответа при передаче адреса
if(_bus_status == 0x30) _data_nack = true; // BYTE + NACK ? - нет ответа при передаче данных
return 1; // для совместимости с Wire API
}
uint8_t I2CLIB::available()
{ // Вернуть оставшееся количество запрошенных для чтения байт
return _requested_bytes; // Это содержимое этой переменной
}
uint8_t I2CLIB::read()
{ // Прямое чтение байта из шины после запроса
if (--_requested_bytes) { // Если байт не последний
TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWEA); // Запустить чтение шины (с подтверждением "ACK")
while (!(TWCR & _BV(TWINT))); // Дождаться окончания приема данных
return TWDR; // Вернуть принятые данные , это содержимое data - регистра
}
_requested_bytes = 0; // Если читаем последний байт
TWCR = _BV(TWEN) | _BV(TWINT); // Запустить чтение шины (БЕЗ подтверждения "NACK")
while (!(TWCR & _BV(TWINT))); // Дождаться окончания приема данных
if (_stop_after_request) I2CLIB::stop(); // Если в requestFrom не задан аргумент stop , или stop задан как true - отпустить шину
else I2CLIB::start(); // Иначе - restart (другой master на шине не сможет влезть между сообщениями)
return TWDR; // Вернуть принятый ранее байт из data - регистра
}
uint8_t I2CLIB::requestFrom(uint8_t address , uint8_t length)
{ // Запрос n-го кол-ва байт от ведомого устройства и отпускание шины
return I2CLIB::requestFrom(address , length , true);
}
uint8_t I2CLIB::requestFrom(uint8_t address , uint8_t length , bool stop)
{ // Запрос n-го кол-ва байт от ведомого устройства (Читайте все байты сразу!!!)
_stop_after_request = stop; // stop или restart после чтения последнего байта
_requested_bytes = length; // Записать в переменную количество запрошенных байт
I2CLIB::start(); // Начать работу на шине
I2CLIB::write((address << 1) | 0x1); // Отправить устройству адрес + бит "read"
return length; // вернуть длину сообщения для совместимости с оригинальной Wire API
}
uint8_t I2CLIB::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop){
return requestFrom(address , quantity , sendStop!=0);
}
uint8_t I2CLIB::requestFrom(uint8_t address, uint8_t quantity, uint32_t iaddress, uint8_t isize, uint8_t sendStop){
if (isize > 0) {
// send internal address; this mode allows sending a repeated start to access
// some devices' internal registers. This function is executed by the hardware
// TWI module on other processors (for example Due's TWI_IADR and TWI_MMR registers)
beginTransmission(address);
// the maximum size of internal address is 4 bytes
// не понятно почему ограничение размерности регистра в оригинальной Wire API в 3 байта
if (isize > 4){
isize = 4;
}
// write internal register address - most significant byte first
while (isize-- > 0)
write((uint8_t)(iaddress >> (isize*8)));
endTransmission(false);
}
return requestFrom(address, quantity, sendStop);
}
uint8_t I2CLIB::requestFrom(int address, int quantity)
{
return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true);
}
uint8_t I2CLIB::requestFrom(int address, int quantity, int sendStop)
{
return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)sendStop);
}
size_t I2CLIB::write(const uint8_t *buffer, size_t size){
for (size_t i = 0 ; i < size; ++i)
write(buffer[i]);
return size;
}
void I2CLIB::start()
{ // сервисная функция с нее начинается любая работа с шиной
TWCR = _BV(TWSTA) | _BV(TWEN) | _BV(TWINT); // start + I2CLIB enable + установка флага "выполнить задачу"
while (!(TWCR & _BV(TWINT))); // Ожидание завершения
}
void I2CLIB::stop()
{ // сервисная функция ей заканчивается работа с шиной
TWCR = _BV(TWSTO) | _BV(TWEN) | _BV(TWINT); // stop + I2CLIB enable + установка флага "выполнить задачу"
}
I2CLIB Wire = I2CLIB();
#endif