Dopisek od korzystającego: czytacie uważnie instrukcję laboratoryjną bo poniższa instrukcja się nie pokrywa do końca i zawiera błędy programistyczne, lepiej pisać swoje na jej podstawie
Przykład głupoty: zad2 – używanie warunków gdy będą zawsze spełnione…
Opracował:
Maciej CZERWIŃSKI
Instrukcja ta ma na celu umożliwić Ci zaliczenie lab3 z Akiso na co najmniej 4 punkty
Dobrze by było przed laborką przejrzeć chociaż instrukcje, nauczyć się na wejściówkę i co więcej zapoznać się z tym:
http://forbot.pl/blog/artykuly/programowanie/kurs-arduino-3-uart-komunikacja-z-pc-zmienne-id3836
Widzimy to:
Teraz po kolei co jest do czego i co możemy wyciągnąć z tego pliku.
!!! biblioteka ta ma błąd, czasami po wgraniu na płytkę nie następuje automatyczny reset, dlatego wykonajcie reset raz jeszcze ręcznie przez czerwony przycisk na płytce testowej jeżeli nic by nie reagowało!!!!
Widać że inicjalizacja peryferiów jest zrobiona automatycznie więc nie musimy się teraz tym przejmować, dodatkowo mamy informacje o taktowaniu ale tego nie musimy wiedzieć. I najważniejsze tutaj informacje o prędkości naszej transmisji, ilość bitów, itd. I informacja że jest on podpięty pod printf i scanf. I fakt żeby nie dołączać startupa!!!!!!!
Odnośnie samych funkcji, w delay podajemy odpowiednia wartość us lub ms, przy sterowaniu diodami wpisujemy po prostu numer diody np. „ledOn(1);”. Tak samo przy pozostałych funkcjach z tym związanych. Wpisywanie tekstu na lcd, mamy do dyspozycji 2 funkcje. lcdGoTo przenosi nas na odpowiedni punkt wyświetlacza. Mamy do dyspozycji wyświetlacz lcd 2x16 wiec y może mieć współrzędne 0 lub 1, natomiast x od 0 do 15. W samym lcdWrite podajemy albo tekst w ”tekst przykładowy” albo wskaźnik do zmiennej typu char albo nazwę tablicy typu char. Jeżeli podamy sobie adres y=0 i x=0 i wtedy wyświetlimy ciąg znaków większy niż 16 to automatycznie przeniesie część naszego tekstu na dolny wiersz, jeśli damy więcej niż 32 znaki w takiej sytuacji to końcówka tekstu zostanie zgubiona- czyli nigdzie się nie wyświetli.
TERMINAL
Na laborce będziemy używali terminala hercules, przed użyciem musicie go skonfigurować. Wybieracie zakładkę serial następnie wybieracie port, później szybkość, rozmiar itd. I skonfigurowane okienko wygląda tak:
Teraz wystarczy wcisnąć open i będzie gotowy do pracy.
Niestety z moją przejściówką ten program nie chciał współpracować dlatego zrzuty z terminala pokaże wam z innego programu, ale tutaj będą one wyglądać tak samo tyle że tło będzie inne. Pamiętajcie o konfiguracji wstępnej bo przy źle wybranej prędkości nie uda wam się nawiązać transmisji.
Dobra podstawy omówione, teraz bierzemy się za tworzenie projektu.
Otwieramy keila
Project> new uvision project
Wybieramy mikroprocesor ten co zawsze czyli stm32f103vb
Ok>ok
Tworzymy main, File>New>Save>”main.c”
Wciskamy 3 klocki kolorowe
Zmieniamy nazwe source group na library lub inna
Dodajemy evbLib (ten większy plik-lib)
Dodajemy plik main.c
Wchodzimy w ustawienia (różdżka)
W C/C++ dodajemy w paths ścieżke do stLib
W Debug zaznaczamy programator ST-Link Debugger, później Settings>Flash Download > i zaznaczamy opcje reset and run
Dodajemy w main na samej górze dopisek dołączający biblioteki
#include "evbLib.h"
#include <stdio.h>
Projekt utworzony!
Zad 1
Teraz zadanie najprostsze, jeżeli jeszcze nie włączyłeś terminala to go włącz teraz jeśli masz go już uruchomionego to wpisujesz te linijki kodu:
int main(void)
{
int i=0;
printf("Hello World!!!\r\n"); // funkcja do drukowania w terminalu, po ukosnikach nowa linia (n) i przesuniecie kursora na poczatek(r)
while(1)
{
printf("%i\r\n",i); // %i oznacza ze tu bedzie wstawiona jakas zmienna int, w naszym przypadku i
delayMs(1000);
i++;
}
}
Masz 1 punkt!
W terminalu wygląda to tak:
Zad 2
W drugim zadaniu zajmiemy się lcd. Dostaniesz jakiś napis który będziesz musiał wyświetlić i przesuwać, tutaj ważne jest żebyś rozumiał wielkość wyświetlacza wytłumaczoną wcześniej bo będziesz musiał dobrać odpowiednie wartości zmiennych przy rotacji żeby to się wszystko zgrało odpowiednio. Jeżeli nie rozumiesz to dobieraj eksperymentalnie aż ci się uda.
Sam kod:
void czyszczenie_lcd(); //funkcja do wymazywania napisow
int main(void)
{
int x,y,i; //tworze zmienne
while(1)
{
x=0; //musialem to tutaj umiescic dla stabilnosci programu
y=0; // x wspolrzedna x, y wspolrzedna y -> logiczne
if(y==0)
{
for(i=0;i<11;i++) // petla wypisujaca
{
lcdGoTo(y,x); //przesuwanie sie na ekranie
lcdWrite("kbzddm"); //wypisujemy nasz zadany tekst
x++; //przesuniecie o jeden w bok
delayMs(500); //czas opoznienia, potrzebny zeby zobaczyc wyswietlane wartosci
czyszczenie_lcd(); // czyszczenie ekranu
}
y++; //przesuwamy sie na nastepny wiersz
}
if(y==1) //tu wszystko analogicznie tyle ze w druga strone
{
x--;
for(i=0;i<11;i++)
{
lcdGoTo(y,x);
lcdWrite("kbzddm");
x--;
delayMs(500);
czyszczenie_lcd();
}
y--;
}
}
}
void czyszczenie_lcd()
{
lcdGoTo(0,0); // przenosimy sie na poczatek
lcdWrite(" "); //wyrzucenie wszystkiego poza ekran
lcdGoTo(0,0); //przeniesienie na poczatek ekranu
}
Recepta jak to obliczyć, zliczamy ilość znaków naszego słowa i w obydwu pętlach for ustalając warunek górny robimy operacje 17-”ilość znaków”, w moim przypadku 17-6=11 i tak ustawiamy w obu pętlach. Czas dobierzecie tak jak powie prowadzący, przy zbyt szybkim przesuwaniu wyświetlacz nie nadąża więc czas dolny jest ograniczony. Zrobiłem funkcje do czyszczenia ekranu bo tak jest przejrzyściej. Wytłumacze jeszcze czyszczenie ekranu, przenosimy się na pozycje 0,0 i wyświetlamy 32 spacje, wszystkie znaki z ekranu są wyrzucane poza niego a my widzimy tylko pusty ekran. Może mało eleganckie, ale nic innego lepszego nie znalazłem.
Masz znowu 1 pkt!!
Zad 3
Zadanie to to połączenie 2 zadań, musimy pobrać tekst terminala czyli wpisać go ręcznie i zakończyć enterem. Pokazuje wam już program z zabezpieczeniem ilości znaków
void czyszczenie_lcd(); //funkcja do wymazywania napisow
int main(void)
{
int i;
printf("Wpisz tekst ktory mam wyswietlic na wyswietlaczu!!!\r\n");
printf("Moze byc maksymalnie 16 znakowy!\r\n");
while(1)
{
char tab_znak1[17]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // o jeden wiekszy rozmiar tablicy bo zostawiamy miejsce dla znaku konczacego
scanf("%16s", tab_znak1); // okreslamy ze bedzie tylko 16 znakow na wejsciu
printf("\r\n"); // nowa linia
czyszczenie_lcd(); //czyscimy poprzedni napis
lcdWrite(tab_znak1); // wyswietlamy na ekranie
}
}
void czyszczenie_lcd()
{
lcdGoTo(0,0); // przenosimy sie na poczatek
lcdWrite(" "); //wyrzucenie wszystkiego poza ekran
lcdGoTo(0,0); //przeniesienie na poczatek ekranu
}
Całe zadanie zostało ułatwione przez zastosowanie scanf, chodzi konkretnie o dopisek liczby po %, określa ona ile znaków będzie mogło się zmieścić. W momencie gdy wpiszemy 16 znaków funkcja zostaje przycięta, jest też inna opcja z przypisywaniem do nowej tablicy, ale myśle że ta będzie prostsza, a powinien się na nią bezproblemowo zgodzić. Sama konstrukcja scanf, jak chcemy pobrać jakąś daną wstawiamy po % jej typ, np. %i-int, a po przecinku wrzucamy nazwe zmiennej do której wpiszemy tą wartość. Jako że my wrzucamy ciąg znaków dajemy je bezpośrednio do tablicy jednowymiarowej, i zapisujemy tam każdy znak jak oddzielny element. Jak wpiszemy scanf to program będzie stał i czekał aż coś dostanie na wejściu. Samo wyświetlanie i czyszczenie jest jak poprzednio.
Masz następne 2 pkt!!
Zad 4
Teraz raczej koniec twoich punktów. Ten podpunkt jest całkiem trudny i wymaga zrozumienia, sam musiałem się pomęczyć żeby to napisać, nie wiem może jest jakaś prostsza droga napisania tego wszystkiego ale mi się udało tak. Działa? Działa, i o to chodzi. Wklejam dla was kod, ja wybrałem opcje zadania tworząc kalkulator 4 funkcyjny. To akurat jest najmniejszy problem w tym wszystkim. Bo jeżeli dostaniecie inną operacje to wystarczy zmienić tam operator przy samym c. Najgorszy jest odczyt zmiennych tekstowych i ich konwersja na int. Jak i podział danych wejściowych na składniki. Nie będę opisywał krok po kroku co robiłem bo tego nie da rady napisać. Jest sporo komentarzy, więc może ktoś będzie miał czas na laborce to i to ogarnie za 3 dodatkowe punkty.
Kod: - jest dość rozbudowany, 140 linijek, wybaczcie że nie będzie kolorowych komentarzy
#include <stdlib.h> //do zadania 4
// przyjmijmy ze robimy kalkulator podstawowy +,-,*,/
void czyszczenie_lcd(); //funkcja do wymazywania napisow
void wyswietlanie_wynik(int wartosc); //funkcja do wyswietlania wyniku operacji matematycznej
int main(void)
{
int i1,i2,i,p,a,b,c;
printf("Maszyna liczaca z interfejsem tekstowym\r\n");
printf("Obsluguje polecenia wejsciowe do 16 znakow\r\n");
printf("Liczy podstawowe dzialania matematyczne na liczbach calkowutych +,-,*,/\r\n");
printf("Format wprowadzania: a 'operacja' b \r\n");
while(1)
{
// tworzenie czystych zmiennych co krok
char tab_znak1[17]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
char tab_znak2[17]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
char tab_znak3[17]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
p=1;
i=0;
i1=0;
i2=0;
a=0;
b=0;
c=0;
scanf("%16s", tab_znak1); // pobieram tekst
czyszczenie_lcd();
lcdWrite(tab_znak1); //wyswietlamy wprowadzony tekst
while(p>0) //stworzenie petli z flaga
{
if(tab_znak1[i]=='+') //jak znajdzie odpowiedni znak wchodzi w operacje
{
p=0; //zdjecie flagi
for(i1=0;i1<i;i1++) //przypisanie liczby a
{
tab_znak2[i1]=tab_znak1[i1];
}
a=atoi(tab_znak2); //konwersja liczby a
for(i2=0;i2<(15-i);i2++) //przypisanie liczby b
{
tab_znak3[i2]=tab_znak1[i1+1];
i1++;
}
b=atoi(tab_znak3); //konwersja liczby b
c=a+b; //wykonana operacja
wyswietlanie_wynik(c); //wyswietlenie
}
if(tab_znak1[i]=='-') //jak znajdzie odpowiedni znak wchodzi w operacje
{
p=0; //zdjecie flagi
for(i1=0;i1<i;i1++) //przypisanie liczby a
{
tab_znak2[i1]=tab_znak1[i1];
}
a=atoi(tab_znak2); //konwersja liczby a
for(i2=0;i2<(15-i);i2++) //przypisanie liczby b
{
tab_znak3[i2]=tab_znak1[i1+1];
i1++;
}
b=atoi(tab_znak3); //konwersja liczby b
c=a-b; //wykonana operacja
wyswietlanie_wynik(c); //wyswietlenie
}
if(tab_znak1[i]=='*') //jak znajdzie odpowiedni znak wchodzi w operacje
{
p=0; //zdjecie flagi
for(i1=0;i1<i;i1++) //przypisanie liczby a
{
tab_znak2[i1]=tab_znak1[i1];
}
a=atoi(tab_znak2); //konwersja liczby a
for(i2=0;i2<(15-i);i2++) //przypisanie liczby b
{
tab_znak3[i2]=tab_znak1[i1+1];
i1++;
}
b=atoi(tab_znak3); //konwersja liczby b
c=a*b; //wykonana operacja
wyswietlanie_wynik(c); //wyswietlenie
}
if(tab_znak1[i]=='/') //jak znajdzie odpowiedni znak wchodzi w operacje
{
p=0; //zdjecie flagi
for(i1=0;i1<i;i1++) //przypisanie liczby a
{
tab_znak2[i1]=tab_znak1[i1];
}
a=atoi(tab_znak2); //konwersja liczby a
for(i2=0;i2<(15-i);i2++) //przypisanie liczby b
{
tab_znak3[i2]=tab_znak1[i1+1];
i1++;
}
b=atoi(tab_znak3); //konwersja liczby b
c=a/b; //wykonana operacja
wyswietlanie_wynik(c); //wyswietlenie
}
//jesli jeszcze nie ma znaku
i++;
if(i==16) // jesli nie znajdzie znaczy ze komenda bledna
{
p=0;
printf("Bledna komenda, wprowadz raz jeszcze\r\n");
}
}
printf("\r\n");
}
}
void wyswietlanie_wynik(int wartosc)
{
char wynik[17];
lcdGoTo(1,0);
sprintf(wynik,"%d",wartosc); //zamiana z int na char
lcdWrite(wynik); //wyswietlenie koncowego wyniku
}
void czyszczenie_lcd()
{
lcdGoTo(0,0); // przenosimy sie na poczatek
lcdWrite(" "); //wyrzucenie wszystkiego poza ekran
lcdGoTo(0,0); //przeniesienie na poczatek ekranu
}
Tutaj zrzut działającego programu z terminala. Nie wiem czy radze to komuś kopiować nie rozumiejąc tego chociaż odrobine. Myślę że to mogłoby być trochę przegięcie.
To tyle, życzę powodzenia na laborce. Instrukcje sprawdziłem krok po kroku działa cała, także nie powinniście się w niej dopatrywać błędu.