Serwisy partnerskie:
Close icon
Serwisy partnerskie

7-segmentowy mini zegar wykorzystujący PIC16F628A i DS1307 RTC

Article Image
Elmax
Oto mały zegar oparty na mikrokontrolerze PIC16F628A i układzie scalonym DS1307 RTC. Jest on w stanie pokazywać tylko czas na małym 7-segmentowym wyświetlaczu o łącznej liczbie 4 segmentów.

Wyświetlacz, którego użyliśmy to 0,28″ SR440281N RED ze wspólną katodą, ale możesz użyć również innych wyświetlaczy, takich jak 0,56″ Kingbright CC56-21SRWA. Ten projekt jest mocno inspirowany przez "Simple Digital Clock with PIC16F628A and DS1307" w przypadku schematu i użyliśmy również tego samego .hex co "Christo".

Schemat

Schemat jest prosty. Sercem jest mikrokontroler PIC16F628A pracujący na wewnętrznym oscylatorze 4MHz, więc nie jest potrzebny zewnętrzny kwarc. Oszczędza to nam 2 dodatkowe IO. Pin RESET (MCLR) jest również używany jako wejście dla jednego z przycisków. Wszystkie segmenty wyświetlacza są podłączone do PORTB, a COMy są podłączone do PORTA. Układ RTC jest również podłączony do PORTA za pomocą magistrali I2C.

Schemat elektryczny mini zegara

Częstotliwość odświeżania cyfr wynosi około 53 Hz i nie ma widocznego migotania. Segmenty wyświetlacza są multipleksowane czasowo, co powoduje, że wydają się one ciemniejsze niż w specyfikacji. Aby to skompensować zamierzamy użyć kilku rezystorów na anodach. "Christo" testował go z różnymi wartościami rezystorów ograniczających prąd R1-R7 i poniżej 220 Ω mikrokontroler zaczyna się źle zachowywać (niektóre cyfry zaczynają migotać), powyżej 220 Ω wszystko wydaje się być w porządku. Na zastosowanym przez nas wyświetlaczu dwie środkowe kropki nie są podłączone do żadnego pinu na pakiecie, więc do wskaźników sekundowych użyliśmy kropek "przecinków". Te piny są podłączone do pinu SQW układu DS1307, który dostarcza na wyjście przebieg prostokątny o okresie 1 sekundy. Pin SQW jest otwarty, więc musimy dodać rezystor podciągający. Wartość tego rezystora została wybrana na 470 Ω, po kilku próbach i błędach. Po stronie wejściowej MCU znajdują się dwa przyciski do ustawiania MINUT i GODZIN zegara, jak pokazano na schemacie. Na płytce znajduje się również złącze do programowania ICSP, aby pomóc we wgrywaniu firmware. Na koniec pozostał jeden niewykorzystany pin (RB7), który można wykorzystać do dodatkowych funkcji, takich jak dodanie brzęczyka lub dodatkowej diody LED.

RTC DS1307 potrzebuje zewnętrznego kwarcu do podtrzymania wewnętrznego zegara oraz zapasowej baterii do podtrzymania pracy, gdy główne zasilanie jest wyłączone. Dzięki temu, przy następnym włączeniu zasilania zegar będzie wskazywał aktualny czas. Aby zachować małe wymiary płytki zastosowaliśmy uchwyt na baterię CR1220 z odpowiednią baterią 3 V. Pobór prądu wynosi około 35-40 mA przy napięciu wejściowym 5 V.

Kod

Jak podaje autor, kod został napisany i skompilowany za pomocą MikroC Pro i wykorzystuje wbudowaną programową bibliotekę I2C do komunikacji z układem RTC. Jeśli chcesz użyć MPLAB IDE do kompilacji kodu powinieneś napisać własną bibliotekę I2C od podstaw. Do programowania płytki użyliśmy programatora i oprogramowania PICkit 3. W tym przypadku w menu "Tools" należy zaznaczyć opcję "Use VPP First Program Entry".

Konfiguracja programatora PIC

Kod dla tego projektu jest podany poniżej. Dodatkowo potrzebny będzie plik "Digital Clock (PIC16F628A, DS1307, v2).h", który znajduje się w pliku .zip w plikach do pobrania poniżej. Skompilowany plik .hex jest również dostarczony w tym samym pliku .zip.

#include "Digital Clock (PIC16F628A, DS1307, v2).h"
#define b1 RA6_bit
#define b2 RA5_bit

// b1_old, b2_old - old state of button pins
// hour10, hour1 - tens and ones of the hour
// min10, min1 = tens and ones of the minutes
byte b1_old, b2_old, hour1, hour10, min1, min10;

// definitions for Software_I2C library
sbit Soft_I2C_Scl           at RA0_bit;
sbit Soft_I2C_Sda           at RA7_bit;
sbit Soft_I2C_Scl_Direction at TRISA0_bit;
sbit Soft_I2C_Sda_Direction at TRISA7_bit;


//  correct bits for each digit
//     RB6 RB5 RB4 RB3 RB2 RB1 RB0
//     g   f   e   d   c   b   a
//  0: 0   1   1   1   1   1   1   0x3F
//  1: 0   0   0   0   1   1   0   0x06
//  2: 1   0   1   1   0   1   1   0x5B
//  3: 1   0   0   1   1   1   1   0x4F
//  4: 1   1   0   0   1   1   0   0x66
//  5: 1   1   0   1   1   0   1   0x6D
//  6: 1   1   1   1   1   0   1   0x7D
//  7: 0   0   0   0   1   1   1   0x07
//  8: 1   1   1   1   1   1   1   0x7F
//  9: 1   1   0   1   1   1   1   0x6F
// BL: 0   0   0   0   0   0   0   0x00

const byte segments[11] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x00};


//***********************************************//
//   Sets read or write mode at select address   //
//***********************************************//
void DS1307_Select(byte Read, byte address) {
     Soft_I2C_Start();
     Soft_I2C_Write(0xD0);       // start write mode
     Soft_I2C_Write(address);    // write the initial address
     if (Read) {
        Soft_I2C_Stop();
        Soft_I2C_Start();
        Soft_I2C_Write(0xD1);    // start read mode
     }
}

//********************************//
//   Initialize the DS1307 chip   //
//********************************//
void DS1307_Init() {
     byte sec, m, h;
     DS1307_Select(1, 0);                 // start reading at address 0
     sec = Soft_I2C_Read(1);              // read seconds byte
     m = Soft_I2C_Read(1);                // read minute byte
     h = Soft_I2C_Read(0);                // read hour byte
     Soft_I2C_Stop();
     if (sec > 127) {                     // if the clock is not running  (bit 7 == 1)
        DS1307_Select(0, 0);              // start writing at address 0
        Soft_I2C_Write(0);                // start the clock (bit 7 = 0)
        Soft_I2C_Stop();
        DS1307_Select(0, 7);              // start writing at address 7
        Soft_I2C_Write(0b00010000);       // enable square wave output 1 Hz
        Soft_I2C_Stop();
     }
     m = (m >> 4)*10 + (m & 0b00001111);  // converting from BCD format to decimal
     if (m > 59) {
        DS1307_Select(0, 1);              // start writing at address 1
        Soft_I2C_Write(0);                // reset the minutes to 0
        Soft_I2C_Stop();
     }
     if (h & 0b01000000) {                // if 12h mode (bit 6 == 1)
        if (h & 0b00100000)               // if PM (bit 5 == 1)
           h = 12 + ((h >> 4) & 1)*10 + (h & 0b00001111);
        else
           h = ((h >> 4) & 1)*10 + (h & 0b00001111);
     }
     else
        h = ((h >> 4) & 3)*10 + (h & 0b00001111);
     if (h > 23) {
        DS1307_Select(0, 2);              // start writing at address 2
        Soft_I2C_Write(0);                // reset the hours to 0 in 24h mode
        Soft_I2C_Stop();
     }
}


void incrementH() {     // increments hours and write it to DS1307
     hour1++;
     if ((hour10 < 2 && hour1 > 9) || (hour10 == 2 && hour1 > 3)) {
        hour1 = 0;
        hour10++;
        if (hour10 > 2)
           hour10 = 0;
     }
     DS1307_Select(0, 2);
     Soft_I2C_Write((hour10 << 4) + hour1);
     Soft_I2C_Stop();
}


void incrementM() {     // increments minutes and write it to DS1307
     min1++;
     if (min1 > 9) {
        min1 = 0;
        min10++;
        if (min10 > 5)
           min10 = 0;
     }
     DS1307_Select(0, 0);
     Soft_I2C_Write(0);                       // reset seconds to 0
     Soft_I2C_Write((min10 << 4) + min1);     // write minutes
     Soft_I2C_Stop();
}

void main(){
     // pos: current digit position;
     // counter1, counter2: used as flag and for repeat functionality for the buttons
     // COM[]: drive the common pins for the LED display
     byte pos, counter1, counter2, COM[4] = {0b11101111, 0b11110111, 0b11111011, 0b11111101};
     CMCON = 0b00000111;             // comparator off
     TRISA = 0b01100000;
     TRISB = 0b00000000;
     b1_old = 1;
     b2_old = 1;
     counter1 = 0;
     counter2 = 0;
     pos = 0;
     Soft_I2C_Init();
     DS1307_Init();
     while (1) {
           DS1307_Select(1, 1);      // select reading at address 1
           min1 = Soft_I2C_Read(1);  // read minutes byte
           hour1 = Soft_I2C_Read(0); // read houts byte
           Soft_I2C_Stop();
           min10 = min1 >> 4;
           min1 = min1 & 0b00001111;
           hour10 = hour1 >> 4;
           hour1 = hour1 & 0b00001111;
           if (b1 != b1_old) {        // if the button1 is pressed or released
              b1_old = b1;
              counter1 = 0;
           }
           if (!b1_old) {             // if the button1 is pressed
              if (counter1 == 0)
                 incrementH();        // increment hour
              counter1++;
              if (counter1 > 50)      // this is repeat functionality for the button1
                 counter1 = 0;
           }
           if (b2 != b2_old) {        // if the button2 is pressed or released
              b2_old = b2;
              counter2 = 0;
           }
           if (!b2_old) {             // if the button2 is pressed
              if (counter2 == 0)
                 incrementM();        // increment minutes and reset the seconds to 0
              counter2++;
              if (counter2 > 50)      // this is repeat functionality for the button2
                 counter2 = 0;
           }

           TRISA = TRISA | 0b00011110;       // set all 4 pins as inputs
           switch (pos) {                    // set proper segments high
             case 0: PORTB = segments[hour10]; break;
             case 1: PORTB = segments[hour1]; break;
             case 2: PORTB = segments[min10]; break;
             case 3: PORTB = segments[min1]; break;
           }
           TRISA = TRISA & COM[pos];         // set pin at current position as output
           PORTA = PORTA & COM[pos];         // set pin at current position low
           pos++;                            // move to next position
           if (pos > 3) pos = 0;
     }
}

PCB

Płytka PCB została zaprojektowana w programie Autodesk EAGLE, a pliki projektowe są dostępne w plikach do pobrania poniżej. Całkowite wymiary płytki to 35,56 × 36,61 mm i użyliśmy prawie wszystkich elementów SMD.

Nasze PCB są dostępne do wysyłki na całym świecie. Jeśli chciałbyś otrzymać kilka sztuk, napisz do nas.

Wykaz elementów
Ilość
Symbol
Nazwa/opis/gdzie kupić
7
R1 - R7
220Ω 805
4
R8, R9, R11, R12
10k 805
2
C1, C2
100nF 0805
1
LED Display
SR440281N 0.28"
2
HRS, MIN
Przyciski
Galeria
DATA SHEET
DATA SHEET
Wideo
Do pobrania
Download icon Pliki Altium Designera Download icon Gerber Download icon Wsad mikrokontrolera Download icon Pliki Eagle'a Download icon Nota aplikacyjna Download icon Nota aplikacyjna

Artykuł 7-SEGMENT MINI CLOCK USING PIC16F628A AND DS1307 RTC opracowano w wersji polskiej na podstawie współpracy z portalem www.electronics-lab.com.

Firma:
Tematyka materiału: PIC16F628A, DS1307 RTC
AUTOR
Źródło
www.electronics-lab.com
Udostępnij
Zobacz wszystkie quizy
Quiz weekendowy
Edukacja
1/10 Jak działa rezystor LDR?
UK Logo
Elektronika dla Wszystkich
Zapisując się na nasz newsletter możesz otrzymać GRATIS
najnowsze e-wydanie magazynu "Elektronika dla Wszystkich"