DS1307 a signál obdélníkového průběhu

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žité součástky

Použil jsem tyto součástky:

  • Arduino Mega 2560 ((link)
  • DS1307 (link)
  • Breadboard (link)
  • 3x 10k rezistor - SCL, SDA, SQW
  • 1x modrá LED dioda
  • Baterie CR2032 (link)
  • Battery Socket Holder (link)

Signál s obdélníkovým průběhem

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.

Programy

Napsal jsem dva vzorové příklady:

  • set_sqw_1 - Vzorový příklad pro zapnutí signálu s obdélníkovým průběhem. V programu je nastavena frekvence 1 Hz a zapoznámkované nastavení ostatních frekvencí (4,096 kHz, 8,192 kHz a 32,768 kHz). Ke výstupu SQW lze připojit LED diodu a sledovat blikání na frekvenci 1 Hz.
  • set_sqw_interrupt - V tomto příkladu je zapnutý signál s obdélníkovým průběhem 1 Hz. Výstup je připojen na pin, který poskytuje Arduinu přerušení 0. 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.

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.

set_sqw_1

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);
}

set_sqw_interrupt

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

Zdrojový kód se nachází na serveru GitHub.



Download
  • DS1307 - Datasheet DS1307 - 64 x 8 Serial Real-Time Clock

01.10.2017


Menu