Witam, Sorry za lame, ale... Jakoś nie moge znaleźć pomocnych funkcji w C, których mógłbym użyć do obsługi LCD. Komunikację na 4 bitach sobie zrobiłem. Zrobiłem funkcję, która wypluwa znak o danym ASCII kodzie - to proste. Nie potrafię za to w C tak obrobić zmiennej, zeby ją wypluć na LCD. Jak zrobić banalna wydawałoby się funkcję wypluwającą int na LCD? Niechby jakaś funkcja zapisała mi do tablicy kody ASCII poszczególnych cyfr zmiennej, to bym sobie dalej poradził, ale tego nie potrafię zrobić. Jakoś tego C cały czas nie czuję :(. Jak to się robi? Pozdrawiam, Marek
C do AVR
Jul 19, 2005
41 Replies
U¿ytkownik "Marek" <narower snipped-for-privacy@o2.pl napisa³ w wiadomo¶ci news:Xns9698C1EEFD94Enarowerwonspamo2pl@127.0.0.1...
zazwyczaj mozna uzyc standardowych funkcji z biblioteki
np itoa - integer to ascii
albo bardziej wypasiona z formatowaniem
sprintf();
printujesz do stringa a potem stringa na wyswietlacz
int val = 123; char str[16];
sprintf( str, "%d", val );
pozniej string str na wyswietlacz
Andy wrote: [ciach]
Najwygodniej jest to zrobić nieco inaczej. Jeśli już korzystać z libc to na całego. Za pomocą funkcji fdevopen() rejestruje się funkcję, która potrafi wysłać (ew. odebrać w ogólnym wypadku) znak na urządzenie (tutaj LCD). Potem każda funkcja printf() spowoduje, że znak/ciąg zostanie wyświetlony. Jak pamiętam, to mi to za bardzo nie chciało działać i musiałem robić jakiegoś małego hacka. Nie pamiętam już co nie działało, może to już poprawili w nowszej wersji, może ja coś źle robiłem. Tutaj są kody:
formatting link
. Większość rzeczy jest w lcd.c, interesujące funkcje to: lcd_fdevopen() i lcd_putc_wrap() . Pierwsza zastępuje fdevopen() (ten niby hack), druga jest funkcją, która wysyła znak na ekran (wyświetlacz).
P.S. Link będzie ważny ok. 3, 4 dni.
Łukasz Góralczyk wrote: [ciach]
Pamiętam, chciałem uniknąć funkcji calloc(), która jest wywoływana przez fdevopen(). Wszystko jest fajnie opisane w dokumentacji do libc.
Ja pokaże ci własnoręcznie napisaną funkcję , w przeciwieństwie do gotowej możesz ja modyfikować do swoich potrzeb oraz zaimuje mało miejsca w pamięci programu :) W funkcji zamień wykorzystana jest rekurancja , co oznacza że funkcja wywołuje samą siebie . Zamienia typ całkowity int na string . Jeśli chesz jej używać na liczbach ujemnych musisz dopisać linijkę kodu
- myśle ze dasz radę :) W razie problemów pisz na maila .
oto funkcja z przykładem wywołania w mainie :
#include <stdio.h>
void zamien(int l, char *p) { static char *w = NULL; if (l==0) return; if (p != NULL) w = p; zamien(l/10,NULL); *w++ = l%10 + '0'; if (p != NULL) *w = 0; }
int main(void) { char wynik[32]; zamien(1666, wynik);
printf("%s\n", wynik); }
U¿ytkownik "Marek" <narower snipped-for-privacy@o2.pl napisa³ w wiadomo¶ci news:Xns9698C1EEFD94Enarowerwonspamo2pl@127.0.0.1...
Mo¿e tak
/*######################################################################################################*/ void LCD_WriteDzies2(unsigned char znak) { unsigned char i = (znak%100) / 10 + '0'; LCD_dataWR(i); i = (znak%100) % 10 + '0'; LCD_dataWR(i); }
/*######################################################################################################*/ void LCD_WriteDzies(unsigned char znak) { unsigned char i = znak/100 + '0'; LCD_dataWR(i); i = (znak%100) / 10 + '0'; LCD_dataWR(i); i = (znak%100) % 10 + '0'; LCD_dataWR(i); }
Argumentem miała byc liczba całkowita typu int, a ty typ znakowy char . Poza tym powtarzasz kilka razy "LCD_dataWR(i);" - do tego są pętle.
Piotr Chmiel napisał(a):
Wsadz to w petle... popatrz na wygenerowany kod, zrob bez petli, popatrz na wygenerowany kod, zabierz głos....
Lepiej unikać rekurencji na 8 bitach jeśli kod ma być przenośny, są kompilatory nie wspierające tej techniki np. Hitech PICC18. To tak na marginesie.
Marek wrote: > Jak zrobić banalna wydawałoby się funkcję
// integer = liczba int // string = wskaźnik do bufora wyjściowego // TODO: sprawdzić znak liczby, odwrócić kolejność cyfr w wyniku.
while (integer) { *string++ = (integer % 10) + '0'; integer /= 10; }
lcd_puts(string);
Piotr Chmiel wrote: [ciach]
Jeśli mogę się przyczepić: · kod funkcji zamiany nie będzie specjalnie krótszy w porównaniu do tej z rekurencją, · rekurencja tutaj więcej szkodzi, niż pomaga, każde wywołanie funkcji to dodatkowe 4 bajty na stosie (sprawdzałem dla '-O3'), · jeśli w main() jest printf, to tworzenie takiej funkcji mija się z celem, bo printf ma w sobie już zamianę int → string (polecam zaglądnięcie do kodu, jest to fajnie zrobione), · jeśli już liczba ma być wstawiona do bufora, można to zrobić tak: sprintf( buff, "%d", myint ); · polecam zainteresować się fdevopen() (jak wspomniałem we wcześniejszym poście), można uniknąć dołączania kodu odpowiedzialnego od calloc() (fdevopen() tego używa), przez napisanie własnej funkcji. Wyświetlenie czegokolwiek na lcd to proste wywołanie: printf( "Ala ma kota %d", myint );
Pozdrawiam.
Łukasz Góralczyk wrote: [ciach]
Pomyłka - 6 bajtów, zapomniałem o adresie powrotu. Dla 4 cyfrowej liczby mamy dodatkowe 24 bajty na stosie.
wsadziłem i wychodzi mniejszy kod już dla 2 wywołań :) a przy 3 wywołaniach to już nie ma oczym mówić :P
To mam się do gorszych kompilatorów stosować czy do lepszych - pomyśl ? Ja stawiałem na optymalizacje kodu wynikowego.
Piotr Chmiel napisał(a):
całkiem zgrabny kawałek kodu, ale tylko dopóki ktoś nie spróbuje wyświetlić zera ;)
w.
Dlaczego wstawiasz tu kod którego nie sprawdziłeś ? Przecież to jest źle !!! Chodzi o to, żeby nie odwracać kolejności i aby ta funkcja była powtarzalna, a u ciebie wskaźnik się ciągle zwiększa - w końcu wyskoczy poza ram :)
trzeba coś poświęcić ,
Piotr Chmiel napisał(a):
Jakos na tyle poznalem GCC ze nie chce mi sie wierzyc... Skompiluj i pokaz jak to wyglada dla jednej i drugiej wersji.
jak chcesz optymalizacji to unikaj rekurencji.
Waldek
Do gorszych - nigdy nie wiadomo czy z takim nie bedziesz musial pracowac.
To chyba kiepsko wyszlo ? :-)
J.
Join the Discussion
Have something to add? Share your thoughts — no account required.
Didn't find your answer?
Ask the community — no account required