mirror of
https://github.com/dustinbrun/Binaeruhr-Arduino.git
synced 2025-04-01 07:07:41 +00:00
Upload 1
This commit is contained in:
commit
ef7328c0f1
BIN
Binaeruhr.fzz
Normal file
BIN
Binaeruhr.fzz
Normal file
Binary file not shown.
BIN
Binaeruhr_Platine.fzz
Normal file
BIN
Binaeruhr_Platine.fzz
Normal file
Binary file not shown.
BIN
Frontplatte.pdf
Normal file
BIN
Frontplatte.pdf
Normal file
Binary file not shown.
BIN
Frontplatte.png
Normal file
BIN
Frontplatte.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 203 KiB |
BIN
Frontplatte_10x15_Bilderrahmen.fpd
Normal file
BIN
Frontplatte_10x15_Bilderrahmen.fpd
Normal file
Binary file not shown.
46
README.md
Normal file
46
README.md
Normal 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>.
|
||||
|
||||
|
BIN
pictures/Binaeruhr_Platine_Leiterplatte.png
Normal file
BIN
pictures/Binaeruhr_Platine_Leiterplatte.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 103 KiB |
BIN
pictures/Binaeruhr_Schaltplan.png
Normal file
BIN
pictures/Binaeruhr_Schaltplan.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 176 KiB |
BIN
pictures/Uhr_1.jpg
Normal file
BIN
pictures/Uhr_1.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 234 KiB |
BIN
pictures/Uhr_2.jpg
Normal file
BIN
pictures/Uhr_2.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 269 KiB |
BIN
pictures/Uhr_innen.jpg
Normal file
BIN
pictures/Uhr_innen.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 375 KiB |
179
software_binaeruhr/software_binaeruhr.ino
Normal file
179
software_binaeruhr/software_binaeruhr.ino
Normal 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);
|
||||
}
|
447
software_binaeruhr/src/DS3231.cpp
Normal file
447
software_binaeruhr/src/DS3231.cpp
Normal 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;
|
||||
}
|
||||
|
123
software_binaeruhr/src/DS3231.h
Normal file
123
software_binaeruhr/src/DS3231.h
Normal 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
|
154
software_binaeruhr/src/hardware/arm/HW_ARM.h
Normal file
154
software_binaeruhr/src/hardware/arm/HW_ARM.h
Normal 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();
|
||||
}
|
||||
}
|
||||
|
13
software_binaeruhr/src/hardware/arm/HW_ARM_defines.h
Normal file
13
software_binaeruhr/src/hardware/arm/HW_ARM_defines.h
Normal 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
|
153
software_binaeruhr/src/hardware/avr/HW_AVR.h
Normal file
153
software_binaeruhr/src/hardware/avr/HW_AVR.h
Normal 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();
|
||||
}
|
||||
}
|
||||
|
6
software_binaeruhr/src/hardware/avr/HW_AVR_defines.h
Normal file
6
software_binaeruhr/src/hardware/avr/HW_AVR_defines.h
Normal file
@ -0,0 +1,6 @@
|
||||
// *** Hardwarespecific defines ***
|
||||
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
|
||||
|
||||
#ifndef TWI_FREQ
|
||||
#define TWI_FREQ 400000L
|
||||
#endif
|
192
software_binaeruhr/src/hardware/pic32/HW_PIC32.h
Normal file
192
software_binaeruhr/src/hardware/pic32/HW_PIC32.h
Normal 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();
|
||||
}
|
||||
}
|
21
software_binaeruhr/src/hardware/pic32/HW_PIC32_defines.h
Normal file
21
software_binaeruhr/src/hardware/pic32/HW_PIC32_defines.h
Normal 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
|
||||
|
Loading…
Reference in New Issue
Block a user