INTERRUPTS
Οι διακοπές που μπορεί να κάνει ο παραπάνω μ/ε είναι (από το .h των μ/ε του compiler).
#define INT_RTCC 0x00F220 // Interrupt του timer0 (ίδιο με το παρακάτω)
#define INT_TIMER0 0x00F220 // Interrupt του timer0
#define INT_TIMER1 0x009D01 // Interrupt του timer1
#define INT_TIMER2 0x009D02 // Interrupt του timer2
#define INT_TIMER3 0x00A002 // Interrupt του timer3
#define INT_EXT 0x00F210 // Interrupt κατά την αλλαγή του πιν INT0
#define INT_EXT1 0x00F008 // Interrupt κατά την αλλαγή του πιν INT1
#define INT_EXT2 0x00F010 // Interrupt κατά την αλλαγή του πιν INT2
#define INT_RB 0x00FFF208// Interrupt κατά την αλλαγή της port_B στα πιν Β4, Β5, Β6, Β7
#define INT_AD 0x009D40 //Analog to digital conversion complete
#define INT_RDA 0x009D20 //RS232 receive data available
#define INT_TBE 0x009D10 //RS232 transmit buffer 0 empty
#define INT_SSP 0x009D08 //Streaming Parallel Port Read/Write
#define INT_CCP1 0x009D04 //Capture or Compare on unit 1
#define INT_CCP2 0x00A001 //Capture or Compare on unit 2
#define INT_BUSCOL 0x00A008 //Bus collision
#define INT_LOWVOLT 0x00A004 //Low voltage detected
#define INT_COMP 0x00A040 //Comparator detect
#define INT_EEPROM 0x00A010 //Write complete
#define INT_OSCF 0x00A080 //System oscillator failed
#define INT_USB 0x00A020 //Universal Serial Bus activity
Οι πρώτες πέντε έχουν εξηγηθεί, προχωράμε λοιπόν στις επόμενες EXT, EXT1, EXT2, RB.
Παράδειγμα:
το κύκλωμα της δοκιμής
#define INT_RTCC 0x00F220 // Interrupt του timer0 (ίδιο με το παρακάτω)
#define INT_TIMER0 0x00F220 // Interrupt του timer0
#define INT_TIMER1 0x009D01 // Interrupt του timer1
#define INT_TIMER2 0x009D02 // Interrupt του timer2
#define INT_TIMER3 0x00A002 // Interrupt του timer3
#define INT_EXT 0x00F210 // Interrupt κατά την αλλαγή του πιν INT0
#define INT_EXT1 0x00F008 // Interrupt κατά την αλλαγή του πιν INT1
#define INT_EXT2 0x00F010 // Interrupt κατά την αλλαγή του πιν INT2
#define INT_RB 0x00FFF208// Interrupt κατά την αλλαγή της port_B στα πιν Β4, Β5, Β6, Β7
#define INT_AD 0x009D40 //Analog to digital conversion complete
#define INT_RDA 0x009D20 //RS232 receive data available
#define INT_TBE 0x009D10 //RS232 transmit buffer 0 empty
#define INT_SSP 0x009D08 //Streaming Parallel Port Read/Write
#define INT_CCP1 0x009D04 //Capture or Compare on unit 1
#define INT_CCP2 0x00A001 //Capture or Compare on unit 2
#define INT_BUSCOL 0x00A008 //Bus collision
#define INT_LOWVOLT 0x00A004 //Low voltage detected
#define INT_COMP 0x00A040 //Comparator detect
#define INT_EEPROM 0x00A010 //Write complete
#define INT_OSCF 0x00A080 //System oscillator failed
#define INT_USB 0x00A020 //Universal Serial Bus activity
Οι πρώτες πέντε έχουν εξηγηθεί, προχωράμε λοιπόν στις επόμενες EXT, EXT1, EXT2, RB.
Παράδειγμα:
το κύκλωμα της δοκιμής
Κώδικας:
#include <18F2550.h>
#FUSES NOWDT, INTRC_IO, NOPUT, NOMCLR
#use delay(clock=4M)
int16 time=1000;
int a;
#int_EXT
void EXT_isr(void)
{
time=100;
}
#int_EXT1
void EXT1_isr(void)
{
time=300;
}
#int_EXT2
void EXT2_isr(void)
{
time=500;
}
#int_RB
void RB_isr(void)
{
time=700;
a=input_b();
//clear_interrupt(int_rb);
}
void main()
{
enable_interrupts(INT_EXT);
enable_interrupts(INT_EXT1);
enable_interrupts(INT_EXT2);
//clear_interrupt(int_rb);
enable_interrupts(INT_RB);
enable_interrupts(GLOBAL);
ext_int_edge(0,l_to_h);
ext_int_edge(1,l_to_h);
ext_int_edge(2,l_to_h);
while (1)
{
output_toggle(pin_A0);
delay_ms(time);
}
}
/*
Την μεταβλητή a την έφτιαξα για να αποθηκεύσω την τιμή της port_b,
αν δεν διαβάσεις την πόρτα κατά την διακοπή της INT_RB δεν κάνει clear το flag με αποτέλεσμα να κολάει σε ατέρμονη λούπα.
Με το clear_interrupt(int_rb) συνέχιζε το κόλλημα (όπου και να το έβαζα)!
*/
#include <18F2550.h>
#FUSES NOWDT, INTRC_IO, NOPUT, NOMCLR
#use delay(clock=4M)
int16 time=1000;
int a;
#int_EXT
void EXT_isr(void)
{
time=100;
}
#int_EXT1
void EXT1_isr(void)
{
time=300;
}
#int_EXT2
void EXT2_isr(void)
{
time=500;
}
#int_RB
void RB_isr(void)
{
time=700;
a=input_b();
//clear_interrupt(int_rb);
}
void main()
{
enable_interrupts(INT_EXT);
enable_interrupts(INT_EXT1);
enable_interrupts(INT_EXT2);
//clear_interrupt(int_rb);
enable_interrupts(INT_RB);
enable_interrupts(GLOBAL);
ext_int_edge(0,l_to_h);
ext_int_edge(1,l_to_h);
ext_int_edge(2,l_to_h);
while (1)
{
output_toggle(pin_A0);
delay_ms(time);
}
}
/*
Την μεταβλητή a την έφτιαξα για να αποθηκεύσω την τιμή της port_b,
αν δεν διαβάσεις την πόρτα κατά την διακοπή της INT_RB δεν κάνει clear το flag με αποτέλεσμα να κολάει σε ατέρμονη λούπα.
Με το clear_interrupt(int_rb) συνέχιζε το κόλλημα (όπου και να το έβαζα)!
*/
Ψαχνόμουν γιατί δεν δούλευε η int_rb και όχι μόνο δεν δούλευε άλλα κολλούσε και όλο το πρόγραμμα, μετά από ψάξιμό στον internet είδα πως για να ξεπεράσουν αυτό το πρόβλημα διάβαζαν την πόρτα Β κατά την διακοπή.
Στις δοκιμές που έκανα, καθάρισμα της flag κατά την διακοπή ή πριν την int_rb, ακόμη και με διάβασμα της πόρτας το πρόγραμμά συνέχιζε να κολλάει.
Tελικά δούλεψε όταν κατά την διακοπή διάβαζα την πόρτα και αποθήκευα την τιμή της σε μια μεταβλητή, στο datasheet πρέπει να το ψάξεις αρκετά για να βρεις το συγκεκριμένο bug.
Στις δοκιμές που έκανα, καθάρισμα της flag κατά την διακοπή ή πριν την int_rb, ακόμη και με διάβασμα της πόρτας το πρόγραμμά συνέχιζε να κολλάει.
Tελικά δούλεψε όταν κατά την διακοπή διάβαζα την πόρτα και αποθήκευα την τιμή της σε μια μεταβλητή, στο datasheet πρέπει να το ψάξεις αρκετά για να βρεις το συγκεκριμένο bug.