RB portu değişim kesmesinde sıkıntı

Başlatan seyityildirim, 24 Ocak 2016, 23:54:57

seyityildirim

Merhaba arkadaşlar..
XC8 de RB portu kesmesini denemek istedim. Kodlar şöyle
#include <xc.h>



// CONFIG
#pragma config FOSC = XT        // Oscillator Selection bits (XT oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

#define _XTAL_FREQ 4000000 
#define _delay_us(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000000.0)))
#define _delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))


void interrupt portb_kesme()
{
    if(INTCONbits.RBIF==1)
    {
            INTCONbits.RBIF=0;
            PORTA=0x02;
            _delay_ms(100);
            PORTA=0x00;
            _delay_ms(100);
    }
    
}

void main(void) {
    TRISA=0x00;             // a portu cikis olarak ayarlandi.
    TRISB=0xFF;             // b portu giris olarak ayarlandi.
    PORTA=0x00;             // 
    INTCONbits.GIE=1;       // genel kesme açildi
    INTCONbits.PEIE=1;      // cevresel kesme acildi
    INTCONbits.RBIE=1;      // PortB degisimindeki kesme acildi
    INTCONbits.RBIF=0;
    while(1);               // sonsuz döngü
    
    
    return;
    
}


sıkıntı şu: isis de RB portunda bir değişiklik yaptığımda A portu 100 ms aralıkla 0x02 ve 0x00 olup bitmesi gerekirken bu döngü sonsuz şekilde devam ediyor. yani sürekli yanıp sönüyor. ben ise sadece 1 kez yapmak istiyorum. sıkıntı nerde olabilir?
Şimdiden teşekkür ederim

dursuncemal

#1
main icindeki return  olmaz

mesaj birleştirme:: 25 Ocak 2016, 14:30:31

semani da atabilirmisin
:=

seyityildirim

return komutunu kaldırdım yine değişmedi zaten. while(1) sonsuz döngüsü olduğu için return komutunu görmüyordu bile. buda şematik pull-up larla falan uğraşmayayım diye logicstate kullandım


vitruvius

Sorunun datasheet'te yazıyor.

Datasheet: https://cdn.sparkfun.com/datasheets/Components/General%20IC/PIC16F877A.pdf
Sayfa: 44

Alıntı YapFour of the PORTB pins, RB7:RB4, have an interrupton-change feature. Only pins configured as inputs can cause this interrupt to occur (i.e., any RB7:RB4 pin configured as an output is excluded from the interrupton-change comparison). The input pins (of RB7:RB4) are compared with the old value latched on the last read of PORTB. The "mismatch" outputs of RB7:RB4 are OR'ed together to generate the RB port change interrupt with flag bit RBIF (INTCON<0>).

This interrupt can wake the device from Sleep. The user, in the Interrupt Service Routine, can clear the interrupt in the following manner:

a) Any read or write of PORTB. This will end the mismatch condition.
b) Clear flag bit RBIF.


A mismatch condition will continue to set flag bit RBIF. Reading PORTB will end the mismatch condition and allow flag bit RBIF to be cleared.

Sorununun kaynağı da çözümü de datasheet'te işaretlediğim yerlerde mevcut. Özetle PORTB kesmesi, pinlerin o anki durumu ile bir önceki okunuşundaki durumlarını karşılaştırarak çalışır.

Eğer kesmeyi uygun şekilde temizlemezsen, RBIF bayrağı her zaman "set" edilecektir. Bu da kesme fonksiyonunun sonsuz döngüde çalışmasına sebep olacaktır.

Kesmeyi uygun bir şekilde temizlemek için gerekli talimatları da vermiş. Önce PORTB'nin durumunu formaliteden okumalısın. Sonra kesme bayrağını temizlemelisin.

void interrupt portb_kesme()
{
    int temp = 0x00;
    
    if(INTCONbits.RBIF==1)
    {
            PORTA=0x02;
            _delay_ms(100);
            PORTA=0x00;
            _delay_ms(100);
            temp = PORTB;
            INTCONbits.RBIF=0;
    }    
}


Kolay gelsin.

dursuncemal

pardon ozur ben interruptun icindeki isleme bakıp  detayi kacirmisim ext int e gitti kafam.    port b yi okumalisin cunku interruptun hangi pinden geldiginide bilmen gerek.yoksa portb 4 / 7 change int kullanmanın anlami olmaz.
:=

seyityildirim

@vitruvius hocam anladım teşekkür ederim sorunum çözüldü.