Mam problem z prostym licznikiem impulsów 0-999
Otóż, po przekroczeniu wartości 255 cyfra setek wskakuje na 0 a dziesiątki i jedności liczą się dalej.
Co może być nie tak?
(...) ' 5
Data 250 ' 6
Data 131 ' 7
Data 251 ' 8
Data 219 ' 9
Wstępna ocena dostępnych informacji W kodzie widzimy dwa liczniki (Liczba_ok i Liczba_nok) zadeklarowane jako zmienne typu Word, a także tablice na cyfry (Cyfra_ok i Cyfra_nok) jako typ Byte. Z punktu widzenia zakresu wartości samych liczników (od 0 do 999) nie powinno to powodować błędów – Word pozwala zliczać nawet do 65535. W kodzie jest też zmienna Wyswietlacz (typu Byte), której wartość steruje tym, która cyfra akurat trafia na wyświetlacz (Select Case).
Problem opisywany przez autora sprowadza się do niepoprawnego wyświetlania/obsługi licznika, gdy wartości przekraczają 255. Najczęściej w takim wypadku dwie rzeczy mogą być źródłem błędu: 1. Zmienna Wyswietlacz jako Byte „zawija się” z 255 na 0. 2. Obsługa tablic Lookup lub tablic cyfr (Cyfra_ok, Cyfra_nok) nie uwzględnia wartości spoza założonego zakresu.
Z analizy kodu wynika, że Liczba_ok i Liczba_nok są resetowane po przekroczeniu 999, więc same nie wyjdą poza zakres 0–999. Kluczem jest sprawdzenie, jak zachowuje się Wyswietlacz oraz czy odwołanie do tabeli Kody7seg ma zawsze poprawny indeks.
Bezpośrednia odpowiedź na pytanie Najbardziej prawdopodobną przyczyną błędnego zachowania powyżej 255 jest to, że zmienna Wyswietlacz (typu Byte) przepełnia się i wraca do 0, a warunek If Wyswietlacz > 6 Then Wyswietlacz = 1 tego nie przechwytuje (bo 0 wcale nie jest „>6”). W efekcie może pojawiać się nieoczekiwane zachowanie w sekcji Select Case – zamiast wartości 1..6 (dziesiątki/hornset?), program może trafić na Wyswietlacz=0 lub inne błędne wartości.
Szczegółowa analiza problemu 1. Zmienna Wyswietlacz jest wykorzystywana do multipleksowego wyświetlania kolejnych cyfr: » W przerwaniu Timer0: Incr Wyswietlacz : If Wyswietlacz > 6 Then Wyswietlacz = 1 Po przekroczeniu wartości 6 Wyswietlacz wraca do 1, więc w normalnych warunkach pozostaje zawarte w przedziale 1..6.
2. Jeśli jednak Wyswietlacz dojdzie do 255 i zostanie „inkrementowany” na wartość 256, to w typie Byte wartość ta fizycznie zawija się na 0 (256 w 8-bitach daje nadmiar, który „zetnie się” na 0). Warunek If Wyswietlacz > 6 Then Wyswietlacz = 1 już go wtedy nie skoryguje, bo 0 nie jest „> 6”. W efekcie w Select Case Wyswietlacz może przyjąć wartość 0, która nie została obsłużona w kodzie: Select Case Wyswietlacz Case 1: ... Case 2: ... Case 3: ... Case 4: ... Case 5: ... Case 6: ... End Select Brakuje Case 0, przez co program może wykonywać się z nieprzewidywalnym skutkiem (np. ustawia niewłaściwe sygnały na porcie, co wizualnie może wyglądać jak „)”).
3. Dzięki temu, że Liczba_ok oraz Liczba_nok to typ Word, obsługa zakresu 0..999 na poziomie arytmetyki jest poprawna – problem tkwi raczej w mechanizmie wyświetlania.
Aktualne informacje i trendy Choć w wielu projektach tak prosta zmienna typu Byte do przełączania multipleksu wystarcza, coraz częściej stosuje się bardziej jednoznaczne zapisy (np. operator Mod lub pętlę for) albo mechanizmy chroniące przed przepełnieniem. Te praktyki są szczególnie popularne w nowszych implementacjach, aby kod był bezpieczniejszy i łatwiejszy w utrzymaniu.
Wspierające wyjaśnienia i detale • Jeżeli wartość zmiennej Byte przekroczy 255, następuje przepełnienie, a faktycznie w rejestrze ląduje reszta z dzielenia przez 256 (256 % 256 = 0). • Z tego powodu warunek If Wyswietlacz > 6 Then Wyswietlacz = 1 nie chroni, gdy Wyswietlacz przejdzie na 0.
Aspekty etyczne i prawne Nie występują tu szczególne kwestie etyczne czy prawne; problem dotyczy prostego fragmentu kodu w Bascom.
Praktyczne wskazówki • Najprostszym rozwiązaniem jest zmodyfikowanie sekcji obsługi Wyswietlacz tak, by zabezpieczyć się przed wartością 0: Incr Wyswietlacz If Wyswietlacz = 0 Then Wyswietlacz = 1 End If If Wyswietlacz > 6 Then Wyswietlacz = 1 End If
• Alternatywnie można bezpośrednio nadać Wyswietlaczowi wartość w oparciu o operator Mod: Wyswietlacz = (Wyswietlacz Mod 6) + 1
• Jeżeli ktoś woli powiększyć zakres zmiennej Wyswietlacz tak, by zapobiec przepełnieniom przy długim działaniu programu, można zadeklarować ją jako typ Word: Dim Wyswietlacz As Word
Ewentualne zastrzeżenia lub uwagi dodatkowe W innych fragmentach kodu (np. rozbijanie liczby na cyfry) zdefiniowane typy Byte, Word czy tablice wyglądają prawidłowo dla zakresu 0..999, więc nie muszą być modyfikowane, o ile faktycznie chcemy wyświetlać tylko do 999. Gdyby docelowo licznik miał zliczać większe wartości (powyżej 9999 itp.), należałoby rozbudować zarówno tablice, jak i wyświetlanie.
Sugestie dalszych badań • Upewnij się, że kod przerwania Timer0 nie konkuruje o zasoby z pętlą główną (czasem warto wyłączyć przerwania na czas operacji na zmiennych współdzielonych). • Warto dodać wyświetlanie tymczasowych wartości w monitorze lub symulatorze Bascoma, by na bieżąco sprawdzać, co dzieje się z Wyswietlaczem i licznikami.
Krótkie podsumowanie Najprawdopodobniej za błędne wyświetlanie odpowiada zmienna Wyswietlacz, która jako Byte zawija się na 0 po przekroczeniu 255. Warunek If Wyswietlacz > 6 Then Wyswietlacz = 1 nie „łapie” zera, więc program wchodzi w nieobsłużoną ścieżkę. Rozwiązaniem jest zabezpieczyć kod przed 0 (np. przez dodatkowy warunek lub operator Mod) albo zmienić Wyswietlacz na typ Word.
Pytania do użytkownika (jeśli potrzebne) • Czy obserwujesz dokładnie ten sam błąd w chwili, gdy licznik teoretycznie powinien dojść do wartości 256, czy błąd pojawia się już wcześniej? • Czy weryfikowałeś w symulatorze lub przez wyświetlanie wartości zmiennej Wyswietlacz, jaka jest jej rzeczywista zawartość w momencie wystąpienia błędu?
Pozdrawiam i życzę powodzenia w dalszych pracach! Jeśli pojawią się dodatkowe pytania lub wątpliwości, chętnie pomogę w ich rozwiązaniu.
Możesz mnie wywołać w każdym temacie pisząc @ElektrodaBot. Zastrzeżenie: Niektóre odpowiedzi udzielone przez ElektrodaBota mogą być niedokładne. Elektroda nie ponosi odpowiedzialności za dokładność, rzetelność ani kompletność prezentowanych informacji. Wszystkie odpowiedzi ElektrodaBota powinny być zweryfikowane przez użytkownika. OpenAI może monitorować i zapisywać informacje wprowadzane po wywołaniu ElektrodaBota.
Nasza sztuczna inteligencja słusznie zauważyła możliwość przekręcania się zmiennej "Wyswietlacz" ale to nie to...
Przyjrzałbym się $swstack = 8 czy nie zwiększyć np na 16. Kolejny trop to przeliczanie tutaj:
Kod: Arduino
Zaloguj się, aby zobaczyć kod
Na próbę można w tablicę liczb wpisać 999 i zobaczyć czy się wyświetli poprawnie
Bascom zawsze używa metody obliczeniowej, która należy do zmiennej wynikowej. Oznacza, że w tym przypadku Bascom wykonuje obliczenia na bajtach. Wartość obliczeniowa2 jest typu Word.
Czyli
zmienna Liczba_ok traktowana jest jako byte.
Jedynym sposobem na konwersję jednego typu na inny jest po prostu przypisanie go w ten sposób
Wartość obliczona2 = Wartość obliczona1.
W procedurze wyświetlania zapisany jest warunek wygaszanie zer nie znaczących, a po przekroczeniu 255 cyfra setek wyświetla 0 i ono nie gaśnie.
Czyli zmienna liczy się nadal, co wskazuje rzeczywiście na problem z wyświetlaniem a nie liczeniem.
Po wpisaniu "na twardo"
Liczba_nok = 987
Liczba_ok = 654
wyświetlacz pokazuje 287 i 154
Wydaje mi się, że kompilator nie ma problemu z funkcją "mod" (dlatego też dwie ostatnie cyfry się zgadzają), tylko przy dzieleniu zmiennej typu word, dającej zmienną typu byte jako wynik.
Możesz mi napisać kawałek kodu z tym MOD jak to powinno wyglądać?
Tylko użyj proszę nazw zmiennych jakich ja używam, OK?
Ze 100x robiłam liczniki liczące setki, czy tysiące i nigdy nie było problemu.
Dłuższa przerwa z BASCOM i wywalanie z komputera niepotrzebnych programów się właśnie zemściło...
Użytkownik zgłosił problem z licznikiem impulsów 0-999 na mikrokontrolerze ATtiny2313, który po przekroczeniu wartości 255 wyświetla cyfrę setek jako 0, podczas gdy dziesiątki i jedności działają poprawnie. Analiza kodu wskazuje, że zmienne typu Byte mogą powodować "zawijanie się" wartości, co prowadzi do błędów w wyświetlaniu. Sugerowane rozwiązania obejmują zmianę typu zmiennych na Word oraz sprawdzenie obliczeń związanych z dzieleniem i operacjami modulo. Po wprowadzeniu poprawek, takich jak zmiana typu zmiennych na Integer, problem został rozwiązany. Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.