Technical Site

BASCOM 8051 i AVR

BASCOM to program, który tłumaczy (kompiluje) napisany przez człowieka program na język zrozumiały dla procesora. Programuje się dosyć łatwo, ponadto BASCOM sam wykrywa błędy i mówi, co jest źle. Jak już napiszesz jakiś program, przed przetestowaniem należy go zapisać na dysku. Następnie wciskasz F7 i on szuka błędów. Po stwierdzeniu braku błędów, możesz wcisnąć F2. Przeniesie cię do okna symulatora. Zanim wciśniesz "play" warto zwrócić uwagę na ikonę przedstawiającą dłoń nad kartką papieru. Jeśli nie jest aktywna to program podczas symulacji nie będzie pokazywał zmian na portach (nieładnie mówiąc - lampkach), co jest dość ważne. Po prostu warto, aby ikonka była zawsze aktywna. Ostatnie, co potrzebujesz w oknie symulatora to ikona z napisem "LCD". Wewnątrz znajdziesz wyświetlacz, oraz sygnalizatory portów. I to by było na tyle, jeśli chodzi o orientację w programie. Warto zauważyć, że będziesz używał dwóch wersji programu; 8051 i AVR. Warto mieć je ściągnąć.

Ściągnij BASCOM 8051

Ściągnij BASCOM 8051

Ściągnij BASCOM AVR

Ściągnij BASCOM AVR

Deklaracja zmiennych

Dość ważna rzecz. Aby zaoszczędzić miejsce stosuje się wiele rodzajów zmiennych. Powiedzmy, że chcesz wpisać do pamięci wartość "1". Możesz ją zapisać jako zmienna "bit" i stracić mało pamięci, albo jako "byte" w postaci "00000001" i stracić osiem razy więcej. Oczywiście nie należy tak robić. Poniżej wypisałem wszystkie zmienne, przedziały w których znajdują się zbiory ich wartości, oraz zajętość pamięci.

Dim x as bit
Dim x as byte
Dim x as word
Dim x as integer
Dim x as long
Dim x as single
Dim x as string * y
x ∈ {0, 1}
x ∈ N: <0, 255>
x ∈ N: <0, 65535>
x ∈ C: <-65535, 65535>
x ∈ C: <-2147483647, 2147483647>
x ∈ R: <-2147483647, 2147483647>
x ∈ alfanumeryczne
1 bit
2 bajty
2 bajty
2 bajty
4 bajty
4 bajty
y bajtów

Bit, byte i word mogą przedstawiać liczby nieujemne całkowite, integer, long i single mogą być ujemne, ale tylko single może być ułamkiem. Ułamki polecam wpisywać w postaci dzielenia przez dziesięć, sto, tysiąc i tak dalej. Zmienna string może zawierać tekst. Przy deklaracji zamiast "y" należy wpisać liczbę o jeden większą od ilości znaków w zmiennej. Dla "Technical Site" będzie to piętnaście.

Komendy

Lista komend. Nie będę ich opisywał szczegółowo, ponieważ łatwo załapać o co chodzi, oglądając przykłady programów poniżej.

$sim

Dim Q As Byte, V As Byte

Q = 5
V = &H0F
X = &B11010101

Incr Q
Decr Q

Shift Q, Left
Shift V, Right

P1 = Q
Portb = Q

Print Q
Print "tekst"
Print Q ; "kota" ; V ; "ala"


Do
    [...]
Loop

For Q=0 To 100
    [...]
Next


If Q = 60 Then
    [...]
End if

If V = X Then
    [...]
Else
    [...]
End if

Declare sub nazwa
Sub [nazwa]
    [...]
End sub

Config Lcd = 16*1
Cursor off
Cls

Lcd Q
Lcd ; "kot" ; V ; "ali" ; Q ;
Locate 1,7
    Lcd Q


nazwa:
    Data: 11, &H1A, &B110110001

Q = Lookup(v , nazwa)


Home
End
Symulacja (zawsze na początku kodu)

Deklaracja zmiennych.

Zmienna Q przyjmuje wartość pięć.
V wartość heksadecymalną 0F.
X binarną 11010101.

Zwiększa zmienną Q o jeden.
Zmniejsza Q o jeden.

Przesuwa bity zmiennej Q w lewo.
To samo ale w prawo.

[8051] Wysyła wartość Q na port 1.
[AVR] To samo.

Wypisuje wartość zmiennej Q na ekran.
Wypisuje tekst podany w cudzysłowach.
Wypisuje Q, potem tekst,
V i znowu tekst w jednej linii.

Początek nieskończonej pętli.
    Polecenia do wykonania.
Koniec pętli.

Dla Q równego 0 do 100 wykonaj pętlę.
    Wpisane tu polecenia wykonają
    się UWAGA! 101 razy.
Koniec pętli.

Jeżeli Q jest równe 60 wykonaj.
    Polecenia.
Koniec.

Jeżeli V jest równe Q wykonaj
    Polecenia.
Jeżeli V nie było równe Q to wykonaj.
    Polecenia.
Koniec.

Deklaracja podprogramu "nazwa".
Początek podprogramu "nazwa"
    Polecenia.
Koniec podprogramu.

Ustaw wyświetlacz 16x1.
Wyłącz kursor.
Wyczyść LCD.

Wyświetl zmienną Q na wyświetlaczu.
Wyświetla tekst "kot" potem V,
potem "ala" i Q w jednej linii.
Lokalizuje pozycję 7 w 1 wierszu.
    Wyświetla Q rozpoczynając od 1,7.

Tablica o nazwie "nazwa".
      Elementy tablicy.

Podstaw pod zmienną Q element
numer v z tablicy "nazwa".

Powrót na początek programu.
Koniec programu.

Powyższy zbiór pochodzi z wszystkich lekcji, w kolejności mniej-więcej chronologicznej.

Zajęcia I

Pierwszym programem jaki będziesz pisać, będzie mniej więcej polegał na uzyskaniu efektu lampek choinkowych. Symulacyjny "procesor" BASCOM ma osiem specjalnych wyjść, nazywanych portem. Chodzi o to, aby na zmianę "świeciły się" pierwsze cztery wyjścia, a następnie cztery ostatnie i od nowa. Wystarczy na zmianę wpuszczać tam jedynki, a następnie zera. P=11110000 (240), po chwili P=00001111 (15). Problem polega na tym, że procesor działa bardzo szybko, i tych zmian może dokonywać tysiące razy na sekundę (albo i więcej, zależy od kompa). Dlatego należy użyć [pod]programu opóźniającego.

$sim
Dim P As Byte, Q As Byte
Declare Sub Czekaj
Do
   Q = &H0F
   P1 = Q
   Czekaj
   Q = &HF0
   P1 = Q
   Czekaj
Loop
Sub Czekaj
   For P = 0 To 250
   Next
End Sub
Symulacja
Deklaracja zmiennych P i Q jako bajt
Deklaracja podprogramu o nazwie "Czekaj"
Start pętli
Zmienna Q przyjmuje wartość hex 0F czyli 15
Wysłanie wartości Q na wyjścia P1
Podprogram "Czekaj"
Q przyjmuje wartość F0 czyli 11110000
Wysłanie wartości Q na wyjścia P1
Podprogram "Czekaj"
Zakończenie pętli
Ustalenie podprogramu "Czekaj"
Pętla
Koniec pętli
Koniec podprogramu

W podprogramie "czekaj" wykonuje się 251 razy (tak, tak, od 0 do 250 będzie 251 i to trzeba wiedzieć na kolokwium) pętla, która nic nie robi, opóźniając czas przeskoku stanów na wyjściach pierwszego portu. Im większą liczbę tam podasz, tym dłużej "lampki" będą świecić. W pracowni wystarczy 100, lub 300, ale w domku raczej spotyka się lepsze komputery i należy podać więcej. :)

Jako zadanie domowe, trzeba wykonać podobny program, ale mają "świecić się" wyjścia nieparzyste, a następnie parzyste i od nowa. P=10101010 (170), po chwili P=01010101 (85). Oczywiście wystarczy podmienić wartości zmiennych z poprzedniego zadania i już będzie śmigać. Jednak wymagane jest użycie funkcji "Shift" (przesunięcie). Działa w dwa sposoby; albo w lewo, albo w prawo. Polega to na tym, że przesuwa bity danej wartości w wskazany kierunek, a pierwszy i ostatni bit zamieniają się miejscami. Kiedy P=10101010 "shiftniemy" w prawo, otrzymamy P=01010101. Nie jestem pewien, ale chyba funkcja "shift" jest tańsza pamięciowo, niż nadpisanie zmiennej.

Zadanie domowe

W animacji pominięto "czekaje". Przypomnij sobie teraz rejestry. Czuć podobieństwo? Twoje bity trzymane są w rejestrach procesora, a w razie potrzeby przesuwa się je w lewo lub w prawo (na UTK tylko w jednym kierunku). Ale zobaczmy jak to będzie wyglądało w pełnym programie.

$sim
Dim Q As Byte, P As Byte
Q = &B01010101
Declare Sub Czekaj
Do
   P1 = Q
   Czekaj
   Shift Q , Right
   P1 = Q
   Czekaj
   Shift Q , Right
Loop
Sub Czekaj
   For P = 0 To 100
   Next
End Sub
Symulacja
Deklaracja zmiennych Q i P jako bajt
Zmienna Q przyjmuje wartość 01010101
Deklaracja podprogramu o nazwie "Czekaj"
Start pętli
Wysłanie wartości Q na wyjścia P1
Podprogram "Czekaj"
Przesunięcie bitów zmiennej Q w prawo
Wysłanie wartości Q na wyjścia P1
Podprogram "Czekaj"
Przesunięcie bitów zmiennej Q w prawo
Zakończenie pętli
Ustalenie podprogramu "Czekaj"
Pętla
Koniec pętli
Koniec podprogramu

Sporo jak na jedne zajęcia, nie?

Zajęcia II

Na drugich zajęciach gwoździem programu będzie komenda "print", oraz wyświetlacz LCD. Pierwsze zadanie polega na napisaniu programu pseudo-zegarka, czyli czegoś, co bardzo szybko będzie liczyć w górę, podając sekundy, minuty i godziny. Pierw trzeba się zastanowić, jak działa zegarek-stoper. Cały czas zwiększa liczbę sekund o jeden. Jeśli zmienna reprezentująca sekundy, będzie równa 60, to zwiększy się zmienna minut, a sekundowa spadnie do zera i od nowa będzie się zwiększać. Jeśli zaś minuty osiągną 60, to godziny rosną, a minuty spadają do zera. Teraz wytłumacz to procesorowi. ;)

$sim
Dim S As Byte , M As Byte ,
G As Byte , C As Byte
Declare Sub Czekaj
Do
   Print S ; " sek " ; M ;
   " min " ; G ; " godz "
   Incr S
   If S = 60 Then
      Incr M
      S = 0
   End If
   If M = 60 Then
      Incr G
      M = 0
   End If
   If G = 24 Then
      G = 0
   End If
   Czekaj
Loop
Sub Czekaj
   For C = 0 To 100
   Next
End Sub
				
Symulacja
Ustalanie zmiennych

Deklaracja podprogramu
Początek pętli
Wyświetlenie stanu stopera
(to w jednej linii!)
Zwiększenie sekund
Jeśli sekundy dotarły do 60, to:
Zwiększ minuty
Sekundy zmniejsz do zera
Koniec warunkowania
Jeśli minuty dotarły do 60, to:
Zwiększ godziny
Zeruj minuty
Koniec warunkowania
Jeżeli godziny dotarły do 24, to:
Zeruj godziny
Koniec warunkowania
Opóźnienie
Koniec pętli
Podprogram Czekaj
Pętla powtórzy się 101 razy
Koniec pętli
Koniec podprogramu
				

Komenda "print" nazywa się "print" (drukuj), ponieważ raz wyświetlonej (wydrukowanej) treści nie zmienisz. Testując program widziałeś niekończący się ciąg linijek. Trochę to mało estetyczne. Dlatego jest wyświetlacz LCD. Za jego pomocą można przedstawić aktualny stan stopera, bardzo podobnie jak na cyfrowych zegarkach. Użyję wyświetlacza 16*1. Najpierw trzeba rozplanować, co i gdzie będzie się wyświetlać.

Wyświetlacz LCD

Pierwsze cztery komórki opuszczam, żeby było ładnie. ;) W komórce siódmej i dziesiątej są dwukropki i nigdy się nie zmieniają. Reszta jest oczywista. Tak naprawdę, największym problemem w tym zegarku jest sposób wyświetlania liczb poniżej dziesięciu. Jeśli każesz mu wyrzucić "24" na pierwszej komórce, to on wyświetli w pierwszej "2", a w sąsiedniej "4". Jeśli zaś ma wyświetlić "5", to tak zrobi. My jednak chcielibyśmy, aby liczby jednocyfrowe wyświetlał jako "01, 02, 03..." i tak dalej. W tym celu, należy użyć warunkowania. Jeżeli liczba będzie większa od "10", to niech wyświetli w komórce numer jeden. Jeśli mniejsza, niech wyświetli w komórce numer dwa, a w pierwszej zero.

$sim
Config Lcd = 16 * 1
Cursor Off
Cls
Dim S As Byte , M As Byte ,
G As Byte , C As Byte
Declare Sub Czekaj
Locate 1 , 7
   Lcd ":"
Locate 1 , 10
   Lcd ":"
Do
   If S = 60 Then
      Incr M
      S = 0
   End If
   If M = 60 Then
      Incr G
      M = 0
   End If
   If G = 24 Then
      G = 0
   End If
   If S < 10 Then
      Locate 1 , 11
         Lcd 0
      Locate 1 , 12
         Lcd S
   Else
      Locate 1 , 11
         Lcd S
   End If
   If M < 10 Then
      Locate 1 , 8
         Lcd 0
      Locate 1 , 9
         Lcd M
   Else
      Locate 1 , 8
         Lcd M
   End If
   If G < 10 Then
      Locate 1 , 5
         Lcd 0
      Locate 1 , 6
         Lcd G
   Else
      Locate 1 , 5
         Lcd G
   End If
   Incr S
   Czekaj
Loop
Sub Czekaj
   For C = 0 To 250
   Next
End Sub
Symulacja
Ustawienie LCD
Wyłączenie kursora
Wyczyszczenie LCD
Ustawienie zmiennych

Deklaracja podprogramu
Komórka siódma "na warsztat"
Wyświetl w tej komórce dwukropek
Komórka dziesiąta "na warsztat"
Wyświetl w tej komórce dwukropek
Pętla nieskończona
Jeżeli sekundy osiągneły "60", to:
Zwiększ minuty
Zeruj sekundy
Koniec warunkowania
Jeżeli minuty osiągneły "60", to:
Zwiększ godziny
Zeruj minuty
Koniec warunkowania
Jeżeli godziny osiągneły "24", to:
Zeruj godziny
Koniec warunkowania
Jeżeli sekundy są mniejsze od "10", to:
Komórka jedenasta "na warsztat"
Wyświetl w tej komórce zero
Komórka dwunasta "na warsztat"
Wyświetl w tej komórce wartość sekund
W przeciwnym wypadku:
Komórka jedenasta "na warsztat"
Wyświetl w tej komórce wartość sekund
Koniec warunkowania
Jeżeli minuty są mniejsze od "10", to:
Komórka ósma "na warsztat"
Wyświetl w tej komórce zero
Komórka dziewiąta "na warsztat"
Wyświetl w tej komórce wartość minut
W przeciwnym wypadku:
Komórka ósma "na warsztat"
Wyświetl w tej komórce wartość minut
Koniec warunkowania
Jeżeli godziny są mniejsze od "10", to:
Komórka piąta "na warsztat"
Wyświetl w tej komórce zero
Komórka szósta "na warsztat"
Wyświetl w tej komórce wartość godzin
W przeciwnym wypadku:
Komórka piąta "na warsztat"
Wyświetl w tej komórce wartość godzin
Koniec warunkowania
Zwiększ sekundy o jeden
Opóźnienie
Koniec pętli
Podprogram opóźniający
Pętla powtórzy się 251 razy
Koniec pętli
Koniec podprogramu
				

Pierw program na stałe wyrzuca na pozycje siódmą i dziesiątą dwukropki. Następnie wchodzi do pętli, która na początku sprawdza, czy zmienne nie przekroczyły swojego progu. Jeśli tak, to zwiększa wartość wyższej jednostki i się zeruje. Kolejne trzy funkcje warunkują, czy zmienna jest mniejsza od dziesięciu. Jeśli tak, to przed wartością zmiennej wrzuca zero. Jeśli nie - zamiast zera wrzuca właśnie zmienną. Dzięki temu zegarek lepiej wygląda. Dopiero na samym końcu pętli znajduje się komenda przyrostu sekund oraz dobrze znane "czekaj".

Zajęcia III

Zadanie podobne, jak na pierwszych zajęciach. Chcę na porcie otrzymać efekt piłeczek, ale przy pisaniu programu muszę skorzystać z tablicy. Tablica, to taka duża zmienna, zawierająca zmienne. Przykładowo, tablica o nazwie "Klasa 1Ic", zawiera 32 wartości - uczniów. Każdy uczeń ma numer, i po tymże numerze można go wywołać z tablicy. Dlaczego jest to lepsze od rozwiązania z pierwszych zajęć? Ponieważ tam zmienne są wpisane do procesora, i bez wgrywania programu od nowa ich nie zmienisz, w przeciwieństwie do tablicy.

Porty: skaczące piłeczki/choinkowe lampki
$sim
Dim A As Byte , B As Byte ,
C As Word
Declare Sub Moment
Do
   For A = 0 To 5
      B = Lookup(a , Tablica)
      Portb = B
      Moment
   Next
Loop
Sub Moment
   For C = 0 To 150
   Next
End Sub
Tablica:
   Data 24 , 36 , 66 ,
        129 , 66 , 36
Symulacja
Deklaracja zmiennych

Deklaracja podprogramu
Pętla
Powtóż 6 razy, zwiększając zmienną "a"
Zmienna B = element "a" z "Tablica"
Wysyła wartość zmiennej B na port
Opóźnienie
Powtóż
Koniec pętli
Podprogram opóźniający
Pętla powtórzy się 151 razy
Koniec pętli
Koniec podprogramu
Tablica o nazwie "Tablica":
Elementy
(w jednej linii!)

Drugim i ostatnim zadaniem było to samo, ale na sześciu portach na raz.

$sim
Dim X As Byte , Y As Byte , K As Byte
Declare Sub Moment!
Do
   For X = 0 To 5
      K = Lookup(x , Tablica0)
      P0 = K
      P1 = K
      P2 = K
      P3 = K
      P4 = K
      P5 = K
      Moment!
   Next
Loop
Sub Moment!
   For Y = 0 To 150
   Next
End Sub
Tablica0:
   Data 24 , 36 , 66 , 129 , 66 , 36

Tym razem kod bez komentarzy. Teraz nie są Ci już potrzebne. ;)