| Home Pic in Greek Παραδείγματα χρήσης Pic Χρονόμετρο Αντίστροφης Μέτρησης Ανάλυση προγράμματος |
Χρονόμετρο αντίστροφης μέτρησης - Ανάλυση προγράμματος
Τίτλος προγράμματος
    ;*********************************************************************
    ;                                                                    *
    ;             The Countdown timer processing                        *
    ;                                                                    *
    ;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 (Κάτω παύλες), πριν από την ψευδοεντολή. Δείτε στον πίνακα που ακολουθεί αναλυτικά τις ρυθμίσεις για το συγκεκριμένο Configuration Word.
Είδος | Λειτουργία | Field name | Bit(s)
--- | --- | --- | ---
Προστασία κώδικα | Χωρίς | CP | 1111111111
Χρον. Εκκίνησης | Με | PWRTE(inv) | 0
Χρόν.Watchdog | Χωρίς | WDTE | 0
Επιλογή ταλαντωτή | High Speed | FOSC1 and FOSC0 | 10
Ορισμός ονομάτων (Ετικετών)
    ;****************  Label Definition  ********************
Σε αυτό το σημείο ‘βαφτίζουμε’ τους ελεύθερους προς χρήση καταχωρητές του μικροεπεξεργαστή και ότι άλλο χρειαζόμαστε, με ονόματα που θα μπορούμε να θυμόμαστε κατά την διάρκεια γραφής του προγράμματος . Η κατάσταση κάθε τμήματος των Display για την απεικόνιση των αριθμών ορίζεται με της ψευδοεντολές EQU. Στον πίνακα που ακολουθεί φαίνεται η κατάσταση των τμημάτων για κάθε αριθμό.
|  | '0' : Αναμμένο, '1' : Σβησμένο.
| Επάνω όψη |
| a | b | c | d | e | f | g
0 | 0 | 0 | 0 | 0 | 0 | 0 | 1
1 | 1 | 0 | 0 | 1 | 1 | 1 | 1
2 | 0 | 0 | 1 | 0 | 0 | 1 | 0
3 | 0 | 0 | 0 | 0 | 1 | 1 | 0
4 | 1 | 0 | 0 | 1 | 1 | 0 | 0
5 | 0 | 1 | 0 | 0 | 1 | 0 | 0
6 | 0 | 1 | 0 | 0 | 0 | 0 | 0
7 | 0 | 0 | 0 | 1 | 1 | 1 | 1
8 | 0 | 0 | 0 | 0 | 0 | 0 | 0
9 | 0 | 0 | 0 | 0 | 1 | 0 | 0
Λειτουργία γρήγορης εξομοίωσης
    ;**************  Debugging mode setting  ****************
    ;Για γρηγορότερη εξομοίωση το Ελληνικό ερωτηματικό, ";" της επόμενης εντολής πρέπει να διαγραφεί.
    ;#define  _debug
Υπάρχει τρόπος με ένα κολπάκι κατά την μεταγλώττιση, να παρακάμπτονται οι υπορουτίνες χρόνου, για πιο γρήγορο έλεγχο του προγράμματος με την λειτουργία της εξομοίωσης. Με αυτό το 'κόλπο' οι τιμές των μετρητών, κ.λ.π, ορίζονται έτσι ώστε ο εξομοιωτής να εκτελεί τις υπορουτίνες χρόνου μόνο μία φορά. Στο παράδειγμα μας για να γίνει αυτό χρησιμοποιείται η ετικέτα '_debug', και οι ψευδοεντολές '#ifdef, #else, #endif και #ifndef. Για λεπτομέρειες, δηλαδή πώς γίνεται, κάντε κλικ στο: "Εξομοίωση χρονόμετρου". Εκκίνηση προγράμματος
    ;****************  Program Start  ***********************
Μετά το Power on ο μικροεπεξεργαστής αρχίζει να εκτελεί τις εντολές που έχει αποθηκευμένες στην μνήμη του από την διεύθυνση μηδέν ‘Address 0’. Σε περίπτωση που χρησιμοποιούμε Interrupts η εκτέλεση των εντολών αρχίζει από την διεύθυνση τέσσερα. Λειτουργία αρχικοποίησης
    ;****************  Initial Process  *********************
Μετά την τροφοδοσία του μικροεπεξεργαστή με ρεύμα, ακολουθούν οι παρακάτω ενέργειες αρχικοποίησης του.
Ορισμός κατάστασης για τα ποδαράκια της PORTA.
| Τα ποδαράκια RA0 έως RA3 ορίζονται σαν έξοδοι, ενώ το RA4 ορίζεται σαν είσοδος και λειτουργεί σαν πλήκτρο διακοπής της λειτουργίας του χρονόμετρου.
Ενεργοποιείται η λειτουργία pull-up της PORTB (RPBU=0).
| Για λεπτομέρειες σχετικά με την λειτουργία Pull-up κάντε κλικ στο : "Το εσωτερικό της Β port (ποδαράκια RB0-RB3 )".
Ορισμός τιμών για τον χρονομετρητή TMR0.
| Επιλογή χρήσης του εσωτερικού χρονομετρητή, με προδιαιρέτη (prescaler), η τιμή του οποίου είναι 256 (1/256).
Ορισμός κατάστασης ρελέ.
| Βάζει το ρελέ σε κατάσταση ηρεμίας.
Φόρτωμα της κατάστασης των LED Display για κάθε αριθμό, σε καταχωρητές της μνήμης RAM.
Μηδενισμός των καταχωρητών των δευτερολέπτων (δεκάδες - μονάδες).
Ορίζει την αρχική τιμή του Time_f με μηδέν '0' (Σήμανση time-out).
Λειτουργία αναμονής χρονόμετρου (Timer stand-by)
    ;*************  Timer stand-by Process  *****************
Η παρακάτω λειτουργία επαναλαμβάνεται μέχρις ότου αρχίσει η αντίστροφη χρονομέτρηση. Η δυαδική τιμή στην έξοδο των διακοπτών BCD, ορίζεται σαν 'Αρχικός χρόνος'. Απεικονίζονται τα περιεχόμενα των μετρητών στα LED Display. Ορίζεται το ποδαράκι RB6 σαν είσοδος. Ελέγχεται εάν πατήθηκε το μπουτόν εκκίνησης του χρονόμετρου. Λειτουργία εκκίνησης & αντίστροφης μέτρησης του χρονόμετρου
    ;**************  Timer start Process  *******************
Η παρακάτω λειτουργία γίνεται όταν πατηθεί το μπουτόν εκκίνησης και αρχίσει η αντίστροφη χρονομέτρηση. Ενεργοποιείται το ρελέ και ανάβει το LED ένδειξης του χρονόμετρου. Ορίζονται τις τιμές των μετρητών. Για να υπάρχει ακρίβεια στη μέτρηση, πρέπει τα νούμερα του χρονόμετρου να αλλάζουν ακριβώς κάθε δευτερόλεπτο. Για τον υπολογισμό των τιμών που πρέπει να έχουν οι μετρητές (TMR0, Prescaler & Multipliers), ακολουθείστε την παρακάτω διαδικασία ή χρησιμοποιείστε το πρόγραμμα Pic Timer.
Συχνότητα ταλαντωτή | : | Για το παράδειγμα είναι 10-MHz
Τιμή προδιαιρέτη (prescaler). | : | Ορίστηκε η τιμή 256. για να γίνεται μία αύξηση των πολλαπλασιαστών κάθε 256 υπερχειλίσεις (overflow interrupt) του TMR0
Τιμή έναρξης TMR0 | : | Ορίστηκε η τιμή που δίνει την μικρότερη απόκλιση κατά την μέτρηση του δευτερόλεπτου.( 213 αυξήσεις ) Η τιμή έναρξης του TMR0 βγαίναι από την αφαίρεση, 256-213=43.
Τιμή πολλαπλασιαστών | : | Για την προσέγγιση του δευτερόλεπτου με το μικρότερο σφάλμα πρέπει ο πολλαπλασιαστής να πάρει την τιμή 46.
Ενεργοποιούνται τα interrupts. Η λειτουργία που ακολουθεί επαναλαμβάνεται μέχρις ότου υπάρξει διακοπή (interrupt). Απεικονίζονται οι τιμές των λεπτών και δευτερόλεπτων στα LED Display. Γίνεται έλεγχος για το τέλος χρόνου (Μηδενισμός χρονόμετρου) Μετά το μηδενισμό του χρονόμετρου επιστρέφει στην κατάσταση αναμονής.
Ο χρόνος για το δευτερόλεπτο υπολογίζεται με την ακόλουθη διαδικασία. (Εάν θέλετε απόλυτη ακρίβεια χρησιμοποιήστε κρύσταλλο 3,2768MHz και τροποποιήστε ανάλογα τις ρουτίνες χρόνου).
Χρόνος | = (4/συχνότητα ταλαντωτή) x προδιαιρέτη x αυξήσεις TMR0 x φορές πολλαπλασιαστή
| = 0.4 x 10-6 x 256 x 217 x 45
| = 0.999936 Δευτερόλεπτα
Εάν για παράδειγμα χρησιμοποιήσετε κρύσταλλο 4.19MHz και TMR0=186, πολλαπλασιαστή=22, το αποτέλεσμα θα ήταν χρόνος ίσος με 1.000049642 δευτερόλεπτα. Για μέτρηση 99 λεπτών το σφάλμα (απόκλιση) είναι -20 δευτερόλεπτα (το χρονόμετρο μηδενίζει πιο γρήγορα). Ενώ για μέτρηση ενός δευτερόλεπτου η απόκλιση είναι 0.003367 δευτερόλεπτα. Με τις τιμές, κρύσταλλο 10MHz, TMR0=213, και πολλαπλασιαστή=46, το σφάλμα για μέτρηση 99 λεπτών είναι μόνο 1 δευτερόλεπτο.
Χρόνος | = (4/συχνότητα ταλαντωτή) x προδιαιρέτη x αυξήσεις TMR0 x φορές παλλαπλασιαστή
| = 0.4 x 10-6 x 256 x 213 x 46
| = 1.0033152 Δευτερόλεπτα
Η τιμή εκκίνησης του χρονομετρητή (TMR0) είναι εκείνη που βγαίνει από την αφαίρεση του αριθμού των αυξήσεων που πρέπει να κάνει πρίν υπερχειλίσει, από το σταθερό αριθμό 256. 256-213=43(2Bh) Για απόλυτο χρόνο ενός δευτερόλεπτου, πρέπει να βάλετε κρύσταλλο 3,2768MHz, προδιαιρέτη=256, TMR0=200, πολλαπλασιαστή=16
Χρόνος | = (4/συχνότητα ταλαντωτή) x προδιαιρέτη x αυξήσεις TMR0 x φορές παλλαπλασιαστή
| = 1.220703125 x 10-6 x 256 x 200 x 16
| = 1,0000 Δευτερόλεπτα
Απεικόνιση χρόνου
    ;**************  LED Control Subroutine  ****************
Ο χρόνος μετριέται με την βοήθεια καταχωρητών. Το περιεχόμενο αυτών των καταχωρητών απεικονίζεται στα LED Display επτά τμημάτων, με την εξής σειρά : Δεκάδες λεπτών, Μονάδες λεπτών, : δεκάδες δευτερόλεπτων, Μονάδες δευτερόλεπτων. Μετατροπή BCD σε κώδικα επτά τμημάτων (7 segment data)
    ;*******  Change BCD to 7segment data Subroutine  *******
Γίνεται μετατροπή των δυαδικά κωδικοποιημένων δεκαδικών αριθμών, σε κώδικα επτά τμημάτων και απεικόνιση τους μέσο της PORTB στα LED Display. Υπορουτίνα χρόνου, 1 μιλισεκόντ (millisecond)
    ;*************  1msec Timer Subroutine  *****************
Όπως προαναφέρθηκε, η PORTB διαβάζει ή οδηγεί περισσότερα από ένα υλικά, πχ. τους διακόπτες BCD, το μπουτόν εκκίνησης (start), τα LED Display. Τα τρανζίστορ που χρησιμοποιούνται στο κύκλωμα για να συνδέουν το κάθε υλικό με την PORTB, για να αλλάξουν κατάσταση (από αγωγιμότητα σε αποκοπή και αντίστροφα), χρειάζονται κάποια μικροσεκοντ (εξαρτάται από τα χαρακτηριστικά των τρανζίστορ). Με χρονισμό 10MHz ο PIC εκτελεί κάθε εντολή σε 0,4μSec, συνεπώς για να προλαβαίνουν τα τρανζίστορ να αλλάζουν κατάσταση πρέπει να υπάρχει και η ανάλογη χρονική καθυστέρηση. Προσοχή χρειάζεται σε αυτό το σημείο γιατί εάν ο χρόνος αυτός είναι μεγάλος τότε τα LED Display θα φαίνονται σαν να τρεμοσβήνουν. Στην περίπτωση του διαβάσματος ενός υλικού, εκτελείται πρώτα η καθυστέρηση του ενός μιλισεκόντ (1mSec), και μετά γίνεται η ανάγνωση της κατάστασης του υλικού που επιλέχτηκε. Στην περίπτωση της οδήγησης, το υλικό οδηγείται μετά την καθυστέρηση. Εάν δεν συνδεσμολογήσετε το κύκλωμα είναι πολύ δύσκολο να καταλάβετε με την χρήση του εξομοιωτή την χρησιμότητα της καθυστέρησης του ενός μιλισεκόντ (1mSec). Επομένως ποτέ μην ξεχνάτε πως πρέπει να υπολογίζεται και τον χρόνο ανταπόκρισης των υλικών. Λειτουργία διακοπής (Interruption)
    ;************  Begin Interruption Process  **************
Όταν υπάρξει διακοπή της ροής του προγράμματος, η υπορουτίνα αυτή, αποθηκεύει τα περιεχόμενα των W και STATUS στους καταχωρητές w_save , s_save και επιβεβαιώνει ότι έγινε η διακοπή από υπερχείλιση του TMR0 με ανάγνωση του ψηφίου TOIF. Λειτουργία τερματισμού διακοπής (Interruption)
    ;************  END of Interruption Process **************
Μόλις ολοκληρωθεί η ρουτίνα διακοπής (interruption), ο μετρητής προγράμματος επιστρέφει και εκτελεί τον κώδικα από το σημείο που είχε σταματήσει όταν συνέβη η διακοπή. Το περιεχόμενο του καταχωρητή STATUS επαναφέρεται πρώτα και μετά του W. Για την επαναφορά του W, πρέπει να ακολουθήσετε την εξής διαδικασία: Επειδή το περιεχόμενο του STATUS αλλάζει εάν επαναφέρετε το W με την εντολή MOVF, η επαναφορά πρέπει να γίνει με την χρήση της εντολής SWAPF, έτσι το περιεχόμενο που μόλις πριν επαναφέρθηκε στον STATUS παραμένει αναλλοίωτο. Παρατηρήστε πώς για την επαναφορά του W η εντολή SWAPF χρησιμοποιείται δύο φορές. Η ρουτίνα κλείνει με την εντολή RETFIE, η οποία επαναφέρει το τον μετρητή προγράμματος (Program counter) στο σημείο που ήταν πριν την διακοπή, επίσης κάνει '1' (ενεργοποιεί) το ψηφίο GIE του καταχωρητή INTCON. Υπερχείλιση χρονομετρητή TMR0 (time out)
    ;***********  Time-out interruption Process  ************
Αυτή η ρουτίνα εκτελείται κάθε φορά που υπερχειλίζει ο TMR0. Την μέτρηση του χρόνου κάθε ένα δευτερόλεπτο κάνει ο χρονομετρητής TMR0, με μέγιστο χρόνο (για χρονισμό 10MHz) δίχως πολλαπλασιαστές τα 26,214 mSec. Για να μετρηθεί λοιπόν ένα δευτερόλεπτο, μετριούνται οι υπερχειλίσεις του TMR0. Λειτουργία αντίστροφης μέτρησης (Countdown)
    ;*************  Timer Countdown Process  ***************
Αυτή η ρουτίνα εκτελείτε κάθε δευτερόλεπτο. Πρώτα ελέγχει τον μετρητή των μονάδων των δευτερόλεπτων εάν είναι 0, στην περίπτωση που είναι μηδέν, επειδή υπάρχει η πιθανότητα να έχει γίνει υπερχείλιση του TMR0, άρα και διακοπή, ελέγχει όλους τους μετρητές για να δεί εάν έχουν μηδενιστεί "Τέλος χρόνου". Για να καταλάβει ο PIC ότι ένας μετρητής έχει μηδενίσει ή όχι, διαβάζει το περιεχόμενο του με την εντολή, movf και ελέγχει το ψηφίο Z bit του καταχωρητή STATUS. Εάν το ψηφίο Ζ (Zero) είναι σε λογικό '1' το περιεχόμενο του μετρητή είναι μηδέν. Κατά την εκτέλεση της αντίστροφης μέτρησης, ελέγχονται τα περιεχόμενα των μετρητών και στην περίπτωση που κάποιος γίνει μηδέν αμέσως επαναφέρεται με τον μέγιστο για αυτόν αριθμό. Για παράδειγμα, ο μεγαλύτερος αριθμός για τον μετρητή των δεκάδων των λεπτών, είναι το 5 ενώ για τον μετρητή των μονάδων των λεπτών είναι το 9. Τέλος κώδικα
    ;********************************************************
    ;          END of Count Down Timer processing
    ;********************************************************

            end
Στο τέλος του κώδικα πάντα πρέπει να υπάρχει η ψευδοεντολή END, προσέξτε εάν λείπει δεν θα γίνει η μεταγλώττιση.