Zamolio bih vas ako mi može netko pomoći.
Počeo sam pisati program za PIC 16F877 u HI-TECH PIC 9.80, i došao sam do problema odma na početku programa.
Evo programa:
#define XTAL_FREQ 4MHZ
#include <htc.h>
#include<math.h>
#include<pic.h>
_CONFIG( WDTDIS & PWRTDIS & BORDIS & LVPDIS & PWRTEN & DEBUGDIS & UNPROTECT);
#define BITNUM(adr, bit) ((unsigned)(&adr)*8+(bit)) /* used for port defs*/
volatile int m1;
static bit motor_nap @ BITNUM(PORTD,4);
static bit motor_nat @ BITNUM(PORTD,5);
static bit paljenje @ BITNUM(PORTD,6);
void main()
{
/**** Set up Ports ****/
TRISA=0B000000;
TRISB=0B11111101;
PORTC=0B00000000;
TRISD=0B00000000;
TRISE=0B000;
/**** Initialise Variables ****/
SSPSTAT = 0B00000000;
T1CON = 0b00000001;
/**** Set Up Interrupts ****/
INTCON=0x00; /* Disable All Interrupts and clear flags */
GIE = 1;
INTE = 1 ; /* Enable Ext Interrupt */
PEIE = 1; /* Enable peripheral int*/
RBIE = 1;
RBPU = 0; // pull-up
TMR1IE = 1; /*Enable Timer1 interrupt*/
TMR1IF = 0;
/************* Main Program Loop **************/
PORTD=0;
paljenje=1;
motor_nap=0;
motor_nat=0;
while(1){
while(m1<5){
motor_nap=1;
motor_nat=0;
}
while(m1>5 && m1<10){
motor_nap=0;
motor_nat=1;
}
}
}
interrupt isr(){
if (INTF ){
INTF=0;
m1=m1++;
}
}
Problem je u tome da kad se dogodi interrupt i m1 promjeni vrijednost, while petlja ne "registrira" to.
Ovaj program sam napisao iz toga što sam uspio sam naučiti preko interneta i raznih primjera, i u svemu tome sam početnik.
Unaprijed zahvaljujem!
Čisto par ideja:
1. Da li ti se uopste odradjuje ISR (Interrupt Service Routine)? Odkuda znaš da se m1 uopste mijenja?
2. Ako ti se odradjuje ISR, na koji način MAIN NE prepoznaje? Jeli stalno drži kao da je m1<5 ili nešto drugo?
3. Zar ne bi trebao negdje vratiti ovaj m1 da bude između 0 i 10 kada npr pređe 10?
1.ISR se odrađuje, probao sam dodati par if petlji u interrupt funkciju, da se mijenjaju određeni pinovi na PICu s obzirom na vrijednost m1. i simulirao u proteusu.
2. Da stalno drži kao da je m1<5.
3. To je samo početak programa, pokušavam napraviti dio po dio ali sam naisao na problem pa nisam isao dalje dok to ne rijesim.
Ne radim odavno sa tim kompajlerom ali znam da je dolazilo nekoliko primjera sa njim, tako i primjer kako se odrajuju prekidi.
Ukratko kompajler ima funkciju koju treba da pozoves koja je izvan tvoje while(1) petlje, tu onda napises kod koji ispituje do kojeg interapta je doslo (zaostala pic16 arhitektura) , izvrsis neki vrlo kratki kod a takodje i brises flagove jer kompajler to ne radi sam. Vrlo je vazno da vrijeme koje mikrokontroler izgubi na izvrsenje koda u prekidu bude krace od vremena kada ce se dogoditi sljedeci prekid , recimo kod tajmera a i kod ostalih sve zavisi sta okida prekid.
Sada sam pogledao kod i sve mi se cini ok. Kako ti je m1 globalna promjenjiva trebalo bi da se poveca , kazes da se poveca, onda ti kod u while petlji nije dobar ili taj simulator ne radi kako treba:).
PS. sada vidio kodu while i mogu reci da to nista ne valja, napisi kod tako da u while petlji nemas ni jednu while petlju i radice to kako treba ako se prekid ukljucuje kako kazes:)
Takodje m1 ti se u prekidu povecava dok je manja od zadane vrijednosti radi jedno kada dodje do 10 radi drugo a m1 se povecava i nikad ju ne resetira , sta onda cekas ljetnje dopodne da dodje opet do 10 ili
U svakom programu bi trebalo da se program izvrsava kao da je na traci da se ne zaustavlja ,a ne da ga zaglavis while i cekas nesto a ostalo ti stoji osim razumje se glavne petlje.
Pocni tako da razmisljas i prepravi taj kod da umjesto while upotrijebis if , uf dosta sam mljeo.
m1 moras da inicijalizujes jer kompajler cita sta je na toj memorijskoj lokaciji a moze teoretski da bude svasta, znaci m1=0;
takodje m1 stavis da bude unsigned char m1; nije ti potreban toliko broj kada brojis samo do 10 a i koristis samo vrijednosti vece od 0 , jer int ide i ispod nule i na to moras da pazis:)
Hvala vam na odgovorima!
Probao sam i sa if petljama i for petljama ali ne radi, varijablu m1 sam inicijalizirao -m1=0, isto ništa.
Program sam radio prema primjerima koji dolaze sa hi techom.
Možda bih trebao probati u drugom simulatoru. Ima koji da dobro radi?
Jos jednu stvar mozda trebas provjeriti. Cini mi se da f877 dijeli interapt pin sa nekim analognim ulazom.
Kako je setovan taj pin? Mozda u switchevima trebas setovati (kod programiranja uC) da ti je ovaj pin I/O port a ne analogni. Sjecam se da je mene to jedom zezalo duze vremena!
#define XTAL_FREQ 4MHZ
#include <htc.h>
// zelis da PWRT bude onemogucen ili omogucen, Nije neka greska ali makni jedno
_CONFIG( WDTDIS & PWRTDIS & BORDIS & LVPDIS & PWRTEN & DEBUGDIS & UNPROTECT);
#define BITNUM(adr, bit) ((unsigned)(&adr)*8+(bit)) /* used for port defs*/
// dal zaista koristis tako velike brojeve ? PIC je 8bitni i najbrzi je ako koristis 8bitne varijable:
// signed char (vrijednosti od -128 do 127), unsigned char (od 0 do 255)
volatile unsigned char m1;
// m1 je globalna i trebala bi biti automatski inicijalizirana na 0, provjeri joj vrijednost po ulasku u main(), ak0 je razlicito od 0 inicijaliziraj ju.
static bit motor_nap @ BITNUM(PORTD,4);
// Zasto ne #define motor_nap RD4 (ili PORTDbits.RD4 ovisno kak je vec pin >>vec<< definiran)
static bit motor_nat @ BITNUM(PORTD,5);
// Zasto ne #define motor_nat RD5 (ili PORTDbits.RD5 ovisno kak je vec pin >>vec<< definiran)
static bit paljenje @ BITNUM(PORTD,6);
// Zasto ne #define motor_nat RD5 (ili PORTDbits.RD5 ovisno kak je vec pin >>vec<< definiran)
void main()
{
/**** Set up Ports ****/
TRISA=0B000000;
TRISB=0B11111101;
PORTC=0B00000000;
TRISD=0B00000000;
TRISE=0B000;
/**** Initialise Variables ****/
SSPSTAT = 0B00000000;
T1CON = 0b00000001;
/**** Set Up Interrupts ****/
INTCON=0x00; /* Disable All Interrupts and clear flags */
INTE = 1 ; /* Enable Ext Interrupt */
PEIE = 1; /* Enable peripheral int*/
RBIE = 1;
RBPU = 0; // pull-up
TMR1IE = 1; /*Enable Timer1 interrupt*/
TMR1IF = 0;
GIE = 1;
/************* Main Program Loop **************/
PORTD=0;
paljenje=1;
motor_nap=0;
motor_nat=0;
while(1){
if(m1<5){
motor_nap=1;
motor_nat=0;
continue;
}
if(m1<10){
motor_nap=0;
motor_nat=1;
continue;
}
// reset m1 ?
m1 = 0;
}
}
// imas omogucene sljedece interrupt-e: INTE, RBIE te TMR1IE, a po ulasku u isr obradjujes samo "external interrupt".
// To ti je i namjera ili? Znaci m1 ce se uvecati samo kada dobijes "okidni brid" na RB0, za Timer1 overflow i promjenu na RB4-RB7 ne.
void interrupt isr(){
if (INTF ){
INTF=0;
//m1=m1++; _ebi ga: m1 ce se pridruziti m1, a zatim ce se m1 povecti za jedan. Vjerujem da je m1++; dovoljno
m1++;
}
}
Inace doticni kompajler ukoliko radi u PRO modu (bar je tako bilo prije, negdje verzija 9,6 - 9,7) ima neki cudni princip optimizacije i dogodilo mi se da bas zbog toga program ne radi kako treba. Probaj kompajlirati u standard modu.
Budem probao u standard modu, probao sam u lite modu, ali isto se dogadjalo, znam da su uključeni prekidi za t1 i RB4-RB7, to mi treba za ostatak programa.
Jučer sam probao rijesiti program bez prekidi i dobro radi, pa ću najvjerojatnije izbaciti prekide .
I samo još jedno pitanje:
Koja je razlika između ovoga koda:
while(1)
{
if(m1<5) {
// radi nesto
continue; // c1
}
// dok je m1 < 5 sve ispod se nece izvrsavati;
// c1 vraca na pocetak petlje (sljedeca iteracija)
if(m1<10) {
// radi nesto
continue; // c2
}
// dok je m1 < 10 sve ispod se nece izvrsavati;
// c2 vraca na pocetak petlje (sljedeca iteracija)
m1 = 0;
}
Port A se moze koristiti kao analogni ulaz, tako da to nema veze s portom B,
aha,ovo za continue sad kuzim, hvala na objasnjenju.
Ja bih pretpostavio da mi je problem sa simulatorom, jer niti primjer koji dolazi sa hi techom ne radi kako bi trebao. Postoji još koji nacin za simulirati rad PICa ili samo testna pločica?
Koje vi kompajlere koristite?
Deevil wrote:Port A se moze koristiti kao analogni ulaz, tako da to nema veze s portom B,
aha,ovo za continue sad kuzim, hvala na objasnjenju.
Ja bih pretpostavio da mi je problem sa simulatorom, jer niti primjer koji dolazi sa hi techom ne radi kako bi trebao. Postoji još koji nacin za simulirati rad PICa ili samo testna pločica?
Koje vi kompajlere koristite?
Ja skinuo taj kompajler i isprobao tvoj primjer koji si dao na pocetku u MPLAB simulatoru.
Prvo , imas neke sitnije greske u kodu , drugo vaznije NISI UKLJUCIO TAJMER i zato ti program ne radi niti se m1 povecava.
Skini PDF od 877 i tamo nadji kako se ukljucuje tajmer i onda prepravi taj kod i radice.
Setovao si tajmer a cekas na RB0 da se dogodi interapt, to ti je isto kao da si rekao nekom da te ceka u x ulici u cetvrtak a ti se pojavis u petak u y ulici i kazes "nije mi jasno kako se nije pojavio".
Ustvari nisi ni rekao koji si interapt setovao i sta uopste ocekujes da program radi:)
Samo da kazem kad ispravis u interapt funkciji testiranje tajmera1 koji si setovao program ispravno radi i m1 se povecava. Nadji u pdf fajlu kako se zove flag za tajmer jedan i stavi ga umjesto RBO flaga i radice ti program.
Mislim da smo se krivo razumijeli, meni treba da se m1 poveča kad se dogodi interrupt na RB0 a ne na TMR1...
Ipak je bio problem u simulatoru, sad sam konacno uspio pokrenuti simulator MPLAB SIM i program radi dobro, samo moram promjeniti greske koje ste mi napomenuli. Zahvaljujem vam na trudu!
Deevil wrote:Mislim da smo se krivo razumijeli, meni treba da se m1 poveča kad se dogodi interrupt na RB0 a ne na TMR1...
Ipak je bio problem u simulatoru, sad sam konacno uspio pokrenuti simulator MPLAB SIM i program radi dobro, samo moram promjeniti greske koje ste mi napomenuli. Zahvaljujem vam na trudu!
To kazes poslije 10 poruka, i to je vec napredak:)
Setovao si interapte za tajmer1 ,RB0 i promjene stanja na RB4 do RB7 a nisi to odradio u interapt funkciji, imaces problema zbog toga jer kod prekida promjena stanja na RB4 -RB7 pic ce ti pozivati non stop prekid a ti ne brises flag tog prekida niti ga obradjujes.