 |
 |
|
Πινακίδα Ι - θεωρητικό κύκλωμα |
Τίτλος
προγράμματος
;**********************************************************************
; *
; Πινακίδα μηνυμάτων Ι *
; *
; Author : Seiichi Inoue Ελληνική απόδοση : Παναγιώτης Πανταζόπουλος *
;**********************************************************************
Ο
τίτλος και τα σχόλια του προγράμματος πρέπει υποχρεωτικά να έχουν μπροστά
το σύμβολο ( ; ).
Ψευδοεντολές LIST &
INCLUDE
list p=pic16f84a
include p16f84a.inc
Ο τύπος του μικροεπεξεργαστή δηλώνεται με την
ψευδοεντολή List.
Με το αρχείο p16f84a.inc
και με την ψευδοεντολή Include, εισάγονται στον κώδικα σας έτοιμες
αντιστοιχίες ονομάτων με καταχωρητές, κ.λ.π Εάν
χρησιμοποιείτε το include αρχείο της Microchip, κατά την μεταγλώττιση θα
σας εμφανίζεται ένα μήνυμα προειδοποίησης σχετικά με τους καταχωρητές
TRISA και TRISB. Για να αποφύγετε την εμφάνιση του μηνύματος αυτού
μπορείτε να κάνετε την παρακάτω τροποποίηση.
Τα include αρχεία συνήθως βρίσκονται στον
κατάλογο:
c:\Program
Files\Mplab\p16f84a.inc
; P16F84A.INC Standard Header File, Version 2.00'(Διόρθωση)
TRISA EQU H'0085' -> H'0005'
TRISB EQU H'0086' -> H'0006'
Μπορείτε επίσης να χρησιμοποιήσετε την
ψευδοεντολή ERRORLEVEL για να απενεργοποιήσετε την εμφάνιση
του μηνύματος.
Διαμόρφωση μικροεπεξεργαστή
Με το Configuration
Word
ενημερώνεται
ο
Assembler για τις
ρυθμίσεις των ‘σημαιών’ διαμόρφωσης του μικροεπεξεργαστή όπως, αν θα
χρονίζει με κρύσταλλο, αν θα ενεργοποιήσουμε το Watchdog
timer, αν θα
προστατεύσει το πρόγραμμα από αντιγραφή κ.λ.π .
__config _hs_osc & _wdt_off & _pwrte_on & _cp_off
Το Configuration Word μπορείτε να το δηλώσετε μέσα από
το λογισμικό της συσκευής προγραμματισμού, ή να δηλωθεί αυτόματα
χρησιμοποιώντας την ψευδοεντολή CONFIG.
Παρατηρήστε πώς υπάρχουν δύο underscore (Κάτω παύλες),
πριν από την ψευδοεντολή.
Εάν δεν
χρησιμοποιήσετε το p16f84a.inc πρέπει να εισάγετε στον κώδικά σας τα
παρακάτω. _CP_OFF EQU H'3FFF'
_PWRTE_ON EQU H'3FF7'
_WDT_OFF EQU H'3FFB'
_HS_OSC EQU H'3FFE'
Επειδή οι τιμές των δηλώσεων προστίθενται, η τελική
τιμή του Configuration Word θα είναι όπως παρακάτω:
 |
_CP_OFF |
0011 1111 1111 1111 |
(3FFFh) |
| AND |
| _PWRTE_ON |
0011 1111 1111 0111 |
(3FF7h) |
| AND |
| _WDT_OFF |
0011 1111 1111 1011 |
(3FFBh) |
| AND |
| _HS_OSC |
0011 1111 1111 1110 |
(3FFEh) |
|
| Αποτέλεσμα |
0011 1111 1111 0010 |
(3FF2h) |
__config h'3ff2' ή __CONFIG _CP_OFF & _PWRTE_ON & _WDT_OFF & _HS_OSC
Ορισμός ονομάτων
(Ετικετών)
;**************** Label Definition ********************
Σε αυτό
το σημείο ‘βαφτίζουμε’ τους ελεύθερους προς χρήση καταχωρητές του
μικροεπεξεργαστή και ότι άλλο χρειαζόμαστε, με ονόματα που θα μπορούμε
να θυμόμαστε κατά την διάρκεια γραφής του προγράμματος . Δείτε το
παράδειγμα για να καταλάβετε περισσότερα.
;************************
;* Time adjust *
;************************
;Σε αυτό το σημείο αντιστοιχίζετε η ταχύτητα σάρωσης των Led με την τιμή 0ch (12). Σάρωση ανά 26msec.
tm_adj equ 0c ;Time adjust(26msec x 12)
;************************
;* EEPROM data size *
;************************
;Το e_size αντιστοιχίζεται με την τιμή 32, δηλαδή το μέγεθος των δεδομένων θα είναι ίσο με 32 ψηφιολέξεις (Bytes).
e_size equ d'32' ;EEPROM data size
Ορισμός των δεδομένων της
EEPROM
;*************** EEPROM Data Definition ***************
org h'2100'
de b'11111111'
Στο παράδειγμα αυτό, το κινούμενο μήνυμα
αποθηκεύεται στην μνήμη EEPROM. Η διεύθυνση
h'2100' είναι η πρώτη κατά σειρά διεύθυνση της EEPROM. Η προσπέλαση της διεύθυνσης της EEPROM γίνεται με την ψευδοεντολή
ORG. Κάθε ένα ψηφίο (bit) του δυαδικού
αριθμού δηλώνει την κατάσταση των Led, το "1" σημαίνει Led σβηστό, ενώ
το "0", Led αναμμένο.
Εκκίνηση προγράμματος
;**************** Program Start ***********************
Μετά το
Power
on ο
μικροεπεξεργαστής αρχίζει να εκτελεί τις εντολές που έχει αποθηκευμένες
στην μνήμη του από την διεύθυνση μηδέν ‘Address
0’. Σε
περίπτωση που χρησιμοποιούμε Interrupts
η
εκτέλεση των εντολών αρχίζει από την διεύθυνση τέσσερα.
Λειτουργία αρχικοποίησης
;**************** Initial Process *********************
Λειτουργία οδήγησης "φορτώματος" της
οθόνης
;************** Screen Load Process *******************
Επειδή το μήνυμα απεικονίζεται σε 128 Led (16
κολώνες x 8 στήλες), το σύνολο αυτών των Led ονομάζεται
οθόνη. Η κατάσταση (αναμμένο - σβηστό) όλων των
Led ρυθμίζεται από 16 ψηφιολέξεις (Bytes), της μνήμης
Ram. Επειδή η πόρτα RB μπορεί να οδηγήσει μία
μόνο στήλη (8 Led) κάθε φορά, η οδήγηση και των 128 Led γίνεται με
μεγάλη ταχύτητα έτσι ώστε το ανθρώπινο μάτι να βλέπει το μήνυμα στην
οθόνη κανονικό. Η οδήγηση ξεκινά από την πρώτη από δεξιά στήλη και
ολισθαίνει στην επόμενη προς τα αριστερά. Εάν
αλλάξετε τα δεδομένα των 16 ψηφιολέξεων της μνήμης Ram που οδηγούν την
οθόνη, το μήνυμα θα αλλάξει ανάλογα. Η οδήγηση
κάθε στήλης Led γίνεται απευθείας από την πόρτα RB, ενώ η οδήγηση της
κάθε μίας κολώνας γίνεται από την έξοδο της πόρτας RA (RA3-RA0) στην
είσοδο του 74HC154 και την έξοδο του τελευταίου που οδηγεί το
αντίστοιχο τρανζίστορ κάθε κολώνας.
 |
Για την οδήγηση της οθόνης
χρησιμοποιείται η έμμεση προσπέλαση της μνήμης
Ram. Έτσι η προς προσπέλαση διεύθυνση μνήμης "φορτώνεται" στον καταχωρητή INDF.
Θα μπορούσατε να χρησιμοποιήσετε τον άμεσο τρόπο
προσπέλασης της μνήμης αλλά αυτό θα είχε σαν αποτέλεσμα την μεγάλη
αύξηση των γραμμών του κώδικα. |
bcf intcon,gie ;Interrupt disable
bsf intcon,gie ;Interrupt enable |
|
Ένα σημείο που πρέπει να προσέξετε
είναι πως κατά την ανανέωση - οδήγηση της οθόνης, δεν πρέπει να
υπάρξει παλμός διακοπής ροής προγράμματος
(Interrupt). Όταν δημιουργηθεί παλμός
διακοπής (interrupt), διακόπτεται προσωρινά η εκτέλεση του
προγράμματος, και εκτελείται η υπορουτίνα του interrupt. Συνεπώς
καταλαβαίνετε πως εάν υπάρξει interrupt κατά την ανανέωση της
οθόνης, η ανανέωση θα σταματήσει για να εκτελεστεί η υπορουτίνα
του interrupt, και έτσι η απεικόνιση του μηνύματος θα παρουσιάζει
κενά. Το interrupt μπορεί να χρησιμοποιηθεί μόνο κατά την
προετοιμασία της επόμενης
οθόνης. |
Λειτουργία διακοπής προγράμματος (Interruption)
;************ Begin Interruption Process **************
 Στα μαθήματα για
τον 16F84A είδατε πως διακοπή ροής
προγράμματος δημιουργείται και όταν υπερχειλίζει ο χρονομετρητής.
Μετά την διακοπή ροής, ο μετρητής προγράμματος (Program counter),
δείχνει την διεύθυνση '0004h', την ίδια στιγμή το ψηφίο T0IF του
καταχωρητή INTCON γίνεται '1', η διεύθυνση επιστροφής από την
υπορουτίνα του interrupt αποθηκεύεται στον καταχωρητή σωρού
(Status), και το ψηφίο GIE του καταχωρητή INTCON
αυτόματα γίνεται '0' για να αποφευχθεί διπλό
interrupt.
Στη συνέχεια αποθηκεύονται
τα περιεχόμενα των καταχωρητών W και
STATUS. Πρώτα αποθηκεύεται το
περιεχόμενο του καταχωρητή W γιατί θα χαθεί, κατά την
αποθήκευση του περιεχομένου του STATUS, αφού ο πρώτος
χρησιμοποιείται για την μεταφορά των δεδομένων από και προς τους
καταχωρητές. |
Τέλος γίνεται έλεγχος του είδους της διακοπής, ελέγχεται το
ψηφίο (T0IF) για time-out. Εάν δεν υπάρχει time-out και προκύψει
interrupt η εκτέλεση του προγράμματος συνεχίζεται στην υπορουτίνα
αρχικοποίησης "Initial Process".
Λειτουργία τερματισμού διακοπής
(Interruption)
;************ END of Interruption Process **************
Μόλις ολοκληρωθεί η ρουτίνα διακοπής (interruption), ο
μετρητής προγράμματος επιστρέφει και εκτελεί τον κώδικα από το σημείο
που είχε σταματήσει όταν συνέβη η διακοπή. Το περιεχόμενο του καταχωρητή STATUS επαναφέρεται πρώτα και μετά
του W, για το λόγο που αναφέραμε στη Λειτουργία
παλμού διακοπής προγράμματος. Για την επαναφορά του W, πρέπει να ακολουθήσετε την εξής
διαδικασία:
Επειδή το περιεχόμενο του STATUS αλλάζει εάν επαναφέρετε
το W με την εντολή MOVF, η επαναφορά πρέπει να γίνει με την χρήση
της εντολής SWAPF, έτσι το περιεχόμενο που μόλις πριν επαναφέρθηκε στον
STATUS παραμένει αναλλοίωτο. Παρατηρήστε πώς για την επαναφορά του W η
εντολή SWAPF χρησιμοποιείται δύο φορές. Η ρουτίνα
κλείνει με την εντολή RETFIE, η οποία επαναφέρει το τον μετρητή
προγράμματος (Program counter) στο σημείο που ήταν πριν την διακοπή,
επίσης κάνει '1' (ενεργοποιεί) το ψηφίο GIE του καταχωρητή
INTCON.
Λειτουργία διακοπής ροής προγράμματος
από υπερχείλιση του χρονομετρητή
;*********** Time-out interruption Process ************
Ο μέγιστος χρόνος που μπορεί να μετρηθεί από τον
χρονομετρητή του PIC, ακόμα και με την χρήση προδιαιρέτη (Prescaler),
είναι περίπου 26mSec (milliseconds), με κύκλωμα χρονισμού 10-MHz. Στη
διάρκεια αυτού του χρόνου το μήνυμα ολισθαίνει (κυλάει) επάνω στην
οθόνη. Εάν υποτεθεί πως χρησιμοποιούμε τα 26 mSec, τότε η ταχύτητα
ολίσθησης του μηνύματος θα είναι, 16 κολώνες x 26mSec = 416mSec, η οποία
είναι υπερβολικά γρήγορη (Θα μοιάζει σαν να ανάβουν όλα τα Led
ταυτόχρονα). Στο παράδειγμα μας μετρούνται οι φορές που υπερχειλίζει
(Time-out) ο χρονομετρητής (TMR0) και πολλαπλασιάζεται με τα 26mSec. Οι
φορές που χρειάζεται να υπερχειλίσει ο χρονομετρητής (TMR0) μπορεί να
ρυθμιστεί αλλάζοντας τιμή στην ετικέτα : tm_adj. Εάν η tm_adj
έχει την τιμή 6 τότε το μήνυμα για να κυλήσει επάνω στην οθόνη θα κάνει
χρόνο ίσο με 16 κολώνες x 26mSec x 6 interrupt time-outs= 2,496mSec,
δηλαδή περίπου 2,5 δευτερόλεπτα.
Το ψηφίο T0IF του καταχωρητή INTCON γίνεται '1'
(παράγεται interrupt) κάθε φορά που υπερχειλίζει ο χρονομετρητής.
Προσέξτε, πως εάν δεν μηδενίσετε το ψηφίο T0IF εσείς μέσα από το
πρόγραμμα, την επόμενη φορά που θα υπερχειλίσει ο χρονομετρητής
δεν θα δημιουργηθεί interrupt. Επίσης
πρέπει να ορίσετε ξανά τον αριθμό υπερχειλίσεων που θα μετρηθούν (για
παράδειγμά η τιμή '6').
Ο χρονομετρητής TMR0
μετρά πάντοτε θετικά (count up timer), υπερχειλίζει και παράγει διακοπή
(interrupt), κάθε φορά που η τιμή του γίνεται από 255 (FFh) --> 0
(00h). Συνεπώς εάν θέλετε να κάνει 6 υπερχειλίσεις πρέπει να κάνετε την
αφαίρεση 256 μετρήσεις (0 έως και 255 = 256) μείων 6 υπερχειλίσεις =
250, άρα σαν τιμή εκκίνησης του TMR0 πρέπει να δηλώσετε την τιμή
250.
Για χρονισμό 10-MHz, ο κύκλος μηχανής είναι 0,4μSec, εάν
δηλωθεί τιμή προδιαιρέτη (prescaler) ίση με 256 ο μέγιστος χρόνος για
μια υπερχείλιση θα είναι 256 μετρήσεις x 0.4 κύκλος μηχανής = 102.4
µsec. Για χρόνο ίσο με 20mSec θα έχουμε 20mSec /
0.1024 = 195 μετρήσεις δηλαδή η τιμή έναρξης του TMR0 θα είναι 256-195 =
61(3Dh).
Για να μην μπερδεύεστε με πράξεις και κάνετε λάθος
μπορείτε να χρησιμοποιήσετε το ΔΩΡΕΑΝ
προγραμματάκι PIC
TIMER που έχω φτιάξει. Aπλά εισάγετε τη συχνότητα του κυκλώματος
χρονισμού (π.χ κρυστάλλου), και τον επιθυμητό χρόνο, πατήστε το κουμπί
υπολογισμός και θα σας δείξει αμέσως την τιμή εκκίνησης του TMR0, την
τιμή του προδιαιρέτη (prescaler), και των καταχωρητών πολλαπλασιασμού
εάν χρειάζονται.
Λειτουργία ολίσθησης (κίνηση
μηνύματος) οθόνης
;************ Screen data shift Process ***************
Σε κάθε υπερχείλιση του χρονομετρητή δημιουργείται μία
διακοπή προγράμματος (Interrupt time-out), και γίνεται μία ολίσθηση του
μηνύματος της οθόνης, από δεξιά προς αριστερά. Η
ολίσθηση αυτή μετακινεί το μήνυμα μία κολώνα (κάθετη σειρά Led)
αριστερά, ενώ εμφανίζει τον επόμενο χαρακτήρα στην πρώτη από δεξιά
κολώνα. Πρώτα ολισθαίνει η δεύτερη κολώνα μια
θέση αριστερά, μετά η τρίτη στη δεύτερη κ.ο.κ, συνολικά γίνονται 15
ολισθήσεις. Όπως προαναφέρθηκε για αυτή την λειτουργία χρησιμοποιείται
έμμεση (Indirect) προσπέλαση της μνήμης.
Λειτουργία ανάγνωσης δεδομένων από την
EEPROM
;************** New data write Process ****************
Μετά τις 15 ολισθήσεις έχει ολοκληρωθεί η απεικόνιση
του μηνύματος. Το πρόγραμμα διαβάζει πάλι δεδομένα από την μνήμη EEPROM
και ξεκινά την εμφάνιση του μηνύματος από την πρώτη δεξιά κολώνα
ολισθαίνοντας προς την επόμενη αριστερά.

Για την ανάγνωση από την EEPROM χρησιμοποιούνται
οι καταχωρητές, EEADR, EECON1, EEDATA. Πρώτα ορίζεται η προς προσπέλαση διεύθυνση στον καταχωρητή
EEADR, μετά πρέπει το ψηφίο RD του καταχωρητή EECON1 να γίνει '1'
(έναρξη ανάγνωσης eeprom), μόλις ολοκληρωθεί η ανάγνωση το ψηφίο
RD γίνεται αυτόματα '0' και τα δεδομένα που διαβάστηκαν από την
μνήμη EEPROM αποθηκεύονται στον καταχωρητή EEDATA. Οι διευθύνσεις
της EEPROM που μπορείτε να προσπελάσετε είναι από την '00'h έως
'3f'h και στο σύνολο τους αποτελούν 64 ψηφιολέξεις
(bytes).
| Προσοχή!
η πρώτη διεύθυνση της EEPROM για προσπέλαση μέσα από το
πρόγραμμα είναι η '00'h και όχι η '2100'h. Η τελευταία
δηλώνεται με την ψευδοεντολή org και χρησιμοποιείται για να
εγγραφούν δεδομένα στην EEPROM κατά την μεταφορά του
μεταγλωττισμένου κώδικα στον
μικροεπεξεργαστή. |
movwf eeadr ;Ορισμός διεύθυνσης EEPROM
bsf status,rp0 ;Αλλαγή σε Bank1
bsf eecon1,rd ;Έναρξη ανάγνωσης
bcf status,rp0 ;Αλλαγή σε Bank0
movf eedata,w ;Μεταφορά περιεχομένων του EEDATA στον W | |
Τα δεδομένα που διαβάστηκαν από την πρώτη διεύθυνση της μνήμης
EEPROM μεταφέρονται στην PORTB όπου και οδηγούν τα Led της πρώτης από
δεξιά κολώνας, γίνεται μία ολίσθηση προς αριστερά, διαβάζεται η επόμενη
διεύθυνση και ο κύκλος επαναλαμβάνεται έως ότου ολόκληρο το μήνυμα
απεικονιστεί στην οθόνη.
Τέλος κώδικα
;********************************************************
; END of signboard control processing
;********************************************************
end
Στο τέλος του κώδικα πάντα πρέπει να υπάρχει η
ψευδοεντολή END, προσέξτε εάν λείπει δεν θα γίνει η μεταγλώττιση.
|
 |