Kaytec Napisano Styczeń 25, 2011 Udostępnij Napisano Styczeń 25, 2011 Witam, potrzebuję pomocy w optymalizacji kodu. Jest to proste dodatkowe urządzenie do robota, mierzące napięcie akumulatora, i w przyszłości temperaturę ogniw. Atmega 8 ma podłączony wyświetlacz siedmiosegmentowy mniej więcej według tego schematu: Wszystko działa fajnie, pobieram sobie wartość z ADC, operacjami dzielenia i modulo rozbijam to tak abym miał pojedyncze wartości na każdy wyświetlacz. Z tym nie ma problemu. Problem jest taki że chce aby po naciśnieciu przycisku (pinb.1) szedł do podprogramu "wygas", po kolejnym wracał do podprogramu "pomiar". Pisząc to w głównej pętli, działa, ale trzeba trzymać przycisk w odpowiednim momencie. Wstawiając do przerwań LED, działa znakomicie ale nie mogę potem potem wrócić. Najlepiej wyjaśni to kod: '*WEJSCIA I WYJSCIA* Config Portc = Output Portc = &HFF Config Portd = Output Portd = &HFF Config Portb = Output Portb = &HFF Config Portc.5 = Input 'adc Config Portb.1 = Input 'przycisk '*WYSWIETLACZE* W1 Alias Portc.0 W2 Alias Portc.1 W3 Alias Portc.2 W4 Alias Portc.3 Kropka Alias Portc.4 '***************************************** $regfile = "m8def.dat" $crystal = 1000000 Config Timer0 = Timer , Prescale = 8 'konfiguracja Timer0 jako timer Declare Sub Pobr_znaku(cyfra As Byte) 'deklaracja procedury pobierajacej Declare Sub Pomiar Declare Sub Wygas On Timer0 Multi_wysw 'przerwanie od przepelnienia Timer0, 'skok do podprogramu multi_wysw Dim A As Byte , B As Byte , C As Byte , D As Byte 'definicje zmiennych w ktorych bedzie 'przechowywana wartosc do wyswietlenia Dim Nr_wysw As Byte 'zmienna okreslajaca nr zapalonego wyś. Dim X As Word Dim Tysiace As Word Dim Setki As Word Dim Jednosci As Word Dim Dziesiatki As Word Dim Wynik As Single Enable Interrupts 'odblokowanie globalnego systemu przerwan Enable Timer0 'odblokowanie przerwania od Timer0 Load Timer0 , 125 'zaladowanie do licznika wartosci poczatkowej 131 Config Adc = Single , Prescaler = Auto , Reference = Avcc Start Adc Do Call Pomiar Loop End 'koniec programu Sub Wygas A = 10 B = 10 C = 10 D = 10 End Sub Sub Pomiar 'pomiar adc X = Getadc(5) Wynik = X * 0.175 X = Wynik 'obliczenie do wyswietlania pojedynczych cyfr Setki = X Mod 1000 Tysiace = X / 1000 Dziesiatki = Setki Mod 100 Setki = Setki / 100 Jednosci = Dziesiatki Mod 10 Dziesiatki = Dziesiatki / 10 A = Jednosci B = Dziesiatki C = Setki D = 10 If C = 0 Then C = 10 End If Wait 1 'jeśli wynik wiekszy niż 110 to wygaś lcd na 1s (miganie lcd) If X > 110 Then A = 10 B = 10 C = 10 D = 10 Wait 1 End If End Sub Sub Pobr_znaku(cyfra As Byte) 'definicja procedury pobr_znaku If Pinb.1 = 0 Then Call Wygas End If If Cyfra < 10 Then Portd = Lookup(cyfra , Kody7seg) Else Portd = 255 'w przeciwnym razie wygas wyswietlacz End If End Sub Multi_wysw: 'podprogram obslugi wyswietlania multipleksowego Load Timer0 , 125 Set W1 'wygaszenie wyswietlacza 1 Set W2 'wygaszenie wyswietlacza 2 Set W3 'wygaszenie wyswietlacza 3 Set W4 'wygaszenie wyswietlacza 4 Select Case Nr_wysw Case 0: Call Pobr_znaku(a) Reset W1 Case 1: Call Pobr_znaku(b) Reset W2 Case 2: Call Pobr_znaku(c) Reset W3 Case 3: Call Pobr_znaku(d) Reset W4 End Select Incr Nr_wysw If Nr_wysw = 4 Then Nr_wysw = 0 End If Return 'powrot z podprogramu Kody7seg: 'tablica stalych kody7seg Data &B11000000 , &B11111001 , &B10100100 , &B10110000 , &B10011001 Data &B10010010 , &B10000010 , &B11111000 , &B10000000 , &B10010000 Gdzie wstawić ify przycisków aby działały praktycznie od razu?
Bobby Styczeń 25, 2011 Udostępnij Styczeń 25, 2011 Zawsze możesz zaprząc drugi timer do okresowego sprawdzania przycisków, w przerwaniu od niego byłyby próbkowane piny, do których podpięte są przyciski i ustawiane odpowiednieflagi, które to sprawdzałbyś dalej w pętli głównej. Z tym, że działałoby to tak, że przycisk możesz nacisnąć prawie w dowolnym momencie (byleby tylko przerwanie timera zdążyło się wykonać - trzeba by potestować różne czasy), a to co chcesz, by było wykonane wykonane by zostało dopiero po skończeniu podprogramu "pomiar". 1
Kaytec Styczeń 25, 2011 Autor tematu Udostępnij Styczeń 25, 2011 Chciałem to zrobić używając pętli. Czyli jak już przekieruje do podprogramu "wygaś" to wyjdzie z niego tylko jak kliknę przycisk. To ma być na zasadzie ze na początku wyświetla się pomiar napiecia, potem pomiar temperatury, potem się gasi i tak w koło macieja. Problem w tym że jak już napisze coś takiego: Sub Wygas A = 10 B = 10 C = 10 D = 10 If Pinb.1 = 0 Then Goto Pomiar Else Goto Wygas End If End Sub To wygasi mi wszystkie wyświetlacze, ale tylko do póki trzymam przycisk
Zaja Luty 7, 2011 Udostępnij Luty 7, 2011 To dla tego że po puszczeniu przycisku timer0 śmiga dalej, wywołuje przerwanie do obsługi wyświetlaczy i dalej przerwanie steruje Ci nimi normalnie. Żeby gasły na stałe musisz wyłączyć przerwania albo timer po tym jak wchodzisz w "wygas" i włączyć potem ponownie w momencie pomiaru. 1
Kaytec Luty 7, 2011 Autor tematu Udostępnij Luty 7, 2011 Poradziłem sobie już z przyciskami. Działa to mniej więcej tak: Config Portc = Output Portc = &HFF Config Portd = Output Portd = &HFF Config Portb = Output Portb = &HFF Config Portc.2 = Input Config Portc.3 = Input 'adc Config Portb.1 = Input 'przycisk '*WYSWIETLACZE* W1 Alias Portb.2 W2 Alias Portb.3 W3 Alias Portb.4 W4 Alias Portb.5 Kropka Alias Portb.0 '***************************************** $regfile = "m16def.dat" $crystal = 8000000 Config Timer0 = Timer , Prescale = 64 'konfiguracja Timer0 jako timer Declare Sub Pobr_znaku(cyfra As Byte) 'deklaracja procedury pobierajacej Declare Sub Engine Declare Sub Wygas Declare Sub Napiecie On Timer0 Multi_wysw 'przerwanie od przepelnienia Timer0, Dim A As Byte , B As Byte , C As Byte , D As Byte Dim Nr_wysw As Byte Dim X As Word Dim Tysiace As Word Dim Setki As Word Dim Jednosci As Word Dim Dziesiatki As Word Dim Wynik As Single Dim Klik As Byte Dim Krop As Byte Enable Interrupts 'odblokowanie globalnego systemu przerwan Enable Timer0 'odblokowanie przerwania od Timer0 Load Timer0 , 125 'zaladowanie do licznika wartosci poczatkowej 131 Config Adc = Single , Prescaler = Auto , Reference = Avcc Start Adc Klik = 1 Krop = 1 Do If Klik = 4 Then Klik = 1 End If If Klik = 1 Then Call Engine Elseif Klik = 2 Then Call Napiecie Elseif Klik = 3 Then Call Wygas End If Loop End 'koniec programu '***************************************** Sub Wygas A = 10 B = 10 C = 10 D = 10 If Pinb.1 = 0 Then Klik = Klik + 1 Waitms 250 End If End Sub '***************************************** '***************************************** Sub Napiecie Incr Krop If Krop = 3 Then Krop = 2 End If X = Getadc(3) Wynik = X * 0.19 X = Wynik 'obliczenie do wyswietlania pojedynczych cyfr Setki = X Mod 1000 Tysiace = X / 1000 Dziesiatki = Setki Mod 100 Setki = Setki / 100 Jednosci = Dziesiatki Mod 10 Dziesiatki = Dziesiatki / 10 A = Jednosci B = Dziesiatki C = Setki D = 10 If C = 0 Then C = 10 End If Waitms 100 'jeśli wynik wiekszy niż 110 to wygaś lcd na 1s (miganie lcd) If Pinb.1 = 0 Then Waitms 250 Incr Klik Krop = Krop - 1 End If End Sub '***************************************** '***************************************** Sub Engine If Pinb.1 = 0 Then Klik = Klik + 1 Waitms 250 End If X = Getadc(2) 'wartości temperatury od ADC If X <= 895 And X > 890 Then X = 16 Elseif X <= 890 And X > 885 Then X = 17 Elseif X <= 885 And X > 875 Then X = 18 Elseif X <= 875 And X > 870 Then X = 19 Elseif X <= 870 And X > 860 Then X = 20 Elseif X <= 860 And X > 855 Then X = 21 Elseif X <= 855 And X > 845 Then X = 22 Elseif X <= 845 And X > 840 Then X = 23 Elseif X <= 840 And X > 835 Then X = 24 Elseif X <= 835 And X > 830 Then X = 25 Elseif X <= 830 And X > 825 Then X = 26 Elseif X <= 825 And X > 820 Then X = 27 Elseif X <= 820 And X > 810 Then X = 28 Elseif X <= 810 And X > 800 Then X = 29 Elseif X <= 800 And X > 795 Then X = 30 Elseif X <= 795 And X > 790 Then X = 31 Elseif X <= 790 And X > 780 Then X = 32 Elseif X <= 780 And X > 775 Then X = 33 Elseif X <= 775 And X > 760 Then X = 34 Elseif X <= 760 And X > 750 Then X = 35 Elseif X <= 750 And X > 745 Then X = 36 Elseif X <= 745 And X > 740 Then X = 37 Elseif X <= 740 And X > 735 Then X = 38 Elseif X <= 735 And X > 720 Then X = 39 Elseif X <= 720 And X > 715 Then X = 40 Elseif X <= 715 And X > 710 Then X = 41 Elseif X <= 710 And X > 700 Then X = 42 Elseif X <= 700 And X > 690 Then X = 43 Elseif X <= 690 And X > 680 Then X = 44 Elseif X <= 680 And X > 670 Then X = 45 Elseif X <= 670 And X > 660 Then X = 46 Elseif X <= 660 And X > 650 Then X = 47 Elseif X <= 650 And X > 640 Then X = 48 Elseif X <= 640 And X > 630 Then X = 49 Elseif X <= 630 And X > 620 Then X = 50 Elseif X <= 620 And X > 610 Then X = 51 Elseif X <= 610 And X > 600 Then X = 52 Elseif X <= 600 And X > 590 Then X = 53 Elseif X <= 590 And X > 580 Then X = 54 Elseif X <= 580 And X > 570 Then X = 55 Elseif X <= 570 And X > 560 Then X = 56 Elseif X <= 560 And X > 555 Then X = 57 Elseif X <= 555 And X > 550 Then X = 58 Elseif X <= 550 And X > 540 Then X = 59 Elseif X <= 540 And X > 525 Then X = 60 Elseif X <= 525 And X > 510 Then X = 61 Elseif X <= 510 And X > 505 Then X = 62 Elseif X <= 505 And X > 495 Then X = 63 Elseif X <= 495 And X > 480 Then X = 64 Elseif X <= 480 And X > 470 Then X = 65 Elseif X <= 470 And X > 460 Then X = 66 Elseif X <= 460 And X > 455 Then X = 67 Elseif X <= 455 And X > 450 Then X = 68 Elseif X <= 450 And X > 440 Then X = 69 Elseif X <= 440 And X > 430 Then X = 70 Elseif X <= 430 And X > 420 Then X = 71 Elseif X <= 420 And X > 415 Then X = 72 Elseif X <= 415 And X > 410 Then X = 73 Elseif X <= 410 And X > 400 Then X = 74 Elseif X <= 400 And X > 390 Then X = 75 Elseif X <= 390 And X > 380 Then X = 76 Elseif X <= 380 And X > 370 Then X = 77 Elseif X <= 370 And X > 365 Then X = 78 Elseif X <= 365 And X > 355 Then X = 79 Elseif X <= 355 And X > 345 Then X = 80 Elseif X <= 345 And X > 340 Then X = 81 Elseif X <= 340 And X > 335 Then X = 82 Elseif X <= 335 And X > 330 Then X = 83 Elseif X <= 330 And X > 320 Then X = 84 Elseif X <= 320 And X > 315 Then X = 85 Elseif X <= 315 And X > 310 Then X = 86 Elseif X <= 310 And X > 305 Then X = 87 Elseif X <= 305 And X > 300 Then X = 88 Elseif X <= 300 And X > 295 Then X = 89 Elseif X <= 295 And X > 290 Then X = 90 Elseif X <= 290 And X > 285 Then X = 91 Elseif X <= 285 And X > 280 Then X = 92 Elseif X <= 280 And X > 275 Then X = 93 Elseif X <= 275 And X > 265 Then X = 94 Elseif X <= 265 And X > 260 Then X = 95 Elseif X <= 260 And X > 255 Then X = 96 Elseif X <= 255 And X > 250 Then X = 97 Elseif X <= 250 And X > 245 Then X = 98 Elseif X <= 245 And X > 240 Then X = 99 Elseif X <= 240 And X > 235 Then X = 100 Elseif X <= 235 And X > 230 Then X = 101 Elseif X <= 230 And X > 225 Then X = 102 Elseif X <= 225 And X > 220 Then X = 103 Elseif X <= 220 And X > 215 Then X = 104 Elseif X <= 215 And X > 210 Then X = 105 Elseif X <= 210 And X > 205 Then X = 106 Elseif X <= 205 And X > 200 Then X = 107 Elseif X <= 200 And X > 195 Then X = 108 Elseif X <= 195 And X > 190 Then X = 109 Elseif X <= 190 And X > 185 Then X = 110 Elseif X <= 185 And X > 180 Then X = 111 Elseif X <= 180 And X > 175 Then X = 112 Elseif X <= 175 And X > 170 Then X = 113 Elseif X <= 170 And X > 165 Then X = 114 Elseif X <= 165 And X > 160 Then X = 115 Elseif X <= 160 And X > 155 Then X = 116 Elseif X <= 155 And X > 150 Then X = 117 Elseif X <= 150 And X > 145 Then X = 118 Elseif X <= 145 And X > 140 Then X = 119 Elseif X <= 140 And X > 0 Then X = 120 End If 'obliczenie do wyswietlania pojedynczych cyfr Setki = X Mod 1000 Tysiace = X / 1000 Dziesiatki = Setki Mod 100 Setki = Setki / 100 Jednosci = Dziesiatki Mod 10 Dziesiatki = Dziesiatki / 10 A = Jednosci B = Dziesiatki C = Setki D = 10 If C = 0 Then C = 10 End If Waitms 100 'jeśli wynik wiekszy niż 110 to wygaś lcd na 1s (miganie lcd) If X > 110 Then A = 10 B = 10 C = 10 D = 10 Waitms 100 End If End Sub '***************************************** '***************************************** Sub Pobr_znaku(cyfra As Byte) 'definicja procedury pobr_znaku If Cyfra < 10 Then Portd = Lookup(cyfra , Kody7seg) Else Portd = 255 'w przeciwnym razie wygas wyswietlacz End If End Sub '***************************************** Multi_wysw: 'podprogram obslugi wyswietlania multipleksowego Load Timer0 , 125 Set Kropka Set W1 'wygaszenie wyswietlacza 1 Set W2 'wygaszenie wyswietlacza 2 Set W3 'wygaszenie wyswietlacza 3 Set W4 'wygaszenie wyswietlacza 4 Select Case Nr_wysw Case 0: Call Pobr_znaku(a) Reset W1 Case 1: Call Pobr_znaku(b) If Krop = 2 Then Reset Kropka End If Reset W2 Case 2: Call Pobr_znaku(c) Reset W3 Case 3: Call Pobr_znaku(d) Reset W4 End Select Incr Nr_wysw If Nr_wysw = 4 Then Nr_wysw = 0 End If Return 'powrot z podprogramu Kody7seg: 'tablica stalych kody7seg Data &B11000000 , &B11111001 , &B10100100 , &B10110000 , &B10011001 Data &B10010010 , &B10000010 , &B11111000 , &B10000000 , &B10010000 Dzięki za pomoc.
Pomocna odpowiedź
Bądź aktywny - zaloguj się lub utwórz konto!
Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony
Utwórz konto w ~20 sekund!
Zarejestruj nowe konto, to proste!
Zarejestruj się »Zaloguj się
Posiadasz własne konto? Użyj go!
Zaloguj się »