-
1. Data: 2017-03-14 19:07:22
Temat: sdcc i at89c51 - dostęp do pinu "na około"
Od: Atlantis <m...@w...pl>
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ę?
-
2. Data: 2017-03-14 19:48:57
Temat: Re: sdcc i at89c51 - dostęp do pinu "na około"
Od: "J.F." <j...@p...onet.pl>
Użytkownik "Atlantis" napisał w wiadomości grup
dyskusyjnych:oa9bgq$7fd$...@n...icm.edu.pl...
>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.
Atlantisie - na moj gust, jak bedziesz takie ambitne struktury robil
... to ci pamieci zabraknie :-)
Duza ta klawiatura ? Regularnie zrobiona ?
Moze regularne metody lepsze.
>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;
* 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;
>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.
Ciekawe, na ile to optymalne. Przy kilku przyciskach ... moze ..
>NIE DZIAŁA natomiast następująca konstrukcja:
>key_press = !(*(key->port) & (1<<(key->pin)));
Zlikwiduj testowo te :3, :4. Albo sobie wydrukuj ... albo wrzuc jak
kompilator to na assembler zamienil.
>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?
89c51 czy 89c52 ?
Bo tu chyba jest pies pogrzebany
http://www.8052.com/tutaddr.phtml
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.
>2) Działa także konstrukcja key_press = !(P0 & (1<<NUMER_PINU))
a ta kompilator moze skompilowac wstawiajac adres na stale.
J.
-
3. Data: 2017-03-14 19:54:09
Temat: Re: sdcc i at89c51 - dostęp do pinu "na około"
Od: Janusz <j...@o...pl>
W dniu 2017-03-14 o 19:07, Atlantis pisze:
> 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ę?
>
Zobacz w asemblerze jak to kompilator przetłumaczył, może się okazać że
poszedł w maliny.
--
Pozdr
Janusz
-
4. Data: 2017-03-14 21:03:03
Temat: Re: sdcc i at89c51 - dostęp do pinu "na około"
Od: Atlantis <m...@w...pl>
W dniu 2017-03-14 o 19:48, J.F. pisze:
> Atlantisie - na moj gust, jak bedziesz takie ambitne struktury robil ...
> to ci pamieci zabraknie :-)
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. ;)
> * ciekawe czy ten kompilator sobie radzi z tym :3.
> Skoro deklaracje przyjmuje, to niby powinien.
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 czy 89c52 ?
> Bo tu chyba jest pies pogrzebany
> http://www.8052.com/tutaddr.phtml
89c51
> 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.
Innymi słowy: da się jakoś dostać do tego portu z poziomu C? ;)
-
5. Data: 2017-03-14 21:09:05
Temat: Re: sdcc i at89c51 - dostęp do pinu "na około"
Od: Zbych <a...@o...pl>
W dniu 14.03.2017 o 19:07, Atlantis pisze:
> 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.
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.
-
6. Data: 2017-03-14 21:21:58
Temat: Re: sdcc i at89c51 - dost?p do pinu "na oko?o"
Od: a...@m...uni.wroc.pl
Atlantis <m...@w...pl> wrote:
> 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;
<snip>
> NIE DZIA?A natomiast nast?puj?ca konstrukcja:
>
> key_press = !(*(key->port) & (1<<(key->pin)));
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.
--
Waldek Hebisch
-
7. Data: 2017-03-14 21:34:40
Temat: Re: sdcc i at89c51 - dostęp do pinu "na około"
Od: Atlantis <m...@w...pl>
W dniu 2017-03-14 o 19:54, Janusz pisze:
> Zobacz w asemblerze jak to kompilator przetłumaczył, może się okazać że
> poszedł w maliny.
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
-
8. Data: 2017-03-14 22:02:07
Temat: Re: sdcc i at89c51 - dost?p do pinu "na oko?o"
Od: Atlantis <m...@w...pl>
W dniu 2017-03-14 o 21:21, a...@m...uni.wroc.pl pisze:
> Twoj problem jest prawdopodobnie zwiazany z at89c51, ale
> bez 'volatile' mozesz miec problem na dowolnym procku.
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. ;)
-
9. Data: 2017-03-14 22:29:02
Temat: Re: sdcc i at89c51 - dostęp do pinu "na około"
Od: Atlantis <m...@w...pl>
Ok, zrobiłem banalny "workaround" rezygnując z przekazywania adresu
portu przez wskaźnik. Zamiast tego przekazuje jego numer i na jego
podstawie, za pomocą sekwencji if-ów wykonuję operację na właściwym
porcie. ;) Dodatkowo za pomocą pól bitowych udało mi się zmieścić
identyfikator portu razem z identyfikatorem pinu i stanem maszyny stanów
w jednej ośmiobitowej zmiennej. :)
To może zapytam jeszcze o jedną rzecz, z którą obecnie walczę i chwilowo
wygrać nie mogę. Projekt wykorzystuje RTC na DS1307. Sam układ działa
(przetestowałem go za pomocą Arduino). Nie mogę jednak za nic
skomunikować go z at89c51.
Korzystam z tej biblioteki:
http://saeedsolutions.blogspot.com/2012/11/interfaci
ng-of-8051-with-ds1307-rtc.html
Czy winę może ponosić fakt, iż mój projekt dość intensywnie korzysta z
przerwań? Powinienem je wyłączać na czas każdej transmisji I2C, czy
raczej nie tutaj szukać przyczyny?
-
10. Data: 2017-03-15 01:42:31
Temat: Re: sdcc i at89c51 - dostęp do pinu "na około"
Od: "J.F." <j...@p...onet.pl>
Dnia Tue, 14 Mar 2017 22:29:02 +0100, Atlantis napisał(a):
> To może zapytam jeszcze o jedną rzecz, z którą obecnie walczę i chwilowo
> wygrać nie mogę. Projekt wykorzystuje RTC na DS1307. Sam układ działa
> (przetestowałem go za pomocą Arduino). Nie mogę jednak za nic
> skomunikować go z at89c51.
>
> Korzystam z tej biblioteki:
> http://saeedsolutions.blogspot.com/2012/11/interfaci
ng-of-8051-with-ds1307-rtc.html
>
> Czy winę może ponosić fakt, iż mój projekt dość intensywnie korzysta z
> przerwań? Powinienem je wyłączać na czas każdej transmisji I2C, czy
> raczej nie tutaj szukać przyczyny?
Raczej nie tutaj.
Ogolnie - predkosc w I2C moze byc dosc dowolna.
Za szybko nie wolno ... ale 100kHz chyba nie przekraczasz,
za wolno ... tylko niektore uklady maja jakies timeouty,
ale az tak bardzo przerwania Ci chyba nie spowalniaja.
Za to oczywiscie w przerwaniu mozna duzo sp* - wiec moze wylacz i
zobacz czy lepiej dziala.
J.