Ta strona używa ciasteczek (plików cookies), dzięki którym może działać lepiej. Dowiedz się więcejRozumiem i akceptuję

[C] Licznik modulo i wyświetlanie na LCD. Intel 8051.

Autor Wiadomość
Yggas 



Posty: 6
Wysłany: 19-03-2017, 11:27   [C] Licznik modulo i wyświetlanie na LCD. Intel 8051.

Witam. Miałem na zajęciach z mikroprocesorów zrobić licznik modulo 100 i miał być wyświetlany na LCD. Problem w tym, że licznik jakoś tam udaje mi się robić lepiej lub gorzej ale nie wiem jak wyświetlać to na ekranie...

Mam tylko pozmieniać (w gotowym pliku prezentacyjnym kontrolera) void(main) i pętle while(1).

Kod programu: Zaznacz cały
void disptext(unsigned char xdata *wsk){
unsigned char data i;
adrlcd(adres_linijka1);
for(i=0;i<16;i++){
    datw=*wsk;
    wsk++;
    busylcd();
                }
adrlcd(adres_linijka2);
for(i=0;i<16;i++){
    datw=*wsk;
    wsk++;
    busylcd();
                }
                                }


To jest chyba od sterowania wyświetlaniem tekstu tak? Tylko, że to się chyba odwołuje do tablicy, a nie wiem jak w tablicy zamieścić zmienną i by licznik był od 0 do np 100 czyli 3 pozycje na wyświetlaczu 2x16. (mam to być w pierwszej linijce wyświetlacza)

Jak by mi to ktoś wyjaśnił to będę niezmiernie wdzięczny!
Polecany artykuł z FORBOT.PL:
Sekrety profesjonalnego programowania

Niniejszy artykuł będzie dotyczył programowania. Prawdopodobnie będzie się jednak zdecydowanie różnił od zdecy... Czytaj całość

Ostatnio popularny » Kurs STM32 F4 - #9 - Obsługa I2C, akcelerometr


Ostatnio zmieniony przez Yggas 19-03-2017, 11:29, w całości zmieniany 1 raz  
Postaw piwo autorowi tego posta
 
 
marek1707 



Posty: 3754
Pomógł: 405 razy
Otrzymał 539 piw(a)
Skąd: WAW
Programuję w:
C, asm
Wysłany: 19-03-2017, 12:01   

1. Licznik modulo 100 to dwie cyfry dziesiętne do wyświetlenia, bo liczy w cyklu 0..99.
2. Pokazałeś funkcję obsługi wyświetlacza. Wygląda, że jest on podłączony (jako urządzenie w obszarze zewnętrznej pamięci danych?) pod adresem datw i że po ustawieniu "kursora" funkcją adrlcd() potem wystarczy wysłać kody znaków.

Jeśli nie chcesz modyfikować pokazanej funkcji, musisz zadeklarować sobie swój własny bufor danych, np:
Kod programu: Zaznacz cały
unsigned char xdata ekran_wyswietlacza[32];
Potem piszesz do niego (wstawiasz do tablicy) potrzebne znaki w odpowiednie miejsca i po wywołaniu funkcji:
Kod programu: Zaznacz cały
disptext(ekran_wyswietlacza);
masz to pokazane na wyświetlaczu.

A licznik modulo N możesz z robić na kilka sposobów:
a. zliczasz binarnie w cyklu od 0 do N-1:
Kod programu: Zaznacz cały
if (++licznik >= N)
   licznik = 0;
b. korzystasz z operatora modulo:
Kod programu: Zaznacz cały
licznik = (licznik + 1) % N;
ale te dwa pomysły dają licznik binarny, którego zawartość musisz przed wysłaniem do wyświetlacza przekonwertować na ciąg cyfr dziesiętnych. Na szczęście w przypadku małych liczb (w zakresie 0..99) jest to trywialne:
Kod programu: Zaznacz cały
dziesiatki = licznik / 10;
jednosci = licznik % 10;
Te dwie wartosci zamieniasz na znaki ASCII i pokazujesz na wyswietlaczu:
Kod programu: Zaznacz cały
ekran_wyswietlacza[0] = dziesiatki + '0';
ekran_wyswietlacza[1] = jednostki + '0';
adrlcd(adres_linijka1);
disptext(ekran_wyswietlacza);
To by było na tyle.

Oczywiście można wymyślić sobie o wiele ładniejszy i bardziej uniwersalny program obsługujący większe i mniejsze N gdzie będzie potrzebna lepsza konwersja bin→dec itd, ale powyższe chyba spełnia założenia. Umieść odliczanie i wyświetlanie w pętli w main() i nie zapomnij o jakimś opóźnieniu, bo takie rzeczy to nawet '51 umie bardzo szybko liczyć :)

Postaw piwo autorowi tego posta
 
 
Yggas 



Posty: 6
Wysłany: 19-03-2017, 12:32   

No niby jest OK ale nie :D

Kod programu: Zaznacz cały
    while(1){
       
        if (++licznik >= N)
        licznik = 0;
        licznik = (licznik + 1) % N;
        dziesiatki = licznik / 10;
        jednosci = licznik % 10;
        tblcw[9] = dziesiatki + '0';
        tblcw[10] = jednosci + '0';

        disptext(tblcw);
       
        for(i=0;i<20000;i++)
        ;
       
}


To opóźnienie na końcu to prowadzący nam pokazał i mówi, że prymitywne :P

Licznik odlicza ale co 2.

Co to znaczy jak użyłeś wpis: "dziesiatki + '0' "
Co oznacza to + "0"?
a inkrementacja jest już zrobiona w warunku ?

Ostatnio zmieniony przez Yggas 19-03-2017, 12:50, w całości zmieniany 1 raz  
Postaw piwo autorowi tego posta
 
 
marek1707 



Posty: 3754
Pomógł: 405 razy
Otrzymał 539 piw(a)
Skąd: WAW
Programuję w:
C, asm
Wysłany: 19-03-2017, 12:59   

Pozbądź się nawyku kopiowania wszystkiego. Przecież pokazałem dwie różne metody inkrementacji licznika, ale powinieneś stosować je alternatywnie (którą wolisz) a nie jednocześnie, bo +1+1 to razem +2, prawda?

Wyglądało, że masz problem jedynie z ogarnięciem wyświetlacza, inkrementacją modulo i konwersją bin->dec a nie ogólnie z programowaniem :) Zaproponuj coś z tym opóźnieniem. Jak Ty byś chciał to zrobić? Jaka metoda wg Ciebie lub prowadzącego nie jest prymitywna (jakby cały ten "program" taki nie był..)? Chcesz się czegoś nauczyć? Wiesz coś więcej o '51 czy próbujesz tanim kosztem opędzić pracę domową? Jeśli to pierwsze, zastanów się i napisz coś konstruktywnego. Czekamy.

BTW: Dodanie stałej '0' jest prostą konwersją liczby binarnej w zakresie 0..9 na kod znaku '0'..'9' jakim posługuje się wyświetlacz. Hasło do poszukania: tablica znaków kodu ASCII.

Popularny artykuł » Cadsoft Eagle - część 1 (Schematy)


Postaw piwo autorowi tego posta
 
 
Yggas 



Posty: 6
Wysłany: 20-03-2017, 10:40   

No niestety mam braki, mało się przykładałem na początku studiów do programowania (kierunek elektryczny) w dodatku ocena z zajęć była na obecność co też nie zachęcało.

Ale staram się to w miarę nadrobić i się do tego przyłożyć.

Co do opóźnień to na chwilę obecną będę stosował takie :P

Tutaj program z dwiema zmiennymi, jakoś bardziej byłem nastawiony, że jedna się zwiększa o jeden i jeżeli dojdzie do tej naszej dzielnej = 100 to się zeruje i od nowa, a inna zmienna licznik zlicza zerowania.

Kod programu: Zaznacz cały
    while(1){
       
        do
            k++;
        while(k%N==0);
        licznik++;
        k=0;
        jednosci=licznik%10;
        dziesiatek=licznik/10;
       
        tblcw[9]=dziesiatek + '0';
        tblcw[10]=jednosci + '0';
        if(licznik>=N)
            licznik=0;

        disptext(tblcw);
       
        for(i=0;i<15000;i++)
        ;
       
}


W sumie dużo zmian nie zrobiłem :/ Muszę jeszcze poczytać o kodowaniu ASCI lub znaleźć gdzie to jest wytłumaczone. Wcześniej jak próbowałem to właśnie mi zliczało ale po cyfrze 9 pojawiały się litery duże potem małe a potem znaczki i nie wiedziałem co tam się dzieje :P

Teraz będę kombinował z odczytaniem sygnału analogowego z potencjometru i wyświetleniem napięcia. Przy tym chyba będę musiał przeliczyć to jakoś *5.0/1023.0 ? Tak jak się robi w Arduino?

Postaw piwo autorowi tego posta
 
 
marek1707 



Posty: 3754
Pomógł: 405 razy
Otrzymał 539 piw(a)
Skąd: WAW
Programuję w:
C, asm
Wysłany: 20-03-2017, 11:52   

Albo to jest część jakiegoś Wielkiego Planu którego nie ogarniam albo robisz w kodzie jakieś głupstwa.
Czy mógłbyś na chłopski rozum wytłumaczyć do czego służą te machlojki ze zmienną k? Ani razu nie używasz jej wartości w sensowny sposób. Poniżej wrzucam Twój kod z usuniętymi liniami korzystającymi z k. Działa tak samo:
Kod programu: Zaznacz cały
  while(1){
        jednosci=licznik%10;
        dziesiatek=licznik/10;
       
        tblcw[9]=dziesiatek + '0';
        tblcw[10]=jednosci + '0';

        if (++licznik>=N)
            licznik=0;

        disptext(tblcw);
       
        for(i=0;i<15000;i++)
        ;
}
Zmieniłem odrobinkę inkrementację licznika by było widać, że jest to zliczanie modulo. Dwie rozstrzelone po kodzie linie nie ułatwiają zrozumienia. Staraj się pisać programy jak list do kogoś, tłumaczący co chcesz zrobić. Nie gub wątków, nie mieszaj myśli, za to skupiaj się na jednej rzeczy w danym miejscu na raz.

A konwersję ADC na mV napięcia możesz zrobić wprost, używając arytmetyki zmiennoprzecinkowej:
float voltage_mv = (float)ADC * 5.0 / 1023.0;
Tak robi wielu ludzi i gdy masz dużo czasu i miejsca w pamięci, zadziała. Gdy jesteś sportowcem lub masz jakieś pojęcie o arytmetyce komputerów, zrobisz to bez problemu na stałym przecinku.

Acha, pomyśl jak zrobić konwersję większej liczby (np. z zakresu 0..255 lub 0..65535) na postać dziesiętną, znakową.

Postaw piwo autorowi tego posta
 
 
Yggas 



Posty: 6
Wysłany: 20-03-2017, 20:41   

Kod programu: Zaznacz cały
    while(1){

for(i=0;i<10000;i++)
    ;
    odczytADC=PTAC;
    wynik=odczytADC/51;
    tblcw[10]=wynik + '0';
       
    disptext(tblcw);
       
   
   
}


Takie coś zrobiłem, przetwornik ADC jest 8-bitowy czyli jego rozmiar danych to 0-255, dobrze to rozumiem? No i trzeba z tego zrobić proporcję czyli dlatego dopisałem dzielenie przez 51 by wyszedł zakres wyświetlania 0V-5V.
Niestety (albo stety bo nie określone mam czy część ułamkową też ma pokazywać) pokazuje napięcie w liczbach całkowitych. Nie wiem czy jeszcze dziś będę miał czas ogarnąć ale jak tylko znajdę chwilkę (dla mnie pewnie trochę dłużej) to postaram się to zrozumieć i napisać i wtedy wrzucę do sprawdzenia.


EDIT:
Tamten post z kodem ze zmienną k rozumiałem(czy tam wyobraziłem sobie) na ten sposób, że zliczam taktowanie jakiegoś sygnału i to k imitowało ten sygnał, a licznik zliczał. No i tak właśnie z tym wymyślaniem było :<

Ostatnio zmieniony przez Yggas 20-03-2017, 20:46, w całości zmieniany 1 raz  
Postaw piwo autorowi tego posta
 
 
marek1707 



Posty: 3754
Pomógł: 405 razy
Otrzymał 539 piw(a)
Skąd: WAW
Programuję w:
C, asm
Wysłany: 20-03-2017, 23:00   

Mając 8-bitowy ADC dostajesz z niego trochę ponad 2 dziesiętne cyfry znaczące. Trzech nie ma sensu wyświetlać, ale dwie wypadałoby (z ew. kropką między nimi i symbolem 'V' na końcu?). Pokazywanie jednej leży moim zdaniem poniżej poziomu dopuszczalnej chały.
Musisz więc zmapować zakres 0..255 na 0..99 a potem to już łatwo: masz liczbę co najwyżej 2-cyfrową czyli zadziała prymitywna konwersja bin->dec, której już używałeś. Do roboty :)

Postaw piwo autorowi tego posta
 
 
Yggas 



Posty: 6
Wysłany: 21-03-2017, 00:59   

Kod programu: Zaznacz cały

//Zmienna tablicy jest taka:
unsigned char xdata tblcw[]="Napiecie: 0.0 V";

    while(1){

        for(i=0;i<10000;i++)
            ;
        wynik=PTAC;
        jednosci=wynik/51;
        switch(jednosci){
            case 0:
                ulamek1= (wynik/26) % 10;
                        break;
            case 1:
                ulamek1= (wynik/26) % 10;
                        break;
            case 2:
                ulamek1= (wynik/26) % 10;
                        break;
            case 3:
                ulamek1= (wynik/26) % 10;
                        break;
            case 4:
                ulamek1= (wynik/26) % 10;
                        break;
            default:
                ulamek1=0;
            break;
        }
        ulamek2=(jednosci*2)%10;
        tblcw[10]=jednosci +'0';
        tblcw[12]=ulamek1 + '0';
        tblcw[13]=ulamek2 + '0';
       
    disptext(tblcw);
       
   
   
}


Działa lecz odczyt nie jest zbyt liniowy chyba :P Bardziej pięcio(sześcio)-pozycyjny.

EDIT: Zmieniłem na pokazywanie trzech. Zdaję sobię sprawę z tego, że pewnie niekonieczne było użycie funkcji switch ale inaczej nie wykombinowałem. Do tego druga cyfra po przecinku zmienia się od 0 do 9 nie zerując się przy liczbie całkowitej :< Jutro to dokończę.

A jutro już kolejne zajęcia gdzie mam przerwania i multipleksowanie. Kiedy ja to nadrobie :roll:

Ostatnio zmieniony przez Yggas 21-03-2017, 01:34, w całości zmieniany 2 razy  
Postaw piwo autorowi tego posta
 
 
marek1707 



Posty: 3754
Pomógł: 405 razy
Otrzymał 539 piw(a)
Skąd: WAW
Programuję w:
C, asm
Wysłany: 21-03-2017, 15:01   

Sam widzisz, że marnie to wygląda. Bardziej eleganckich sposobów konwersji jest kilka. Jeden z nich to znów wykorzystanie operatora modulo. Prosty kod wyliczający trzy cyfry z liczby 8-bitowej wyglądałby jakoś tak:
Kod programu: Zaznacz cały
jednostki = licznik % 10;
licznik /= 10;
dziesiatki = licznik % 10;
licznik /= 10;
setki = licznik;
Przemyśl jak to działa.

Gdybyś miał wypisywać jakąś większą liczbę (np. 16-bitową czyli 5 cyfr), możesz łatwo rozszerzyć powyższą metodę do 4 razy modulo i 4 dzieleń, ale ładniej będzie to zapisać w pętli:
Kod programu: Zaznacz cały
char cyfry[5];
for(n=0; n<5; n++)
{
   cyfry[n] = (licznik % 10) + '0';
   licznik /= 10;
}
Po zakończeniu pętli masz w tablicy cyfry[] rozwinięcie dziesiętne licznika od razu w postaci znaków ASCII. Najmłodsza cyfra została policzona pierwsza więc jest w cyfry[0], najstarsza w cyfry[4] :)

Nadrobisz, nadrobisz, brakuje Ci trochę programistycznej ogłady, ale przecież nie święci garnki lepią.

Postaw piwo autorowi tego posta
 
 
Wyświetl posty z ostatnich:   
Odpowiedz do tematu
Nie możesz pisać nowych tematów
Nie możesz odpowiadać w tematach
Nie możesz zmieniać swoich postów
Nie możesz usuwać swoich postów
Nie możesz głosować w ankietach
Nie możesz załączać plików na tym forum
Możesz ściągać załączniki na tym forum
Wersja do druku

Skocz do:  

Nie rozwiązałeś swojego problemu? Zobacz podobne tematy: [ Bascom] Jak zrobić... Kombinowanie z przer... Generowanie przebieg... Mikrokontrolery z ob...
lub przeszukaj forum po wybranych tagach: 8051., intel, lcd., licznik, modulo, na, wyswietlanie


Powered by phpBB modified by Przemo © 2003 phpBB Group
Popularne kursy: Arduinopodstawy elektroniki