Haberler:

Foruma Resim Yükleme ve Boyut Sınırlaması ( ! )  https://bit.ly/2GMFb8H

Ana Menü

int32 tipindeki verinin aktarımı

Başlatan ranadilara, 01 Mayıs 2008, 16:24:25

ranadilara

Merhaba arkadaşlar;

int32 tipinde bir veriyi bir pic'ten diğer bir pic'e nasıl aktarabilirim?

RS232 komutlarında putc(), puts() ve printf() komutları var.Bu komutları kullanarak int32 tipindeki veriyi gönderemiyorum.Bu işi nasıl gerçekleştirebilirim?

iyi günler...

kadirbas

Selamlar,

puts fonksiyonu hariç, diğer iki fonksiyonu da bu iş için kullanabilirsiniz bence. Ama daha sağlıklı olması açısından, putc fonksiyonunu kullanarak byte byte aktarım yapmanızı önerebilirim. Açıkçası nerede takıldığınızı da tam olarak anlayamadım.

ranadilara

byte byte gönderme işlemini gerçekleştirmek için ben daha önce şöyle bir yöntem düşünmüştüm:
int32 tipindeki veriyi 3 defa 1000'e bölüp kalanları farklı değişkenlere atayıp sırayla göndermek.

fakat bundan daha basit bir yöntem var mı diye sormak istedim.

iyonosfer

int32 veri;
veri = 0xa048d21e;

putc(make8(veri,0));  // 0x1e;
putc(make8(veri,1));  // 0xd2;
putc(make8(veri,2));  // 0x48;
putc(make8(veri,3));  // 0xa0;

alıcı kısmındada
int32 veri; 
int v1,v2,v3,v4;

v1 = getc();
v2 = getc();
v3 = getc();
v4 = getc();

veri = make32(v4,v3,v2,v1) //0xa048d21e;
----------------------------------- veya-------------------------------
int i;
int veri[4];

for(i=0;i<4;i++)
  putc(veri[i]);

---- alıcı için
int i;
int data[4];

for(i=0;i<4;i++)
   veri[i] = getc();  // yoğun istek üzerine editlenmiş satır :) gözünden bişey kaçmıyor kadir


----- BUDA DAHA BASIT AMA DAHA ÇOK KOD YİYECEK Bİ YONTEM--
#include <stdlib.h>
int32 veri;
char text[15];

veri = 0xabcdef01;
itoa(veri,10,text)
puts(text);

------alıcı------
int32 veri;
char text[15]
gets(text)
veri = atoi32(text);


yöntemleriyle yapılabilir

Kolay gelsin
Blog Sayfam: www.teknobakis.com

kadirbas

Alıntı yapılan: "iyonosfer"
----------------------------------- veya-------------------------------
int i;
int veri[4];

for(i=0;i<4;i++)
  putc(veri[i]);

---- alıcı için
int i;
int data[4];

for(i=0;i<4;i++)
   getc(veri[i]);

...


iyonosfer. Bu ikinci yöntem biraz yanlış olmuş sanki :D Doğru kodlanmış hali:

int i;
BYTE veri[4];

for(i=0;i<4;i++)
  putc(veri[i]);

---- alıcı için
int i;
BYTE data[4];

for(i=0;i<4;i++)
   data[i] = getc();

...


Bunun dışında, biraz karışık olmakla birlikte, yapıları da kullanarak şu şekilde verinizi parçalamanızı önerebilirim:

// Öncelikle 4 byte'lık  veriyi parçalamak için bir "birlik" (union) oluşturuyoruz.
// Bu birlik tanımı iki PIC kodunda da olmalı...
//________________________________________________//
typedef union tagDWORD_VAL
{
       int32    val;
       struct 
       {
              int16    val[2];
       }words;
       struct
       {
              int8     val[4];
       }bytes;
}DWORD_VAL;
//________________________________________________//

/* verici kısım */
DWORD_VAL gonderilecek;

gonderilecek.val = 0x12345678;

putc(gonderilecek.bytes.val[0]);
putc(gonderilecek.bytes.val[1]);
putc(gonderilecek.bytes.val[2]);
putc(gonderilecek.bytes.val[3]);

/* alıcı kısım */
DWORD_VAL alinan;

alinan.bytes.val[0] = getc();
alinan.bytes.val[1] = getc();
alinan.bytes.val[2] = getc();
alinan.bytes.val[3] = getc();

// alinan.val değerini tepe tepe kullanabilirsiniz :D


Bu kodlama, belki anlaşılması zor bir kodlama olabilir. Belki henüz birlik'in ne olduğunu da bilmiyorsunuzdur. Böyle bir örneği vermemin amacı farklı bir teknik göreniz ve eğer bilmiyorsanız ufkunuzun açılmasını sağlamak.

Kolay gelsin...

ranadilara

@iyonosfer

gönderdiğiniz kod için teşekkürler...
make8 ve make32 komutlarını kullandım fakat şöyle bir sorunla karşılaştım.
Örneğin;65444325 sayısını 8'er 8'er böldürmek istediğimde aldığım sonuçlar: -27, -103, -26 ve 3 oldu. Burada nasıl bir işlem gerçekleştirilip bu sonuçların çıktığını anlayamadım.Yardımcı olursanız sevinirim...

iyonosfer

65444325 = 03E699E5

int i;
int32 veri = 0x03e699e5;

i = make8(veri,0); komutu e5 değerini döndürür bu değerin işaretili tam sayı karşılığı -27 dir;

unsigned int olarak tanımlayıp denermisin
Blog Sayfam: www.teknobakis.com

ranadilara

tekrar merhaba,
make8(),make32() komutlarını kullanarak istediğim kodları yazdım ancak şimdi de şöyle bir sorun var: örneğin 6000 sayısını yolladığımda alıcı kısımda 800,1000 gibi değişken ve doğru olmayan değerler elde ediyorum.Bu problemi aşmak için programda farklı delay süreleri denedim ancak yine de tam doğru sonuca ulaşamadım.Alıcı verici arasındaki senkronizasyonu nasıl sağlayabiirim?

//verici kod
#include <16F877A.H>
#fuses XT,NOWDT,NOPROTECT,BROWNOUT,PUT,NOLVP
#use delay (clock=4000000)
#use rs232 (baud=2400, xmit=PIN_C6)

unsigned int16 tmrSayac = 0;
unsigned int1 portDurum = 0;
unsigned int32 ArabaVarZaman_ms = 0;
unsigned int32 ArabaYokZaman_ms = 0;
unsigned int1  arabaVar = true;
unsigned int   arabaSayac = 0;
unsigned int16 KontrolSuresi = 0;
unsigned int32 OrtYokZaman=0;
unsigned int32 OrtVarZaman=0;
unsigned int32 TopVarZaman=0;
unsigned int32 TopYokZaman=0;


void main()
{
   delay_ms(20);
   enable_interrupts(int_RB);
   enable_interrupts(int_timer1);
   enable_interrupts(int_timer0);
   enable_interrupts(global);

   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_CCP1(CCP_OFF);
   setup_CCP2(CCP_OFF);


   setup_timer_0(RTCC_internal | RTCC_div_256);
   set_timer0(0);

   setup_timer_1(T1_internal | T1_div_by_8);
   set_timer1(15535);

   set_tris_b(0x10);

   while(1)
   {if (KontrolSuresi>=500)

    {
     delay_ms(35);
     putc(make8(OrtVarZaman,0));
     delay_ms(35);
     putc(make8(OrtVarZaman,1));
     delay_ms(35);
     putc(make8(OrtVarZaman,2));
     delay_ms(35);
     putc(make8(OrtVarZaman,3));
     delay_ms(35);
     putc(arabaSayac);
     delay_ms(35);
    }
   }
}


#int_RB
void kesmeAltFonk()
{
   if(input(pin_b4))      //portb nin 4. pinini oku, pin degeri 1 ise yani arac geldiyse
   {
       arabaVar = true;
       arabaSayac++;
       ArabaYokZaman_ms = ((tmrSayac * 500) + (get_timer1()*8-15535) / 100);  //ms cinsinden toplam geçen zaman
       TopYokZaman=ArabaYokZaman_ms+TopYokZaman;
       OrtYokZaman=TopYokZaman/arabaSayac;
       set_timer1(15535);
       tmrSayac = 0;

   }
   else  // b4 pini 0 ise yani arac sensor onunden gectiyse
   {
      arabaVar = false;
      ArabaVarZaman_ms = ((tmrSayac * 500) + (get_timer1()*8-15535) / 100);  //ms cinsinden toplam geçen zaman
      TopVarZaman=ArabaVarZaman_ms+TopVarZaman;
      OrtVarZaman=TopVarZaman/arabaSayac;
      set_timer1(15535);
      tmrSayac = 0;
   }
}

#int_timer1
void tmr1Kesme()
{
   tmrSayac++; // timer1 aracların IR sensor onunde kalma suresinin hesabinda kullaniliyor

}



#int_timer0
void tmr0Kesme()
{
   KontrolSuresi++; // timer0 bir periyod olusturmak icin kullaniliyor...

   if(KontrolSuresi>=600)
   {
      KontrolSuresi=0;

      set_timer0(0);
      OrtVarZaman=0;
      OrtYokZaman=0;
      arabaSayac=0;
   }
}


//alıcı kod
#include <16F877A.H>
#fuses XT,NOWDT,NOPROTECT,BROWNOUT,PUT,NOLVP
#use delay (clock=4000000)
#use rs232 (baud=2400, rcv=PIN_C7)
#include <lcd.c>


unsigned int32 OrtVarZaman;

unsigned int v1;
unsigned int v2;
unsigned int v3;
unsigned int v4;

unsigned int arabasayisi;


void main()
{
   delay_ms(20);
   enable_interrupts(int_RB);
   enable_interrupts(int_timer1);
   enable_interrupts(int_timer0);
   enable_interrupts(global);

   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_CCP1(CCP_OFF);
   setup_CCP2(CCP_OFF);
   setup_timer_1(T1_DISABLED);

   lcd_init();

   while(1)
   {
    v1=getc();
    v2=getc();
    v3=getc();
    v4=getc();
    arabasayisi=getc();

    OrtVarZaman=make32(v4,v3,v2,v1);

    printf(lcd_putc,"\f OVZ=%ul",OrtVarZaman);
    delay_ms(1500);
    printf(lcd_putc,"\f Arabasayisi=%u",arabasayisi);
    delay_ms(1500);

   }
}

kadirbas

Gönderme işlemi sırasında, bilginin başlangıcını belirtecek birkaç bytelık veri göndermeniz, sorununuzu çözcektir sanırım. Mesela:

// verici
if (KontrolSuresi>=500)

    {
     putc('S');
     putc('t');
     putc('a');
     putc('r');
     putc('t');
     putc(make8(OrtVarZaman,0));
     putc(make8(OrtVarZaman,1));
     putc(make8(OrtVarZaman,2));
     putc(make8(OrtVarZaman,3));
     putc(arabaSayac);
     }
} 

______________________________

// alıcı

while(1)
{
   ch = getc();

   switch(durum)
   {
     case 0:
           if(ch == 'S') durum = 1;
           break;
     case 1:
           if(ch == 't') durum = 2;
           else if(ch == 'S') durum = 1;
           else durum = 0;
           break;
     case 2:
           if(ch == 'a') durum = 3;
           else if(ch == 'S') durum = 1;
           else durum = 0;
           break;
     case 3:
           if(ch == 'r') durum = 4;
           else if(ch == 'S') durum = 1;
           else durum = 0;
           break;
     case 4:
           if(ch == 't') durum = 5;
           else if(ch == 'S') durum = 1;
           else durum = 0;
           break;
     case 5:
           v1=getc();
           v2=getc();
           v3=getc();
           v4=getc();
           arabasayisi=getc();

          OrtVarZaman=make32(v4,v3,v2,v1);

          printf(lcd_putc,"\f OVZ=%ul",OrtVarZaman);
          delay_ms(1500);
          printf(lcd_putc,"\f Arabasayisi=%u",arabasayisi);
          durum = 0;
          break;
      }
}


Bu kod daha da kısaltılabilir elbette...

ranadilara

aynen bu şekilde göndermeyi denedim ancak lcd'de görülen OrtVarZaman ve  arabasayisi değerleri bir öncekine göre daha hatalı oldu.Sorunun ne olduğunu anlayamadım...

kadirbas

Bu gibi durumlarda yapabileceğiniz şeylerden biri de, göndereceğiniz verinin içinde asla olmayacak bir veri varsa, onunla kontrol yapmaktır. Bu gönderi paketinin içinde böyle bir veri yok aslında (çünkü sayılar 00-ff arası herhangi bir değeri alabilir). Fakat böyle bir veri olmasını birkaç yolla sağlayabilirsiniz. Bu yollardan biri kendinize bir başlangıç karakteri (esasında bu da bir sayı tabiki) seçmek ve başlangıçta onu göndermektir. Kendi veriniz içinde o karakterin sayısal karşılığı varsa, o sayıyı iki defa göndererek bu durumun diğerinden farklı olduğunu belirtebilirsiniz. Kodlarsak:

// verici
if (KontrolSuresi>=500)
{
    putc('S');

    putc(make8(OrtVarZaman,0));
    if(make8(OrtVarZaman,0) == 'S') putc(make8(OrtVarZaman,0));

    putc(make8(OrtVarZaman,1));
    if(make8(OrtVarZaman,1) == 'S') putc(make8(OrtVarZaman,1));

    putc(make8(OrtVarZaman,2));
    if(make8(OrtVarZaman,2) == 'S') putc(make8(OrtVarZaman,2));

    putc(make8(OrtVarZaman,3));
    if(make8(OrtVarZaman,3) == 'S') putc(make8(OrtVarZaman,3));

    putc(arabaSayac);
    if(arabaSayac == 'S') putc(arabaSayac);
} 

______________________________

// alıcı
int8 startFlag = 0;
int8 durum = 0;

while(1)
{
    ch = getc();
   
    if(ch == 'S')
    {
        if(startFlag == 0) { startFlag = 1; }
        if(startFlag == 1) {
            switch(durum)
            {
                case 0: v1 = 'S'; break;
                case 1: v2 = 'S'; break;
                case 2: v3 = 'S'; break;
                case 3: v4 = 'S'; break;
                case 4:
                    arabasayisi = 'S';
                    OrtVarZaman=make32(v4,v3,v2,v1);
                    printf(lcd_putc,"\f OVZ=%ul",OrtVarZaman);
                    delay_ms(1500);
                    printf(lcd_putc,"\f Arabasayisi=%u",arabasayisi);
                break;
            }
			++durum;
			if(durum > 4) durum = 0;
            startFlag = 0;
        }
    }
    else
    {
        if(startFlag == 1) {
            durum = 1;
            v1 = ch;
            startFlag = 0;
        }
        else {
            switch(durum)
            {
                case 0: v1 = ch; break;
                case 1: v2 = ch; break;
                case 2: v3 = ch; break;
                case 3: v4 = ch; break;
                case 4:
                    arabasayisi = ch;
                    OrtVarZaman=make32(v4,v3,v2,v1);
                    printf(lcd_putc,"\f OVZ=%ul",OrtVarZaman);
                    delay_ms(1500);
                    printf(lcd_putc,"\f Arabasayisi=%u",arabasayisi);
                    durum = 0;
                break;
            }
			++durum;
			if(durum > 4) durum = 0;
        }
    }
}


Burada da yine kodlar daha kısa ve derli halde yazılabilir fakat bu şekilde daha rahat anlayabileceğinizi düşündüm...

kadirbas

Bu arada lcd'ye yazdırırken bekleme komutlarını atarak ve lcd'nin iki satırını da kullanarak denerseniz daha iyi olur sanırım...

ranadilara

@kadirbas
önerdiğiniz tüm yöntemleri denedim ancak sorun çözülmedi :cry:
en son önerinizdeki 'S' karakteri için uygulanan çift gönderme olayını anlayamadım.bunun sebebi nedir?

ayrıca alıcı kodunda LCD'ye değerleri bir kez yazdırmama rağmen birbirinden farklı ve hatalı OVZ , arabasayisi değerleri görüyorum...

kadirbas

Son yazdığınız konudaki senkronizasyon sorunuyla alakalı olarak, yazdığınız kodu görebilsek daha fazla yardımımız dokunur herhalde.

Bunun dışında, doğru şekilde haberleşebildiğinize emin olmak için öncelikle sürekli tek karakter göndererek doğru alıp alamadığınızı kontrol edin isterseniz. Belkide temelde bir sorun vardır...

Bir de alıcı kısımda karakter kaçırmamak için kesme kullanmanızı öneririm. Bir tampon bölge yaratın ve gelen verileri bu tampon bölgeye doldurun. Ana döngü içinde de bu alanın doluluğunu kotrol ederek yapmak istediğiniz diğer işlemlerinizi gerçekleştirin. Bu işlem bir çok soununuzu halledecektir.

Senkronizasyon için bir önerim daha var. Gerçi önceden bahsettiklerim de işgörür çözümler gibi. Belki 'S' gönderiminde ilk aşamada sorun olabilir ama sonradan düzelecektir. Önerim sisteminize ne kadar uyar bilmiyorum fakat, göndermek istediğiniz veri blokları arasına belirli bir zaman koyabilirsiniz. Örneğin 1sn. Alıcı kısımda da bir timer kullanarak yaklaşık 1sn boyunca veri almamanız durumunda ilk gelen verinin ilk gönderilen olacağını düşünebilirsiniz.

Ben yine de kesme kullanmanızı tavsiye ediyorum...

İyi çalışmalar...

ranadilara

@kadirbas
yazdığım kodların hepsi yukarıda verdiğim gibi. kesme kullanırsam her karakter geldiğinde bir kesme oluşacak herhalde. kesme fonksiyonun içinde mi gelen karakterleri bir değişkene atamam gerekir?. daha sonra da ana program içinde bu değişkenleri kullanarak işlem yapabilir miyim?