Zápisník experimentátora
Hierarchy: DS1307 Hodiny reálneho času
Integrovaný obvod DS1307 má jeden vývod označený jako SQW. Na něm je možné zapnout generování signálu s obdélníkovým průběhem. Generovaný signál může mít nastavenou různou frekvenci. V tomto článku si ukážeme nastavení frekvence signálu a připojíme ho na přerušení v Arduinu.
Použil jsem tyto součástky:
Výstup signálu SQW je zapojen jako tranzistor s otevřeným kolektorem. Aby se na něm objevoval signál, je třeba vývod pomocí rezistoru připojit na VCC. Hodnota rezistoru není kritická. Rezistor omezuje velikost proudu a v tomto případě nám slouží pouze jako signál. Vhodné hodnoty jsou 10k nebo 4k7. V žádném případě ho nesmíte připojit bez rezistoru, protože byste skratovali VCC a GND.
Napsal jsem dva vzorové příklady:
Oba programy využívají podobné nastavení v registru integrovaného obvodu. Nastavením bitu SQWE
se zapíná generování signálu s obdélníkovým průběhem a nastavením bitů RS1
a RS2
se nastavuje frekvence. Lze nastavit čtyři různé frekvence. Protože v našich programech chceme vidět generovaný signál, budeme používat frekvenci 1 Hz.
První program navazuje na předchozí článek, kde jsme si vytvořili třídu DS1307RTCex
, která vypisuje na sériový port obsah RAM v integrovaném obvodu. Vypisování obsahu RAM jsem v programu ponechal a doplnil jsem pouze funkci setSQW
. Tato funkce nastaví obsah registru 7 a tím nastaví průběh generovaného signálu.
Třeba použít zapojení podle schématu, které se nachází u obvodu U2
. Při takovém zapojení bychom sice správně generovali signál, který by přicházel na pin D2
v Arduinu, ale nic bychom neviděli. Proto jsem použil alternativní zapojení podle obvodu U4
. Dioda D1
nám vizualizuje průběh signálu. Já jsem použil modrou LED diodu, ale měla by fungovat prakticky libovolná dioda.
#include <Wire.h>
#include <TimeLib.h>
#include <DS1307RTC.h>
#define DS1307_CTRL_ID 0x68
class DS1307RTCex : public DS1307RTC {
uint8_t ram[64];
public:
DS1307RTCex() : DS1307RTC() {}
bool readRam() {
uint8_t *ptr = ram;
for (uint8_t x = 0; x <= 4; x++) {
Wire.beginTransmission(DS1307_CTRL_ID);
Wire.write((uint8_t)x * 16);
if (Wire.endTransmission() != 0)
return false;
uint8_t sz = 16;
// block
Wire.requestFrom(DS1307_CTRL_ID, 16);
if (Wire.available() < 16) return false;
while (sz) {
*ptr++ = Wire.read();
sz--;
}
}
return true;
}
void dump() {
uint8_t nRows = 4;
char asciiDump[17];
int value;
for (uint8_t r = 0; r < nRows; r++) {
uint8_t a = 16 * r;
Serial.print(F("0x"));
if ( a < 16 * 16 * 16 ) Serial.print(F("0"));
if ( a < 16 * 16 ) Serial.print(F("0"));
if ( a < 16 ) Serial.print(F("0"));
Serial.print(a, HEX); Serial.print(F(" "));
for (int c = 0; c < 16; c++) {
value = ram[a + c];
if (value < 16)
Serial.print(F("0"));
Serial.print(value, HEX);
Serial.print(c == 7 ? " " : " ");
if ((value >= 0x20) && (value < 0x7f))
asciiDump[c] = value;
else
asciiDump[c] = '.';
}
asciiDump[16] = 0;
Serial.println(asciiDump);
}
}
void setSQW(uint8_t value) {
Wire.beginTransmission(DS1307_CTRL_ID);
Wire.write(7);
Wire.write(value);
Wire.endTransmission();
}
};
DS1307RTCex ex;
void setup() {
Serial.begin(9600);
while (!Serial) ; // wait for serial
delay(200);
Serial.println("DS1307RTC Set SQW");
Serial.println("-----------------");
// off
//ex.setSQW(0x00);
// 1Hz
ex.setSQW(0x10);
// 4.096 kHz
//ex.setSQW(0x11);
// 8.192 kHz
//ex.setSQW(0x12);
// 32.768 kHz
//ex.setSQW(0x13);
if (ex.readRam())
ex.dump();
else
Serial.println("DS1307RTC Communication error");
}
void loop() {
delay(1000);
}
Tento program využívá generovaný signál s obdélníkovým průběhem a reaguje na něj pomocí přerušení. Přerušení je nastaveno pomocí funkce attachInterrupt
. Přerušení je nastaveno na klesající hranu. Výsledkem je blikání interní LED diodou, která bliká poloviční frekvencí. To proto, že reaguje pouze na klesající hranu, kdy přepíná stav interní LED diody.
Třeba použít zapojení podle schématu, které se nachází u obvodu U2
. Při takovém zapojení bychom sice správně generovali signál, který by přicházel na pin D2
v Arduinu, ale nic bychom neviděli. Proto jsem použil alternativní zapojení podle obvodu U4
. Dioda D1
nám vizualizuje průběh signálu. Já jsem použil modrou LED diodu, ale měla by fungovat prakticky libovolná dioda. Pokud bychom chtěli mít jistotu, že přidáním LED diody neovlivníme logický signál pro Arduino, měli bychom obvod zapojit pomocí tranzistoru Q1
, tak jak je to na ukázce podle obvodu U3
.
#include <Wire.h>
#define DS1307_CTRL_ID 0x68
#define ledPin LED_BUILTIN
void setSQW(uint8_t value) {
Wire.beginTransmission(DS1307_CTRL_ID);
Wire.write(7);
Wire.write(value);
Wire.endTransmission();
}
void handleInt() {
digitalWrite(ledPin, digitalRead(ledPin) ^ 1);
}
void setup() {
Serial.begin(9600);
while (!Serial) ; // wait for serial
delay(200);
Serial.println("DS1307RTC Set SQW 1 Hz");
Serial.println("Attach interrupt on D2");
Serial.println("----------------------");
pinMode(ledPin,OUTPUT);
// D2 on Arduino Uno
// D2 on Arduino Mega 2560
attachInterrupt(0,handleInt,FALLING);
// 1Hz
setSQW(0x10);
}
void loop() {
}
Zdrojový kód se nachází na serveru GitHub.
01.10.2017