Programowanie AT89Cxx51

Wiem, że mikokontrolery oparte na 8051 powoli wychodzą z mody, ale obecnie muszę napisać nowy wsad do istniejącego urządzenia. Nie mam zamiaru uczyć się assemblera tej rodziny ani bawić się w BASCOM-ie, więc skorzystam z C. W czasach świetności tych MCU powszechnie korzystano z kompilatora Keil, ja jednak postawię na SDCC - z tego co widzę, podobieństwa są dość spore, przynajmniej na pierwszy rzut oka. Proste projekty przykładowe się kompilują.

Mam jednak kilka pytań:

1) Widzę, że możliwy jest dostęp do pinów GPIO za pomocą konstrukcji w rodzaju Px_y, gdzie x oznacza numer portu, a y numer pinu w porcie. Można dzięki temu przypisywać wartość bezpośrednio do pinu, (np. P0_1=1). Czym jest taka konstrukcja? Można zdefiniować jakąś zmienną wskaźnikową, która umożliwi mi dostęp do tak zdefiniowanego pinu? Chciałbym przeportować pewną prostą bibliotekę do obsługi przycisków. Dobrze by było, gdybym mógł przekazać informację o pinie właśnie w ten sposób, jako argument funkcji, a potem trzymać ją w strukturze opisującej przycisk. 2) Czy możliwe jest korzystanie z portów w sposób taki, jak w AVR-ach? To znaczy coś w rodzaju P0 |= (1<<2). 3) Dobrze rozumiem, że te mikrokontrolery nie posiadają żadnych rejestrów konfiguracyjnych, jeśli chodzi o kierunek pinu i działają podobnie do prostych ekspanderów I2C?
Reply to
Atlantis
Loading thread data ...

-- Wiadomość oryginalna (wysłana 14.02.2017 08:30) --

Podstawowa różnica: inna kolejność bajtów w liczbach wielobajtowych.

Zerknij do plików nagłówkowych SDCC, np: __sbit __at (0x87) P0_7

Jak widać, to jest po prostu liczba, tylko z atrybutami __sbit __at

Oczywiście, dokładnie tak samo.

Tu już nie jestem taki pewny, daawno nie programowałem AT89. Ale chyba faktycznie nie ma żadnej konfiguracji, stan niski to twarde 0, stan wysoki to wysoka impedancja.

Pozdrowienia, MKi

Reply to
MKi

Broń Boże. Porty mają do dyspozycji tylko jeden rejestr, który jest wejściem (przy odczycie) i wyjściem (przy zapisie). Kompilator może to przetłumaczyć na instrukcję bitową albo na odczyt, modyfikację i zapis. I wtedy jak z wejścia odczytasz 0 to 0 zapiszesz na wyjście.

Albo korzystasz tylko z instrukcji bitowych do manipulowania I/O, albo musisz dołożyć do tego maskę ustawiającą na 1 bity, które są wejściami.

P0 |= P0_INPUTS_MASK | (1 << 2); P0 = (P0 | P0_INPUTS_MASK) & ~(1 << 2);

Stan wysoki to słaby pullup, co ciekawe wiele '51 na jeden albo dwa cykle zegarowe włącza silny pullup przy zmianie stanu z 0 na 1, żeby szybciej przeładować pojemności na linii.

Reply to
Zbych

Użytkownik "MKi" napisał w wiadomości grup dyskusyjnych:58a2c045$0$15193$ snipped-for-privacy@news.neostrada.pl...

Maja taki specjalny tryb adresacji - dla wybranych rejestrow i kawalka pamieci dostepny jest tryb bitowy. Zapisujesz odpowiedna instrukcja i bit sie zmienia. Ale ... kompilator musi wiedziec, ze tu jest potrzebna specjalna instrukcja.

Przy czym jak tych przyciskow wiecej, to moze byc jednak lepiej oblsugiwac to calymi bajtami.

Ostroznie, tam sa rozne tryby adresacji, i znow trzeba uwazac co kompilator z tym zrobi. Raczej zrobi dobrze, ale instrukcja ORL P0, #01h odczytuje rejestr portu wyjsciowego, ustawia najmlodszy bit i zapisuje ponownie.

Instrukcja MOV A, P0 odczytuje stanu pinow portu. Jak potem zrobisz ORL A,#01h MOV P0,A

To to nie bedzie to samo (patrz nizej).

Dokladnie - rejestry sa jednoczesnie wejsciowe i wyjsciowe. tranzystor wyjsciowy "dolny" jest silny, "gorny" slabiutki, a w zasadzie to stale pull-up (+ te 2 cykle). Jesli ustawisz bit na "0", to wyjscie bedzie na 0, i nie nalezy podawac z zewnatrz stanu wysokiego. Jesli ustawisz bit na "1", to wyjscie bedzie w stanie wysokim, ale slabym (~1mA), mozna z zewnatrz wymusic zero.

Bity, ktore maja byc wejsciowe, musisz najpierw ustawic na 1.

J.

Reply to
J.F.

czy jest jakiś tutorialek do SDCC?

Reply to
invalid unparseable

Ok, wielkie dzięki za informacje. Mam jeszcze jedną prośbę. Zauważyłem, że MCU8051IDE samo z siebie nie potrafi obsługiwać projektów z wieloma plikami. Każdy plik jest kompilowany z osobna i przy próbie skompilowania czegoś z funkcjami pomocniczymi wyskakuje błąd informujący o braku funkcji main. Z tego co wiem, do projektu można jednak podpiąć makefile. W najgorszym razie będę go sobie ręcznie kompilował przez make.

Ktoś z was ma może działający, przykładowy makefile pod sdcc i mcu z serii at89cxxxx?

Reply to
Atlantis

-- Wiadomość oryginalna (wysłana 15.02.2017 06:16) --

Nie używałem SDCC z AT89, więc precyzyjnie Ci nie pomogę, ale może coś moje informacje wprowadzą.

Kompilowałem SDCC na procesorki SiLabs, przy użyciu Silabs IDE, do bezpłatnego pobrania ze strony silabs.com Cześć dotycząca programowania i debugowania jest oczywiście dedykowana do tych procesorów, ale można w tym kompilować programy na inne procesory, wystarczy wskazać ścieżkę do SDCC.

Jakbyś nie chciał walczyć z nowym środowiskiem, to poniżej przykład - jakie polecenia wygenerowało IDE dla dwuplikowego programu, może ułatwi tworzenie makefile:

C:\Programy\SDCC\BIN\sdcc.exe -c --debug --use-stdout -V -I"sciezka" "sciezka\plik1.c"

C:\Programy\SDCC\BIN\sdcpp.exe -nostdinc -Wall -std=c99 -I"sciezka"

-obj-ext=.rel -DSDCC_MODEL_SMALL -DSDCC=260 -DSDCC_mcs51 -D__mcs51

-I"C:\Programy\SDCC\BIN\..\include\mcs51"

-I"C:\Programy\SDCC\BIN\..\include" "sciezka\plik1.c"

C:\Programy\SDCC\BIN\asx8051.exe -plosgffc "plik1.asm"

C:\Programy\SDCC\BIN\sdcc.exe -c --debug --use-stdout -V -I"sciezka" "sciezka\plik2.c"

C:\Programy\SDCC\BIN\sdcpp.exe -nostdinc -Wall -std=c99 -I"sciezka"

-obj-ext=.rel -DSDCC_MODEL_SMALL -DSDCC=260 -DSDCC_mcs51 -D__mcs51

-I"C:\Programy\SDCC\BIN\..\include\mcs51"

-I"C:\Programy\SDCC\BIN\..\include" "sciezka\plik2.c"

C:\Programy\SDCC\BIN\asx8051.exe -plosgffc "plik2.asm"

C:\Programy\SDCC\BIN\sdcc.exe --debug --use-stdout -V -I"sciezka"

-o"sciezka\plik.hex" "sciezka\plik1.rel" "sciezka\plik2.rel"

C:\Programy\SDCC\BIN\aslink.exe -nf "sciezka\plik.lnk"

SDCC jest zainstalowane w C:\Programy\SDCC, projekt w sciezka, pliki źródłowe to plik1.c i plik2.c, pliki wynikowe plik.*.

Pozdrowienia, MKi

Reply to
MKi

Ten co Ci wysłałem do pic32 jest uniwersalny, zdefiniuj tylko LD i CC.

Reply to
Marek

Może to pytanie zabrzmi głupio, ale jak powinna? wyglądać definicja wskaźnika na coś takiego? Chcę mieć funkcję inicjującą strukturę, która będzie przyjmowała jako jeden z argumentów adres pinu (np. &P0_2). Potem ten adres byłby przechowywany właśnie jako zmienna wskaźnikowa wewnątrz struktury.

Powinienem zdefiniować jakąś specjalną zmienną wskaźnikową, czy wystarczy jawne rzutowanie np. na unsigned char *?

Będę mógł za pomocą takiej konstrukcji sterować pinem?

Reply to
Atlantis

W c nie ma wskaźników na bity. Musisz to rozbić na adres portu (w przestrzeni adresowej __data) i maskę bitową.

Reply to
Zbych

Czyli innymi słowy nie ma możliwości na przekazanie do funkcji, a potem przechowanie w strukturze konstrukcji takiej jak P0_2? Będę musiał to zrobić tak, jak w AVR-ach? Czyli innymi słowy:

init(&struktura, &P0, 2);

wewnątrz tej funkcji adres portu zostanie zapisany w zmiennej wskaźnikowej, numer pinu w porcie w zmiennej unsigned char. A potem już standardowa operacja:

key_pressed = !(*port & (1<<pin))

O to chodzi?

Reply to
Atlantis

Mam jeszcze jedno pytanie, dotyczące pamięci RAM w tych MCU. Po pierwsze o co dokładnie chodzi o z modelami pamięci (--model-small,

--model-large) ustalanymi za pomocą flag kompilatora? Natknąłem się też na dziwny objaw - po przekroczeniu 128 bajtów w wyniku zdefiniowana kilku dodatkowych zmiennych program przestał się kompilować, chociaż w tej chwili w makefile mam ustawiony iram na 256 bajtów (eksperymentuję z AT89C52). Mam rozumieć, że ta druga połowa pamięci nie jest bezpośrednio dostępna?

Reply to
Atlantis

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

kompilowac czy dzialac ?

Tak sobie bezposrednio.

51 ma 8-bit adresu danych, a gorna polowa przestrzeni zajeta na rejestry.

w 8052 inststrukcje adresujace posrednio (czyli @R0, @R1) dobieraja sie do calej pamieci, pozostale tryby z adresami 80-FF - do rejestrow.

formatting link
MOV R0,#90h ;Set the indirect address to 90h MOV A,@R0 ;Read the contents of Internal RAM pointed to by R0

MOV A,90h ;Reads the contents of SFR 90h (P1)

Kompilator C musi to jakos respektowac, albo glupoty zrobi :-)

J.

Reply to
J.F.

Model small - wszystkie zmienne, parametry funkcji są alokowane w podstawowej pamięci RAM (masz na to 128 bajtów). O ile dobrze pamiętam, stos jest w IRAM (czyli górnych 128 bajtach).

Model large - obiekty te są alokowane w pamięci XRAM (zazwyczaj do 64KB). Dostęp do każdej zmiennej poprzedzany jest załadowaniem jej adresu do DPTR. Stos też jest w XRAM, co bardzo wydłuża jego obsługę. Pozdrowienia, MKi

Reply to
MKi

Nigdy nie programowałem w assemblerze. Nigdy nie programowałem w C mikrokontrolerów.

Wydaje mi się, że skoro P0_7 jest już samo w sobie adresem pinu (czyli wskaźnikiem na pin) to może uda Ci się obejść bez wskaźników na ten wskaźnik. Warunkiem jest żeby C potrafiło korzystać z rozkazów assemblera z adresowaniem bitowym. P.G.

Reply to
Piotr Gałka

W dniu 23.02.2017 o 10:20, Piotr Gałka pisze:

Adresowanie bitowe w '51 wymaga podania numeru bitu od razu w rozkazie, nie ma trybu adresowania pośredniego przez rejestr.

Spójrz na przykłady użycia:

formatting link

Reply to
Zbych

W dniu 2017-02-23 o 21:07, Zbych pisze:

Całkiem być może, że nie ogarnąłem sedna zagadnienia. Rozumiałem, że: Atlantis chce przechowywać wskaźniki na piny. A ponieważ we wcześniejszych jego pracach (z innymi procesorami) wymagało to użycia jakichś wskaźników w C to teraz też myśli jak zrobić sobie wskaźniki na te numerki określające bitowe adresy pinów. Z jego wypowiedzi rozumiałem, że dotychczas przechowywał wskaźniki na piny, a nie wskaźniki na wskaźniki na piny.

---- koniec opisu jak ja to rozumiałem ----

Chciałem jedynie zwrócić uwagę, że _być_może_ szuka czegoś co ma gotowe, że _być_może_ wystarczy posłużyć się (i przechowywać) te bitowe adresy pinów.

W latach 90-tych napisałem assembler dla 51-ki. Niedawno mnie zmuszono aby go przekompilować aby pod Win10 działał. Miałem z tym trochę zaskakujących problemów ale się udało. Nie pamiętałem oczywiście jak ten adres pinu jest podawany do rozkazu, ale nie rozumiem jakie to ma znaczenie.

Nigdy nie używałem C dla żadnego mikrokontrolera. Wyobrażałem sobie, że C musi być trochę rozszerzane pod dany procesor. Czyli zakładałem, że w C dla 51-ki powinna być jakaś funkcja biblioteczna typu setbit() przyjumująca jako parametr jego adres i potrafiąca przetłumaczyć to na assembler nawet jak nie ma adresowania przez rejestr. P.G.

Reply to
Piotr Gałka

W dniu 24.02.2017 o 11:01, Piotr Gałka pisze:

Napiszę najprościej jak potrafię. Numer bitu w setb i clr musi być na sztywno wpisany w rozkaz, nie ma możliwości zrobienia z niego parametru.

Jak chcesz parametryzować, to wracasz do opisywanego wcześniej rozwiązania "adres portu + maska bitowa".

Reply to
Zbych

W dniu 2017-02-24 o 11:28, Zbych pisze:

Dzięki. W końcu dotarło do mnie :) Jakoś nie zauważyłem, że to wymagałoby dynamicznego dopasowywania kodu programu w czasie jego pracy :( P.G.

Reply to
Piotr Gałka

Użytkownik "Piotr Gałka" napisał w wiadomości grup dyskusyjnych:o8p09b$l8c$ snipped-for-privacy@news.chmurka.net... W dniu 2017-02-23 o 21:07, Zbych pisze:

Ale wlasnie nie mozesz.

Mozesz napisac w C np P0_7 = 1 i miec nadzieje, ze kompilator skompiluje z uzyciem wlasciwych rozkazow.

Ale nie mozesz napisac wskaznik = P0_7 ; ....

*wskaznik = 1 ;

bo ... nie ma takiego rozkazu, ktory moglby kompilator uzyc, aby potrafil zaadresowac bit o numerze w jakims rejestrze podanym.

wiec nie da sie np zrobic funkcji ktora poczeka na nacisniecie klawisza, cos w rodzaju void function wait_for_key(int keynr) { .... }

(zadziala jako macro)

Nie da sie tez zrobic petli sprawdzi bity po kolei itp ...

No i zakladam, ze C jest rozszerzone (w odpowiednio ambitnym kompilatorze), i kompilator potrafi to skompilowac ... o ile adres jest znany w czasie kompilacji. Inaczej, to pozostaja dwie mozliwosci:

1) przygotowujemy sobie odpowiedni rozkaz w pamieci i wykonujemy go. cos typu setbit: ; A zawiera nr bitu mov setbitr+1, A setbitr: setb 0 ret

ha, ha - zycze powodzenia na 8051, z jej rozdzielonymi pamieciami :-) ale jesli system zawiera dodatkowy RAM, ktory bedzie widoczny jako pamiec zewnetrzna i programu jednoczesnie, to moze by sie nawet udalo (np na tym DScostam z bateryjka).

2) przygotowujemy sobie siec rozkazow: setb 0 ret setb 1 ret setb 2 ret ....

i wyliczamy sobie to ktorego adresu skoczyc ... imo - niemal niedopuszczalne, ale jak trzeba, to trzeba :-)

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.