mikrokontrolery.net

 

   

Jako środowisko uruchomieniowe dla ponższego programu wybrałem zestaw AVT-873 firmy AVT-Korporacja. Schemat ideowy zestawu zamieszczony jest tutaj . Wygląd zestawu pokazany jest na poniższym zdjęciu:


Jako literaturę pomocną w programowaniu mikrokontroerów PIC16F84 polecam książkę Tomasza Jabłońskiego "Mikrokontrolery PIC16f8x w praktyce" wydaną przez wydawnictwo BTC. Książka ta ogranicza się niestety tylko do jednego mikrokontrolera i w zasadzie w większości jest tłumaczeniem not katalogowych, ale dla osób nie znających dobrze języka angielskiego jest całkiem dobrą propozycją na początek.
Nasz pierwszy program działa w następujący sposób : w pętli nieskończonej przepisuje zawartość portu B do portu A, efektem czego jest zaświecenie się diody odpowiadającej wciśniętemu przyciskowi. Ze względu jednak, że przyciski podłączone są do linii 4-7 portu B, a diody LED są podłączone do lini 0-3 portu A, konieczne było wprowadzenie dodatkowej operacji, powodującej zamianę miejscami połówek rejestru zawierającego odczytaną wartość z portu A.
Program skompilowano w środowisku MPLAB 6.40, a do zaprogramowania mikrokontrolera zastosowano programator JuPIC. Aby można było wprogramie posługiwać się nazwami symbolicznymi rejestrów, należy najpierw przygotować plik zawierający definicję tych nazw. Plik zastosowany przeze mnie wygląda następująco :

; zawartość pliku 16F84.H
indf equ 0x00;
tmr0 equ 0x01;
pcl equ 0x02;
status equ 0x03;
fsr equ 0x04;
porta equ 0x05;
portb equ 0x06;
eedata equ 0x08;
eeadr equ 0x09;
pclath equ 0x0A;
intcon equ 0x0B;

option_reg equ 0x81;
trisa equ 0x85;
trisb equ 0x86;
eecon1 equ 0x88;
eecon2 equ 0x89;

; Definicje bitów rejestru STATUS
#define C status, 0
#define DC status, 1
#define Z status, 2
#define PO_ status, 3
#define TO_ status, 4
#define RP0 status, 5
#define RP1 status, 6
#define IRP status, 7

; Definicje bitów portu A
#define T0CKI porta, 4

; Definicje bitów portu B
#define INT portb, 0

; Definicje bitów rejestru INTCON
#define RBIF intcon, 0
#define INTF intcon, 1
#define T0IF intcon, 2
#define RBIE intcon, 3
#define INTE intcon, 4
#define T0IE intcon, 5
#define EEIE intcon, 6
#define GIE intcon, 7

;
#define PS0 option_reg, 0
#define PS1 option_reg, 1
#define PS2 option_reg, 2
#define PSA option_reg, 3
#define T0SE option_reg, 4
#define T0CS option_reg, 5
#define INTEDG option_reg, 6
#define RBPU option_reg, 7

;
#define RD eecon1, 0
#define WR eecon1, 1
#define WREN eecon1, 2
#define WRERR eecon1, 3
#define EEIF eecon1, 4

Aby nie kopiować tego pliku do każdeko katalogu z projektem proponuję utworzyć folden o nazwie np. MPLAB i umieścić w nim nasz plik z definicjami, a projekty przechowywać w podkatalogach. W takim przypadku, aby dołączyć plik z definicjami do pliku z programem użyjemy dyrektywy #include "../16f84.h". Cały program wygląda następująco:

; Pierwszy program dla mikrokontrolera PIC16F84
; dołączenie pliku z definicjami rejestrów procesora
#include "..\16f84.h"
; nadanie nazwy symbolicznej liczbie 0x0C,
; którą wykorzystamy jako adres komórki wewnętrznej pamięci RAM
mem1 equ 0x0C
;początek programu głównego
start:
bsf RP0 ; przełącz na bank rejestrów 1
movlw 0x00 ; załaduj do W stałą 0x00
movwf trisa ; ustaw linie portu A jako wyjścia
movlw 0xFF ; załąduj do W stałą 0xFF
movwf trisb ; ustaw linie portu B jako wejścia
bcf RP0 ; przełącz na bank rejestrów 0
petla:
movf portb,0 ; prześlij do W stan linii portu B
movwf mem1 ; prześlij do RAM zawartość W
swapf mem1 ; zamień połówki komórki RAMu
movf mem1,0 ; prześlij do W zawartość mem1
movwf porta ; prześlij do portu A zawartość W
goto petla ; pętla nieskończona
end

Nasz program rozpoczyna się od dyrektywy dołączającej plik z definicjami nazw symbolicznych rejestrów wewnętrznych mikrokontrolera. Następnie nadajemy liczbie 0x0C nazwę symboliczną mem1. Od tego właśnie adresu (0x0C)rozpoczyna się obszar rejestrów ogólnego przeznaczenia. Użycie nazwy symbolicznej, zamiast jawnie podanego adresu czyni nasz program bardziej czytelnym. Następnie po etykiecie start: rozpoczyna się właściwy program. Pierwszą instrukcją jest instrukcja bsf RP0. Instrukcja ta powoduje ustawienie bitu RP0 w rejestrze STATUS. Ustawienie tego bitu powoduje przełączenia aktywnego banku rejestrów na bank 1. Przełączanie banków rejestrów wynika z architektury mikrokontrolerów PIC i niesety jest bardzo często konieczne (rejestry SFR są podzielone na dwa banki, ze względu na ograniczoną długość słowa rozkazowego, a co za tym idzie - długość adresu podawanego jako argument bezpośredni). Po przełączeniu się na bank rejestrów 1 należy skonfigurować porty WE/WY. Port A konfigurujemy jako wyjścia, poprzez zapisanie do rejestru TRISA liczby 0x00, natomiast port B konfigurujemy jako wejście zapisując do rejestru TRISB liczbę 0xFF. Po skonfigurowaniu protów WE/WY przełączamy się z powrotem na bank rejestrów 0. Następnie przesyłamy do rejestru W (pełniącego funkcje akumulatora) stan linii portu B. Teraz należy zamienić połówkami odczytaną wartość. W tym celu należy ja przesłać do jakiegoś rejestru ogólnego zastosowania, ponieważ instrukcja swapf nie moze zmienić zawarości rejestru W, tylko zawartość rejestru w pamięci RAM. Po dokonaniu zamiany połowek rejestru należy z powrotem przesłać tak zmodyfikowaną wartość do rejestru W. Dokonamy tego przez zastosowanie instrukcji movf mem1. Następnie przetworzoną wartość zapisujemy do portu A przez zastosowanie instrukcji movwf porta. Na koniec wykonujemy skok bezwzględny na początek pętli.

 

 

 

 

 

 

 

 

 

 

 

 
 
 
 

(c) 2004-2008 Radosław Kwiecień
Polityka prywatności