RS232 kesmesi (c18)

Başlatan Gökhan BEKEN, 28 Ağustos 2013, 12:18:36

Gökhan BEKEN

Bir kaç farklı yerde örnekler var ancak ben pek bişey anlamadım assembly kod kullanmışlar.
http://www.mcuexamples.com/forum/showthread.php?tid=616
http://www.edaboard.com/thread296240.html#post1266961
http://elkitabim.net/2012/09/19/c18-diliyle-robot-programlama-rs232-seri-haberlesme-usart/

Örnekler nerdeyse birbirinin aynısı.
Bir veri gönderip veri gelene kadar bekleyip, gelen veriyi enter karakteri gelene kadar bir değişkene atıyorum ancak uygulamada bu yetersiz oluyor, beklenmedik anlarda gelen veriler uçup gideceğinden kesme kullanmak şart oluyor.
Amacım beklenmedik anda gelen verileri enter karakteri gelene kadar almak. Yardımcı olur musunuz?

Bu arada, sayın yöneticilerden c18 için bir bölüm açmalarını taleb ediyorum.
c18 için Türkçe kitap var mı? Hi-Tech için yazılmış kaynaklar ve c18 dili için yazılmış ingilizce microchip kaynaklarını kullanıyorum ama her zaman işe yaramıyor.
Özel mesaj okumuyorum, lütfen göndermeyin.

kantirici

asm kod parçası sabit olarak yazılıyor, kesme geldiginde ilgili kesme fonksiyonu belirtiliyor. Enter karakteri gelene kadar veri almak yerine usart kesmesinde gelen veriyi diziye at ve ardından gelene veririn enter olup olmadığını sorgula.Eğer enter gelmişse bir bayragı set et ve main içinde de bu bayrağı sorgulayarak ilgili işlemleri yap.Genel mantık bu şekilde.

Gökhan BEKEN




Bu devrenin isis ve c dosyaları burda: http://gokhanbeken.com/dosyalar/c18-rs232-uygulamasi.rar

Bunu nasıl modifiye edebilirim?

#include <p18cxxx.h>
#include <stdio.h>
#include <delays.h>
#include <usart.h>
 
#pragma config OSC = HS, WDT = OFF, LVP = OFF
 
unsigned char adi[50]={0};
unsigned char soyadi[50]={0};
 
//void veri_iste(char soru[], char *cevap)
void veri_iste(rom char *soru, char *cevap)
{
unsigned char usart_ram[2]={0};
 
////////////////////////////////////////////////////////////////////////////////////////////
//bir diziye aktarma işlemi(şimdilik kullanıza gerek yoksa açıklama olarak bırakabilirsiniz)
////////////////////////////////////////////////////////////////////////////////////////////
int i=0;
unsigned char metin[50]={0}; //verileri aktaracağımız değişken
int strlength = 0; //*soru değişkeninde kaç tane karakter olduğunu tutar
 
////ölçme kısmı/////////////////////////////////////////////////////////////////
while (soru[strlength] != '\0'){ //*soru değişkeninin uzunluğunu hesaplayalım
//putrsUSART((rom char*)soru+strlength); //istersek tek tek te yazdırabiliriz
strlength++;
}
//kaynak: http://stackoverflow.com/questions/14540681/calculating-length-of-a-string-in-c?lq=1
////////////////////////////////////////////////////////////////////////////////
 
for(i=0;i<strlength;i++){ //i yi alınan verinin uzunluğu kadar döndermek gerek
metin[i]=*(soru+i);
}
 
putsUSART(metin);
////////////////////////////////////////////////////////////////////////////////////////////
 
//putrsUSART((rom char*)soru); //alınan veriyi direkt yazar
 
while(1)
{
while(BusyUSART()); // wait for input //while (!DataRdyUSART());
getsUSART(usart_ram, 1); //usart_ram değişkenine 1 karakterlik veri alıyoruz
putsUSART(usart_ram); //adam ne yazdığını bu kod sayesinde görüyor, eğer back spack tuşunuda enter gibi kontrol edersek silmesinide sağlayabiliriz, gerçi isiste backspack tuşu ile silebiliyoruz ama normalde oluyor mu bilmiyorum
if(usart_ram[0]==(char)13)
{
break;
}
*cevap=usart_ram[0];
cevap++;
}
 
*cevap=0;//yazdırdıktan sonra eskiden kalan daha önceki verileri siliyoruz
}
 
void main(void) {
 
ADCON1 = 0x0F;
 
TRISB = 0x07;
PORTB = 0;
TRISA=0x00; PORTA=0x00;
OpenUSART(USART_TX_INT_OFF &
USART_RX_INT_ON &
USART_ASYNCH_MODE &
USART_EIGHT_BIT &
USART_CONT_RX &
USART_BRGH_HIGH,
25 );
SPBRG = ((int)(25000000L/(16UL * 9600) -1)); //şuan 25mhz, 20mhz=20000000L
 
while(1){ //sürekli sorsun
 
putrsUSART("\r\n");
veri_iste("ADINIZ >> ", &adi); putrsUSART("\r\n");
veri_iste("SOYADINIZ >> ", &soyadi); putrsUSART("\r\n");
 
putrsUSART("Merhaba ");
putsUSART(adi);
putrsUSART(" ");
putsUSART(soyadi);
putrsUSART(" bey...");
 
}
 
while(1) {} //program sürekli başa sarmasın diye sonsuz döngüye sokuyoruz
 
}
Özel mesaj okumuyorum, lütfen göndermeyin.

serhat1990

Merhabalar Hocam , size bir proje kullandığım rcif kesme bölümünü ekliyorum . Fonksiyon içeriğini doldurabilirsiniz . Diğer kesme ayarlarını programınızda ayarlayıp kullanabilirsiniz , saygılarımla ...

Umarım yardımı olur ..

/*****************High priority interrupt vector **************************/
#pragma code high_vector=0x08
void interrupt_at_high_vector(void)
{
  _asm GOTO high_isr _endasm
}

#pragma code
/*****************High priority ISR **************************/

#pragma interrupt high_isr
void high_isr (void)
{
 if (PIR1bits.RCIF)
   {  
     PIR1bits.RCIF=0;
	 
		// Kesme işlemleri yapılacaktır ...
		
    }
}

Gökhan BEKEN

#4
Merhaba hocam teşekkür ederim

Veri gelince A portundaki ledleri terslemesini istiyorum ancak bir veri geldiğinde sonsuz döngüye giriyor ve ledler sürekli yanıp sönüyor. Galiba kesmeye girince kesme bayraklarını sıfırlamamız gerekiyordu tam hatırlamıyorum şimdi onu araştırıyorum.

Ha bir de low_isr ve high_isr ne işe yarıyor bilmiyorum. Biri yüksek öncelikli kesme diğeri düşük öncelikli kesme imiş ama hangisi kullanmam gerekiyor acaba?


Güncelleme: aşağıdaki şekilde yazınca düzeldi, sonsuz döngüye girmiyor artık
void high_isr (void)
{

    if(PIR1bits.RCIF == 1) {
        PIR1bits.RCIF = 0;

		LATA=PORTA+1;//kesmeye her girdiğinde portanın değerini 1 artır

        while(!DataRdyUSART());
		{
        	data_rx = (char)ReadUSART();       
		}
    }

}
Özel mesaj okumuyorum, lütfen göndermeyin.

serhat1990

Kusura bakmayın Hocam mesajınızı geç gördüm rica ederim ,  sorunun çözüldüğüne sevindim . Öncelikli kesmeleri siz programınızda ayarlıyorsunuz. Hangi kesmelere öncelik verilecek gibi . Önem sırasına göre işlem yapabiliyorsunuz .

İyi çalışmalar dilerim , saygılarımla ...