DS1307 a signál obdĺžnikového priebehu

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žité súčiastky

Použil som tieto súčiastky:

  • Arduino Mega 2560 ((link)
  • DS1307 (link)
  • Breadboard (link)
  • 3x 10k rezistor - SCL, SDA, SQW
  • 1x modrá LED dióda
  • Batéria CR2032 (link)
  • Battery Socket Holder (link)

Signál s obdĺžnikovým priebehom

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.

Programy

Napísal som dva vzorové príklady:

  • set_sqw_1 - Vzorový príklad na zapnutie signálu s obdĺžnikovým priebehom. V programe je nastavená frekvencia 1 Hz a zapoznámkované nastavenie ostatných frekvencií (4,096 kHz, 8,192 kHz a 32,768 kHz). Ku výstupu SQW je možné pripojiť LED diódu a sledovať blikanie na frekvencii 1 Hz.
  • set_sqw_interrupt - V tomto príklade je zapnutý signál s obdĺžnikovým priebehom 1 Hz. Výstup je pripojený na pin, ktorý poskytuje Arduinu prerušenie 0. 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.

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.

set_sqw_1

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

set_sqw_interrupt

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

Zdrojový kód sa nachádza na serveri GitHub.



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

30.09.2017


Menu