logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Prosty zegar na PIC12F683 - trzy piny, dwie magistrale I2C - DS1307 + FD650

p.kaczmarek2 26 Kwi 2026 08:53 1935 1

TL;DR LABEL_AI_GENERATED

  • Zbudowano miniaturowy zegar na PIC12F683 z wyświetlaczem 7-segmentowym FD650 i RTC DS1307, zasilany i sterowany na dwóch magistralach I2C.
  • Kluczowym trikiem było rozdzielenie SDA dla FD650 i DS1307 przy wspólnym SCL, bo FD650 nie trzyma standardu I2C i zajmuje wiele adresów.
  • PIC12F683 ma tylko 128 bajtów RAM, więc kod mocno zoptymalizowano, a komunikację I2C zbadano analizatorem logicznym.
  • Układ działa: odlicza czas, wyświetla go w formacie mm:ss i pozwala ustawiać godzinę oraz minutę dwoma przyciskami.
  • Po rozbudowie zabrakło miejsca w pamięci, więc trzeba było upraszczać kod i przenosić część testów na Arduino.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA
Słuchaj:
  • Prosty zegar na PIC12F683 - trzy piny, dwie magistrale I2C - DS1307 + FD650
    Dzisiaj budujemy malutki zegar z podtrzymaniem czasu, zrealizujemy go w oparciu o 8-bitowy mikrokontroler PIC12F683 z jedynym 128 bajtów pamięci RAM, moduł wyświetlacza 7-segmentowego z kontrolerem FD650 odzyskany z elektrośmieci oraz zegar RTC DS1307. W temacie też pokażę pełne przebiegi z komunikacji I2C przechwyconej analizatorem logicznym.

    Czemu nie jedna magistrala I2C?
    Zacznijmy od najważniejszego problemu projektowego i oczywistego pytania, które pewnie każdemu się nasuwa po przeczytaniu wstępu do tego tematu - po co w ogóle dwie magistrale I2C? Czy nie można użyć adresów?
    Tak się niestety składa, że duża ilość popularnych chińskich układów nie trzyma się w pełni standardu I2C i nie wspiera adresowania - tam pierwszy wysyłany bajt nie jest adresem indywidualnego układu, lecz np. komendą lub od razu adresem rejestru na na którym operujemy.
    Podobny problem jest w przypadku FD650, na którym oparłem tą konstrukcję. FD650 to klon TM1650, występuje też pod nazwą HD2015. Opisywałem już go szeroko w jednym z tematów:
    Uruchamiamy sterownik wyświetlacza/przycisków HD2015 po inżynierii wstecznej, porównanie z TM1637
    FD650 ma właśnie tą przypadłość, że zakłócać będzie nam inne adresy na magistrali.
    Drugi użyty w projekcie element, DS1307, jest w pełni zgodny z I2C i nie robi problemu, ale co z tego?
    Trzeba rozdzielić magistralę - zdecydowałem się mieć dwie linie danych SDA i wspólny zegar SCL.

    Organizacja pracy
    Projekt jest dość złożony, więc dla uproszczenie pierwsze etapy wykonałem na Arduino. Było to podyktowane przede wszystkim chęcią sprawdzenia, czy mój moduł z FD650 przeżył operację. Dopiero po upewnieniu się, że jest z nim wszystko okej, przeniosę kod na PICa.

    Moduł z FD650
    Moduł odzyskałem ze starego odbiornika telewizji naziemnej. Sprzęt nie miał pilota i nie wspierał już nowszych standardów z DVB-T2. Od jakiegoś czasu dość często tego typu sprzęty otrzymuję, więc odzyskuję z nich masowo części. Nie miałem już miejsca na kolejną płytkę, więc pozwoliłem sobie wyciąć jedynie to, co mi się przyda:
    Prosty zegar na PIC12F683 - trzy piny, dwie magistrale I2C - DS1307 + FD650
    Oprócz czterocyfrowego wyświetlacza 7-segmentowego jest tam jeszcze jego kontroler, FD650, oraz jakiś układ od RF (tutaj zbędny - do usunięcia).
    Prosty zegar na PIC12F683 - trzy piny, dwie magistrale I2C - DS1307 + FD650
    Układ na płytce może wydawać się niekompletny, ale nic bardziej mylnego. FD650 potrzebuje do działania naprawdę mało komponentów. Poniżej przedstawiam jego przykładową aplikację, która jest w dużej mierze zgodna z tym, co mam na płytce. Usunąłem jedynie przyciski.
    Prosty zegar na PIC12F683 - trzy piny, dwie magistrale I2C - DS1307 + FD650
    Jak widać, nawet nie potrzeba wielu rezystorów - tylko ten 2 kΩ od przycisków. Wyświetlacz LED wcale dodatkowych oporników nie potrzebuje.



    Skan I2C z FD650
    Nie musicie mi jednak wierzyć na słowo. Prosty skan I2C jest łatwo uruchomić, wystarczy odpytywać kolejne adresy i sprawdzać sygnał ACK. Dla wygody zrealizowałem to na Arduino. Nie musiałem nawet dawać zewnętrznego rezystora pull up (podciągającego do zasilania), bo Arduino pozwala skonfigurować w tym trybie pin. Odpytywanie odbywa się w pętli i te aktywne są wypisywane na UART:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Na magistrali jest tylko FD650, ale zgłasza się mnóstwo adresów. Zgodnie z obawami.
    Prosty zegar na PIC12F683 - trzy piny, dwie magistrale I2C - DS1307 + FD650
    Dla weryfikacji odłączyłem jedną z linii - od razu komunikacja zostaje przerwana:
    Prosty zegar na PIC12F683 - trzy piny, dwie magistrale I2C - DS1307 + FD650

    Pierwsze segmenty
    Ten akapit będzie skrócony do minimum, gdyż zasadniczo powtórzyłem to 1:1 pracę z poprzedniej prezentacji:
    Uruchamiamy sterownik wyświetlacza/przycisków HD2015 po inżynierii wstecznej, porównanie z TM1637
    Wszystko od razu ruszyło i nie było problemu z segmentami i czcionką. Wygląda na to, że mapowanie segment na pin jest tutaj ustandaryzowane, dzięki temu większość tunerów (czy tam urządzeń?) opartych o FD650 i klony może mieć ten sam kod obsługi.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Prosty zegar na PIC12F683 - trzy piny, dwie magistrale I2C - DS1307 + FD650



    Prosty zegar
    Następnie wdrożyłem funkcję showTime, która pozwala po prostu rozdzielić dwie wartości liczbowe na jedności i dziesiątki, a potem ustawia je na odpowiednich pozycjach i wysyła do wyświetlacza. Nie operuję tutaj na stringu (łańcuch znaków), bo bym musiał ręcznie przesuwać liczbę i dopisywać 0 dla wartości minut i godzin z zakresu od 0 do 9.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Działa:






    Port na PIC12F
    Pora przenieść program na PIC12F. Logika zostanie bez zmian, zmienią się operacje na pinach. Na PICu bezpośrednio wykonujemy to na rejestrach. Dodatkowo ustawiam dla niego wewnętrzny oscylator, taki wystarczy, i tak mam inne plany co do zliczania czasu.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Te delay_ms chyba nawet nie jest przeliczone do bieżącej konfiguracji oscylatora i przekłamuje, ale to nie jest problem, i tak w finalnym produkcie nie powinno być tego typu blokujących oczekiwań. Użyjemy do tego czegoś lepszego.

    Skupmy się na razie na samej komunikacji przez I2C. Warto podejrzeć, co dzieje się na magistrali. Użyłem do tego analizatora stanów logicznych, prezentowałem go już w osobnym temacie:
    Analizator stanów logicznych Salae 24MHz za 40 zł - analiza nieznanego protokołu wyświetlacza LED
    Do zebranych danych dodałem też dekoder I2C, by widzieć przesyłane bajty.
    Najpierw całe transakcje - widać, jak dane są wysyłane co te (powiedzmy) 250 ms na wyświetlacz:
    Prosty zegar na PIC12F683 - trzy piny, dwie magistrale I2C - DS1307 + FD650
    Po przybliżeniu widzimy pojedynczą operację showTime, na nią składa się zbiór operacji zapisu danych do FD650.
    Prosty zegar na PIC12F683 - trzy piny, dwie magistrale I2C - DS1307 + FD650
    Mamy tu kolejno uruchomienie wyświetlacza (zapis 0x11 na adres 0x48) i zapis czterech znaków (adresy 0x68, 0x6A, 0x6C, 0x6E). Ostatnia operacja to powtórne włączenie wyświetlacza - zbędne, zostało na skutek moich eksperymentów i zapomniałem je usunąć do zdjęć.
    Przykładowe zbliżenie na operację uruchomienia wyświetlacza:
    Prosty zegar na PIC12F683 - trzy piny, dwie magistrale I2C - DS1307 + FD650
    Analogicznie, zapis znaków:
    Prosty zegar na PIC12F683 - trzy piny, dwie magistrale I2C - DS1307 + FD650
    Prosty zegar na PIC12F683 - trzy piny, dwie magistrale I2C - DS1307 + FD650


    Integracja DS1307
    Teraz pora wprowadzić DS1307. DS1307 to tzw. RTC (Real Time Clock), czyli układ zegara czasu rzeczywistego, który służy do podtrzymywania aktualnej daty i godziny, nawet gdy mikrokontroler jest wyłączony lub resetowany.
    Prosty zegar na PIC12F683 - trzy piny, dwie magistrale I2C - DS1307 + FD650
    Dzięki zastosowaniu zewnętrznej baterii podtrzymującej (najczęściej CR2032) DS1307 może pracować niezależnie od zasilania głównego układu. Komunikacja z mikrokontrolerem odbywa się poprzez I2C.
    Mój moduł z DS1307 ma jeszcze na pokładzie pamięć EEPROM, ale na razie tu ją pominę.
    Cały problem tutaj polega na tym, że nie mogę umieścić DS na tej samej magistrali co FD650, bo FD650 nie wspiera zasadniczo adresowania i zajmuje wszystkie adresy - pokazałem to w akapicie "Skan I2C z FD650".
    Z tego powodu wprowadziłem podzielenie magistrali, zgodnie z zapowiedzią.
    Teraz:
    - SDA wyświetlacza to pin 0
    - wspólny SCL to pin 2
    - SDA zegara to pin 1
    W celu oszczędności pamięci, złamałem zasadę DRY (Don't Repeat Yourself) i przygotowałem dwa zestawy funkcji I2C - jedne dla pin 0, drugie dla pinu 1.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Rezystory pull up okazały się być znów zbędne - te z PICa starczają. Pokazany kod działa - czas jest odliczany i wyświetlany. Wcześniej RTC trzeba było raz zaprogramować, ale na razie załóżmy, że zrobiliśmy to ręcznie, osobno...
    Zdjęcia pokazują czas w formacie mm:ss, dlatego może wydawać się on dziwny, ale tak wygodniej się testuje.
    Prosty zegar na PIC12F683 - trzy piny, dwie magistrale I2C - DS1307 + FD650
    Prosty zegar na PIC12F683 - trzy piny, dwie magistrale I2C - DS1307 + FD650 Prosty zegar na PIC12F683 - trzy piny, dwie magistrale I2C - DS1307 + FD650
    Jak wygląda to pod maską? Podłączyłem analizator logiczny do linii D0 (zegar), D1 (SDA pierwsze) i D2 (SDA drugie). Dodałem dekodery I2C.
    Prosty zegar na PIC12F683 - trzy piny, dwie magistrale I2C - DS1307 + FD650
    Po powiększeniu widać poprawnie dekodowane transakcje. Nie ma problemów z warunkami startu/stopu, nie ma "duchów" na linii:
    Prosty zegar na PIC12F683 - trzy piny, dwie magistrale I2C - DS1307 + FD650
    Tak wygląda odczyt czasu z DS1307. Widać tu charakterystyczny adres 0x68 (po przesunięciu i dodaniu bitu read/write 0xD0 lub 0xD1) i odczyt z rejestrów 0, 1, i 2, wartości 00:28:50.
    Prosty zegar na PIC12F683 - trzy piny, dwie magistrale I2C - DS1307 + FD650
    Analogicznie, kontrola wyświetlacza. Tu widać wysyłane segmenty poszczególnych cyfr.
    Prosty zegar na PIC12F683 - trzy piny, dwie magistrale I2C - DS1307 + FD650

    Odczyt klawiszy
    Kolejnym etapem jest odczyt klawiszy. Nie mam na swojej płytce klawiszy, więc dodałem dwa wedle schematu wcześniej umieszczonego w poście. Potem zaimplementowałem ich odczyt - odczyt przez I2C z adresu 0x27. Zwracany wtedy jest kod klawisza oraz flaga czy jest/był wciśnięty.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Na próbę wyświetlam ten kod na wyświetlaczu w formacie szesnastkowym. Przy okazji dodałem znaki 10-15 do mapy znaków.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Odczyt widać na analizatorze:
    Prosty zegar na PIC12F683 - trzy piny, dwie magistrale I2C - DS1307 + FD650
    W ten sposób łatwo można zidentyfikować kody posiadanych klawiszy:




    Limity, wszędzie limity
    Na tym etapie limity pamięci PICa zaczęły dawać się we znaki:
    
    pic12f683_clockI2C.asm:1877:Message[1304] Page selection not needed for this device. No code generated.
    message: Using default linker script "C:\Program Files (x86)\gputils\lkr\12f683_g.lkr".
    warning: Relocation symbol "_cinit" [0x0000] has no section. (pass 0)
    error: No target memory available for section "IDD_idata_0_i".
    error: Error while writing hex file.
    

    Program przerobiłem i przepisałem tak, aby w miarę możliwości funkcje umieścić w głównej pętli i zredukować ilość zmiennych.

    Finalizacja zegara
    Ostatnim krokiem jest dodanie nastawiania godziny i minuty. Wystarczą do tego te dwa przyciski. Założyłem, że:
    - jeden tylko przełącza tryb (praca, edycja godziny, edycja minuty)
    - drugi zwiększa wybraną wartość, pojedyncze wciśnięcie zwiększa jednokrotnie, a przytrzymanie zwiększa ciągle o 1 dopóki trzymamy klawisz
    W tym celu odczytuję klawisze co pętle, badam aktualny tryb (praca, edycja godziny, edycja minuty), w przypadku edycji migam wybranymi cyframi i odpowiednio obsługuję zdarzenia klawiszy. Po edycji czas jest zapisywany.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Rezultat:




    Kombinacje z obudową
    Zacząłem też robić obudowę, ale o tym będzie w osobnym temacie.
    Prosty zegar na PIC12F683 - trzy piny, dwie magistrale I2C - DS1307 + FD650
    Prosty zegar na PIC12F683 - trzy piny, dwie magistrale I2C - DS1307 + FD650


    Podsumowanie
    Projekt okazał się być bardzo ciekawym i nietypowym doświadczeniem. FD650 uruchamiałem wcześniej, nie było to problemem, ale tutaj przećwiczyłem oszczędzanie pinów (ten PIC12F ma mało wolnych IO, a mogę jeszcze chcieć dodać wkrótce alarm, ADC też by się przydało), a potem ogólną optymalizację. Ostatecznie udało się całość zmieścić na małym PICu i programowo wyszedł funkcjonalny zegar.
    Teraz można jeszcze ogarnąć hardware - pokazaną płytkę można by jeszcze zmniejszyć, pewnie odcinając od niej zbędne fragmenty laminatu, a potem wydrukować na drukarce 3D obudowę i jakoś sprytnie umiejscowić przyciski.
    Być może zajmę się w tym osobnej części.
    Załączam wersję projektu dla SDCC.
    Załączniki:
    • pic12f683_clockI2C.zip (48.54 KB) Musisz być zalogowany, aby pobrać ten załącznik.

    Fajne? Ranking DIY
    Pomogłem? Kup mi kawę.
    O autorze
    p.kaczmarek2
    Moderator Smart Home
    Offline 
    Inżynier programista z wieloletnim doświadczeniem embedded i full stack developer.
    Specjalizuje się w: embedded, Full-Stack Developer
    p.kaczmarek2 napisał 14795 postów o ocenie 12952, pomógł 659 razy. Jest z nami od 2014 roku.
  • REKLAMA
  • #2 21891616
    viayner
    Poziom 43  
    Posty: 10638
    Pomógł: 1563
    Ocena: 2054
    Witam,
    widzę, że z ekolegą już od jakiegoś czasu omawia układy na PIC-ach, czyżby wróciły do łask?
    To już stare, a nawet bardzo stare układy, ale nadal funkcjonalne, sam ich używałem od dawna, zanim jeszcze pojawiło się arduino czy ATmegi.
    Duże brawa za chęć optymalizacji, po trochu wynikającej z hardwareowych ograniczeń, ale chyba też ze starej szkoły, że optymalizacja kodu jest lepsza niż sięganie po lepszy sprzęt, jak widać takie maleństwo daje radę.
    Pozdrawiam
Słuchaj:
REKLAMA