This commit is contained in:
Dustin Brunner 2021-08-28 09:36:25 +02:00
commit ef7328c0f1
20 changed files with 1334 additions and 0 deletions

BIN
Binaeruhr.fzz Normal file

Binary file not shown.

BIN
Binaeruhr_Platine.fzz Normal file

Binary file not shown.

BIN
Frontplatte.pdf Normal file

Binary file not shown.

BIN
Frontplatte.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 KiB

Binary file not shown.

46
README.md Normal file
View File

@ -0,0 +1,46 @@
# Arduino Binäruhr
Eine Binäruhr basierend auf einem Arduino Nano. Die LEDs werden mit Hilfe von 74HC595 Schieberegistern angesteuert.
[<img src="pictures/Uhr_1.jpg" height="400px">](pictures/Uhr_1.jpg)
[<img src="pictures/Uhr_2.jpg" height="400px">](pictures/Uhr_2.jpg)
[<img src="pictures/Uhr_innen.jpg" height="400px">](pictures/Uhr_innen.jpg)
## Features
- Einbau in einem IKEA Ribba Bilderrahmen 13x18 cm (bzw. 10x15 cm)
- Die Zeit wird von einer DS3231 RTC bereitgestellt
- Ein Taster zum ändern der Anzeige:
- Normalmodus: Zeitanzeige - Stunden, Minuten, Sekunden
- Datumsanzeige - Tag, Monat, Tag der Woche (1-7)
- Temperaturanzeige - Temperaturmessung erfolgt durch das RTC-Modul
- Wenn die Anzeige im Datum- oder Temperaturmodus ist, wechselt sie nach 10 Sekunden automatisch zum Normalmodus zurück
- Eine extra LED blinkt 2 mal jede Sekunde
# Hardware
## Schaltplan
**Im Schaltplan sind keine Vorwiderstände für die einzelnen LEDs eingetragen, diese sollten jedoch verbaut werden! (Wert: 220R)** <br><br>
[<img src="pictures/Binaeruhr_Schaltplan.png" height="700px">](pictures/Binaeruhr_Schaltplan.png)
## Leiterplatte
[<img src="pictures/Binaeruhr_Platine_Leiterplatte.png" height="400px">](pictures/Binaeruhr_Platine_Leiterplatte.png)
## Frontplatte
Ich habe für den Bilderrahmen eine Frontplatte erstellt (Software: Frontplatten Designer, Schaeffer AG). Diese ist passend für den IKEA Bilderrahmen und kann im Format **10x15 cm** ausgeruckt werden.
<br><br>
[<img src="Frontplatte.png" height="600px">](Frontplatte.png)
# Software
Der Code kann ohne weitere Änderungen verwendet werden. Um die Zeit des RTC-Moduls einzustellen müssen im Code die entsprechenden Zeilen auskommentiert und mit der aktuellen Uhrzeit gefüllt werden. Anschließend muss dieser Code **einmalig** auf dem Arduino ausgeführt werden.
Die Verwendete Bibiliothek für die DS3231 ist im Ordner des Programmes bereits hinterlegt und muss nicht extra heruntergeladen werden. Zusätzlich ist die Quelle der Bibiliothek jedoch im Code verlinkt.
# Quellen
- https://pascalstechtips.weebly.com/projekte/arduino-binruhr-v10
- DS3231: http://www.rinkydinkelectronics.com/library.php?id=73
- Software für Frontplatte: https://www.schaeffer-ag.de/frontplatten-designer#
<br><br>
<p xmlns:dct="http://purl.org/dc/terms/" xmlns:cc="http://creativecommons.org/ns#" class="license-text">This work by <span property="cc:attributionName">Dustin Brunner</span> is licensed under <a rel="license" href="https://creativecommons.org/licenses/by/4.0">CC BY 4.0<img style="height:15px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/cc.svg?ref=chooser-v1" /><img style="height:15px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/by.svg?ref=chooser-v1" /></a></p>
<a rel="license" href="http://creativecommons.org/licenses/by/4.0/"><img alt="Creative Commons Lizenzvertrag" style="border-width:0" src="https://i.creativecommons.org/l/by/4.0/88x31.png" /></a><br />Dieses Werk von <span xmlns:cc="http://creativecommons.org/ns#" property="cc:attributionName">Dustin Brunner</span> ist lizenziert unter einer <a rel="license" href="http://creativecommons.org/licenses/by/4.0/">Creative Commons Namensnennung 4.0 International Lizenz</a>.

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

BIN
pictures/Uhr_1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 KiB

BIN
pictures/Uhr_2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 KiB

BIN
pictures/Uhr_innen.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 KiB

View File

@ -0,0 +1,179 @@
#include "src/DS3231.h" //http://www.rinkydinkelectronics.com/library.php?id=73
DS3231 rtc(SDA, SCL);
//Pins
//Pins für Sekunden-Schieberegister
const int clockPinS = 4;
const int latchPinS = 3;
const int dataPinS = 2;
//Pins für Minuten-Schieberegister
const int clockPinM = 7;
const int latchPinM = 6;
const int dataPinM = 5;
//Pins für Stunden-Schieberegister
const int clockPinH = 10;
const int latchPinH = 9;
const int dataPinH = 8;
const int tickled = 13;
const int taster = 12;
//Variablen
long prevMillis = 0;
long interval = 500;
Time t;
int stunden;
int minuten;
int sekunden;
int tag;
int monat;
int wochentag;
int temp;
int halbesekunde = 0;
int modus = 1;
int modustimer = 0;
void setup(){
//Outputpins
pinMode(clockPinS, OUTPUT);
pinMode(dataPinS, OUTPUT);
pinMode(latchPinS, OUTPUT);
pinMode(clockPinM, OUTPUT);
pinMode(dataPinM, OUTPUT);
pinMode(latchPinM, OUTPUT);
pinMode(clockPinH, OUTPUT);
pinMode(dataPinH, OUTPUT);
pinMode(latchPinH, OUTPUT);
pinMode(tickled, OUTPUT);
//Inputpin
pinMode(taster, INPUT_PULLUP);
//RTC
rtc.begin();
// Nachfolgende Linien zur Zeiteinstellung unkommentieren
//rtc.setDOW(2); // Wochentag einstellen -> 1=Montag, 2=Dienstag, ...
//rtc.setTime(16, 58, 00); // Uhrzeit einstellen (Stunde, Minute, Sekunde)
//rtc.setDate(02, 04, 2019); // Datum einstellen (Tag, Monat, Jahr)
//für Debugging un-kommentieren
//Serial.begin(9600);
} //Ende von setup()
void loop(){
/*if (digitalRead(addhour) == LOW){ //falls Minuten erhöht werden sollen
delay(100);
minutes += 1;
if (minutes > 58){
minutes = 0;
}
Serial.println("Minute++");
while(digitalRead(2) == LOW){
delay(10);
}
}*/
if (digitalRead(taster) == LOW){
modus++;
modustimer = 0;
if (modus == 4){
modus = 1;
}
while(digitalRead(taster) == LOW){}
delay(100);
}
if(modustimer >= 10){
modus = 1;
modustimer = 0;
}
unsigned long currentMillis = millis();
if (currentMillis - prevMillis > interval) {
prevMillis = currentMillis;
if(halbesekunde == 1){
if (modus == 1){
t = rtc.getTime();
stunden = t.hour, DEC;
minuten = t.min, DEC;
sekunden = t.sec, DEC;
digitalWrite(tickled, HIGH);
displayTime();
}
else if (modus == 2){
t = rtc.getTime();
tag = t.date, DEC;
monat = t.mon, DEC;
wochentag = t.dow, DEC;
modustimer++;
displayDate();
}
else if (modus == 3){
temp = int(rtc.getTemp());
modustimer++;
displayTemp();
}
//für Debugging un-kommentieren
/*Serial.println("");
Serial.println("Zeit:"); //für debugging
Serial.print(String(stunden));
Serial.print(":");
Serial.print(String(minuten));
Serial.print(":");
Serial.print(String(sekunden));
//*/
halbesekunde = 0;
}
else{
digitalWrite(tickled, LOW);
halbesekunde = 1;
}
}
} //Ende von loop()
void displayTime(){ //Sendet die Zeit zu den Shiftregistern
//Sekunden
digitalWrite(latchPinS, LOW);
shiftOut(dataPinS, clockPinS, MSBFIRST, sekunden);
digitalWrite(latchPinS, HIGH);
//Minuten
digitalWrite(latchPinM, LOW);
shiftOut(dataPinM, clockPinM, MSBFIRST, minuten);
digitalWrite(latchPinM, HIGH);
//Stunden
digitalWrite(latchPinH, LOW);
shiftOut(dataPinH, clockPinH, MSBFIRST, stunden);
digitalWrite(latchPinH, HIGH);
}
void displayDate(){ //Sendet Datum zu den Shiftregistern
digitalWrite(latchPinS, LOW);
shiftOut(dataPinS, clockPinS, MSBFIRST, wochentag);
digitalWrite(latchPinS, HIGH);
digitalWrite(latchPinM, LOW);
shiftOut(dataPinM, clockPinM, MSBFIRST, monat);
digitalWrite(latchPinM, HIGH);
digitalWrite(latchPinH, LOW);
shiftOut(dataPinH, clockPinH, MSBFIRST, tag);
digitalWrite(latchPinH, HIGH);
}
void displayTemp(){ //Sendet Temperatur zu den Shiftregistern
digitalWrite(latchPinS, LOW);
shiftOut(dataPinS, clockPinS, MSBFIRST, temp);
digitalWrite(latchPinS, HIGH);
digitalWrite(latchPinM, LOW);
shiftOut(dataPinM, clockPinM, MSBFIRST, 0);
digitalWrite(latchPinM, HIGH);
digitalWrite(latchPinH, LOW);
shiftOut(dataPinH, clockPinH, MSBFIRST, 0);
digitalWrite(latchPinH, HIGH);
}

View File

@ -0,0 +1,447 @@
/*
DS3231.cpp - Arduino/chipKit library support for the DS3231 I2C Real-Time Clock
Copyright (C)2015 Rinky-Dink Electronics, Henning Karlsen. All right reserved
This library has been made to easily interface and use the DS3231 RTC with
an Arduino or chipKit.
You can find the latest version of the library at
http://www.RinkyDinkElectronics.com/
This library is free software; you can redistribute it and/or
modify it under the terms of the CC BY-NC-SA 3.0 license.
Please see the included documents for further information.
Commercial use of this library requires you to buy a license that
will allow commercial use. This includes using the library,
modified or not, as a tool to sell products.
The license applies to all part of the library including the
examples and tools supplied with the library.
*/
#include "DS3231.h"
// Include hardware-specific functions for the correct MCU
#if defined(__AVR__)
#include "hardware/avr/HW_AVR.h"
#elif defined(__PIC32MX__)
#include "hardware/pic32/HW_PIC32.h"
#elif defined(__arm__)
#include "hardware/arm/HW_ARM.h"
#endif
#define REG_SEC 0x00
#define REG_MIN 0x01
#define REG_HOUR 0x02
#define REG_DOW 0x03
#define REG_DATE 0x04
#define REG_MON 0x05
#define REG_YEAR 0x06
#define REG_CON 0x0e
#define REG_STATUS 0x0f
#define REG_AGING 0x10
#define REG_TEMPM 0x11
#define REG_TEMPL 0x12
#define SEC_1970_TO_2000 946684800
static const uint8_t dim[] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
/* Public */
Time::Time()
{
this->year = 2014;
this->mon = 1;
this->date = 1;
this->hour = 0;
this->min = 0;
this->sec = 0;
this->dow = 3;
}
DS3231::DS3231(uint8_t data_pin, uint8_t sclk_pin)
{
_sda_pin = data_pin;
_scl_pin = sclk_pin;
}
Time DS3231::getTime()
{
Time t;
_burstRead();
t.sec = _decode(_burstArray[0]);
t.min = _decode(_burstArray[1]);
t.hour = _decodeH(_burstArray[2]);
t.dow = _burstArray[3];
t.date = _decode(_burstArray[4]);
t.mon = _decode(_burstArray[5]);
t.year = _decodeY(_burstArray[6])+2000;
return t;
}
void DS3231::setTime(uint8_t hour, uint8_t min, uint8_t sec)
{
if (((hour>=0) && (hour<24)) && ((min>=0) && (min<60)) && ((sec>=0) && (sec<60)))
{
_writeRegister(REG_HOUR, _encode(hour));
_writeRegister(REG_MIN, _encode(min));
_writeRegister(REG_SEC, _encode(sec));
}
}
void DS3231::setDate(uint8_t date, uint8_t mon, uint16_t year)
{
if (((date>0) && (date<=31)) && ((mon>0) && (mon<=12)) && ((year>=2000) && (year<3000)))
{
year -= 2000;
_writeRegister(REG_YEAR, _encode(year));
_writeRegister(REG_MON, _encode(mon));
_writeRegister(REG_DATE, _encode(date));
}
}
void DS3231::setDOW()
{
int dow;
byte mArr[12] = {6,2,2,5,0,3,5,1,4,6,2,4};
Time _t = getTime();
dow = (_t.year % 100);
dow = dow*1.25;
dow += _t.date;
dow += mArr[_t.mon-1];
if (((_t.year % 4)==0) && (_t.mon<3))
dow -= 1;
while (dow>7)
dow -= 7;
_writeRegister(REG_DOW, dow);
}
void DS3231::setDOW(uint8_t dow)
{
if ((dow>0) && (dow<8))
_writeRegister(REG_DOW, dow);
}
char *DS3231::getTimeStr(uint8_t format)
{
static char output[] = "xxxxxxxx";
Time t;
t=getTime();
if (t.hour<10)
output[0]=48;
else
output[0]=char((t.hour / 10)+48);
output[1]=char((t.hour % 10)+48);
output[2]=58;
if (t.min<10)
output[3]=48;
else
output[3]=char((t.min / 10)+48);
output[4]=char((t.min % 10)+48);
output[5]=58;
if (format==FORMAT_SHORT)
output[5]=0;
else
{
if (t.sec<10)
output[6]=48;
else
output[6]=char((t.sec / 10)+48);
output[7]=char((t.sec % 10)+48);
output[8]=0;
}
return (char*)&output;
}
char *DS3231::getDateStr(uint8_t slformat, uint8_t eformat, char divider)
{
static char output[] = "xxxxxxxxxx";
int yr, offset;
Time t;
t=getTime();
switch (eformat)
{
case FORMAT_LITTLEENDIAN:
if (t.date<10)
output[0]=48;
else
output[0]=char((t.date / 10)+48);
output[1]=char((t.date % 10)+48);
output[2]=divider;
if (t.mon<10)
output[3]=48;
else
output[3]=char((t.mon / 10)+48);
output[4]=char((t.mon % 10)+48);
output[5]=divider;
if (slformat==FORMAT_SHORT)
{
yr=t.year-2000;
if (yr<10)
output[6]=48;
else
output[6]=char((yr / 10)+48);
output[7]=char((yr % 10)+48);
output[8]=0;
}
else
{
yr=t.year;
output[6]=char((yr / 1000)+48);
output[7]=char(((yr % 1000) / 100)+48);
output[8]=char(((yr % 100) / 10)+48);
output[9]=char((yr % 10)+48);
output[10]=0;
}
break;
case FORMAT_BIGENDIAN:
if (slformat==FORMAT_SHORT)
offset=0;
else
offset=2;
if (slformat==FORMAT_SHORT)
{
yr=t.year-2000;
if (yr<10)
output[0]=48;
else
output[0]=char((yr / 10)+48);
output[1]=char((yr % 10)+48);
output[2]=divider;
}
else
{
yr=t.year;
output[0]=char((yr / 1000)+48);
output[1]=char(((yr % 1000) / 100)+48);
output[2]=char(((yr % 100) / 10)+48);
output[3]=char((yr % 10)+48);
output[4]=divider;
}
if (t.mon<10)
output[3+offset]=48;
else
output[3+offset]=char((t.mon / 10)+48);
output[4+offset]=char((t.mon % 10)+48);
output[5+offset]=divider;
if (t.date<10)
output[6+offset]=48;
else
output[6+offset]=char((t.date / 10)+48);
output[7+offset]=char((t.date % 10)+48);
output[8+offset]=0;
break;
case FORMAT_MIDDLEENDIAN:
if (t.mon<10)
output[0]=48;
else
output[0]=char((t.mon / 10)+48);
output[1]=char((t.mon % 10)+48);
output[2]=divider;
if (t.date<10)
output[3]=48;
else
output[3]=char((t.date / 10)+48);
output[4]=char((t.date % 10)+48);
output[5]=divider;
if (slformat==FORMAT_SHORT)
{
yr=t.year-2000;
if (yr<10)
output[6]=48;
else
output[6]=char((yr / 10)+48);
output[7]=char((yr % 10)+48);
output[8]=0;
}
else
{
yr=t.year;
output[6]=char((yr / 1000)+48);
output[7]=char(((yr % 1000) / 100)+48);
output[8]=char(((yr % 100) / 10)+48);
output[9]=char((yr % 10)+48);
output[10]=0;
}
break;
}
return (char*)&output;
}
char *DS3231::getDOWStr(uint8_t format)
{
char *output = "xxxxxxxxxx";
char *daysLong[] = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
char *daysShort[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
Time t;
t=getTime();
if (format == FORMAT_SHORT)
output = daysShort[t.dow-1];
else
output = daysLong[t.dow-1];
return output;
}
char *DS3231::getMonthStr(uint8_t format)
{
char *output= "xxxxxxxxx";
char *monthLong[] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
char *monthShort[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
Time t;
t=getTime();
if (format == FORMAT_SHORT)
output = monthShort[t.mon-1];
else
output = monthLong[t.mon-1];
return output;
}
long DS3231::getUnixTime(Time t)
{
uint16_t dc;
dc = t.date;
for (uint8_t i = 0; i<(t.mon-1); i++)
dc += dim[i];
if ((t.mon > 2) && (((t.year-2000) % 4) == 0))
++dc;
dc = dc + (365 * (t.year-2000)) + (((t.year-2000) + 3) / 4) - 1;
return ((((((dc * 24L) + t.hour) * 60) + t.min) * 60) + t.sec) + SEC_1970_TO_2000;
}
void DS3231::enable32KHz(bool enable)
{
uint8_t _reg = _readRegister(REG_STATUS);
_reg &= ~(1 << 3);
_reg |= (enable << 3);
_writeRegister(REG_STATUS, _reg);
}
void DS3231::setOutput(byte enable)
{
uint8_t _reg = _readRegister(REG_CON);
_reg &= ~(1 << 2);
_reg |= (enable << 2);
_writeRegister(REG_CON, _reg);
}
void DS3231::setSQWRate(int rate)
{
uint8_t _reg = _readRegister(REG_CON);
_reg &= ~(3 << 3);
_reg |= (rate << 3);
_writeRegister(REG_CON, _reg);
}
float DS3231::getTemp()
{
uint8_t _msb = _readRegister(REG_TEMPM);
uint8_t _lsb = _readRegister(REG_TEMPL);
return (float)_msb + ((_lsb >> 6) * 0.25f);
}
/* Private */
void DS3231::_sendStart(byte addr)
{
pinMode(_sda_pin, OUTPUT);
digitalWrite(_sda_pin, HIGH);
digitalWrite(_scl_pin, HIGH);
digitalWrite(_sda_pin, LOW);
digitalWrite(_scl_pin, LOW);
shiftOut(_sda_pin, _scl_pin, MSBFIRST, addr);
}
void DS3231::_sendStop()
{
pinMode(_sda_pin, OUTPUT);
digitalWrite(_sda_pin, LOW);
digitalWrite(_scl_pin, HIGH);
digitalWrite(_sda_pin, HIGH);
pinMode(_sda_pin, INPUT);
}
void DS3231::_sendNack()
{
pinMode(_sda_pin, OUTPUT);
digitalWrite(_scl_pin, LOW);
digitalWrite(_sda_pin, HIGH);
digitalWrite(_scl_pin, HIGH);
digitalWrite(_scl_pin, LOW);
pinMode(_sda_pin, INPUT);
}
void DS3231::_sendAck()
{
pinMode(_sda_pin, OUTPUT);
digitalWrite(_scl_pin, LOW);
digitalWrite(_sda_pin, LOW);
digitalWrite(_scl_pin, HIGH);
digitalWrite(_scl_pin, LOW);
pinMode(_sda_pin, INPUT);
}
void DS3231::_waitForAck()
{
pinMode(_sda_pin, INPUT);
digitalWrite(_scl_pin, HIGH);
while (digitalRead(_sda_pin)==HIGH) {}
digitalWrite(_scl_pin, LOW);
}
uint8_t DS3231::_readByte()
{
pinMode(_sda_pin, INPUT);
uint8_t value = 0;
uint8_t currentBit = 0;
for (int i = 0; i < 8; ++i)
{
digitalWrite(_scl_pin, HIGH);
currentBit = digitalRead(_sda_pin);
value |= (currentBit << 7-i);
delayMicroseconds(1);
digitalWrite(_scl_pin, LOW);
}
return value;
}
void DS3231::_writeByte(uint8_t value)
{
pinMode(_sda_pin, OUTPUT);
shiftOut(_sda_pin, _scl_pin, MSBFIRST, value);
}
uint8_t DS3231::_decode(uint8_t value)
{
uint8_t decoded = value & 127;
decoded = (decoded & 15) + 10 * ((decoded & (15 << 4)) >> 4);
return decoded;
}
uint8_t DS3231::_decodeH(uint8_t value)
{
if (value & 128)
value = (value & 15) + (12 * ((value & 32) >> 5));
else
value = (value & 15) + (10 * ((value & 48) >> 4));
return value;
}
uint8_t DS3231::_decodeY(uint8_t value)
{
uint8_t decoded = (value & 15) + 10 * ((value & (15 << 4)) >> 4);
return decoded;
}
uint8_t DS3231::_encode(uint8_t value)
{
uint8_t encoded = ((value / 10) << 4) + (value % 10);
return encoded;
}

View File

@ -0,0 +1,123 @@
/*
DS3231.cpp - Arduino/chipKit library support for the DS3231 I2C Real-Time Clock
Copyright (C)2015 Rinky-Dink Electronics, Henning Karlsen. All right reserved
This library has been made to easily interface and use the DS3231 RTC with
an Arduino or chipKit.
You can find the latest version of the library at
http://www.RinkyDinkElectronics.com/
This library is free software; you can redistribute it and/or
modify it under the terms of the CC BY-NC-SA 3.0 license.
Please see the included documents for further information.
Commercial use of this library requires you to buy a license that
will allow commercial use. This includes using the library,
modified or not, as a tool to sell products.
The license applies to all part of the library including the
examples and tools supplied with the library.
*/
#ifndef DS3231_h
#define DS3231_h
#if defined(__AVR__)
#include "Arduino.h"
#include "hardware/avr/HW_AVR_defines.h"
#elif defined(__PIC32MX__)
#include "WProgram.h"
#include "hardware/pic32/HW_PIC32_defines.h"
#elif defined(__arm__)
#include "Arduino.h"
#include "hardware/arm/HW_ARM_defines.h"
#endif
#define DS3231_ADDR_R 0xD1
#define DS3231_ADDR_W 0xD0
#define DS3231_ADDR 0x68
#define FORMAT_SHORT 1
#define FORMAT_LONG 2
#define FORMAT_LITTLEENDIAN 1
#define FORMAT_BIGENDIAN 2
#define FORMAT_MIDDLEENDIAN 3
#define MONDAY 1
#define TUESDAY 2
#define WEDNESDAY 3
#define THURSDAY 4
#define FRIDAY 5
#define SATURDAY 6
#define SUNDAY 7
#define SQW_RATE_1 0
#define SQW_RATE_1K 1
#define SQW_RATE_4K 2
#define SQW_RATE_8K 3
#define OUTPUT_SQW 0
#define OUTPUT_INT 1
class Time
{
public:
uint8_t hour;
uint8_t min;
uint8_t sec;
uint8_t date;
uint8_t mon;
uint16_t year;
uint8_t dow;
Time();
};
class DS3231
{
public:
DS3231(uint8_t data_pin, uint8_t sclk_pin);
void begin();
Time getTime();
void setTime(uint8_t hour, uint8_t min, uint8_t sec);
void setDate(uint8_t date, uint8_t mon, uint16_t year);
void setDOW();
void setDOW(uint8_t dow);
char *getTimeStr(uint8_t format=FORMAT_LONG);
char *getDateStr(uint8_t slformat=FORMAT_LONG, uint8_t eformat=FORMAT_LITTLEENDIAN, char divider='.');
char *getDOWStr(uint8_t format=FORMAT_LONG);
char *getMonthStr(uint8_t format=FORMAT_LONG);
long getUnixTime(Time t);
void enable32KHz(bool enable);
void setOutput(byte enable);
void setSQWRate(int rate);
float getTemp();
private:
uint8_t _scl_pin;
uint8_t _sda_pin;
uint8_t _burstArray[7];
boolean _use_hw;
void _sendStart(byte addr);
void _sendStop();
void _sendAck();
void _sendNack();
void _waitForAck();
uint8_t _readByte();
void _writeByte(uint8_t value);
void _burstRead();
uint8_t _readRegister(uint8_t reg);
void _writeRegister(uint8_t reg, uint8_t value);
uint8_t _decode(uint8_t value);
uint8_t _decodeH(uint8_t value);
uint8_t _decodeY(uint8_t value);
uint8_t _encode(uint8_t vaule);
#if defined(__arm__)
Twi *twi;
#endif
};
#endif

View File

@ -0,0 +1,154 @@
void DS3231::begin()
{
_use_hw = false;
if ((_sda_pin == SDA) and (_scl_pin == SCL))
{
_use_hw = true;
twi = TWI1;
pmc_enable_periph_clk(WIRE_INTERFACE_ID);
PIO_Configure(g_APinDescription[PIN_WIRE_SDA].pPort, g_APinDescription[PIN_WIRE_SDA].ulPinType, g_APinDescription[PIN_WIRE_SDA].ulPin, g_APinDescription[PIN_WIRE_SDA].ulPinConfiguration);
PIO_Configure(g_APinDescription[PIN_WIRE_SCL].pPort, g_APinDescription[PIN_WIRE_SCL].ulPinType, g_APinDescription[PIN_WIRE_SCL].ulPin, g_APinDescription[PIN_WIRE_SCL].ulPinConfiguration);
NVIC_DisableIRQ(TWI1_IRQn);
NVIC_ClearPendingIRQ(TWI1_IRQn);
NVIC_SetPriority(TWI1_IRQn, 0);
NVIC_EnableIRQ(TWI1_IRQn);
}
else if ((_sda_pin == SDA1) and (_scl_pin == SCL1))
{
_use_hw = true;
twi = TWI0;
pmc_enable_periph_clk(WIRE1_INTERFACE_ID);
PIO_Configure(g_APinDescription[PIN_WIRE1_SDA].pPort, g_APinDescription[PIN_WIRE1_SDA].ulPinType, g_APinDescription[PIN_WIRE1_SDA].ulPin, g_APinDescription[PIN_WIRE1_SDA].ulPinConfiguration);
PIO_Configure(g_APinDescription[PIN_WIRE1_SCL].pPort, g_APinDescription[PIN_WIRE1_SCL].ulPinType, g_APinDescription[PIN_WIRE1_SCL].ulPin, g_APinDescription[PIN_WIRE1_SCL].ulPinConfiguration);
NVIC_DisableIRQ(TWI0_IRQn);
NVIC_ClearPendingIRQ(TWI0_IRQn);
NVIC_SetPriority(TWI0_IRQn, 0);
NVIC_EnableIRQ(TWI0_IRQn);
}
if (_use_hw)
{
// activate internal pullups for twi.
digitalWrite(SDA, 1);
digitalWrite(SCL, 1);
// Reset the TWI
twi->TWI_CR = TWI_CR_SWRST;
// TWI Slave Mode Disabled, TWI Master Mode Disabled.
twi->TWI_CR = TWI_CR_SVDIS;
twi->TWI_CR = TWI_CR_MSDIS;
// Set TWI Speed
twi->TWI_CWGR = (TWI_DIV << 16) | (TWI_SPEED << 8) | TWI_SPEED;
// Set master mode
twi->TWI_CR = TWI_CR_MSEN;
}
else
{
pinMode(_scl_pin, OUTPUT);
}
}
void DS3231::_burstRead()
{
if (_use_hw)
{
// Set slave address and number of internal address bytes.
twi->TWI_MMR = (1 << 8) | TWI_MMR_MREAD | (DS3231_ADDR << 16);
// Set internal address bytes
twi->TWI_IADR = 0;
// Send START condition
twi->TWI_CR = TWI_CR_START;
for (int i=0; i<6; i++)
{
while ((twi->TWI_SR & TWI_SR_RXRDY) != TWI_SR_RXRDY)
{
};
_burstArray[i] = twi->TWI_RHR;
}
twi->TWI_CR = TWI_CR_STOP;
while ((twi->TWI_SR & TWI_SR_RXRDY) != TWI_SR_RXRDY) {};
_burstArray[6] = twi->TWI_RHR;
while ((twi->TWI_SR & TWI_SR_TXCOMP) != TWI_SR_TXCOMP) {};
}
else
{
_sendStart(DS3231_ADDR_W);
_waitForAck();
_writeByte(0);
_waitForAck();
_sendStart(DS3231_ADDR_R);
_waitForAck();
for (int i=0; i<7; i++)
{
_burstArray[i] = _readByte();
if (i<6)
_sendAck();
else
_sendNack();
}
_sendStop();
}
}
uint8_t DS3231::_readRegister(uint8_t reg)
{
uint8_t readValue=0;
if (_use_hw)
{
// Set slave address and number of internal address bytes.
twi->TWI_MMR = (1 << 8) | TWI_MMR_MREAD | (DS3231_ADDR << 16);
// Set internal address bytes
twi->TWI_IADR = reg;
// Send START and STOP condition to read a single byte
twi->TWI_CR = TWI_CR_START | TWI_CR_STOP;
while ((twi->TWI_SR & TWI_SR_RXRDY) != TWI_SR_RXRDY) {};
readValue = twi->TWI_RHR;
while ((twi->TWI_SR & TWI_SR_TXCOMP) != TWI_SR_TXCOMP) {};
}
else
{
_sendStart(DS3231_ADDR_W);
_waitForAck();
_writeByte(reg);
_waitForAck();
_sendStart(DS3231_ADDR_R);
_waitForAck();
readValue = _readByte();
_sendNack();
_sendStop();
}
return readValue;
}
void DS3231::_writeRegister(uint8_t reg, uint8_t value)
{
if (_use_hw)
{
// Set slave address and number of internal address bytes.
twi->TWI_MMR = (1 << 8) | (DS3231_ADDR << 16);
// Set internal address bytes
twi->TWI_IADR = reg;
// Send a single byte to start transfer
twi->TWI_THR = value;
while ((twi->TWI_SR & TWI_SR_TXRDY) != TWI_SR_TXRDY) {};
// Send STOP condition
twi->TWI_CR = TWI_CR_STOP;
while ((twi->TWI_SR & TWI_SR_TXCOMP) != TWI_SR_TXCOMP) {};
}
else
{
_sendStart(DS3231_ADDR_W);
_waitForAck();
_writeByte(reg);
_waitForAck();
_writeByte(value);
_waitForAck();
_sendStop();
}
}

View File

@ -0,0 +1,13 @@
// *** Hardwarespecific defines ***
#define SDA 20
#define SCL 21
#define SDA1 70
#define SCL1 71
#define TWI_SPEED TWI_SPEED_400k // Set default TWI Speed
#define TWI_SPEED_100k 208
#define TWI_SPEED_400k 101
#define TWI_DIV TWI_DIV_400k // Set divider for TWI Speed (must match TWI_SPEED setting)
#define TWI_DIV_100k 1
#define TWI_DIV_400k 0

View File

@ -0,0 +1,153 @@
void DS3231::begin()
{
if ((_sda_pin == SDA) and (_scl_pin == SCL))
{
_use_hw = true;
// activate internal pullups for twi.
digitalWrite(SDA, HIGH);
digitalWrite(SCL, HIGH);
//delay(1); // Workaround for a linker bug
// initialize twi prescaler and bit rate
cbi(TWSR, TWPS0);
cbi(TWSR, TWPS1);
TWBR = ((F_CPU / TWI_FREQ) - 16) / 2;
// enable twi module, acks, and twi interrupt
TWCR = _BV(TWEN) | _BV(TWIE)/* | _BV(TWEA)*/;
}
else
{
_use_hw = false;
pinMode(_scl_pin, OUTPUT);
}
}
void DS3231::_burstRead()
{
if (_use_hw)
{
// Send start address
TWCR = _BV(TWEN) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA); // Send START
while ((TWCR & _BV(TWINT)) == 0) {}; // Wait for TWI to be ready
TWDR = DS3231_ADDR_W;
TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWEA); // Clear TWINT to proceed
while ((TWCR & _BV(TWINT)) == 0) {}; // Wait for TWI to be ready
TWDR = 0;
TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWEA); // Clear TWINT to proceed
while ((TWCR & _BV(TWINT)) == 0) {}; // Wait for TWI to be ready
// Read data starting from start address
TWCR = _BV(TWEN) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA); // Send rep. START
while ((TWCR & _BV(TWINT)) == 0) {}; // Wait for TWI to be ready
TWDR = DS3231_ADDR_R;
TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWEA); // Clear TWINT to proceed
while ((TWCR & _BV(TWINT)) == 0) {}; // Wait for TWI to be ready
for (int i=0; i<7; i++)
{
TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWEA); // Send ACK and clear TWINT to proceed
while ((TWCR & _BV(TWINT)) == 0) {}; // Wait for TWI to be ready
_burstArray[i] = TWDR;
}
TWCR = _BV(TWEN) | _BV(TWINT); // Send NACK and clear TWINT to proceed
while ((TWCR & _BV(TWINT)) == 0) {}; // Wait for TWI to be ready
TWCR = _BV(TWEN)| _BV(TWINT) | _BV(TWSTO); // Send STOP
}
else
{
_sendStart(DS3231_ADDR_W);
_waitForAck();
_writeByte(0);
_waitForAck();
_sendStart(DS3231_ADDR_R);
_waitForAck();
for (int i=0; i<7; i++)
{
_burstArray[i] = _readByte();
if (i<6)
_sendAck();
else
_sendNack();
}
_sendStop();
}
}
uint8_t DS3231::_readRegister(uint8_t reg)
{
uint8_t readValue=0;
if (_use_hw)
{
// Send start address
TWCR = _BV(TWEN) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA); // Send START
while ((TWCR & _BV(TWINT)) == 0) {}; // Wait for TWI to be ready
TWDR = DS3231_ADDR_W;
TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWEA); // Clear TWINT to proceed
while ((TWCR & _BV(TWINT)) == 0) {}; // Wait for TWI to be ready
TWDR = reg;
TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWEA); // Clear TWINT to proceed
while ((TWCR & _BV(TWINT)) == 0) {}; // Wait for TWI to be ready
// Read data starting from start address
TWCR = _BV(TWEN) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA); // Send rep. START
while ((TWCR & _BV(TWINT)) == 0) {}; // Wait for TWI to be ready
TWDR = DS3231_ADDR_R;
TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWEA); // Clear TWINT to proceed
while ((TWCR & _BV(TWINT)) == 0) {}; // Wait for TWI to be ready
TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWEA); // Send ACK and clear TWINT to proceed
while ((TWCR & _BV(TWINT)) == 0) {}; // Wait for TWI to be ready
readValue = TWDR;
TWCR = _BV(TWEN) | _BV(TWINT); // Send NACK and clear TWINT to proceed
while ((TWCR & _BV(TWINT)) == 0) {}; // Wait for TWI to be ready
TWCR = _BV(TWEN)| _BV(TWINT) | _BV(TWSTO); // Send STOP
}
else
{
_sendStart(DS3231_ADDR_W);
_waitForAck();
_writeByte(reg);
_waitForAck();
_sendStart(DS3231_ADDR_R);
_waitForAck();
readValue = _readByte();
_sendNack();
_sendStop();
}
return readValue;
}
void DS3231::_writeRegister(uint8_t reg, uint8_t value)
{
if (_use_hw)
{
// Send start address
TWCR = _BV(TWEN) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA); // Send START
while ((TWCR & _BV(TWINT)) == 0) {}; // Wait for TWI to be ready
TWDR = DS3231_ADDR_W;
TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWEA); // Clear TWINT to proceed
while ((TWCR & _BV(TWINT)) == 0) {}; // Wait for TWI to be ready
TWDR = reg;
TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWEA); // Clear TWINT to proceed
while ((TWCR & _BV(TWINT)) == 0) {}; // Wait for TWI to be ready
TWDR = value;
TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWEA); // Clear TWINT to proceed
while ((TWCR & _BV(TWINT)) == 0) {}; // Wait for TWI to be ready
TWCR = _BV(TWEN)| _BV(TWINT) | _BV(TWSTO); // Send STOP
}
else
{
_sendStart(DS3231_ADDR_W);
_waitForAck();
_writeByte(reg);
_waitForAck();
_writeByte(value);
_waitForAck();
_sendStop();
}
}

View File

@ -0,0 +1,6 @@
// *** Hardwarespecific defines ***
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#ifndef TWI_FREQ
#define TWI_FREQ 400000L
#endif

View File

@ -0,0 +1,192 @@
inline void _waitForIdleBus() { while (I2C1CON & 0x1f) {} }
void DS3231::begin()
{
if ((_sda_pin == SDA) and (_scl_pin == SCL))
{
uint32_t tpgd;
_use_hw = true;
pinMode(SDA, OUTPUT);
digitalWrite(SDA, HIGH);
IFS0CLR = 0xE0000000; // Clear Interrupt Flag
IEC0CLR = 0xE0000000; // Disable Interrupt
I2C1CONCLR = (1 << _I2CCON_ON); // Disable I2C interface
tpgd = ((F_CPU / 8) * 104) / 125000000;
I2C1BRG = (F_CPU / (2 * TWI_FREQ) - tpgd) - 2; // Set I2C Speed
I2C1ADD = DS3231_ADDR; // Set I2C device address
I2C1CONSET = (1 << _I2CCON_ON) | (1 << _I2CCON_STREN); // Enable I2C Interface
}
else
{
_use_hw = false;
pinMode(_scl_pin, OUTPUT);
}
}
void DS3231::_burstRead()
{
if (_use_hw)
{
_waitForIdleBus(); // Wait for I2C bus to be Idle before starting
I2C1CONSET = (1 << _I2CCON_SEN); // Send start condition
if (I2C1STAT & (1 << _I2CSTAT_BCL)) { return; } // Check if there is a bus collision
while (I2C1CON & (1 << _I2CCON_SEN)) {} // Wait for start condition to finish
I2C1TRN = (DS3231_ADDR<<1); // Send device Write address
while (I2C1STAT & (1 << _I2CSTAT_IWCOL)) // Check if there is a Write collision
{
I2C1STATCLR = (1 << _I2CSTAT_IWCOL); // Clear Write collision flag
I2C1TRN = (DS3231_ADDR<<1); // Retry send device Write address
}
while (I2C1STAT & (1 << _I2CSTAT_TRSTAT)) {} // Wait for transmit to finish
while (I2C1STAT & (1 << _I2CSTAT_ACKSTAT)) {} // Wait for ACK
I2C1TRN = 0; // Send the register address
while (I2C1STAT & (1 << _I2CSTAT_TRSTAT)) {} // Wait for transmit to finish
while (I2C1STAT & (1 << _I2CSTAT_ACKSTAT)) {} // Wait for ACK
_waitForIdleBus(); // Wait for I2C bus to be Idle before starting
I2C1CONSET = (1 << _I2CCON_RSEN); // Send start condition
if (I2C1STAT & (1 << _I2CSTAT_BCL)) { return; } // Check if there is a bus collision
while (I2C1CON & (1 << _I2CCON_RSEN)) {} // Wait for start condition to finish
I2C1TRN = (DS3231_ADDR<<1) | 1; // Send device Read address
while (I2C1STAT & (1 << _I2CSTAT_IWCOL)) // Check if there is a Write collision
{
I2C1STATCLR = (1 << _I2CSTAT_IWCOL); // Clear Write collision flag
I2C1TRN = (DS3231_ADDR<<1) | 1; // Retry send device Read address
}
while (I2C1STAT & (1 << _I2CSTAT_TRSTAT)) {} // Wait for transmit to finish
while (I2C1STAT & (1 << _I2CSTAT_ACKSTAT)) {} // Wait for ACK
byte dummy = I2C1RCV; // Clear _I2CSTAT_RBF (Receive Buffer Full)
for (int i=0; i<7; i++)
{
_waitForIdleBus(); // Wait for I2C bus to be Idle before continuing
I2C1CONSET = (1 << _I2CCON_RCEN); // Set RCEN to start receive
while (I2C1CON & (1 << _I2CCON_RCEN)) {} // Wait for Receive operation to finish
while (!(I2C1STAT & (1 << _I2CSTAT_RBF))) {} // Wait for Receive Buffer Full
_burstArray[i] = I2C1RCV; // Read data
if (i == 6)
I2C1CONSET = (1 << _I2CCON_ACKDT); // Prepare to send NACK
else
I2C1CONCLR = (1 << _I2CCON_ACKDT); // Prepare to send ACK
I2C1CONSET = (1 << _I2CCON_ACKEN); // Send ACK/NACK
while (I2C1CON & (1 << _I2CCON_ACKEN)) {} // Wait for ACK/NACK send to finish
}
I2C1CONSET = (1 << _I2CCON_PEN); // Send stop condition
while (I2C1CON & (1 << _I2CCON_PEN)) {} // Wait for stop condition to finish
}
else
{
_sendStart(DS3231_ADDR_W);
_waitForAck();
_writeByte(0);
_waitForAck();
_sendStart(DS3231_ADDR_R);
_waitForAck();
for (int i=0; i<7; i++)
{
_burstArray[i] = _readByte();
if (i<6)
_sendAck();
else
_sendNack();
}
_sendStop();
}
}
uint8_t DS3231::_readRegister(uint8_t reg)
{
uint8_t readValue=0;
if (_use_hw)
{
_waitForIdleBus(); // Wait for I2C bus to be Idle before starting
I2C1CONSET = (1 << _I2CCON_SEN); // Send start condition
if (I2C1STAT & (1 << _I2CSTAT_BCL)) { return 0xff; }// Check if there is a bus collision
while (I2C1CON & (1 << _I2CCON_SEN)) {} // Wait for start condition to finish
I2C1TRN = (DS3231_ADDR<<1); // Send device Write address
while (I2C1STAT & (1 << _I2CSTAT_IWCOL)) // Check if there is a Write collision
{
I2C1STATCLR = (1 << _I2CSTAT_IWCOL); // Clear Write collision flag
I2C1TRN = (DS3231_ADDR<<1); // Retry send device Write address
}
while (I2C1STAT & (1 << _I2CSTAT_TRSTAT)) {} // Wait for transmit to finish
while (I2C1STAT & (1 << _I2CSTAT_ACKSTAT)) {} // Wait for ACK
I2C1TRN = reg; // Send the register address
while (I2C1STAT & (1 << _I2CSTAT_TRSTAT)) {} // Wait for transmit to finish
while (I2C1STAT & (1 << _I2CSTAT_ACKSTAT)) {} // Wait for ACK
_waitForIdleBus(); // Wait for I2C bus to be Idle before starting
I2C1CONSET = (1 << _I2CCON_RSEN); // Send start condition
if (I2C1STAT & (1 << _I2CSTAT_BCL)) { return 0xff; }// Check if there is a bus collision
while (I2C1CON & (1 << _I2CCON_RSEN)) {} // Wait for start condition to finish
I2C1TRN = (DS3231_ADDR<<1) | 1; // Send device Read address
while (I2C1STAT & (1 << _I2CSTAT_IWCOL)) // Check if there is a Write collision
{
I2C1STATCLR = (1 << _I2CSTAT_IWCOL); // Clear Write collision flag
I2C1TRN = (DS3231_ADDR<<1) | 1; // Retry send device Read address
}
while (I2C1STAT & (1 << _I2CSTAT_TRSTAT)) {} // Wait for transmit to finish
while (I2C1STAT & (1 << _I2CSTAT_ACKSTAT)) {} // Wait for ACK
byte dummy = I2C1RCV; // Clear _I2CSTAT_RBF (Receive Buffer Full)
_waitForIdleBus(); // Wait for I2C bus to be Idle before continuing
I2C1CONSET = (1 << _I2CCON_RCEN); // Set RCEN to start receive
while (I2C1CON & (1 << _I2CCON_RCEN)) {} // Wait for Receive operation to finish
while (!(I2C1STAT & (1 << _I2CSTAT_RBF))) {} // Wait for Receive Buffer Full
readValue = I2C1RCV; // Read data
I2C1CONSET = (1 << _I2CCON_ACKDT); // Prepare to send NACK
I2C1CONSET = (1 << _I2CCON_ACKEN); // Send NACK
while (I2C1CON & (1 << _I2CCON_ACKEN)) {} // Wait for NACK send to finish
I2C1CONSET = (1 << _I2CCON_PEN); // Send stop condition
while (I2C1CON & (1 << _I2CCON_PEN)) {} // Wait for stop condition to finish
}
else
{
_sendStart(DS3231_ADDR_W);
_waitForAck();
_writeByte(reg);
_waitForAck();
_sendStart(DS3231_ADDR_R);
_waitForAck();
readValue = _readByte();
_sendNack();
_sendStop();
}
return readValue;
}
void DS3231::_writeRegister(uint8_t reg, uint8_t value)
{
if (_use_hw)
{
_waitForIdleBus(); // Wait for I2C bus to be Idle before starting
I2C1CONSET = (1 << _I2CCON_SEN); // Send start condition
if (I2C1STAT & (1 << _I2CSTAT_BCL)) { return; } // Check if there is a bus collision
while (I2C1CON & (1 << _I2CCON_SEN)) {} // Wait for start condition to finish
I2C1TRN = (DS3231_ADDR<<1); // Send device Write address
while (I2C1STAT & (1 << _I2CSTAT_IWCOL)) // Check if there is a Write collision
{
I2C1STATCLR = (1 << _I2CSTAT_IWCOL); // Clear Write collision flag
I2C1TRN = (DS3231_ADDR<<1); // Retry send device Write address
}
while (I2C1STAT & (1 << _I2CSTAT_TRSTAT)) {} // Wait for transmit to finish
while (I2C1STAT & (1 << _I2CSTAT_ACKSTAT)) {} // Wait for ACK
I2C1TRN = reg; // Send the 1st data byte
while (I2C1STAT & (1 << _I2CSTAT_TRSTAT)) {} // Wait for transmit to finish
while (I2C1STAT & (1 << _I2CSTAT_ACKSTAT)) {} // Wait for ACK
I2C1TRN = value; // Send the 2nd data byte
while (I2C1STAT & (1 << _I2CSTAT_TRSTAT)) {} // Wait for transmit to finish
while (I2C1STAT & (1 << _I2CSTAT_ACKSTAT)) {} // Wait for ACK
I2C1CONSET = (1 << _I2CCON_PEN); // Send stop condition
while (I2C1CON & (1 << _I2CCON_PEN)) {} // Wait for stop condition to finish
}
else
{
_sendStart(DS3231_ADDR_W);
_waitForAck();
_writeByte(reg);
_waitForAck();
_writeByte(value);
_waitForAck();
_sendStop();
}
}

View File

@ -0,0 +1,21 @@
// *** Hardwarespecific defines ***
#if !defined(_UP_MCU_)
#if defined(__32MX320F128H__)
#define SDA 18 // A4 (Remeber to set the jumper correctly)
#define SCL 19 // A5 (Remeber to set the jumper correctly)
#elif defined(__32MX340F512H__)
#define SDA 18 // A4 (Remeber to set the jumper correctly)
#define SCL 19 // A5 (Remeber to set the jumper correctly)
#elif defined(__32MX795F512L__)
#define SDA 20 // Digital 20
#define SCL 21 // Digital 21
#else
#error "Unsupported PIC32 MCU!"
#endif
#endif
#ifndef TWI_FREQ
#define TWI_FREQ 400000L
#endif