Zápisník experimentátora
Hierarchy: DS1307 Hodiny reálneho času
Integrovaný obvod DS1307 má jeden vývod označený ako SQW. Na ňom je možné zapnúť generovanie signálu s obdĺžnikovým priebehom. Generovaný signál môže mať nastavenú rôznu frekvenciu. V tomto článku si ukážeme nastavenie frekvencie signálu a pripojíme ho na prerušenie v Arduine.
Použil som tieto súčiastky:
Výstup signálu SQW je zapojený ako tranzistor s otvoreným kolektorom. Aby sa na ňom objavoval signál, je potrebné vývod pomocou rezistora pripojiť na VCC. Hodnota rezistora nie je kritická. Rezistor obmedzuje veľkosť prúdu a v tomto prípade nám slúži iba ako signál. Vhodné hodnoty sú 10k alebo 4k7. V žiadnom prípade ho nesmiete pripojiť bez rezistora, pretože by ste skratovali VCC a GND.
Napísal som dva vzorové príklady:
Oba programy využívajú podobné nastavenie v registri integrovaného obvodu. Nastavením bitu SQWE
sa zapína generovanie signálu s obdĺžnikovým priebehom a nastavením bitov RS1
a RS2
sa nastavuje frekvencia. Možno nastaviť štyri rôzne frekvencie. Pretože v našich programoch chceme vidieť generovaný signál, budeme používať frekvenciu 1 Hz.
Prvý program nadväzuje na predchádzajúci článok, kde sme si vytvorili triedu DS1307RTCex
, ktorá vypisuje na sériový port obsah RAM v integrovanom obvode. Vypisovanie obsahu RAM som v programe ponechal a doplnil som iba funkciu setSQW
. Táto funkcia nastaví obsah registra 7 a tým nastaví priebeh generovaného signálu.
Treba použiť zapojenie podľa schémy, ktoré sa nachádza pri obvode U2
. Pri takomto zapojení by sme síce správne generovali signál, ktorý by prichádzal na pin D2 v Arduine, ale nič by sme nevideli. Preto som použil alternatívne zapojenie podľa obvodu U4
. Dióda D1 nám vizualizuje priebeh signálu. Ja som použil modrú LED diódu, ale mala by fungovať prakticky ľubovoľná dióda.
#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žíva generovaný signál s obdĺžnikovým priebehom a reaguje naň pomocou prerušenia. Prerušenie je nastavené pomocou funkcie attachInterrupt
. Prerušenie je nastavené na klesajúcu hranu. Výsledkom je blikanie internou LED diódou, ktorá bliká polovičnou frekvenciou. To preto, lebo reaguje iba na klesajúcu hranu, kedy prepína stav internej LED diódy.
Treba použiť zapojenie podľa schémy, ktoré sa nachádza pri obvode U2
. Pri takomto zapojení by sme síce správne generovali signál, ktorý by prichádzal na pin D2 v Arduine, ale nič by sme nevideli. Preto som použil alternatívne zapojenie podľa obvodu U4
. Dióda D1 nám vizualizuje priebeh signálu. Ja som použil modrú LED diódu, ale mala by fungovať prakticky ľubovoľná dióda. Ak by sme chceli mať istotu, že pridaním LED diódy neovplyvníme logický signál pre Arduino, mali by sme obvod zapojiť pomocou tranzistora Q1
, tak ako je to na ukážke podľa 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 sa nachádza na serveri GitHub.
30.09.2017