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

Jak napisać funkcję BIN2BCD w C do konwersji wartości char (0-99) na BCD?

mas24 21 Lis 2014 08:10 1152 12
REKLAMA
  • #1 14150769
    mas24
    Poziom 16  
    Witam,

    Od dłuższego czasu próbuje zrobić funkcję w C, zamieniającą wartość char (zakres 0-99) na wartość BCD, gdzie oba półbity będą upakowane w jednej zmiennej.
    Szukałem w Inetrnecie i jest kilka takich procedur, ale żadna mi nie działa. Czytałem nawet rekomendację Atmela, ale nie wychodzi mi implementacja zawartego tam algorytmu.

    Chodzi mi o to, by wyświetlić wartość np. temperatury na 2 wyświetlaczach 7-segmentowych i muszę mieć każdą cyfrę dla każdego wyświetlacza. Program mam mniej więcej taki:

    
    temperatura=45;
    temperatura=bin2bcd(temperatura);
    cyfra1= temperatura & 0xF0; //dziesiatki
    cyfra2= temperatura & 0x0F; //jedności
    


    tutaj dla przykładu wpisałem temperaturę na twardo
    zmienne "cyfra1" i "cyfra2" są typu char i są pointerami do tablicy z kombinacją segmentów, czytelnych dla człowieka.
  • REKLAMA
  • #2 14150821
    BlueDraco
    Specjalista - Mikrokontrolery
    Zapytaj ucznia drugiej klasy szkoły podstawowej, w jaki sposób obliczyć liczbę dziesiątek liczby z zakresu 0..99 - powinien Ci pomóc.

    d = x / 10;
    j = x % 10;
  • REKLAMA
  • #4 14151940
    mas24
    Poziom 16  
    Wiem, jak obliczyć to matematycznie i takie finalnie rozwiązanie przyjąłem, ale myślałem, że jest jakaś szybsza procedura z dodawaniem i przesuwaniem bitów. Dzielenie jest nieco bardziej powolne.

    Procedurkę zapodaną przez Kolegę adambehnke także ćwiczyłem, ale inaczej miałem nawiasy. Poprawnie zwracał mi tylko część jedności, dziesiątki wychodziły zawsze 0.
  • REKLAMA
  • #5 14153885
    vania
    Poziom 24  
    mas24 napisał:
    Wiem, jak obliczyć to matematycznie i takie finalnie rozwiązanie przyjąłem, ale myślałem, że jest jakaś szybsza procedura z dodawaniem i przesuwaniem bitów. Dzielenie jest nieco bardziej powolne.

    Procedurkę zapodaną przez Kolegę adambehnke także ćwiczyłem, ale inaczej miałem nawiasy. Poprawnie zwracał mi tylko część jedności, dziesiątki wychodziły zawsze 0.

    Double dabble
  • REKLAMA
  • #6 14154021
    tmf
    VIP Zasłużony dla elektroda
    mas24 napisał:
    Wiem, jak obliczyć to matematycznie i takie finalnie rozwiązanie przyjąłem, ale myślałem, że jest jakaś szybsza procedura z dodawaniem i przesuwaniem bitów. Dzielenie jest nieco bardziej powolne.


    A po co ci szybsza funkcja? Przecież robisz okazyjnie konwersję, żeby wyświetlić liczbę na lcd... Czy to będzie wykonywane przez 1000 taktów, czy przez 100 jest kompletnie bez znaczenia. A szybsza, zazwyczaj znaczy mętnie napisana, zawiła i wrażliwa na głupie błędy.
    Wydrukuj sobie i przyklej do monitora (alternatywnie ustaw jako tapetę):
    "Premature optimization is the root of all evil"
  • #7 14154039
    mas24
    Poziom 16  
    Tutaj mam do obsłużenia jedynie 2 wyświetlacze 7-segmentowe, przerwania co 5ms, więc prawie wieczność, choć AVR taktowany jedynie 1MHz. Gorzej będzie, gdy przyjdzie mi przedstawiać większe liczby na kilku wyświetlaczach. Właśnie z myślą na przyszłość chciałem zdobyć szybką procedurę.

    Do tej pory to robiłem tak (pisane z pamięci i może nie działać):

    
    A=1234
    T=A/1000
    Cyfra1=T
    A=A-(T*1000)
    T=A/100
    Cyfra2=T
    A=A-(T*100)
    T=A/10
    Cyfra3=T
    A=A-(T*10)
    Cyfra4=A
    


    Zobaczę jeszcze tą procedurkę Double Dabble, bo chyba chodzi tam o to samo.
  • #8 14154051
    dondu
    Moderator na urlopie...
    mas24 napisał:
    Tutaj mam do obsłużenia jedynie 2 wyświetlacze 7-segmentowe, przerwania co 5ms, więc prawie wieczność, choć AVR taktowany jedynie 1MHz. Gorzej będzie, gdy przyjdzie mi przedstawiać większe liczby na kilku wyświetlaczach. Właśnie z myślą na przyszłość chciałem zdobyć szybką procedurę.

    Skoro to ma być używane tylko do wyświetlania, to w tym momencie należy obliczać. Przecież nie wysyłasz danych do LCD co 5ms :)
  • #9 14154069
    mas24
    Poziom 16  
    Czyli obliczenia z dzieleniem najlepsze?
  • #10 14154159
    alagner
    Poziom 26  
    Zależy. Zasada jest taka - piszesz tak, żeby było czytelnie i dobrze.
    Działa? Świetnie.
    Coś się sypie/brakuje mocy? Szukasz wąskich gardeł.
    Znalazłeś? To optymalizujesz na poziomie kodu (czy to algorytmem czy assemblerem) dopiero wtedy.

    A jak aż tak Cię to bardzo dręczy to podejrzyj plik asemblerowy. Zobaczysz co, jak w i w którą stronę jest nie tak
  • #11 14154299
    excray
    Poziom 41  
    W C masz itoa() więc użyj go.
  • #12 14154635
    tmf
    VIP Zasłużony dla elektroda
    mas24 napisał:
    Tutaj mam do obsłużenia jedynie 2 wyświetlacze 7-segmentowe, przerwania co 5ms, więc prawie wieczność, choć AVR taktowany jedynie 1MHz. Gorzej będzie, gdy przyjdzie mi przedstawiać większe liczby na kilku wyświetlaczach. Właśnie z myślą na przyszłość chciałem zdobyć szybką procedurę.


    To zamiast optymalizować jakąś nic nie znaczącą funkcję przemyśl raczej działanie całego programu. Jak rozumiem masz liczbę zapisaną binarnie, którą przy każdym odświeżeniu LED chcesz zamieniać na BCD po to, żeby z BCD zamienić na kod wyświetlacza 7-segmentowego? Przecież to kompletnie bez sensu.
    Nie prościej przy zmianie wartości zmiennej od razu dokonać konwersję na kod 7-segmentowy lub rozbić na poszczególne cyfry, które będzie wykorzystywać funkcja odświeżająca LED? Przecież temperaturę będziesz uaktualniał może raz na sekundę? W takim przypadku konwersja nawet jeśli zajmie 100 tys. cykli (co raczej jest absurdem) to będzie to kompletnie bez znaczenia.
  • #13 14154822
    mas24
    Poziom 16  
    Dlatego poprzestałem na dzieleniu.
    Zmienne "CyfraX" (X=1,2) są pointerami do tablicy (progmem) i nowe wartości podawane są już na port procka, do którego (przez oporniki) podłączone są katody wyświetlaczy. Anodami sterują inne piny. Nic wielkiego.
REKLAMA