Firmware w C dla STM8L152 (SDCC). Mapa segmentow LCD zostala wyznaczona recznie
(V1) i jest teraz zaszyta w sterowniku src/lcd_map.c z nazwanym API (cyfry,
gwiazdki, timer, twarz, symbole) zamiast surowych indeksow LCD_RAM.
Plytka oryginalnie dzialala jako zegar z modulem bezprzewodowym (CC2500) na 2x AAA - stad zalozenie o trybie energooszczednym i (prawie na pewno) kwarcu LSE 32.768kHz do dokladnego czasu, ktorego jeszcze nie uzywalismy (patrz sekcja o strojeniu kontrastu ponizej).
- Przyciski: PE6, PE7 (pull-up, aktywne w stanie niskim)
- LCD COM0-3: PA4, PA5, PA6, PD1
- LCD SEG: PA7, PE0, PD0, PD2, PD3, PD4, PD5, PB0, PB1, PB2, PB3 (11 linii)
- CC2500 (SPI, jeszcze nieuzywane w V1): SPI1 na PB4-7 (NSS/SCK/MOSI/MISO), GDO0 = PF0, GDO2 = PC1
Zeby zaswiecic konkretny fizyczny segment na LCD, trzeba wiedziec, ktory bit
ktorego rejestru LCD_RAM0..LCD_RAM21 steruje dana para COM/SEG. Ta mapa jest w
reference manual RM0031, ale nie mielismy jak jej w pelni zweryfikowac automatycznie.
Zamiast zgadywac, ten program pozwala znalezc mape eksperymentalnie na zywej plytce.
Uwaga: Adresy/bity rejestrow CLK_* i LCD_* w inc/stm8l152.h sa potwierdzone
z oficjalnego naglowka stm8l15x.h (projekt STM8L-Discovery, ten sam STM8L152C6).
Pamietaj, ze rejestry maski portow LCD (LCD_PM0..PM5) decyduja, ktore fizyczne
piny w ogole sa podlaczone do kontrolera LCD - PE6/PE7 (LCD_SEG26/LCD_SEG27) sa
u nas przyciskami, wiec ich bity w PM3 musza zostac wylaczone (patrz
LCD_PM3_MASK_NO_PE6_PE7 w inc/stm8l152.h), inaczej LCD przejmuje te piny.
Wymaga sdcc oraz make w PATH (zainstalowane w tym srodowisku przez
winget install SDCC.SDCC i winget install ezwinports.make - po instalacji
przez winget czasem trzeba otworzyc nowy terminal, zeby PATH sie odswiezyl).
make
Wynik: build/firmware.hex (format Intel HEX; rozszerzenie .hex zamiast
.ihx, zeby narzedzia typu STVP, ktore filtruja pliki po rozszerzeniu, w ogole
je widzialy).
Zaleznie od posiadanego programatora:
- ST Visual Programmer (STVP) - oficjalne narzedzie ST, dziala z domyslnym
sterownikiem ST-Link bez dodatkowej konfiguracji:
STVP_CmdLine -BoardName=ST-LINK -Device=STM8L152C6 -FileProg="build\firmware.hex" -no_loop - stm8flash (open-source, wymaga libusb i podmiany sterownika ST-Link na
WinUSB przez Zadig na Windows):
stm8flash -c stlinkv2 -p stm8l152c6 -w build/firmware.hex
(dopasuj -Device/-p do konkretnego wariantu STM8L152, jaki masz na plytce).
Wyznaczona recznie kalibratorem (prosty program przelaczajacy pojedynczy bit
LCD_RAM przyciskami PE6/PE7 - historyczna wersja w git blame/historii czatu).
Kazdy "indeks" ponizej to reg_index * 8 + bit_index; src/lcd_map.c sam go
rozklada z powrotem na rejestr i bit (funkcja lcd_set()).
| Segment | Cyfra1 | Cyfra2 | Cyfra3 | Cyfra4 |
|---|---|---|---|---|
| a | 113 | 111 | 109 | 108 |
| b | 85 | 83 | 81 | 79 |
| c | 57 | 55 | 52 | 22 |
| d | 29 | 27 | 25 | 23 |
| e | 34 | 28 | 26 | 24 |
| f | 90 | 84 | 82 | 80 |
| g | 62 | 56 | 54 | 51 |
| dp | 110 |
| Grupa | Element | Indeks |
|---|---|---|
| Gwiazdki | 1 / 2 / 3 / 4 / 5 | 49 / 21 / 20 / 104 / 76 |
| Timer (pasek) | 0 / 1 / 2 / 3 / 4 | 17 / 18 / 47 / 45 / 101 |
| Timer (ikona) | - | 118 |
| Twarz | mrugniecie / brwi / oko / usta gora / usta dol / kacik | 46 / 73 / 74 / 75 / 103 / 102 |
| Bateria | - | 77 |
| Symbole | jezyk / plus / zab / piorko / diament / fala | 19 / 106 / 112 / 107 / 78 / 50 |
Zamiast pisac bezposrednio w LCD_RAM, uzywaj nazwanego API, np.:
lcd_set_digit(0, 7); /* cyfra1 = "7" */
lcd_set_dp(1); /* zapal kropke */
lcd_set_star(3, 1); /* zapal 3. gwiazdke */
lcd_set_face_eye(1); /* zapal oko na "twarzy" */src/main.c w obecnej formie to self-test: w petli zapala po kolei kazdy
element z mapy powyzej, zeby potwierdzic ze cala mapa dziala na fizycznym LCD.
Kolejny krok: sterownik CC2500 po SPI.
Wyjsciowy objaw: delikatne "cienie" na sasiednich segmentach, poza tym wyswietlacz stabilny. Kolejne proby:
- Kontrast na max (
LCD_CR2_CC_3V3, 3.3V) + High Drive (LCD_CR2_HD), FRQ ~74Hz -> duzo gorzej: nieregularne miganie prawie calego ekranu. - To samo CR2, FRQ podniesione do ~148Hz -> jeszcze gorzej ("dyskoteka", miganie kilkanascie razy/s, zwlaszcza sasiednie segmenty).
Wniosek: skoro pogorszenie nastapilo przy WYZSZEJ czestotliwosci (czyli wiekszej liczbie przelaczen na sekunde), to nie jest problem czestotliwosci ramki, tylko poboru pradu - maksymalny kontrast + High Drive najpewniej przeciazyly wewnetrzna pompe ladunkowa Vlcd (ktora musi obslugiwac wszystkie zapalone segmenty), co objawia sie jako nieregularne "przycinanie" napiecia LCD. Wiecej przelaczen/s = wiecej pradu = gorzej - to sie zgadza.
Aktualny stan w lcd_init() (src/main.c) - powrot do bezpiecznego punktu i
zmiana jednej rzeczy na raz:
LCD_FRQ- nietkniete, wartosc domyslna po resecie (~2.4kHz) - to nie byla przyczyna oryginalnego problemu.LCD_CR2- tylko malutkie podbicie kontrastu (LCD_CR2_CC_2V8, 2.8V, zamiast domyslnych 2.6V), bez High Drive.
Jesli male podbicie kontrastu nie usunie "cieni" na sasiednich segmentach,
podnos CC malymi krokami (nastepny: 0x06 = 2.9V, potem 0x08 = 3.0V -
patrz enum LCD_Contrast_* w oficjalnym stm8l15x_lcd.h), sprawdzajac po
kazdym kroku, czy nie wraca niestabilnosc/miganie. High Drive i zmiane LCD_FRQ
zostawilbym na koniec, dopiero jesli sam kontrast nie wystarczy - obie te
zmiany zwiekszaja pobor pradu i, jak widac powyzej, latwo tym przeciazyc
zasilanie LCD.
-
Interaktywne strojenie na zywo (
src/main.c, przyciski PE6=CCwLCD_CR2, PE7=DEAD(dead time) wLCD_CR3, oba 0..7 z zawijaniem, podglad na cyfrach 2/3) -> zaden z tych parametrow, ani proba zmiany bias (LCD_CR1_B2), nie usunal cieni. Zmiana CC/dead time wplywala zarowno na czytelnosc wybranych segmentow, jak i na cienie razem (skaluja sie proporcjonalnie) - to sugeruje, ze problem NIE jest kwestia poziomu napiecia/timingu do dostrojenia, tylko czegos bardziej fundamentalnego.Wazny fakt: oryginalne (fabryczne) firmware tej plytki wyswietlalo obraz czysto, bez cieni - wiec fizyczny wyswietlacz/okablowanie na pewno sa sprawne, a odtworzenie poprawnej konfiguracji LCD to kwestia znalezienia wlasciwych wartosci rejestrow. Niestety nie ma zachowanego zrzutu oryginalnego firmware (nie da sie go odtworzyc/rozdizasemblowac).
VSELwLCD_CR2(zewnetrzne Vlcd) -> obalone. Wymuszenie VSEL=1 calkowicie gasilo wyswietlacz - ta plytka nie ma zewnetrznej sieci do generowania napiec biasu, wraca na VSEL=0 (wewnetrzna pompa, domyslne).Zwiekszanie
DEAD(dead time) -> obalone. Pogarszalo odczyt zamiast poprawiac, wiec zostaje na 0 (wartosc domyslna).
Podsumowanie: kontrast (CC), dead time, bias (przynajmniej 1/2 vs 1/3) i VSEL zostaly przetestowane i zadne nie usuwa cieni - trzy z nich (dead time w gore, VSEL=external) wrecz pogarszaly sprawe. To silna wskazowka, ze problem nie jest kwestia dostrojenia pojedynczego rejestru analogowego/timingowego, tylko czegos bardziej fundamentalnego w konfiguracji multipleksowania.
-
Pomiar multimetrem (AC) linii COM vs referencyjny SEG (PA7=SEG0, na pewno prawdziwy):
Pin Rola AC PA7 SEG0 (referencja) 1,4V PA5 COM1 0,95V PA6 COM2 0,95V PD1 COM3 0,9V PA4 COM0 0,56V (powtarzalne, potwierdzone na mniejszym zakresie) PA5/PA6/PD1 grupuja sie razem, PA4 wyraznie odstaje (~40% nizej) - w trybie pomiarowym (wszystkie segmenty na stale wlaczone) wszystkie 4 linie COM powinny widziec identyczne obciazenie, wiec to realna anomalia, nie tylko niedokladnosc multimetru na zlozonym przebiegu. Odlozone na boku (do sprawdzenia fizycznie pozniej - ciaglosc/lut na PA4) na rzecz bardziej obiecujacego tropu ponizej.
-
Kontekst: plytka to oryginalnie zegar (2x AAA + CC2500) -> zegarek praktycznie na pewno ma kwarc LSE 32.768kHz do dokladnego czasu, ktorego nigdy nie probowalismy - dotychczas zawsze LSI (niekalibrowany, "jittery" oscylator RC). Niestabilny cykl-do-cyklu timing multipleksowania to prawdopodobna przyczyna cieni niezaleznych od CC/dead time/bias/VSEL, bo RMS-owe rozroznienie miedzy stanem wybranym/niewybranym wymaga precyzyjnych, rownych czasow faz.
W
lcd_init()(src/main.c) dodana proba LSE z fallbackiem na LSI (jesliLSERDYnie wstanie w ~2s). Wynik pokazywany na cyfrze4 przez ~1.5s po starcie:1= LSE dziala,0= fallback na LSI (brak/niegotowy kwarc).Wynik: LSE dziala (kwarc jest), ale cienie nie zniknely. Zrodlo zegara odrzucone jako przyczyna.
-
Test obciazenia (pojedynczy segment vs "8888") -> ujawnil dwa osobne zjawiska:
- Pojedynczy segment: widoczny "cien" na sasiednich segmentach TEJ SAMEJ
cyfry (np. zapalone tylko
acyfry1 -> slabo widac tezb,c,d). Nie uklada sie w prosty wzorzec (nie zawsze to sasiedni bit w tym samym rejestrze) - prawdopodobnie realne, nieusuwalne przesluchy multipleksowania tego konkretnego szkla. - "8888" (wszystkie segmenty): gorszy kontrast konkretnie na
a,f,gcyfr 1-3 orazb,ccyfry 4 - rozne litery na roznych cyfrach, co pasuje do hipotezy, ze to konkretnie te segmenty (z racji wlasnego, innego dla kazdej cyfry okablowania SEG) trafiaja na TA SAMA linie COM. Jedyna linia COM zmierzona jako slabsza to PA4/COM0 (patrz pkt. 4 powyzej) - to spojnie tlumaczy, czemu akurat te segmenty siadaja pod obciazeniem. Dodatkowo pojawil sie "duch" na nigdy niezmapowanym indeksie 53 (do zbadania osobno pozniej).
- Pojedynczy segment: widoczny "cien" na sasiednich segmentach TEJ SAMEJ
cyfry (np. zapalone tylko
-
Najwazniejsze odkrycie: fizyczna weryfikacja podlaczenia linii SEG. Bezposredni pomiar (niskie napiecie miedzy COM a kazda linia SEG osobno) pokazal, ze do szkla FAKTYCZNIE podlaczone sa tylko SEG1-13 i SEG18-19 (SEG0 nie zapala niczego). Od poczatku projektu w
lcd_init()wlaczalismy w masce portow (LCD_PMx) wszystkie 38 mozliwych linii SEG (oprocz PE6/PE7) - czyli az ~24 linie, ktore nigdzie fizycznie nie sa podlaczone, byly mimo to aktywnie przelaczane przez kontroler LCD. To bardzo prawdopodobna prawdziwa przyczyna przeslugow z catego watku: plywajace, ale wciaz sterowane sciezki na PCB, przesluchujace pojemnosciowo z prawdziwymi liniami SEG.Poprawka:
LCD_PMxwlcd_init()(src/main.c) zawezone do dokladnie SEG1-13 i SEG18-19 (PM0=0xFE, PM1=0x3F, PM2=0x0C, PM3=PM4=PM5=0). Zaden z 53 juz skalibrowanych elementow nie mogl byc na wylaczanych liniach (fizycznie nie byly podlaczone do szkla, wiec nie moglyby zostac znalezione podczas kalibracji). -
Rozwiazanie. Po poprawce maski portow, dostrojenie CC/PON interaktywnie przyciskami PE6/PE7 (test na statycznym "88") znalazlo kombinacje CC=4 (0x08, 3.0V) + PON=4 (0x80), przy ktorej obraz jest idealny - bez cieni. Utrwalone na stale w
lcd_init():LCD_CR2 = 0x88. Dead time zostaje na 0, bias na 1/4 (B4=1), FRQ na wartosci domyslnej po resecie, bez High Drive.Wniosek na przyszlosc: glowna przyczyna calego watku to byla zla maska portow (pkt. 7), nie kwestia kontrastu/dead time/bias/VSEL/czestotliwosci/ zegara same w sobie - te ostatnie tylko delikatnie doszlifowaly wynik po usunieciu prawdziwej przyczyny. Jesli w przyszlosci (np. przy zmianie pinout/dodaniu nowych elementow LCD) znowu pojawia sie cienie, najpierw sprawdz maske portow zanim zaczniesz stroic CC/PON/bias.