Instrukcja Lab1(1)

background image

1

Architektura Komputerów i Systemy

Operacyjne





Laboratorium 1



Ćwiczenie wstępne













Autor mgr inż. Paweł Wujek

Data 2.10.2011

background image

2

1. Wstęp

Celem niniejszego laboratorium jest zapoznanie studenta z realizacją projektu

wykorzystującego mikrokontroler rodziny STM32 z rdzeniem Cortex – M3.

Niniejsza instrukcja przeprowadzi czytelnika przez proces tworzenia nowego projektu,

zapozna z najczęściej używanymi funkcjami środowiska uruchomieniowego oraz przedstawi

sposób realizacji prostego programu polegającego na zapaleniu diody LED na płycie

uruchomieniowej.

Czytelnik zapozna się z pisaniem prostego programu w języku C, asembler, oraz programu

napisanego w C ze wstawkami asemblerowymi.

2. Tworzenie nowego projektu

Projekty tworzone będą z wykorzystaniem środowiska programistycznego

Keil µVision.

Aby uruchomić środowisko należy dwukrotnie kliknąć na ikonę

znajdującą się na

pulpicie.

Uruchomiony program powinien wyglądać następująco

background image

3

Jeśli program otworzy się i będzie widoczny poprzednio wykorzystywany projekt należy go

zamknąć wybierając PROJECT > Close Project.

1. Następnie należy utworzyć nowy projekt wybierając PROJECT > New µVision Project.

Pojawi się okno, w którym należy wpisać ścieżkę i nazwę projektu.

Jako ścieżkę proszę wybrać C:\AKSIO_LAB\grupa\LAB1

Nazwa projektu lab1.

2. Po wybraniu zapisz pojawi się okno wyboru procesora.

Należy wybrać firmę STMicroelectronics a model procesora STM32F103VB.

background image

4

3. Po zatwierdzeniu pojawi się pytanie, czy skopiować STM32 Startup Code do folderu

projektu. Należy wybrać NIE.

Plik zwierający Startup Code (startup_stm32f10x_md.s) należy dołączyć do projektu.

4. Z prawej strony ekranu w oknie Project należy rozwinąć pole Target 1, następnie kliknąć

prawym przyciskiem myszy na Source Group 1 i wybrać Add Files to Gruop…..

Po wybraniu pliku startup_stm32f10x_md.s (plik ten znajduje się w katalogu z instrukcją)

należy nacisnąć przycisk Add i Close.

5. Następnie wybrać File>New otworzy się pole tekstowe, gdzie należy wprowadzać kod

programu. Następnie należy zapisać utworzony plik wybierając File>Save i nadając mu

nazwę main.c

Plik

main.c

należy

dołączyć

do

projektu

w

sposób

analogiczny

do

pliku

startup_stm32f10x_md.s.

background image

5

6. Kolejnym krokiem jest wybór programatora. W tym celu należy wybrać

Flash>Configure Flash Tools…

Wybrać zakładkę Utilities. Zaznaczyć na niej Use Target Driver…..

Oraz wybrać ST-Link Debugger.

7. Następnie wybrać zakładkę Debug

Zaznaczyć na niej USE: i wybrać w menu rozwijanym ST-Link Debuger.

Na koniec zatwierdzić przyciskiem OK.

background image

6

Można również sprawdzić działanie programu bez wykorzystania płyty uruchomieniowej. Do

tego celu można wykorzystać symulator. Umożliwia on sprawdzanie zawartości wszystkich

rejestrów dostępnych w procesorze.

Aby uruchomić symulator należy w poprzednim oknie zaznaczyć po prawej stronie USE

Simulator.

3. Kompilacja i uruchamianie pierwszego programu

W niniejszym rozdziale student zostanie przeprowadzony przez proces pisania pierwszego

programu, kompilację, debugging oraz jego uruchomienie na płycie uruchomieniowej.

An początek należy wpisać poniższy kod programu w oknie edytora.

#include "stm32f10x.h"

int main(void)

{

while(1)

{

}

}

Linia pierwsza pozwala na dołączenie pliku nagłówkowego dostarczanego przez producenta

mikroprocesora. Plik ten zawiera zdefiniowane nazwy wszystkich rejestrów, które będą

używane w kolejnych przykładach.

background image

7

Pliki nagłówkowe udostępnione przez środowisko Keil uVision wymagają wskazania rodziny

procesorów, której używamy. Procesor dostępny w laboratorium należy do rodziny „Medium

density devices”. Wyboru rodziny można dokonać poprzez wybranie

Flash>Configure Flash Tools…

A następnie w zakładce C/C++ w polu Define wpisać STM32F10X_MD.

Co przedstawiono na rysunku

Na koniec należy zatwierdzić przyciskiem OK.

Następnie należy skompilować program naciskając przycisk Rebuild all target files. W ten

sposób tworzony jest plik wynikowy typu hex. Nie jest konieczne zapisywanie projektu, jest

on zapisywany automatycznie przed kompilacją:

Ewentualne błędny kompilacji można obserwować w oknie Build Output znajdującym się na

dole ekranu.

Po pierwszej kompilacji okno powinno wyglądać podobnie jak na rysunku poniżej

background image

8

W przypadku braku błędów można wgrać oprogramowanie do pamięci mikrokontrolera, w

tym celu naciśnij przycisk Start/Stop Debug Session

Po naciśnięciu przycisku w oknie edycji programu pokazywany jest plik po deasemblacji,

zauważ w jaki sposób są kodowane rozkazy i ich argumenty

Przydatne funkcje debuggera

Pierwsza ikona z lewej na powyższym rysunku służy do resetowania programu w procesorze.

Kolejna ikona umożliwia uruchomienie programu.

Trzecia służy do zatrzymania działającego programu. (staje się aktywna w momencie

uruchomienia programu)

Kolejna grupa ikon przeznaczone jest do obsługi pracy krokowej programu. Umożliwiają one

wykonywanie instrukcji krok po kroku, lub przejście do kolejnej pułapki.

background image

9

W momencie pisania programu lub po wejściu w tryb debuggera możliwe jest dodawanie

„pułapek”, w których program w czasie pracy zatrzyma się. Dodawanie pułapek polega na

dwukrotnym kliknięciu w szare pole po lewej stronie interesującej nas linii kodu. Poprawnie

ustawiona pułapka wygląda następująco:

Kolejną

przydatną

funkcja

jest

możliwość

podglądania

zawartości

rejestrów

odpowiedzialnych za pracę poszczególnych peryferiów.

Przykładowo aby zobaczyć rejestry odpowiedzialne za pracę portu A procesora należy

wybrać Peripherals>General Purpose I/O>GPIOA. Aktywne stanie się wtedy następujące

okno

4. Przykładowy program

4.1 Pierwszy program w C

W niniejszym rozdziale zostanie zaprezentowany prosty program prezentujący sposób

zapalenia diody LED.

Na wstępie proszę wpisać następujący kod i uruchomić program.

#include "stm32f10x.h"

int main(void)

{

background image

10

unsigned int licznik=0;

RCC->APB2ENR=0x00000008;

GPIOB->CRH=0x33333333;

while(1)

{

GPIOB->ODR=0x00000000;

for(licznik=1000000;licznik>0;licznik--);

GPIOB->ODR=0x00000100;

for(licznik=1000000;licznik>0;licznik--);

}

}

Efektem poprawnie uruchomionego programu będzie cykliczne zapalenie i zgaszenie

diody LED1.

Kolejnym zadaniem jakie należy wykonać to zapalanie co drugiej dioda LED w pętli

(maja być zapalone diody 1,3,5,7 a potem 2,4,6,8).

Pierwszym

krokiem

jest

skonfigurowanie

wszystkich

rejestrów

zegarowych

mikroprocesora.

Dokumentacja

mikroprocesora

znajduje

się

w

katalogu

C:\AKSIO_LAB\PDF w pliku o nazwie stm32f10xxx.pdf.

Ponieważ zadaniem jest tylko zapalanie i gaszenie diody LED nie musimy konfigurować

źródeł sygnału zegarowego, ani jego częstotliwości ponieważ ustawienia domyślne są

wystarczające dla tego zadania. (Domyślnie wybrany jest wewnętrzny zegar o

częstotliwości 8MHz).

Przed konfiguracją pryferiów konieczne jest włączenie sygnału zegarowego taktującego

dany układ peryferyjny. W naszym przypadku konieczna będzie konfiguracja rejestru

APB2ENR. Aby tego dokonać należy wpisać w kodzie następująca linię

RCC->APB2ENR = 0x00000000;

W miejsce zer podstawiając odpowiednią wartość. Należy zapoznać się ze słowem

konfiguracyjnym tego rejestru. W naszym przypadku należy wpisać 0x00000008.

Dlaczego? Odpowiedz powinna być jasna po dalszej konfiguracji.

background image

11

Następnym krokiem jest konfiguracji portów IO. Należy zacząć od znalezienia na

schemacie płyty uruchomieniowej (schematy dostępne są na końcu instrukcji) diody LED.

Należy następnie śledząc drogę połączeń odnaleźć układ do którego połączone są diody.

Z powyższego schematu można zauważyć, że sygnał sterujący diodą D1 „przechodząc”

przez układ 74LVD541 (układ buforujący) otrzymuje nazwę PB8. Nazwy tej należy

szukać na liniach podłączonych do innych układów.

Sygnał PB8 został podłączony do mikroprocesora STM32F103VBT6 do portu PB8.

Czytając w dokumentacji procesora rozdział dotyczący obsługi portów I/O (rozdział 8)

znajdziemy w nim informację dotyczące funkcjonowania GPIO(General Purpose IO).

Znajdują się wśród nich schematy elektryczne portów, informacje na temat trybów pracy

oraz konfiguracji.

Na początek należy wypisać nazwy wszystkich rejestrów oraz zastanowić się jakie jest ich

przeznaczenie i sposób wykorzystania.

W naszym przykładzie została wpisana linia

background image

12

GPIOB->CRH = 0x33333333;

Dlaczego akurat taka konfiguracja? Proszę się zastanowić.

Po poprawnym skonfigurowaniu portu GBPIOB należy ustawić określoną wartość na jego

wyjściu. Wiemy, że chcąc zapalić diodę D1 musimy wystawić jedynkę na bicie 8 portu.

Można to zrobić na jeden z poniższych sposobów.

GPIOB->ODR = 0x00000100;

GPIOB->BSRR=0x00000100;

Natomiast zero można ustawić na jeden z następujących sposobów:

GPIOB->ODR = 0x00000000;

GPIOB->BSRR=0x01000000;

GPIOB->BRR = 0x00000100;

Proszę zastanowić się nad różnicami oraz zaletami i wadami powyższych sposobów.

4.2 Pierwszy program napisany w języku asembler

Na początku należy utworzyć nowy projekt tak samo jak poprzednio jednak w punkcie 4

należy wpisać nazwę main.asm

Po punkcie 7 należy wybrać zakładkę Target i zaznaczyć opcję Use MicroLIB.

Ważne:

W języku asembler każde polecenie należy pisać w nowej linii poprzedzając je spacją.

Etykiety należy pisać od nowej linii.

Komentarze rozpoczynają się po średniku.

background image

13

Na początek w oknie kodu programu należy wpisać:

AREA MAINE, CODE, READONLY

EXPORT __main

Pierwsza i druga linia rozpoczyna się ze spacją.

Linie te odpowiadają za poinformowanie kompilatora o miejscu rozpoczynania się głównej

funkcji programu (main)

Następnie należy wpisać etykietę funkcji głównej:

__main

Można przejść teraz do pisania właściwego kodu programu.

Podobnie jak w języku C na początek należy włączyć zegar na port B.

Poleceniu RCC->APB2ENR=0x00000008; w asemblerze odpowiada zestaw poleceń:

LDR R0, =0x40021018

LDR R1,=0x00000008

STR R1,[R0]

Pierwsza linia powoduje wpis do rejestru R0 wartości 0x40021018. Jest to adres rejestru

APB2ENR w przestrzeni adresowej.

Druga linia powoduje wpis do rejestru R1 wartości 0x00000008. Jest to wartość jaka należy

wpisać do rejestru APB2ENR.

Trzecia linia powoduje wpis do pamięci pod adres z rejestru R0 wartości z rejestru R1.

Analogicznie poleceniu z języka C:

GPIOB->CRH=0x33333333;

W asemblerze odpowiada:

LDR R0, =0x40010C04

LDR R1, =0x33333333 ;

STR R1,[R0]

Wywołanie funkcji o nazwie DEL z parametrem w języku asembler wygląda następująco.

Parametr zapisany jest w rejestrze R2

LDR R2, =0x1E8480

background image

14

BL DEL

Bezwzględny skok do etykiety (nazwa etykiety loop) realizowany jest za pomocą polecenia:

B loop

Funkcja odmierzająca czas zrealizowana jest poprzez zmniejszanie o jeden wartości zapisanej

w rejestrze R2 a następnie sprawdzanie, czy jest to już wartość zero. Jeśli nie to następuje

skok do etykiety DEL. Realizuje to następujący fragment kodu:

DEL

NOP

SUBS R2, #1

BNE DEL

BX lr

Polecenie NOP dla procesora oznacza pustą instrukcję. Zabiera ona czas oraz powoduje

zwiększenie licznika rozkazów. Nie powoduje żadnych inny efektów.

Polecenie SUBS R2, #1 powoduje odjęcie od wartości w rejestrze R2 liczby 1 oraz ustawienie

flagi informującej czy wynik odejmowania jest równy zero.

Polecenie BNE DEL sprawdza, czy flaga ustawiana przez polecenie SUBS jest ustawiona.

Jeśli nie jest, następuje skok do etykiety DEL. Jeśli jest ustawiona następuje przejście do

kolejnej linii kodu.

Polecenie BX lr odpowiada za skok do miejsca z którego została wywołana funkcja.

W pełni funkcjonalny kod wygląda następująco:

AREA MAINE, CODE, READONLY

EXPORT __main

;wywolanie glownej funkcji main

__main

; RCC->APB2ENR=0x00000008;

LDR R0, =0x40021018

LDR R1, =0x00000008

STR R1,[R0]

background image

15

; GPIOB->CRH=0x33333333;

LDR R0, =0x40010C04

LDR R1, =0x33333333

STR R1,[R0]

loop ;petla zapalaja i gaszaca diode

;GPIOB->ODR=0x00000000;

LDR R0, =0x40010C0C

LDR R1, =0x00000000

STR R1,[R0]

;wywolanie funkcji odmierzajacej czas z parametrem zapisanym w R2

LDR R2, =0x1E8480

BL DEL

;GPIOB->ODR=0x00000100;

LDR R0, =0x40010C0C

LDR R1, =0x00000100

STR R1,[R0]

;wywolanie funkcji odmierzajacej czas z parametrem zapisanym w R2

LDR R2, =0x001E8480

BL DEL

;skok do poczatku petli

B loop

;funkcja odmierzajaca czas z parametrem R2

DEL

NOP

SUBS R2, #1

BNE DEL

BX lr

;koniec funkcji odmierzającej czas

background image

16

NOP

END

4.3 Pierwszy program napisany w języku C z wstawką

asemblerową

Po napisaniu pierwszego programu w C i w asemblerze widzimy, że dużo łatwiej i przyjaźniej

pisze się programy z wykorzystaniem języka C. Czasem jednak zdarza się, że chcemy mieć

pełna kontrolę nad sprzętem lub maksymalnie przyspieszyć wykonywanie instrukcji. W takim

przypadku możemy skorzystać z wstawek asemblerowych w języku C.

Przykładowo w naszym kodzie napisanym w C linię

RCC->APB2ENR=0x00000008;

Możemy zastąpić wstawką asemblerową.

W miejsce tej linii należy wpisać wywołanie funkcji

funkcja_asm();

Teraz należy napisać funkcję która będzie wywoływana. Wygląda ona następująco:

__asm funkcja_asm(void)

{

LDR R0, =0x40021018

LDR R1, =0x00000008

STR R1,[R0]

BX lr

NOP

}

Działanie poszczególnych poleceń asemblerowych wykorzystanych w funkcji jest zapewne

dobrze znana.

background image

17

Polecenie BX lr dodane jest po to aby po zakończeniu operacji asemblerowych powrócić do

miejsca skąd funkcja została wywołana.

Polecenie NOP dodane jest w celu wyeliminowania ostrzeżenia kompilatora.

Ostatecznie cały program napisany w C z wstawką asemblerową wygląda następująco:

#include "stm32f10x.h"

__asm funkcja_asm(void)

{

LDR R0, =0x40021018

LDR R1, =0x00000008

STR R1,[R0]

BX lr

NOP

}

int main(void)

{

unsigned int licznik=0;

funkcja_asm();

GPIOB->CRH=0x33333333;

while(1)

{

GPIOB->ODR=0x00000000;

for(licznik=1000000;licznik>0;licznik--);

GPIOB->ODR=0x00000100;

for(licznik=1000000;licznik>0;licznik--);

}

}

Teraz należy samodzielnie wykonać zadanie postawione na początku ćwiczenia.

background image

18

Należy zapalić tylko diody D1, D3, D5, D7, następnie tylko diody D2, D4, D6, D8.

Do tego celu można wykorzystać jeden z powyżej przedstawionych programów.

background image

19

5. Schematy elektryczne płyty bazowej

background image

20

background image

21

6. Polecenia języka Asembler

background image

22

background image

23


Wyszukiwarka

Podobne podstrony:
INSTRUKCJE, lab1, Wykorzystanie interfejsu graficznego
Instrukcja lab1
INSTRUKCJA LAB1
Potencjometria lab1, WIMiC, instrumentalne
Lab1 Instrukcja (2)
lab1 Instrukcja id 750240 Nieznany
Lab1 Instrukcja 4
Lab1 Instrukcja
Lab1 Instrukcja 2 id 258957 Nieznany
Lab1 instrukcja2010
sieci LAB1, Informatyka, Informatyka - UJK, Sieci komputerowe, Instrukcje
lab1 instrukcja
Instrukcja Ptel Lab1
T I C ?NA Sem4 Optional Lab1 TSU Instructor1
Instrukcja IEF Algorytmy i struktury danych lab1
Lab1 Instrukcja
Lab1 Instrukcja

więcej podobnych podstron