the_maniac

Üye
Katılım
25 Nis 2009
Mesajlar
48
Puanları
1
Selam arkadaşlar,

Ben 16F877 kullanıyorum ve kodumu microcde yazıyorum. Kodumda PORTB.F6'ya bağlanmış bir butonum var(latching buton yani momentary(anlık) değil) ve sırf butona bastığımda interrupt gelsin ve PORTD.F1'deki ledimi toggle etsin istiyorum. Fakat ledim yanmıyor yani interrupta girmiyor. Koddaki hatanın ayarlarla ilgili bir sorun olduğunu düşünüyorum. Yardımcı olabilirseniz çooooooook sevinirim :)

Kod aşağıdaki gibi:
Kod:
void main()
{
  //*************************TIMER AYARLARI**************************//

 TRISA=0x00;
 TRISB=0xFF;     
 TRISC=0xFF;    
 TRISD=0x00;
 TRISE=0x00;

 PORTA=0x00;
 PORTB=0x00;
 PORTC=0x00;
 PORTD=0x00;
 PORTE=0x00;
T1CON.TMR1CS=0; //TMR1CS: Timer1 Clock Source Select bit,0 = Internal clock (FOSC/4)
 // T1CON.F2=0;   //This bit is ignored. Timer1 uses the internal clock
 T1CON.T1CKPS1=1; //Prescale bits 1:8 olarak ayarlandı
 T1CON.T1CKPS0=1; //Prescale bits
 T1CON.T1OSCEN=0;//Timer1 Oscillator Enable Control bit
                 //1 = Oscillator is enabled
                 //0 = Oscillator is shut-off (the oscillator inverter is turned off to eliminate power drain)
 PIR1.TMR1IF=0; //TMR1IF: Timer1 Overflow Interrupt Flag bit,0 = Timer1 has not overflowed
 TMR1H=0x00;
 TMR1L=0x00;
PIE1.TMR1IE=1; //TMR1IE: Timer1 Overflow Interrupt Enable bit,1 = Enables the Timer1 overflow interrupt

 INTCON.GIE=1;  //GIE: Global Interrupt Enable bit, Enables all unmasked interrupts
 INTCON.PEIE=1; //Peripheral Interrupt Enable bit, 1 = Enables all unmasked peripheral interrupts
 INTCON.RBIE=1; //RB Port Change Interrupt Enable bit, 1 = Enables the RB port change interrupt
 INTCON.RBIF=0; //RBIF: RB Port Change Interrupt Flag bit
CCP1CON.CCP1M3=0;  //Capture/Compare/PWM off
 CCP1CON.CCP1M2=0;
 CCP1CON.CCP1M1=0;
 CCP1CON.CCP1M0=0;

Bu kısım interrupt ayarlarının olduğu kısım. İnterrupt alt yordamının içi de şöyle :

Kod:
void interrupt()      
{
 if (PIR1.TMR1IF==1) {
    flag=1;
    PIR1.TMR1IF=0;    //0 = Timer1 has not overflowed, Interrupt flag is cleared.
    if (BK=='B')
    {
     PORTD.F6=0;
     if (a==10){
        PORTD.F7=1;
     }
     else if(HL=='H'){
                HL='L';x=b;PORTD.F7=0;
     }
     else {
          HL='H';x=a;PORTD.F7=1;
     }
    }
    else if (BK=='K'){
         PORTD.F7=0;
         if (a==10){
            PORTD.F6=1;
         }
         else if(HL=='H'){
                HL='L';x=b;PORTD.F6=0;
         }
         else {
              HL='H';x=a;PORTD.F6=1;
         }
    }
    else {
         PORTD.F7=0;
         PORTD.F6=0;
    }
 }
 else if (PORTB.F7==1)
 {
  INTCON.RBIE=0; //RB Port Change Interrupt Enable bit, 1 = Enables the RB port change interrupt
  //INTCON.GIE=0;  //GIE: Global Interrupt Enable bit, Enables all unmasked interrupts
  PORTD.F7=0;
  PORTD.F6=1;
  //PORTD.F1=~PORTD.F1;
  if (emergency_flag==0){
     emergency_flag=1;
  }
  okuma_b=PORTB;
  INTCON.RBIF=0;
  //PORTD.F5=1;
  //INTCON.GIE=1;  //GIE: Global Interrupt Enable bit, Enables all unmasked interrupts
  INTCON.RBIE=1; //RB Port Change Interrupt Enable bit, 1 = Enables the RB port change interrupt
 }
 else if (PORTB.F7==0)
 {
  INTCON.RBIE=0; //RB Port Change Interrupt Enable bit, 1 = Enables the RB port change interrupt
  PORTD.F7=0;
  PORTD.F6=0;
  //PORTD.F5=~PORTD.F5;
  if (emergency_flag_low==0){
     emergency_flag_low=1;
  }
  okuma_b=PORTB;
  INTCON.RBIF=0;
  INTCON.RBIE=1; //RB Port Change Interrupt Enable bit, 1 = Enables the RB port change interrupt
 }
 //else if (PORTB.F6==1 || PORTB.F5==1)
 else if (INTCON.RBIF==1)
 {
  PORTD.F1=~PORTD.F1;
  okuma_b=PORTB;
  INTCON.RBIF=0;
  INTCON.RBIE=1; //RB Port Change Interrupt Enable bit, 1 = Enables the RB port change interrupt
}

Şimdiden ilgilenen herkese tekrar teşekkürler :)
 
Kodun tamamını okumadım ama timer interruptını butondan gelecek interrupt için kullanmış gibi görünüyorsun. (yanlış anladıysam kusura bakma). Bu arada anlık olmayan buton ne tam bilmiyorum dediğim gibi yanlış anlamadıysam :D

RB4..RB7 butonlarına bastığında kesmeye girmesini istioyorsun.

ozaman

RBIE=1; //RB4..RB7 kesme izinleri set edilir
RBIF=0; // RB4..RB7 kesme bayrağı temizlenir
GIE=1; // Genel kesmeler set edilir.

ile interrupt izinlerini vereceksin.

static void interrupt kesmeadı(){
if (RBIF=1){ // RB4..RB7 kesmesi oluşursa
GIE=0 // Genel kesme izinleri kaldır (kesmede iken tekrar kesme oluşmasın diye)
if(RB6=1){ // RB6 ya bağlı butona basıldıysa
.....
......
RBIF=0; // RB4..RB7 kesme bayrağını tekrar temizle
}
GIE=1; // Genel kesmelere tekrar izin verir
}


hi-tech compiler için C ile yazdım. senin kod biraz farklı galiba ama anlayabilirsin galiba bunuda
 
Son düzenleme:
Anladım :) Çok teşekkür ederim :) ayarlarımda bir sorun olduğunu görüp düzelttim problemi :)
 
Kod:
RBIE=1;      //RB4..RB7 kesme izinleri set edilir
RBIF=0;      // RB4..RB7 kesme bayrağı temizlenir
GIE=1;        // Genel kesmeler set edilir.

ile interrupt izinlerini vereceksin.

static void interrupt kesmeadı(){
if (RBIF=1){                   // RB4..RB7 kesmesi oluşursa
         GIE=0                  // Genel kesme izinleri kaldır (kesmede iken tekrar kesme oluşmasın diye)
         if(RB6=1){            // RB6 ya bağlı butona basıldıysa 
         .....                         
         ......
         RBIF=0;                // RB4..RB7 kesme bayrağını tekrar temizle  
         }
         GIE=1;                   // Genel kesmelere tekrar izin verir
}


Kod:
RBIF=0;      // RB4..RB7 kesme bayrağı temizlenir
RBIE=1;      //RB4..RB7 kesme izinleri set edilir
GIE=1;        // Genel kesmeler set edilir.
önce flag temizlenir sonra interruptı enable edilir. Dahili veya harici pullup dirençler nedeniyle hatalı kesme oluşmaması için.

Kod:
Yanlış.         if(RB6=1){            // RB6 ya bağlı butona basıldıysa 
Doğrusu      if(RB6==1){            // RB6 ya bağlı butona basıldıysa

Kod:
static void interrupt kesmeadı(){...}
Gereksiz GIE=0;... ;GIE=1;

ISR içerisinde portb okutulmuş ise RBIF otomatik olarak sıfırlanır. Port okuma (pin değil) işlemi yapılmış ise aşağıdaki kod gereksizdir.
RBIF=0; // RB4..RB7 kesme bayrağını tekrar temizle
 
Hepinize verdiğiniz bilgiler için çok teşekkürler :) Artık ayarlar konusunda kesmelerde problem yaşamayacağımı umuyorum :)
 
Kod:
static void interrupt kesmeadı(){...}
Gereksiz GIE=0;... ;GIE=1;

ISR içerisinde portb okutulmuş ise RBIF otomatik olarak sıfırlanır. Port okuma (pin değil) işlemi yapılmış ise aşağıdaki kod gereksizdir.
RBIF=0; // RB4..RB7 kesme bayrağını tekrar temizle

genel kesme izinlerini disable etmezsek kesme sırasında başka bir kaynaktan kesme gelebilir. o yüzden kesme fonksiyonuna GIE=0;... GIE=1; ekledim. Bunun neden yanlış olduğunu öğrenebilir miyim?

ayrıca ISR içerisinde PORTB okutmak ne demektir?
 
genel kesme izinlerini disable etmezsek kesme sırasında başka bir kaynaktan kesme gelebilir. o yüzden kesme fonksiyonuna GIE=0;... GIE=1; ekledim. Bunun neden yanlış olduğunu öğrenebilir miyim?
Size öyle yapmanız gerektiğini kim söyledi? kullandığınız mcu nun datasheetini en azından bir kere okuyun.

assembly komutlarını da öğrenin. yukarıdaki ile alakalı olarak retie komutu nedir öğrenip buraya yazarsanız kendi sorunuza kendiniz cevap vermiş olacaksınız.
 
Size öyle yapmanız gerektiğini kim söyledi? kullandığınız mcu nun datasheetini en azından bir kere okuyun.

assembly komutlarını da öğrenin. yukarıdaki ile alakalı olarak retie komutu nedir öğrenip buraya yazarsanız kendi sorunuza kendiniz cevap vermiş olacaksınız.

aslında assembly biliyorum. datasheetin de bana lazım olan yerlerini lazım oldukça okuyorum. retie? diye bir komuta hiçbir yerde rastlamadım (datasheet -google). ayrıca hala kesme sırasında başka kaynaktan kesme gelebileceğini düşünüyorum. bunun "yanlış ise" yanlış olduğunu açıklamanız yeterli olacaktır.

ve ISR in ne demek olduğunu da bulamadım.
 
aslında assembly biliyorum. datasheetin de bana lazım olan yerlerini lazım oldukça okuyorum. retie? diye bir komuta hiçbir yerde rastlamadım (datasheet -google). ayrıca hala kesme sırasında başka kaynaktan kesme gelebileceğini düşünüyorum. bunun "yanlış ise" yanlış olduğunu açıklamanız yeterli olacaktır.

ve ISR in ne demek olduğunu da bulamadım.
ISR interrupt service routine demektir.

komutu eksik yazmışım, o nedenle komuta ulaşamamışsınız. Sizin yerinize olsam öncelikle 35 adet komutun ne işe yaradığını baştan sona öğrenirdim. Maalesef ihtiyaç olan yere bakmanız, sizin aslında nelere ihtiyaç duyduğunuzu kaçırmanıza neden oluyor. Bu yazışmadaki konu çok önemli değil aslında ama önemli olduğu yerler de gelecektir.

PicMicro larda interrupta gidildiği anda GIE biti otomatik olarak donanım tarafından 0 yapılır. Dolayısıyla, kesme içerisindeyken çevre birimlerden interruptı etkin olanlardan bir aktifleme (yani kesme) geldiğinde tekrar kesmeye gidilmesini önler. kesme rutinleri (yani ISR) her zaman retfie komutu ile döner. Bu komut ana programa dönerken aynı zamanda GIE ın 1 olmasını sağlar (donanım halleder bunu). Keşke bunu kendiniz datasheetten okuyup öğrenseydiniz...
 
ben PIC16F877 ENTEGRESİ VE PCF8583(SAAT VE TARİH İÇİN ENTEGRE),LM35 ISI SENSÖRÜ İE TARİH SAAT VE SICAKLIĞI Lcd EKRANDA GÖSTERMEK İSTİYORUM..
BUNUNLA İLGİLİ BİR PROGRAMA SAHİBİM AMA BENİM PROGRAMIMDA SICAKLIĞI GAYET İYİ GÖSTERİYOR SICAKLIKTA SORUN YOK.. AMA TARİH VE SAAT SABİT BİR ŞEKİLDE KALIYOR İLERLEMİYOR
MESELA SAAAT 12:10:09 BİR TÜRLÜ 12:10:10 OLMUYOR SABİT KALIYOR BEN MİCROC PRO FOR PİC PROGRAMIYLA YAZILMIŞ BİR PROGRAM...
PROTEUSDA SİMULASYON YAPTIĞIM ZAMAN DEVAMLI SAAT KONUSUNDA SORUN YAŞIYORUM...BEN DEVREMDE KULLANDIĞIM MALZEMELERİ,PROTEUSDA ÇİZİLMİŞ DEVREMİ VE PROGRAMIMI
ATACAĞIM YARDIMCI OLURSANZ ÇOK SEVİNİRİM...BUNU YAPAMAZSAM DERSTEN KALACAĞIM
KULLANDIĞIM MALZEMELE: Materials: RS232 İLETİŞİM KABLOSU,PIC16F877 ENTEGRESİ,LCD 2*16 Ekran,LM35 SICAKLIK SENSÖRÜ,12 volt AC/DC Adaptor,ButtonLAR,
4 pieces 10k resistance,3 pieces 560 resistance,2 pieces 22 Pf capacitor,
5 PARÇA 1 mf KONDANSATÖR,2 PARÇA 100 mf KONDANSATÖR ,3 pARÇA 100 nf KONDANSATÖR,1 PARÇA 25 pf KONDANSATÖR,Max232 ENTERGRESİ,7805 ENTEGRESİ,
1 pARÇA 9 PİNLİ CONNECTOR,1 PARÇA KRYSTAL KONDANSATÖR 25-40 MHZ ARASI,1 PARÇA PERTİNAX,
10K LIK POTANSİYOMETRE(POTANSİYOMETRE İLE 2 MİLİSANİYELİK GECİKTİRME YAPRAK 2 TANE LEDİMİN YANIP SÖNMESİNİ SAĞLIYORUM)


MİCROC PRO FOR PİC C KODUM:

#define uchar unsigned char
// LCD module connections
sbit LCD_RS at RD2_bit;
sbit LCD_EN at RD3_bit;
sbit LCD_D4 at RD4_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D7 at RD7_bit;

sbit LCD_RS_Direction at TRISD2_bit;
sbit LCD_EN_Direction at TRISD3_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;
// End LCD module connections
//output definitions
#define backlight PORTC.F0
#define sistemled portb.f1
#define outled portc.f2
//buttons definitions
#define btnEnter porte.f2
#define btnEsc porta.f2
#define btnUp porte.f0
#define btnDown porta.f4
#define btnLeft porta.f5
#define btnRight porte.f1
//
uchar seconds = 0;
uchar minutes = 0;
uchar hours = 0;
uchar day = 0;
uchar month = 0;
uchar year = 0;

uchar gorev=0;
// fonksiyon prototipleri
void initial();
void Read_Time();
void Transform_Time();
void Display_Time();
void clockprogramming();
void timetask();
void temperaturetask();
void menufunc();
void sicaklikoku(unsigned char kanal,unsigned char* dizi);
//fonksiyon prototipleri sonu

void main() {
initial();
while(1){
switch (gorev){
case 1: timetask();break;
case 2: temperaturetask();Delay_Ms(250);break;
//case 3: break;
default: ;
}
if(!btnEnter) menufunc();



} // main while

} // void main

void initial(){

PORTA=0;
TRISA=0xff;
ADCON0=0xa0; // Configure AN pins porta.f0,f1 analog;porta.f3 analog; diğerleri dijital
ADCON1=0x85; //
PORTB = 0;
TRISB = 0;
PORTC=0;
TRISC=0X80;
PORTD=0;
TRISD=0;
PORTE=0;
TRISE=7;
I2C1_Init(100000); // initialize I2C communication
UART1_Init(9600); // Initialize UART module at 9600 bps
Lcd_Init(); // Initialize LCD
Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off
backlight=1;
Lcd_Out(1,1,"merhaba");
sistemled=1;
outled=1;
clockprogramming();
OPTION_REG=0;
INTCON=0X90;
}
//--------------------- Reads time and date information from RTC (PCF8583)
void interrupt(){
if(intcon.intf){
intcon.intf=0;
gorev=1;
sistemled=~sistemled;
/*
Read_Time();
Transform_Time();
Display_Time();
*/
}


}// interrupt
/////////////////////////////
void menufunc(){
gorev=2;
Lcd_Out(1,3,"TEMPERATURE");

}
////////////////////////////
void Read_Time() {

I2C1_Start(); // Issue start signal
I2C1_Wr(0xA0); // Address PCF8583, see PCF8583 datasheet
I2C1_Wr(2); // Start from address 2
I2C1_Start(); // Issue repeated start signal
I2C1_Wr(0xA1); // Address PCF8583 for reading R/W=1

seconds = I2C1_Rd(1); // Read seconds byte
minutes = I2C1_Rd(1); // Read minutes byte
hours = I2C1_Rd(1); // Read hours byte
day = I2C1_Rd(1); // Read year/day byte
month = I2C1_Rd(0); // Read weekday/month byte
I2C1_Stop(); // Issue stop signal

}

//-------------------- Formats date and time
void Transform_Time() {
seconds = ((seconds & 0xF0) >> 4)*10 + (seconds & 0x0F); // Transform seconds
minutes = ((minutes & 0xF0) >> 4)*10 + (minutes & 0x0F); // Transform months
hours = ((hours & 0xF0) >> 4)*10 + (hours & 0x0F); // Transform hours
year = (day & 0xC0) >> 6; // Transform year
day = ((day & 0x30) >> 4)*10 + (day & 0x0F); // Transform day
month = ((month & 0x10) >> 4)*10 + (month & 0x0F); // Transform month
}

//-------------------- Output values to LCD
void Display_Time() {

Lcd_Chr(1, 6, (day / 10) + 48); // Print tens digit of day variable
Lcd_Chr(1, 7, (day % 10) + 48); // Print oness digit of day variable
Lcd_Chr(1, 9, (month / 10) + 48);
Lcd_Chr(1,10, (month % 10) + 48);
Lcd_Chr(1,15, year + 56); // Print year vaiable + 8 (start from year 2008)

Lcd_Chr(2, 6, (hours / 10) + 48);
Lcd_Chr(2, 7, (hours % 10) + 48);
Lcd_Chr(2, 9, (minutes / 10) + 48);
Lcd_Chr(2,10, (minutes % 10) + 48);
Lcd_Chr(2,12, (seconds / 10) + 48);
Lcd_Chr(2,13, (seconds % 10) + 48);
}
/////////////////////////////////////////
void clockprogramming(){

I2C1_Start(); // Issue start signal
I2C1_Wr(0xA0); // Address PCF8583, see PCF8583 datasheet
I2C1_Wr(0); // Start from address 0 (configuration memory location)
I2C1_Wr(0x80); // Write 0x80 to configuration memory location (pause counter...)
I2C1_Wr(0); // Write 0 to cents memory location
I2C1_Wr(0); // Write 0 to seconds memory location
I2C1_Wr(0x30); // Write 0x30 to minutes memory location
I2C1_Wr(0x12); // Write 0x12 to hours memory location
I2C1_Wr(0x24); // Write 0x24 to year/date memory location
I2C1_Wr(0x08); // Write 0x08 to weekday/month memory location
I2C1_Stop(); // Issue stop signal

I2C1_Start(); // Issue start signal
I2C1_Wr(0xA0); // Address PCF8530
I2C1_Wr(0); // Start from address 0
I2C1_Wr(0); // Write 0 to configuration memory location (enable counting)
I2C1_Stop(); // Issue stop signal
} //
//////////

void menufunc(){
Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off
Lcd_Out(1,5,"MENU");
Lcd_Out(2,1,"1: Mod Sel");
}
void timetask(){
Read_Time();
Transform_Time();
Display_Time();
}
////////////////
float adimbuyuklugu=5/1023;
unsigned long temperature=0;
unsigned int sicaklik=0;
unsigned int isi=0;
unsigned char isidegeri[16];
unsigned char setdegeri[16];
unsigned int isideger=0;
unsigned int setdeger=0;
unsigned char offset=20;
//////////////
void temperaturetask(){
unsigned char temp=0;
isideger=setdeger=0;
sicaklikoku(0,isidegeri);
sicaklikoku(1,setdegeri);
if(outled==1)if(isideger<=(setdeger-(unsigned int)offset))outled=0;
if(outled==0) {if(isideger>=setdeger)outled=1;}

Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off
Lcd_Out(1,1,"Set : ");Lcd_Out_Cp(setdegeri);
Lcd_Out(2,1,"Temp: ");Lcd_Out_Cp(isidegeri);
}

void sicaklikoku(unsigned char kanal,unsigned char* dizi){
uchar i=0;
sicaklik=ADC_Read(kanal);
for(i=0;i<11;i++){
sicaklik += ADC_Read(kanal);
sicaklik=sicaklik/2;
}

if(kanal==0) {temperature = (long)sicaklik*1000;}
else if(kanal==1){ temperature = (long)sicaklik*100;}
temperature=(temperature/1023)*5;
sicaklik = (unsigned int)temperature;
if(kanal==0)isideger=sicaklik;else setdeger=sicaklik;
// sicaklik = 4999;
isi = sicaklik/1000;
if(isi==0) dizi[0]=32;else dizi[0]=48+isi;

isi = sicaklik-(isi*1000);
isi = isi/100;
if(isi==0){ if(dizi[0]==32)dizi[1]=32;else dizi[1]=48;}
else if(isi>0){dizi[1]=48+isi;}

sicaklik = sicaklik%100;
isi = sicaklik/10;
dizi[2]=48+isi;dizi[3]='.';

isi=sicaklik%10;
dizi[4]=48+isi;dizi[5]=0;

}//
//////////////////////


proteus devrem bu linkte

saat tarih sıcaklık - Windows Live
 

Forum istatistikleri

Konular
129,845
Mesajlar
930,720
Kullanıcılar
452,698
Son üye
uguraydemir

Yeni konular

Geri
Üst