18f877 KESME SORUNU! ACİL!

Başlatan hacimusatr, 04 Kasım 2013, 20:59:11

hacimusatr

Arkadaşlar öcelikle herkese selamlar.
Bir proje üzerinde çalışmaktayım. Fakat benim bir sorunum var. Hi-Tech C biliyorum. Programımıda Hi-Tech de yazdım. Fakat nedendir bilmiyorum ve gezmediğim site araştırmadığım başlık karıştırmadığım kitap kalmamasına rağmen sorunumu çözemedim.
Öncelikle projem hakkında bilgi vereyim. Projem Seri porttan gönderilen veriyi bir adet 16f628a ile işleyip rf aracılığı ile 16f877a ya ileterek işlem yapmayı sağlamak. 16f628a seri porttan gelen veriyi yaptığım testler sonucu okuyup anlayabiliyor. Yani if döngüsü içerisine gelen veri 1 ise led yak dediğim zaman ve seri porttan 1 gönderdiğim zaman ledi yakıyor. 2 gönderiyorum led yanmıyor. 16f628a ile birlikte uyumlu anlaşarak çalışıyoruz fakat 877 inatçı. Veri gönderdiğim zaman kesmeye girmiyor.
RF alıcı verici arası bir problem mi var diyerek kablo çekip rx ucuna verdim. Fakat sonuç yine hüsran. Kesme olayı 16f628a ile aynı kodlara sahipken 877 de işe yaramıyor. Program while döngüsü içerisinde sonsuzluğa girip kesme bekliyor. Buyrun bunlarda kodlar.

#include <pic.h>
#include <htc.h>
#include "delay.h"
#include "uart.h"
#include "lcd.h"
#define    MENU    RB4
#define    OK         RB5
#define    BTN2     RB6
#define    BTN1     RB7
char TEMP;
void main()
{
    TRISC=0x80;
    TRISB=0xF0;
    PORTC=0x00;
    PORTB=0x00;
    RCIE=1;
    RCIF=0;
    GIE=1;
    PEIE=1;
    while(1)
    {
        if(MENU)
        {
            PORTB=0x02;
        }
        if(OK)
        {
            PORTB=0x04;
        }
        if(BTN2)
        {
            PORTB=0x08;
        }
        if(BTN1)
        {
            PORTB=0x07;
        }
    }
}

static void interrupt kesmeler()
{
    if(RCIF)
    {
        GIE=0;
        TEMP=RCREG;
        if(TEMP==1)
        {
            PORTB=0x01;
        }
    }
    RCIF=0;
    GIE=1;
}


Arkadaşlar gördüğünüz gibi 4 buton kullanmaktayım. LCD kütüphanesini ekledim çünkü LCD ekran da var. ancak kodlarını yazma gereği duymadım. Şimdi burada basitçe özetlersem sorunumu 628a ile aynı kodları kullanmaktayım ve 877 kesmeye girmiyor 628a kesmeye giriyor. Sizce sebebi ne olabilir. yaklaşık 5 gündür bunu araştırıyorum. Burada ana main programı içerisinde normalde RB4-RB7 kesmesi kullanıyordum fakat problem olunca kesmeden çıkarıp bir de böyle deneyeyim dedim. Fakat bu şekilde de olmadı. Nolur yardım edin bana

Edit:
Arkadaşlar şu anda 628a ile aynı yazılımları kullanıp deneme yapacağım. Sonuçları yine buraya yazacağım. 877A açılır açılmaz kesmeye giriyor bu arada. Sonra kesmeden çıkıyor ve ana programı işlemeye devam ediyor. Sonra da bir daha kesmeye girmiyor. Acaba diyorum RF Alıcının DATA ucunda sürekli bir voltaj var o yüzden mi girmiyor diyeceğim ama saçma olmaz mı o zaman. Neyse denememi yapayım sonucu yazacam

hacimusatr

Arkadaşlar kimse yardım etmiyor. Neden bilmiyorum ama sorunumu yaptığım denemeler sonucu hala çözemedim. Kafayı yemek üzereyim. Yeni 877 aldım problem hala aynı. Değişiklik yok

justice_for_all

Baslangicta Kesme bayraklarini temizlememissin ondandir sorunun.
Deneyip de başaramayanları değil, yalnızca denemeye bile kalkışmayanları yargıla.   Gökhan Arslanbay

ete

C den pek anlamam. Ancak usart kesmesinde önemli bir kriter var. Buda kesme bayrağı olan RCIF biti direk ulaşılabilir bir bit değildir. Dolayısıyla bu biti Rcif=0 diyerek silemezsin. Bu konudaki temel kural Rcreg registeri okunduğunda yada içeriği bir başka değişkene aktarıldığında otomatikman Rcif biti de sıfırlanır şeklindedir.
Bu biti sıfırlayamazsan program kesmeden kurtulmaz. Kesme kısmında temp=Rcreg şeklinde bir komutun var ama peşinde başka şeylerde var ve sanki program bu datıra ulaşamıyor. Bu konuya odaklansan iyi olur.
Ete
Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

hacimusatr

Alıntı yapılan: justice_for_all - 05 Kasım 2013, 18:03:32
Baslangicta Kesme bayraklarini temizlememissin ondandir sorunun.
Hocam kesme bayrakları nasıl temizlenir ne demek istediniz anlamadım. RCIF bayrağını başlangıçta bir değişkene mi atamalıyım. RCREG bufferini değişkene atayıp değişkenden çıkıldığını ledler ile test ettim. Ama RCREG boş mu onu bilemiyorum. Ayrıca neden 628a ile çalışıyor da bununla çalışmıyor aklım almıyor. Deli etti bu pic beni ya.

justice_for_all

kesmeye girmiyorsa bunu bir cok nedeni olabilir 628a programini aynen attiysan calismaz cunku entegre ayni degil.Baudlari farkli olabilir.bide data yalnis geliyor olabilir.yalnis hatirlamiyorsam error gibi bise olcakti RXSTA registerinde onu arastirmanizi oneririm.

Not:seri port alimi icin RX pini giris olarak ayarlanmalidir.
Deneyip de başaramayanları değil, yalnızca denemeye bile kalkışmayanları yargıla.   Gökhan Arslanbay

selimkoc

#6
Birde buraya bakarmısın.
http://elektrokod.wordpress.com/2013/10/07/pic16f628-mikrodenetleyicinde-rb0-kesmesi-interrupt/

kesme bayraklarının kullanılışıyla ilgili örnek var. Faydalı olur diye ümit ediyorum. Bayrağı temizlemek için registerin ilgili IF bayrağı sıfır yapılır. Ornek; PIR1.RCIF=0;

Bayrak "0" değilse kesmeye girmez.

Aslında siz RCIF=0; demekle bu işi yapmışsınız. Acaba register isminin tam yazılması mı gerekiyor?

ete

Yeniden söylüyorum usart kesme bayrağı olan RCIF Kullanıcı tarafından RCIF=0 komutu verilerek sıfırlanmaz. Bu bayrak ancak ve ancak RCREG Registerinin içi boşaltıldığı zaman işlemci tarafından sıfırlanır.
Dolayısıyla RCIF=0 diye komut verdiğiniz zaman derleyici itiraz etmez ancak komut yerine getirilemez.
Bir registerin içini boşaltmak demek onu bir başka değişkene aktarmak demektir. Yani TEMP=RCREG  yazarak registerin içini boşaltmış olur ve dolayısıyla RCIF bitinide sıfırlamış olursun.
Toparlarsak kesme açıldığında gerekirse TEMP=RCREG komut satırını vererek kesme bayrağını sıfırlaman gerekebilir. Daha sonra kesme içinde de benzer şekilde TEMP=RCREG komutunu vererek kesme bayrağı sıfırlanır ve sonra kesmeden çıkılır.
Ete
Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

hacimusatr

Alıntı yapılan: justice_for_all - 05 Kasım 2013, 22:36:06
kesmeye girmiyorsa bunu bir cok nedeni olabilir 628a programini aynen attiysan calismaz cunku entegre ayni değil.Baudlari farkli olabilir.bide data yalnis geliyor olabilir.yalnis hatirlamiyorsam error gibi bise olcakti RXSTA registerinde onu arastirmanizi oneririm.

Not:seri port alimi icin RX pini giris olarak ayarlanmalidir.

Hocam alım pinleri TRISC6=1; ve TRISC7=1; olarak uart.h dosyasında tanımlanmaktadır. İkisinide neden giriş tanımlıyoruz bunu da anlamış değilim zaten ama bir çok sitede yaptığım araştırmalarda herkes giriş yapıyor.
İkincisi 628a programını aynen attıysam neden çalışmasın. Sadece port atamaları ile tüm pic programları Hi-Tech de yazılmış ise aynı işleri yapabilir. Sadece Port yetersizliği ve Port atamaları problem çıkarır. Onun haricinde Hi-Tech de yazılmış bir program 12 serisinde de 16 serisinde de çalışır. 18 in derleyicisi ayrı ama import etmek hiç zor değildir.

hacimusatr

Alıntı yapılan: ete - 06 Kasım 2013, 07:13:00
Yeniden söylüyorum usart kesme bayrağı olan RCIF Kullanıcı tarafından RCIF=0 komutu verilerek sıfırlanmaz. Bu bayrak ancak ve ancak RCREG Registerinin içi boşaltıldığı zaman işlemci tarafından sıfırlanır.
Dolayısıyla RCIF=0 diye komut verdiğiniz zaman derleyici itiraz etmez ancak komut yerine getirilemez.
Bir registerin içini boşaltmak demek onu bir başka değişkene aktarmak demektir. Yani TEMP=RCREG  yazarak registerin içini boşaltmış olur ve dolayısıyla RCIF bitinide sıfırlamış olursun.
Toparlarsak kesme açıldığında gerekirse TEMP=RCREG komut satırını vererek kesme bayrağını sıfırlaman gerekebilir. Daha sonra kesme içinde de benzer şekilde TEMP=RCREG komutunu vererek kesme bayrağı sıfırlanır ve sonra kesmeden çıkılır.
Ete

Hocam dediğinizi hemen deneyeceğim. Başlangıçta RCREG bayrağı boş ise program çakılıp kalır diye tedirgin oluyorum sonucu size bildireceğim yine.

hacimusatr

#10
Hocam tam kodu vermek istiyorum. uart.h yi de vereyim belki hata ordadır. uart.h yi yabancı bir siteden aldım. Dediğim gibi 628a da çalışıyor.
buyrun bu uart.h
#define FOSC 4000000L
char UART_Init(const long int baudrate)
{
unsigned int x;
	x = (FOSC - baudrate*64)/(baudrate*64);
	if(x>255)
	{
		x = (FOSC - baudrate*16)/(baudrate*16);
		BRGH = 1;
	}
	if(x<256)
	{
	  SPBRG = x;
	  SYNC = 0;
	  SPEN = 1;
	  RX9 = 0;
      RC6 = 1;
      RC7 = 1;
      CREN = 1;
      TXEN = 1;
	  return 1;
	}
	return 0;
}

char UART_TX_Empty()
{
  return TRMT;
}

char UART_Data_Ready()
{
   return RCIF;
}
char UART_Read()
{
 
  while(!RCIF);
  return RCREG;
}

void UART_Read_Text(char *Output, unsigned int length)
{
	int i;
	for(int i=0;i<length;i++)
		Output[i] = UART_Read();
}

void UART_Write(char data)
{
  while(!TRMT);
  TXREG = data;
}

void UART_Write_Text(char *text)
{
  int i;
  for(i=0;text[i]!='\0';i++)
	  UART_Write(text[i]);
}


buda 877.c

#include <pic.h>
#include <htc.h>
#include "delay.h"
#include "lcd.h"
#include "uart.h"
#define		MENU 	RB4
#define		OK		RB5
#define		BTN2	RB6
#define		BTN1	RB7
#define		BUZZER	RB1
__CONFIG(XT & WDTDIS & PWRTEN & BORDIS & LVPDIS & DUNPROT & WRTEN& DEBUGDIS & UNPROTECT);

char TEMP; 
int karakter_sayisi=0;
int i=0;

void kesme_init()
{
	RCIE=1;
	PEIE=1;
	RCIF=0;
	GIE=1;
}
void main()
{
	TRISB=0xF0;
	PORTB=0x00;
	TRISA=0x00;
	PORTA=0x00;
	ADCON1=0x07;
	TRISD=0x00;
	PORTD=0x00;
	lcd_init();
	lcd_write("BY HMTR DIGITAL ");
	lcd_goto(2,1);
	lcd_write("   TECHNOLOGY   ");
	DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);
	lcd_clear();
	lcd_write(" QR KOD OKUYUCU ");
	lcd_goto(2,1);
	lcd_write("   YARDIMCISI   ");
	DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);
	lcd_clear();
	lcd_write("  HOSGELDINIZ   ");
	lcd_goto(2,1);
	lcd_write("CHZ BASLATILIYOR");
	DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);
	DelayMs(1000);
	kesme_init();
	lcd_clear();
	DelayMs(1000);DelayMs(1000);
	lcd_write("MENUYE GIRIS");
	lcd_goto(2,1);
	lcd_write("YAPILIYOR");
	DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);
	lcd_clear();
	lcd_write("1.TAKIP       >>");
	lcd_goto(2,1);
	lcd_write("2.GIRIS CIKIS >>");
	UART_Init(1200);
	TEMP=RCREG;
	while(1)
	{
		if(MENU)
		{
			if(i==0) // TEST VERİSİ GÖNDER
			{
				DelayMs(1000);
				if(MENU)
				{
					DelayMs(1000);
					if(MENU)
					{
						DelayMs(1000);
						if(MENU)
						{
							DelayMs(1000);
							if(MENU)
							{
								lcd_clear();
								lcd_write("TEST ICIN PC'YE");
								lcd_goto(2,1);
								lcd_write("BAKINIZ.");
								PORTB=0x0C;
								UART_Write('T');
								DelayMs(20);
								UART_Write('E');
								DelayMs(20);
								UART_Write('S');
								DelayMs(20);
								UART_Write('T');
								DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);
								lcd_clear();
								lcd_write("TEST VERISI");
								lcd_goto(2,1);
								lcd_write("GONDERILDI");
								DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);
								lcd_clear();
								lcd_write("1.TAKIP       >>");
								lcd_goto(2,1);
								lcd_write("2.GIRIS CIKIS >>");
								PORTB=0x00;
							}
						}
					}
				}
			}
			else if(i==1)
			{
				DelayMs(1000);
				PORTB=0x00;
				i=0;
				lcd_clear();
				lcd_write("1.TAKIP       >>");
				lcd_goto(2,1);
				lcd_write("2.GIRIS CIKIS >>");
			}
			else if(i==2)
			{
				PORTB=0x00;
				i=0;
				lcd_clear();
				lcd_write("1.TAKIP       >>");
				lcd_goto(2,1);
				lcd_write("2.GIRIS CIKIS >>");
			}
		}
		if(OK) // OK. BUTONU
		{
			if(i==0) // HİÇ BİR İŞLEVİ YOK
			{
			}
			else if(i==1)
			{
				lcd_clear();
				lcd_write(" PALET NUMARASI ");
				lcd_goto(2,1);
				PORTB=0x01;
			}
			else if(i==2)
			{
				lcd_clear();
				lcd_write(" PALET NUMARASI ");
				lcd_goto(2,1);
				PORTB=0x04;
			}
			else if(i==3)
			{
				lcd_clear();
				lcd_write("  PALET CIKISI  ");
				lcd_goto(2,1);
				lcd_write("  YAPILSIN MI?  ");
				
			}
		}
		if(BTN2) // 2. BUTON
		{
			DelayMs(200);
			if(BTN2)
			{
				if(i==0)
				{  //GİRİŞ ÇIKIŞ SİSTEMİ
					lcd_clear();
					lcd_write(" PALET NUMARASI ");
					lcd_goto(2,1);
					PORTB=0x04;
					i++;
					i++; // İ'Yİ 2 YAP
				}
				else if(i==1) // İŞLEVSİZ
				{
				}
				else if(i==2)
				{
					lcd_clear();
					lcd_write("PALET CIKISI");
					lcd_goto(2,1);
					lcd_write("IPTAL EDILDI");
					PORTB=0x02;
					DelayMs(1000);DelayMs(1000);DelayMs(1000);
					PORTB=0x04;
					lcd_clear();
					lcd_write(" PALET NUMARASI ");
					lcd_goto(2,1);
				}
			}
		}
		if(BTN1) // 1. BUTON
		{
			if(i==0)
			{  //TAKİP SİSTEMİ
				lcd_clear();
				lcd_write(" PALET NUMARASI ");
				lcd_goto(2,1);
				PORTB=0x01;
				i++; // İ'Yİ 1 YAP
			}
			else if(i==1) // İŞLEVSİZ
			{
			}
			else if(i==3) // PALET ÇIKIŞINI ONAYLA
			{
				PORTB=0x0C;
				UART_Write('E');
				DelayMs(1000);
				i--;
				lcd_clear();
				lcd_write("CIKIS YAPILDI");
				lcd_goto(2,1);
				lcd_write("LUTFEN BEKLEYIN");
				DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);DelayMs(1000);
				PORTB=0x04;
				lcd_clear();
				lcd_write(" PALET NUMARASI ");
				lcd_goto(2,1);
			}		
		}	
	}	
}

static void interrupt kesmeler(void)
{
	if(RCIF)
	{
		GIE=0;
		TEMP=RCREG;
		karakter_sayisi++;
		lcd_data(TEMP);
		BUZZER=1;
		DelayMs(1000);
		if(karakter_sayisi==13)
		{
			if(i==1)
			{
				while(1)
				{
					TEMP=UART_Read();
					if(TEMP=='1')
					{
						lcd_clear();
						lcd_write("  DOGRU PALET   ");
						lcd_goto(2,1);
						lcd_write("YUKLEME YAPINIZ.");
						karakter_sayisi=0;
						break;
					}
					else if(TEMP=='2')
					{
						lcd_clear();
						lcd_write("  YANLIS PALET  ");
						lcd_goto(2,1);
						lcd_write("YUKLEME YAPMA!!!");
						karakter_sayisi=0;
						break;
					}
				}
			}
			else if(i==2)
			{
				i++;
			}
		}
		RCIF=0;
		GIE=1;
		BUZZER=0;
	}
}


ETE hocam dediğinizi yaptım ama olmadı. Denemediğim şey kalmadı. Artık umutsuzluğa kapılmaya başladım. Ne yapacağımı bilemez haldeyken moralim sıfıra indi. Çözümü olmaması çok saçma bir şey olsa gerek. Mutlaka vardır ama bilemiyorum işte.
RF Alıcının modeli RXB11. Piyasada bolca bulunuyor. En son çare olarak onu söküp deneyeceğim. Mantık dışı ama bir forumda öyle bir problem olduğunu okumuştum. RF alıcı sürekli 5 volt veriyor pic'in RX bacağına. Acaba değişimden haberi olmuyor mu pic'in. Artık bunu düşünmeye başladım yani

hacimusatr

Arkadaşlar bugün yine defalarca testlerde bulundum. Yine bir sonuç alamadım. En son programı hi-tech den vazgeçip ccs c de yazdım. Program yine benzeri özelliklere sahip. Amacım hi-tech de hata var mı diye incelemekti. Program yine çalışmadı. Dediğim gibi sorunumun donanımsal olduğunu düşünüyorum. Şimdi sizlerden rf hakkında incelikleri öğrenmek istiyorum
Sitemizdeki bir paylaşımda bir yorum okumuştum PC ile haberleşirken 5. bacağa pici beslediğin GND sinyaliyle aynı yere bağla. Bugün çalışan 628a yı board üzerine alıp aynı devreyi kurdum. Sonuç çalışmadı. Yani GND ucu picle aynı beslemeden olması bu kadar önemli mi? Bu birinci sorumdu. Geçelim diğerine. Pici çalıştırmaya başlıyorum. Bu sorum çok ilginç vereceğiniz bilgiler hayati önem taşımakta. Okuyan ve cevap verenlerden şimdiden Allah razı olsun. Pic çalışmaya başlayıp 2 sn geçtikten sonra kesmeye girmeye başlıyor ard arda 3 kesme her kapatıp açtığımda aynı. Lcd ye acayip karakterler bazen boşluk bazen ö bazen - bazen de ters ok basıyor. Bunlar sadece benim gördüklerim. 3. veri alımından sonra kesiliyor. Bu kadar hızlı veri transferini isis bile desteklemiyor. Virtual seri porttan 4 haneli bir rakam gönderdiğimde pic kilitleniyor. Acaba gerçekte de pic 3. den sonra kilitleniyor olabilir mi? Gelen verileri kim gönderiyor nereden geliyor nasıl geliyor. Bu olaydan sonra gelen verilere maskeleme yaptım. 6 karakter tanıtıp getchar() ile if döngüleri içerisine iç içe ifler yerleştirip veri alabilmesi için 6 karakteri görmesi lazım olduğunu pice öğrettim. Böylece pic veri alma işini kesti. Ondan önce tek karakter yaptım x karakteri koydum küçük harf onu geçti ve tek karakter veri aldı. x i nasıl denk getirdi nerden nasıl bir parazit aldı hala aklım almıyor. RF alıcının beslemesini (karşılıklı haberleştirmeden dolayı kendi verisini kendisi almasın diye) transistör ile sürüyorum. Yalnız beslemeyi değil GND sinyalini. Acaba problem çıkarır mı? Bu iş artık beni yordu değerli üsdatlarım. Beni aşmaya başladı. Günlerdir rüyalarımda hi-tech kodları görüyorum picler görüyorum kafayı yemeye başladım. Şu işi halledeyim inanın çözümünü başkası benim yaşadığımı yaşamasın diye paylaşacağım. Bu iş insanı deli ediyor. Pic ne lanet bir işlemciymiş. İnanın picden soğudum. Atmel kullancam bundan sonra. Neyse üsdatlar vereceğiniz cevaplardan şimdiden Allah razı olsun. Tekrar tekrar teşekkür ediyorum. Umarı sorularıma cevap bulabilirim.