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.
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".
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.