paczkaexpres Napisano Kwiecień 3, 2012 Udostępnij Napisano Kwiecień 3, 2012 Cześć,Ostatnio natknąłem się na taki problem otóż mój program nie wraca z funkcji Shift_register do maina. Objawia się to tym ,że gdy jest załadowany program w którym wszytko jest w funcki main program działa (ledy się przełączają , buzzer sygnalizuje poprawną pracę) jednak gdy obsługę rejestru umieszczę w oddzielnej funkji program przestaje działać (tak jakby się zawiesił /nie wraca do maina) ledy nie świecą buzzer nie gra. Dzieje się tak nawet wtedy gdy funkcja Shift_register jest pusta. Programuję atmege 128, używam eclipsa z wtyczką avr , korzystam z optymalizacji kodu Op 1. Shift_register.h #ifndef SHIFT_REGISTER_H_ #define SHIFT_REGISTER_H_ //void Shift_register(int); //output enable input (active LOW) #define SR_OEI_SET PORTE |= (1<<0) #define SR_OEI_CLR PORTE &= ~(1<<0) #define SR_OEI_OUT DDRE |= (1<<0) //shift register clock input #define SR_STCP_SET PORTE |= (1<<1) #define SR_STCP_CLR PORTE &= ~(1<<1) #define SR_STCP_OUT DDRE |= (1<<1) // master reset (active LOW) #define SR_RESET_SET PORTE |= (1<<2) #define SR_RESET_CLR PORTE &= ~(1<<2) #define SR_RESET_OUT DDRE |= (1<<2) // storage register clock input #define SR_SHCP_SET PORTE |= (1<<6) #define SR_SHCP_CLR PORTE &= ~(1<<6) #define SR_SHCP_OUT DDRE |= (1<<6) //serial data input #define SR_DATA_SET PORTE |= (1<<7) #define SR_DATA_CLR PORTE &= ~(1<<7) #define SR_DATA_OUT DDRE |= (1<<7) #endif /* SHIFT_REGISTER_H_ */ Program główny dla którego wszystko działa poprawnie. Main.c #include <avr/io.h> #include <avr/iom128.h> #include <util/delay.h> #include "Shift_register.h" #define BUZZER_CLR PORTE |= (1<<5) #define BUZZER_SET PORTE &= ~(1<<5) #define BUZZER_OUT DDRE |= (1<<5) static void Inicialization(void); int a,b; int main(void) { Inicialization(); while(1) { b++; a=b; SR_STCP_SET; SR_STCP_CLR; for(int i=0;i<16;i++) { SR_DATA_CLR; if(!(a%2==1)) SR_DATA_SET; SR_SHCP_SET; SR_SHCP_CLR; a=a/2; } SR_STCP_SET; SR_STCP_CLR; BUZZER_SET; _delay_us(1000); BUZZER_CLR; _delay_ms(20); } } void Inicialization(void) { BUZZER_OUT; BUZZER_CLR; SR_OEI_OUT; SR_DATA_OUT; SR_STCP_OUT; SR_SHCP_OUT; SR_RESET_OUT; SR_RESET_SET; SR_OEI_CLR; } ale gdy w definicjach odkomentuję void Shift_register(int) i zmienie wywołanie funcji na: main.c #include <avr/io.h> #include <avr/iom128.h> #include <util/delay.h> #include "Shift_register.h" #define BUZZER_CLR PORTE |= (1<<5) #define BUZZER_SET PORTE &= ~(1<<5) #define BUZZER_OUT DDRE |= (1<<5) static void Inicialization(void); int a,b; int main(void) { Inicialization(); while(1) { b++; a=b; Shift_register(a); BUZZER_SET; _delay_us(1000); BUZZER_CLR; _delay_ms(20); } } void Inicialization(void) { BUZZER_OUT; BUZZER_CLR; SR_OEI_OUT; SR_DATA_OUT; SR_STCP_OUT; SR_SHCP_OUT; SR_RESET_OUT; SR_RESET_SET; SR_OEI_CLR; } Shift_register.c #include <avr/io.h> #include <util/delay.h> #include <avr/iom128.h> #include "Shift_register.h" void Shift_register(int a) { SR_STCP_SET; SR_STCP_CLR; for(int i=0;i<16;i++) { SR_DATA_CLR; if(!(a%2==0)) SR_DATA_SET; SR_SHCP_SET; SR_SHCP_CLR; a=a/2; } SR_STCP_SET; SR_STCP_CLR; } Najlepsze jest to że nawet gdy funkcja Shift_register jest w środku pusta to program i tak nie działa (przez nie działa rozumiem że się kompiluje bez errorów i warningów ale buzzer nie sygnalizuje pracy). Cytuj Link do komentarza Share on other sites More sharing options...
Treker (Damian Szymański) Kwiecień 3, 2012 Udostępnij Kwiecień 3, 2012 A nie zabrakło Ci w tej funkcji Shift_register return 0;? Cytuj Link do komentarza Share on other sites More sharing options...
Foadrian Kwiecień 3, 2012 Udostępnij Kwiecień 3, 2012 Witaj! A nie zabrakło Ci w tej funkcji Shift_register return 0;? raczej nie, to funkcja typu void i return był by błędem. Zastanawia mnie że dublujesz inicjalizację tej funkcji. Czyli na początku programu wstawiasz #include "Shift_register.h" a na końcu programu wstawiasz: void Shift_register(int a) { SR_STCP_SET; SR_STCP_CLR; for(int i=0;i<16;i++) { SR_DATA_CLR; if(!(a%2==1)) SR_DATA_SET; SR_SHCP_SET; SR_SHCP_CLR; a=a/2; } SR_STCP_SET; SR_STCP_CLR; } - To co zawarte już było w bibliotece Shift_register.h Czy to przypadkiem nie jest zbędne ?? Nie mam praktycznych podstaw by twierdzić że to błąd ale na zdrowy rozsądek i wyczucie wydaje mi się że właśnie to może być problemem. Cytuj Link do komentarza Share on other sites More sharing options...
paczkaexpres Kwiecień 3, 2012 Autor tematu Udostępnij Kwiecień 3, 2012 Foadrian oczywiście to jest zbędne. Jest to tylko pozostałość po źle skopiowanym kodzie i w programie tego nie ma. Cytuj Link do komentarza Share on other sites More sharing options...
Polecacz 101 Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Produkcja i montaż PCB - wybierz sprawdzone PCBWay! • Darmowe płytki dla studentów i projektów non-profit • Tylko 5$ za 10 prototypów PCB w 24 godziny • Usługa projektowania PCB na zlecenie • Montaż PCB od 30$ + bezpłatna dostawa i szablony • Darmowe narzędzie do podglądu plików Gerber Zobacz również » Film z fabryki PCBWay
koval_blazej Kwiecień 3, 2012 Udostępnij Kwiecień 3, 2012 Zastanawia mnie że dublujesz inicjalizację tej funkcji. Najpierw jest deklaracja a potem definicja. Jak najzupełniej poprawne i zgodne z testamentem. BTW, zmień wywołanie na shift_register(b++) i możesz się pozbyć 2 linijek wyżej. (Po co w ogóle to przypisanie a=b?) Cytuj Link do komentarza Share on other sites More sharing options...
marek1707 Kwiecień 3, 2012 Udostępnij Kwiecień 3, 2012 Hm, w kodzie nie widać niczego dziwnego. Masz gdzieś zdefiniowany symbol F_CPU? - to tak na marginesie. Przede wszystkim sprawdź to samo dla ustawienia optymalizatora = 2. To pewnie banał ale upewnij się także, że używasz rzeczywiście pliku nagłówkowego odpowiadającego procesorowi na płytce. Ja kiedyś naciąłem się na projekt na ATmega2561 - niby to samo co 128 (tak myślałem) i kompilowałem na 128. A ten duży zaczął się sypać właśnie przez stos bo inaczej gospodaruje RAMem podczas wywołań funkcji. Instrukcja wywołania podprogramu CALL zapisuje na stosie 3 bajty a nie 2 jak w mega128 i dopóki funkcje były trywialne, działało. Wystarczyło jednak, że w funkcji użyłem zmiennej automatycznej a specyficznie generowana ramka na stosie podczas prologu, podczas epilogu funkcji była "zdejmowana" w zupełnie niesymetryczny sposób i niszczyła adres powrotu. Deklaracja int wewnątrz nawiasu for nie jest zgodna z "kanonicznym" C ale jeśli masz włączone rozszerzenia C99, powinno być OK. Shift_register jest pierwszą wywoływaną funkcją używającą argumentu ale przekazywanie tak prostych danych jest bezbolesne, bo odbywa się przez rejestry. To samo z wartością oddawaną. Czy mógłbyś pokazać albo wkleić link do pliku .lss po kompilacji niedziałającej wersji? Być może tam jest wytłumaczenie. Acha, wyrażenie a%2 naprawdę wywołuje funkcję dzielenia. Chyba optymalizator nie wyczaja, że chcodzi Ci o sprawdzenie najmłodszego bitu. Żaby go wyłuskać wystarczy zrobić a&1. Cytuj Link do komentarza Share on other sites More sharing options...
paczkaexpres Kwiecień 3, 2012 Autor tematu Udostępnij Kwiecień 3, 2012 Może komuś to pomoże : Gdy usunę static przy funkcji inicjalizacja to program też przestaje działać poprawnie. Co ciekawe jeżeli w tej funkcji wywołam funkcję main() to program wraca do funckji main (ale zaczyna ją wykonywać od początku) Debug.rar Cytuj Link do komentarza Share on other sites More sharing options...
dondu Kwiecień 3, 2012 Udostępnij Kwiecień 3, 2012 Co ciekawe jeżeli w tej funkcji wywołam funkcję main() to program wraca do funckji main (ale zaczyna ją wykonywać od początku) Oj to coś bardzo namieszałeś. Nie możesz się dziwić, że main wykonuje się od początku. To normalna funkcja. Jeśli ją wywołasz z innej funkcji programu, to musi się rozpocząć od początku. Pytanie jest - Dlaczego wywołujesz main() z innej funkcji? Cytuj Link do komentarza Share on other sites More sharing options...
paczkaexpres Kwiecień 3, 2012 Autor tematu Udostępnij Kwiecień 3, 2012 Chciałem sprawdzić czy będąc w funkcji Shift_register program się zacina czy nie. Skoro jest w stanie po wywołaniu main() powrucić do funkcji głównej czyli się nie zacina. Cytuj Link do komentarza Share on other sites More sharing options...
marek1707 Kwiecień 3, 2012 Udostępnij Kwiecień 3, 2012 Funkcja main jest domyślnie wołana przez system jako poaczątek kodu. Raczej nie powinno się jej wołać bo to oznacza wzajemną rekurencję. W C nie jest to zakazane a wręcz są algorytmy które zgrabnie to wykorzystują. Ale sensu wywoływania akurat main z tego samego programu raczej nie widzę - chcesz zacząć od początku? Przecież funkcja wywołująca main musiała być z niej kiedyś wywołana - inaczej nie dostałaby sterowania. Z pierwszego oglądu plików wynikowych wygląda że: - Funkcja inicjująca została włączona do main jakby była inline. Być może optymaliztor uznał, że ponieważ wywołujesz ją tylko raz, można ją po prostu w to miejsce wstawić zamiast wywołania. - Wielkości opóźnień wskazują (jeśli się nie pomyliłem) na zegar 20MHz (5000 obrotów 4-cyklowej pętli ma dać 1 milisekundę). Jeśli z takim zegarem pędzisz swoją megę128, ma prawo nie nadążać i coś jej się w RAMie kwasi. - Dość dziwnie wygląda prolog w main. Cztery instrukcje PUSH wskazują na potrzebę ochrony zawartości dwóch par rejstrów ale ponieważ nie ma wyjścia z main bo wstawiłeś nieskończoną pętlę while, nie ma też instruckji RET ani zdjęcia ze stosu zachowanych rejestrów. W każdym razie to dziwne. - Sama funkcja Shift_register wywoływana jest poprawnie i także prawidłowo wraca do main. Co więc nie działa? Czyżby ten za szybki zegar? OT: Generalnie używasz zmiennych typu int czyli 16-bitowych ze znakiem tam, gdzie to jest zupełnie niepotrzebne. Np. operacje na zmiennej "a" zamiast prostej instrukcji przesunięcia w prawo próbują powielać bit znaku na MSB i cały shift robią na 16-bitach. Procesor jest 8-bitowy więc warto mu zaoszczędzić roboty, bo to dla niego duża różnica. Przykład kolejny: 16-bitowy licznik "i" liczący tylko do 16. Cytuj Link do komentarza Share on other sites More sharing options...
paczkaexpres Kwiecień 3, 2012 Autor tematu Udostępnij Kwiecień 3, 2012 W eclipse ustawiłem Target Hardwere -> MCU Clock Freqency na 1 MHz. Cytuj Link do komentarza Share on other sites More sharing options...
marek1707 Kwiecień 3, 2012 Udostępnij Kwiecień 3, 2012 Nieważne co ustawiłeś, najwyżej będą źle liczyły się opóźnienia, ale co masz na płytce przy procesorze. Swoją drogą chyba o tym 1MHz kompilator nie wie. Jak weryfikujesz poprawność wykonania programu? Po wynikach działania funkcji Shift... która coś gdzieś wysyła czy po buzzerku? Cytuj Link do komentarza Share on other sites More sharing options...
Pomocna odpowiedź
Dołącz do dyskusji, napisz odpowiedź!
Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!