sdcc i at89c51 - dostęp do pinu "na około"

Ciąg dalszy moich eksperymentów z archaicznymi mikrokontrolerami. ;)

Już kiedyś pytałem, czy da się w jakiś sposób przesłać wygodną konstrukcję wskazującą bezpośrednio na pin (np. "P0_0") za pomocą wskaźnika w C. Otrzymałem odpowiedź, że się nie da i muszę to robić w sposób standardowy.

Natknąłem się jednak na pewne problemy... Próbuję przeportować pewną bibliotekę do obsługi przycisków (debouncing + wykrywanie długiego wciśnięcia). Kod podpatrzony w jednej z książek pana Kardasia, z paroma moimi modyfikacjami.

Generalnie sprowadza się do tego, że mam strukturę opisującą przycisk:

typedef struct key { unsigned char *port; unsigned char pin:3; unsigned char state:4; unsigned int timer; void (*push_proc)(void); void (*long_proc)(void); } key_t;

Struktura jest inicjowana za pomocą funkcji key_init(), która przypisuje argumenty do struktury przekazanej przez wskaźnik, czyli wygląda to w ten sposób:

key_init(&button2, &P0, 0, funkcja, funkcja);

Kolejne argumenty oznaczają: adres struktury, adres portu, numer pinu w porcie, wskaźnik na funkcję wykonywaną po krótkim wciśnięciu przycisku i wskaźnik na funkcję wykonywaną po przytrzymaniu przycisku.

Potem stan przycisku jest cały czas sprawdzany wewnątrz funkcji key_update(), która przyjmuje za argument adres struktury.

Tyle tytułem wprowadzenia.

Sęk w tym, że kod nie chce działać. Drogą eliminacji doszedłem do tego, że:

1) Same wejścia cyfrowe działają - odwołanie się do nich bezpośrednio daje pozytywny efekt. 2) Działa także konstrukcja key_press = !(P0 & (1<<NUMER_PINU)) 3) Program wchodzi do funkcji key_update.

NIE DZIAŁA natomiast następująca konstrukcja:

key_press = !(*(key->port) & (1<<(key->pin)));

Strukturę inicjuję podając dane właściwego portu i pinu, a pomimo tego wciskanie przycisku nie jest widoczne.

I teraz pytanie: co jest nie tak. Czyżbym w sdcc i/lub at89c51 nie mógł przesyłać w ten sposób informacji o porcie? A może po prostu coś przeoczyłem i w powyższej linijce tkwił jakiś banalny błąd, który umyka mojej uwadze, gdy na nią patrzę?

Reply to
Atlantis
Loading thread data ...

Użytkownik "Atlantis" napisał w wiadomości grup dyskusyjnych:oa9bgq$7fd$ snipped-for-privacy@news.icm.edu.pl...

Atlantisie - na moj gust, jak bedziesz takie ambitne struktury robil ... to ci pamieci zabraknie :-)

Duza ta klawiatura ? Regularnie zrobiona ? Moze regularne metody lepsze.

typedef struct key { unsigned char *port; unsigned char pin:3; unsigned char state:4;

  • ciekawe czy ten kompilator sobie radzi z tym :3. Skoro deklaracje przyjmuje, to niby powinien.

unsigned int timer; void (*push_proc)(void); void (*long_proc)(void); } key_t;

Ciekawe, na ile to optymalne. Przy kilku przyciskach ... moze ..

Zlikwiduj testowo te :3, :4. Albo sobie wydrukuj ... albo wrzuc jak kompilator to na assembler zamienil.

89c51 czy 89c52 ? Bo tu chyba jest pies pogrzebany
formatting link
Indirect addressing always refers to Internal RAM; it never refers to an SFR.

MOV R0,#99h ;Load the address of the serial port MOV @R0,#01h ;Send 01 to the serial port -- WRONG!!

This is not valid. Since indirect addressing always refers to Internal RAM these two instructions would write the value 01h to Internal RAM address 99h on an 8052. On an 8051 these two instructions would produce an undefined result since the 8051 only has 128 bytes of Internal RAM.

A aby zaadresowac taka nieokreslona komorke pamieci, kompilator musi skorzystac z adresowania posredniego.

Swoja droga on tak to napisal, jakby pod 8051 bylo tak samo ... prawde mowiac nie pamietam, wydaje mi sie, ze mozna bylo adresowac porty @Rn.

a ta kompilator moze skompilowac wstawiajac adres na stale.

J.

Reply to
J.F.

W dniu 2017-03-14 o 19:07, Atlantis pisze:

Zobacz w asemblerze jak to kompilator przetłumaczył, może się okazać że poszedł w maliny.

Reply to
Janusz

W dniu 2017-03-14 o 19:48, J.F. pisze:

Pilnuję zawartości pliku .mem i na razie mieszczę się w wyznaczonej normie. Przycisków jest kilka i tylko niektóre z nich wymagają podwójnej funkcjonalności przyciśnięcie/przytrzymanie. Pozostałym zrobię prostszy debouncing. ;)

Wygląda na to, że sobie radzi. Po dodaniu pól bitowych do definicji typu struktury zużycie pamięci zmniejszyło się o kilka bajtów. I z całą pewnością pola bitowe nie są przyczyną, bo na początku ich nie było, a problem występował. ;)

89c51

Innymi słowy: da się jakoś dostać do tego portu z poziomu C? ;)

Reply to
Atlantis

W dniu 14.03.2017 o 19:07, Atlantis pisze:

Używasz 51 czy 52? Bo w 52 odwołanie pośrednie do adresu 80h (port P0), spowoduje odwołanie do pamięci idata pod adres 80h.

Reply to
Zbych

<snip>

Przy dostepie do portow powinno byc 'volatile', np:

typedef struct key { volatile unsigned char *port; ....

Twoj problem jest prawdopodobnie zwiazany z at89c51, ale bez 'volatile' mozesz miec problem na dowolnym procku.

Reply to
antispam

W dniu 2017-03-14 o 19:54, Janusz pisze:

Niestety, nie znam asemblera, więc kod niewiele mi mówi... :(

; src/SuperDebounce.c:18: key_press = !(*(key->port) & (1<<(key->pin))); mov _key_update_key_1_13,dpl mov (_key_update_key_1_13 + 1),dph mov (_key_update_key_1_13 + 2),b lcall __gptrget mov r2,a inc dptr lcall __gptrget mov r3,a inc dptr lcall __gptrget mov r4,a mov dpl,r2 mov dph,r3 mov b,r4 lcall __gptrget mov r2,a mov a,#0x03 add a,_key_update_key_1_13 mov r1,a clr a addc a,(_key_update_key_1_13 + 1) mov r3,a mov r4,(_key_update_key_1_13 + 2) mov dpl,r1 mov dph,r3 mov b,r4 lcall __gptrget anl a,#0x07 mov r1,a mov b,r1 inc b mov a,#0x01 sjmp 00176$

00174$: add a,acc 00176$: djnz b,00174$ mov r1,a anl ar2,a mov a,r2 cjne a,#0x01,00177$ 00177$: clr a rlc a
Reply to
Atlantis

W dniu 2017-03-14 o 21:21, snipped-for-privacy@math.uni.wroc.pl pisze:

Dodałem "volatile", ale nie ma żadnej zmiany. Więc jednak nie o to chodziło...

Powinienem przyjąć, że w przypadku tych MCU nie da się odwołać do portu przez wskaźnik? Mogę to obejść w inny sposób - najprościej będzie chyba przekazywać normalną liczbę i w zależności od jej wartości, odwoływać się do konkretnego portu, określonego twardo w kodzie. Sądziłem tylko, że może będzie się to dało zrobić bardziej elegancko. ;)

Reply to
Atlantis

Dnia Tue, 14 Mar 2017 21:03:03 +0100, Atlantis napisał(a):

A tam masz program czy RAM ? Ja sie o (I)RAM martwie - 128 bajtow to tyle co nic :-)

Dajac staly adres.

J.

Reply to
J.F.

Jedno i drugie.

To mniej-więcej tyle, co we współczesnych ATTiny. :)

Zawartość pliku poniżej. Nie wygląda to źle zważywszy na fakt, że program jest prawie gotowy. Pewnie dałoby się odzyskać jeszcze parę bajtów. :)

Jedyne co mnie zastanawia, to te "PAGED EXT. RAM" i "EXTERNAL RAM". Powinienem to jakoś wyłączyć, skoro nie korzystam z zewnętrznej pamięci? Jeśli tak, to gdzie?

Internal RAM layout: 0 1 2 3 4 5 6 7 8 9 A B C D E F

0x00:|0|0|0|0|0|0|0|0|a|a|b|b|b|b|b|b| 0x10:|b|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c| 0x20:|c|c|c|c|c|c|c|d|d|d|d|e|e|e|e|e| 0x30:|e|e|e|e|e|e|e|e|e|e|e|e|e|e|e|e| 0x40:|e|e|Q|Q|Q|Q|Q|Q|S|S|S|S|S|S|S|S| 0x50:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S| 0x60:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S| 0x70:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S| 0x80:| | | | | | | | | | | | | | | | | 0x90:| | | | | | | | | | | | | | | | | 0xa0:| | | | | | | | | | | | | | | | | 0xb0:| | | | | | | | | | | | | | | | | 0xc0:| | | | | | | | | | | | | | | | | 0xd0:| | | | | | | | | | | | | | | | | 0xe0:| | | | | | | | | | | | | | | | | 0xf0:| | | | | | | | | | | | | | | | | 0-3:Reg Banks, T:Bit regs, a-z:Data, B:Bits, Q:Overlay, I:iData, S:Stack, A:Absolute

Stack starts at: 0x48 (sp set to 0x47) with 56 bytes available.

Other memory: Name Start End Size Max ---------------- -------- -------- -------- -------- PAGED EXT. RAM 0 256 EXTERNAL RAM 0 1024 ROM/EPROM/FLASH 0x0000 0x0b4a 2891 4096

Reply to
Atlantis

W dniu 2017-03-15 o 01:46, J.F. pisze:

Obecnie nic, ale kiedyś to było bardzo dużo :-) W PiccoGALu w tych 128 bajtach mieściły nam się:

- stos procesora,

- stos danych FORTH,

- bufor danych programowania/odczytywania EEPROMów / GALi

- cały program w FORTH konkretnej (odczyt, zapis, weryfikacja...) obsługi danej kostki.

Może mieściły to nie dokładne określenie, bo bufor danych zachodził zazwyczaj na początek programu, ale był używany już po wykonaniu tego początku programu i dojściu do głównej pętli. P.G.

Reply to
Piotr Gałka

Użytkownik "Piotr Gałka" napisał w wiadomości grup dyskusyjnych:oaavl5$ilc$ snipped-for-privacy@news.chmurka.net... W dniu 2017-03-15 o 01:46, J.F. pisze:

Ale w Forth nie miales takich ambitnych struktur danych :-)

Dobrze ze z RS czy Centronicsa, bo juz z dyskietka mialbys problem :-)

J.

Reply to
J.F.

W dniu 2017-03-15 o 10:21, J.F. pisze:

Nie za bardzo rozumiem. RS czy Centronics to sposób komunikacji, a dyskietka to inny świat. Masz na myśli urządzenie, które miałoby zapisywać/odczytywać dane na dyskietkach, czy może urządzenie podłączane jakoś zamiast dyskietki (sposób komunikacji). P.G.

Reply to
Piotr Gałka

Użytkownik "Piotr Gałka" napisał w wiadomości grup dyskusyjnych:oab2oh$jpv$ snipped-for-privacy@news.chmurka.net... W dniu 2017-03-15 o 10:21, J.F. pisze:

Dyskietka to tez sposob komunikacji - komputer nagrywa dane na dyskietke, dyskietke sie wsadza w programator, programator czyta i programuje kosc.

Tylko ta cholera ma sektor 512 bajtow :-)

Dyskietka to moze niezbyt szczesliwy przyklad, ale nawet na magnetofon dane sie czesto blokami nagrywalo ..

J.

Reply to
J.F.

W dniu 2017-03-15 o 11:16, J.F. pisze:

Gdyby programator miał czytnik dyskietek (jak dla mnie to egzotyczny pomysł) to tez jakoś można by sobie poradzić - procedura czytaj n-tą

16-kę bajtów z m-tego sektora. P.G.
Reply to
Piotr Gałka

Użytkownik "Piotr Gałka" napisał w wiadomości grup dyskusyjnych:oabn9j$rgj$ snipped-for-privacy@news.chmurka.net... W dniu 2017-03-15 o 11:16, J.F. pisze:

Egzotyczny od czasu pecetow - a jak przygotowac eprom do pierwszego peceta ? :-)

Mialem kiedys na uczelni taki programator - klawiatura hex i komunikujemy sie. Chyba nie uzywalem, z oczywistych wzgledow :-)

Za dyskietke bym ozlocil, za czytnik tasiemki perforowanej tez - o ile mialbym perforator :-)

Istniejace kosci raczej nie mialy, ale moze daloby sie jakos obejsc i faktycznie tak obsluzyc. A co z zapisem ? Odczyt epromu i zrzut do pliku uzyteczna funkcja :-)

W kazdym badz razie w miare rozwoju apetyt rosnie i 128 bajtow staje sie niewystarczajace. Szczegolnie jak sie komus marza jakies ambitne struktury w C, po 10 bajtow na klawisz :-)

J.

Reply to
J.F.

W dniu 2017-03-15 o 17:01, J.F. pisze:

Tak jak się uruchamiało MERĘ 300 - zestaw przełączników określających bity i przycisk zapisz (licznik adresów automatycznie zwiększający stan to nie problem). W MERZE 300 wpisywało się chyba około 10 słów pierwszego programu czytającego tasiemkę i go uruchamiało, a dalej z tasiemki.

Należało by wpisać przełącznikami do EPROMu najprostszy program czytaj bajt z tasiemki i wpisz do EPROMu. Potem za jego pomocą wpisało by się do następnego już lepszy program i potem z górki.

Czytnik tasiemki (lub kart) (z ręcznym przesuwem) wydaje mi się, że dało by się zmajstrować. P.G.

Reply to
Piotr Gałka

J.F. <jfox snipped-for-privacy@poczta.onet.pl> napisał(a):

W czasach bardziej współczesnych miałem mikrokomputer z 8051 (AVT2250) i programowałem go właśnie szesnastkowo. Miałem kartkę z listą rozkazów '51 i program pisało się od razu w języku maszynowym :)

Reply to
Grzegorz Niemirowski

Użytkownik "Grzegorz Niemirowski" napisał w wiadomości grup dyskusyjnych:oabqj0$dn3$ snipped-for-privacy@node2.news.atman.pl... J.F. <jfox snipped-for-privacy@poczta.onet.pl> napisał(a):

No ba, pierwszy program maszynowy na ZX81 napisalem w zeszycie, przetranslowalem recznie i wpisalem korzystajac z prostego programiku w basicu. Jeszcze liczbami dziesietnymi - tak bylo prosciej niz hex sie bawic :-)

Ale nie twierdze, ze to jest wlasciwy sposob pracy :-)

J.

Reply to
J.F.

Użytkownik "Piotr Gałka" napisał w wiadomości grup dyskusyjnych:oabpr3$sgg$ snipped-for-privacy@news.chmurka.net... W dniu 2017-03-15 o 17:01, J.F. pisze:

W Riadzie/IBM360 to byl rozkaz do "kanału", czyli takiego pomocniczego komputera/zaawansowanego sterownika urzadzen zewnetrznych. Ten rozkaz czytal kolejne rozkazy dla kanału, az sie system zaladowal :-)

problem techniczny to byly male wymiary dziurek - nawet specjalne fototranzystory czy fotodiody robili, srednicy ~2mm.

Jeden z takich czytnikow to mnie zadziwil - silnik z rolka przesuwu, elektromagnes dociskajacy tasme do rolki i fotoelementy ze wzmacniaczami. Zadnej precyzji, pracy krokowej - nic. Tasma sobie leciala swoim tempem, a fotodioda od tych srodkowych malych dziurek najwyrazniej robila za zrodlo sygnalu zegarowego dla odbiorcy.

To byl taki model samodzielny - mala skrzyneczka z jakims dziwnym gniazdem. Do czego to bylo przeznaczone - pojecia nie mam. Byc moze chocby do takich programatorow epromow - czytanie danych do RAM na paru TTL mozna zrobic :)

J.

Reply to
J.F.

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.