Programowanie mikrokontrolerów AVR w języku Bascom

To forum jest dla wszystkich pasjonatów mikrokontrolerów AVR Atmela. Wymiana doświadczeń i pomoc dla początkujących w pisaniu programów zarówno w C, Asemblerze jak i BASCOM. Zapraszam znawców tematu, aby pomogli wszystkim początkującym!
snow
Użytkownik
Posty: 794
Rejestracja: 16 sty 2007, 3:44
Lokalizacja: lubelskie
Kontakt:

Post autor: snow » 27 wrz 2009, 15:07

Jak nie wyjdzie 1?

Awatar użytkownika
matrix
Użytkownik
Posty: 1796
Rejestracja: 15 mar 2006, 5:21
Lokalizacja: Sochaczew
Kontakt:

Post autor: matrix » 27 wrz 2009, 15:08

Jak nie wyjdzie 1?
no wychodzi 100. wynikiem jest 100

snow
Użytkownik
Posty: 794
Rejestracja: 16 sty 2007, 3:44
Lokalizacja: lubelskie
Kontakt:

Post autor: snow » 27 wrz 2009, 15:11

To dzielenie daje równo 1. 8000000/256/250/125 daje 1

Awatar użytkownika
matrix
Użytkownik
Posty: 1796
Rejestracja: 15 mar 2006, 5:21
Lokalizacja: Sochaczew
Kontakt:

Post autor: matrix » 27 wrz 2009, 15:14

snow pisze:To dzielenie daje równo 1. 8000000/256/250/125 daje 1
przepraszam. rzeczywiście 1. liczyłem na telefonie a mi się klawisze zacinają i dodało mi dwa zera. policzyłem na kompie i zgadza się. jeszcze raz przepraszam. dobra, pomijając ten fakt, to skąd to się wzięło i jak to liczyć?

Awatar użytkownika
Ertew
Użytkownik
Posty: 1414
Rejestracja: 03 lip 2005, 10:36
Lokalizacja: Leszno
Kontakt:

Post autor: Ertew » 27 wrz 2009, 15:18

Timer posiada dzielnik i licznik. Podział wstępny dzielnika można wybrać, jednak nie może on posiadać dowolnej wartości, tylko jedną z ustalonych przez producenta. Tu jest wybrana wartość 256.

Licznik zlicza impulsy wstępnie podzielone. Jego pojemność jest zależna od ilości bitów. Tu prawdopodobnie jest wykorzystany licznik 8 bitowy (o pojemności 256).
Po osiągnięciu tej wartości licznik jest zerowany i generowane jest przerwanie, które zmienia wartość licznika (jak się nie mylę, to ładuje do licznika 6).
W ten sposób licznik generuje następne przerwanie po 250 impulsach z dzielnika.

W obsłudze przerwania jest także prosty licznik (dodawanie 1 do zmiennej), który zlicza wystąpienia tego przerwania i tylko raz na 125 cykli jest wykonywane zliczenie jednej sekundy.

Awatar użytkownika
matrix
Użytkownik
Posty: 1796
Rejestracja: 15 mar 2006, 5:21
Lokalizacja: Sochaczew
Kontakt:

Post autor: matrix » 27 wrz 2009, 16:18

a powiedzmy że w czasie trwania danego impulsu na wejściu INT0 pozwolę licznikowi zliczać, a jak pojawi się tam stan niski to licznik zatrzymam. to jak przypisać jakiejś zmiennej wartość tego licznika w chwili jego zatrzymania?
ianczej mówiąć, jeśli pozwolę licznikowi zliczać w trakcie tej 1ms i po tym czasie zatrzymam go, to jak wartość licznika przypisać zmiennej A?

czy wystarczy napisać

Kod: Zaznacz cały

A=timer0
?
nie wywala żadnego błędu.

snow
Użytkownik
Posty: 794
Rejestracja: 16 sty 2007, 3:44
Lokalizacja: lubelskie
Kontakt:

Post autor: snow » 27 wrz 2009, 16:19

Raczej A=tcnt0

Awatar użytkownika
matrix
Użytkownik
Posty: 1796
Rejestracja: 15 mar 2006, 5:21
Lokalizacja: Sochaczew
Kontakt:

Post autor: matrix » 27 wrz 2009, 18:21

a mam kolejne pytanie: co dzieje się z programem w pętli głównej jeśli przychodzi przerwanie z zewnątrz?
znaczy to normalne, program zostaje przerwany i następuje obsługa przerwania, ale jak to się odbija na wizualności? dajmy na to w pętli głównej mam program który obsługuje dwie diody jako stroboskopy i kilka diod jako linijkę gdzie punk świetlny się przesuwa. jak to będzie wyglądało jak program w pętli głównej zostanie przerwany i obłuży dane przerwanie? czy zauważymy przerwę w świeceniu diod?

snow
Użytkownik
Posty: 794
Rejestracja: 16 sty 2007, 3:44
Lokalizacja: lubelskie
Kontakt:

Post autor: snow » 27 wrz 2009, 20:05

Przerwania zawsze mają nadrzędny priorytet nad samym programem, dlatego należy w obsłudze przerwania unikać opóźnień.

Awatar użytkownika
matrix
Użytkownik
Posty: 1796
Rejestracja: 15 mar 2006, 5:21
Lokalizacja: Sochaczew
Kontakt:

Post autor: matrix » 27 wrz 2009, 20:51

snow pisze:Przerwania zawsze mają nadrzędny priorytet nad samym programem, dlatego należy w obsłudze przerwania unikać opóźnień.
no tak ale czy wizualnie bedzie widac przeerwe w dzialaniu programu głównego czyli w miganiu diod?

Awatar użytkownika
Ertew
Użytkownik
Posty: 1414
Rejestracja: 03 lip 2005, 10:36
Lokalizacja: Leszno
Kontakt:

Post autor: Ertew » 28 wrz 2009, 17:41

Program w pętli głównej zostanie na chwilkę przerwany.
Jako, że nie będzie on wykonywany, to nie będzie zmieniać stanu portów (o ile program obsługi przerwania nie zmieni portów).

Na szybko taki program:

Kod: Zaznacz cały

Config Timer1 = Timer , Prescale = 256                       
Enable Interrupts
Enable Timer1
On Timer1 Czekaj                                         
Start Timer1

Ddrb = 0           'wyjście

Do
   Set Portb.0
   Waitms 1
   Reset Portb.0
   Set Portb.1
   Waitms 2
   Reset Portb.1
   Set Portb.2
   Waitms 3
   Reset Portb.2
   Set Portb.3
   Waitms 4
   Reset Portb.3
Loop
End

Czekaj:
   Waitms 250
Return
Jeśli się nie pomyliłem, to program powinien zaświecić diody 4 LED podłączone do pinów 0-3 portu B. Będą się one nierówno świecić światłem ciągłym (ponieważ są po kolei włączane).
Wygenerowanie przerwania T1 spowoduje chwilowe świecenie się jednej z nich (procesor wtedy ,,czeka'' w przerwaniu i nie zmienia stanu LEDów).
Program nie sprawdzony praktycznie.

[ Dodano: 2009-09-28, 18:45 ]
Jeśli zmniejszysz czas czekania w przerwaniu T1 10 krotnie, a czasy w pętli głównej zwiększysz 100 krotnie, to efekt nie będzie aż tak bardzo widoczny.
Ale nadal będzie występować.

mopeqq
-
Posty: 6
Rejestracja: 28 mar 2010, 22:22
Lokalizacja: BCN

Post autor: mopeqq » 15 lip 2010, 14:18

Witam. Jakiś czas temu zakupiłem kurs mikrokontrolerów wraz z płytką testową, która pozwala na testowanie układów według książki "Mikrokontrolery dla początkujących" autorstwa P. Góreckiego. Doszedłem to ćwiczenia, pozwalającego wykonanie prostego stopera. Oto listing;

Kod: Zaznacz cały

'C012a      Bardzo prosty stoper 0,1-sekundowy
Dim Dziesek As Byte , Sekjed As Byte , Sekdzies As Byte , Minjed As Byte
Dim 100ms As Byte , Ktorywysw As Byte , Licz As Bit
Config Portb = 255 : Portb = &B11111111 : Config Portd = &B1111100 : Portd = &B1111111
Config Timer0 = Timer , Prescale = 64 : Enable Interrupts : Enable Timer0
Dziesek = 0 : Sekjed = 0 : Sekdzies = 0 : Minjed = 0
On Timer0 Co4ms

Do : Loop : End                                             'to jest główny program - pusta nieskończona pętla

Co4ms:                                                      'procedura obsługi przerwania od Timera T/C0 wykonywana co 4ms
Load Timer0 , 250                                           'załaduj do Timera0, żeby zliczył 250 (=256-6) impulsów
If Pind.0 = 0 Then Licz = 1                                 'sprawdź stan S1 i ewentualnie rozpocznij zliczanie czasu
If Pind.1 = 0 Then Licz = 0                                 'sprawdź stan S2 i ewentualnie zakończ zliczanie czasu
If Licz = 1 Then                                            'tylko wtedy, gdy stoper ma liczyć czas
   Incr 100ms                                               'co 4ms zwiększ wartość licznika o nazwie 100ms
   If 100ms = 25 Then                                       'skróc cykl licznika 100ms właśnie do 100ms
      100ms = 0                                             'czyli 0,1 sekundy
      Incr Dziesek                                          'co 0,1s zwiększ stan licznika dziesiatych części sekundy
      If Dziesek = 10 Then                                  'ten licznik liczy do dziesieciu
         Dziesek = 0                                        'czyli cykl trwa 1 sekundę
         Incr Sekjed                                        'co 1 sekundę  zwiększ licznik jednostek sekund
         If Sekjed = 10 Then
            Sekjed = 0                                      'co 10 sekund
            Incr Sekdzies                                   'zwiększ stan licznika dziesiatek sekund
               If Sekdzies = 6 Then                         'liczy do 6 bo minuta ma 60 sekund
                  Sekdzies = 0
                  Incr Minjed                               'co 60 sekund zwiększ stan licznika minut
                     If Minjed = 10 Then Minjed = 0         '0...9 minut
               End If                                       'więc maksymalny stan licznika to:
         End If                                             '9 minut, 59 sekund i 9 dziesiatych sekundy
      End If
   End If
End If
Incr Ktorywysw : If Ktorywysw = 4 Then Ktorywysw = 0        'skróć cykl: 0...3
Portd = &B1111111                                           ' wygaś wyświetlacze
Select Case Ktorywysw                                       ' obsługa wyświetlacza
Case 0:                                                     'wyświetl zawartość licznika jednostek
   Portb = Lookup(dziesek , Tabela)                         'najpierw przepisz do PortB kody
   Portd.3 = 0                                              'potem włącz T3 - wyświetlacz jednostek
Case 1:                                                     'wyświetl zawartość licznika dziesiątek
   Portb = Lookup(sekjed , Tabela)                          'najpierw przepisz do PortB kody
   Portb.7 = 0                                              'włącz punkt dziesiętny
   Portd.4 = 0                                              'potem włącz T4 - wyświetlacz dziesiątek
Case 2:                                                     'wyświetl zawartość licznika setek
   Portb = Lookup(sekdzies , Tabela)                        'przepisz do PortB kody
   Portd.5 = 0                                              'włącz T5 - wyświetlacz setek
Case 3:                                                     'wyświetl zawartość licznika tysięcy
   Portb = Lookup(minjed , Tabela)                          'przepisz do PortB kody
   Portb.7 = 0                                              'włącz punkt dziesiętny
   Portd.6 = 0                                              'włącz T6 - wyświetlacz tysięcy
End Select
Return                                                      'koniec procedury obsługi przerwania

Tabela:                                                     'potrzebna do wyświetlenia cyfr 0...9
Data 192 , 249 , 164 , 176 , 153 , 146 , 130 , 248 , 128 , 144
Jednak niestety program w żadnym wypadku nie mierzy precyzyjnie czasu (robi to znacznie wolniej). Obliczyłem granicę błędu i wyszło mi, że procek pokazuje jedną sekundę w czasie około 8 sekund. Uznałem, że rezonator nie działa tak jak powinien. Kupiłem kilka rezonatorów o większych częstotliwościach, obliczałem parametry, a program wciąż działał tak samo tak jakby był taktowany czymś innym. W końcu całkowicie wyjąłem rezonator z podstawki i układ wciąż działał. Jestem amatorem, więc nie wiem gdzie robię błąd i jak sobie z nim poradzić. Pomożecie?

Wojtek
Moderator
Posty: 2606
Rejestracja: 04 sie 2002, 19:00
Lokalizacja: --
Kontakt:

Post autor: Wojtek » 15 lip 2010, 16:53

Bo pewnie jest ustawiony domyslnie na 1M wewnętrzny. Trzeba mu zadklarować odpowiedni zewnetrzny zegar i fusebity przy programowaniu ustawic.
Ostatnio zmieniony 16 lip 2010, 6:06 przez Wojtek, łącznie zmieniany 1 raz.

Awatar użytkownika
matrix
Użytkownik
Posty: 1796
Rejestracja: 15 mar 2006, 5:21
Lokalizacja: Sochaczew
Kontakt:

Post autor: matrix » 15 lip 2010, 21:09

najpewniej fusy. pewnie masz ustawioną funkcję podziału zegara przez 8?

mopeqq
-
Posty: 6
Rejestracja: 28 mar 2010, 22:22
Lokalizacja: BCN

Post autor: mopeqq » 31 lip 2010, 12:47

Mam kolejne pytanie. Otóż uczę się teraz rozdziału ósmego, poświęconego pamięci eeprom. Programy po bezbłędnym skompilowaniu i przesłaniu do procka nie wizualizują rezultatów na wyświetlaczach. Korzystam z BASCOM-AVR 1.11.8.1 oraz Avr Studio. Domyślam się, że pewnie gdzieś trzeba coś skonfigurować, a nie chcę namieszać...
PS. W Avr Studio do flash wrzucam plik z rozszerzeniem "hex", a do eeprom z rozszerzeniem eep. W drugim przypadku pojawia się napis: "Getting isp parameter.. SD=0x06 .. OKThe specified file is not a valid Intel HEX file".

ODPOWIEDZ