Byte-Integer dönüşüm sorunu

Başlatan nocturnal, 29 Ocak 2013, 11:17:16

nocturnal

Arkadaşlar Merhaba,

İki işlemcim var. Aralarında USART haberleşiyorlar (19200BR) ilki preprocessor olarak işlemleri yapıp karşı tarafa pulse sayısını aktarıyor. Bunu 000000 olmak üzere altı tane byte gönrererek yapıyor. her birini putch ile gönderiyorum.

Karşı taraftaki işlemci ise bu altı byte'ı alıyor ve lcd ekrana basıyor. Pulse sayısını unsigned long int olarak tanımladım. Bu USART'la gelen veri alınıp daha sonra hem Pulse sayısı şeklinde hem de bir satır altında milimetre ile gösteriliyor.

Sorunum şu; bunu yaparken 40.000'e kadar program düzgün çalışırken 40 bine gelince Pulse_Count (yani ona bağlı olarak da mm) değeri sapıtıyor. 65535'i geçince tekrar düzeliyor fakat bu kez 000000 olarak. Bunun nedeni nedir? Ben aldığım byte'ları integer'a çevirirken olduğu kanaatine vardım çünkü diğer tüm rutinler sağlam çalışıyor. Fikriniz nedir?

Aşağıdaki kodda gelen byte'ların integer'a dönüştürme rutini gözükmektedir.


unsigned long int Pulse_Count, mm;


unsigned char Read_Data(){

          if(getch()!='P') NOP();
          else {

          for (j=0; j<6 ; j++){
          bilgi[j]=getch();           // bilgi paketi alınıyor
          }

          Pulse_Count=100000*(bilgi[0]-48);
          Pulse_Count+=10000*(bilgi[1]-48);
          Pulse_Count+=1000*(bilgi[2]-48);     //gelen 6 byte unsigned long int'e çevriliyor(!)
          Pulse_Count+=100*(bilgi[3]-48);
          Pulse_Count+=10*(bilgi[4]-48);
          Pulse_Count+=(bilgi[5]-48);
          

        mm=Pulse_Count/50;

        lcd_gotoxy(3,8);
        veri_yolla((mm%10000)/1000+48);
        lcd_gotoxy(3,9);
        veri_yolla((mm%1000)/100+48);
        lcd_gotoxy(3,10);
        veri_yolla((mm%100)/10+48);
        lcd_gotoxy(3,11);
        veri_yolla(',');
        lcd_gotoxy(3,12);
        veri_yolla(mm%10+48);

          return 'P';

          }
          }

Kabil ATICI

Çevirme rutinlerini kontrollerini kontrol etmen kolay. Program başında uart'den alman gereken değerleri sabit değer olarak ata ve onları ekrana bastır. Bu işlem doğru şekilde yapılıyorsa. Bildiğin sabit olarak atadığın sayıları uart üzerinden gönder ve bastırmayı dene. Buradaki duruma bakarsak sanki uart üzerinden veri aktarılırken veri kaybı oluyor. İlk iki baytı alıyor ki tam alamıyor. UART Veri hatası oluşuyor gibi. Kullandığın baud hızını düşürerek deneyebilirsin. İşlemci sistemlerin çalışma hızları farklı ise uart hatası olma olasılığı var.
ambar7

nocturnal

Proteusta sabit verdiğim değerlerin bazılarında diğer işlemci sapıtmaya devam etti bazılarını ise düzgün alıp bastı. Baud hızını azaltmayı düşündüm fakat sorun donanımsal değil. Simülasyonda giden byte'ların değerleri doğru iken bazı sayıları basmıyor. Çok uğraştım fakat hangi sayıları basmadığını tek tek elle 6 basamaklı sayılar vererek bulamadım. Elimdeki tek ipucu sayıların hangi aralıkta doğru basıldıkları.

0-039999  DÜZGÜN (küsurattan emin değilim)
40000 - 65535 FARKLI DEĞER (örn: 974214) tümleyeni mi alıyor ne yapıyor anlamadım
65535'ten sonra mm 0'a dönüyor! bu da demektir ki Pulse_Count adlı long int değeri sıfırlanıyor. bu da gelen bilgiden olur. fakat gelen bilgi doğru, kontrolünü yapıyorum.  Bence burada veri tipleri arasındaki dönüşümle ilgili bi espri var

nocturnal

Örneğin 075536 sabitini gönderdiğimde çevirme işleminden sonra LCD'ye basılan değer: ......852752

RaMu

Bence uart ve 2. m.d. de byte int çevrimi yapan kısım olarak ikiye ayırıp incelemekte fayda var, uart kısmında yardımcı olamam hatta program için kod olarakta pek faydam olmaz ama asm olarak kod isterseniz size 8-16-32 kaç bit isterseniz çok sağlam denediğim bir rutini yazabilirim sizde bunu programınız içerisinde kullanabilirsiniz. 2. kısım yani byte int çevirip lcd de göstermede FFFFh dan yani 65535 den sonraki sayılar başa dönüyor çünkü bence çevirici 16 bitlik bu yüzden 65535 den büyük değeri çeviremiyor, bunun için isterseniz 32 bit dönüştürücü asm olarak verebilirim.
Sorularınıza hızlı cevap alın: http://www.picproje.org/index.php/topic,57135.0.html

fatih6761

@nocturnal hocam hangi derleyiciyi kullanıyorsunuz? Bu kısım önemli. Çünkü bazı derleyiciler unsigned long'u 8-byte olarak alıyor bazıları ise 4-byte. Ne  yazık ki bunun yam bir standardı yok. GCC derleyicileri içind bile ayrım var. Hem platforma göre de değişiyor.

nocturnal

#6
Cevaplarınız için teşekkür ederim. Maalesef ki lisansı ucuz olduğu için MikroC kullanıyorum. Normalde Hi-Tech'çiydim. Overflow ilk aklıma gelen şey oldu. Muhtemelen öyle bir şey var fakat nerede bulmakta zorlanıyorum. Bunun yüzünden başka yöntemlerle işi tek işlemciye düşürdüğümü düşünürsek bu sorunla karşılaştığım iyi oldu :) yalnız hala cevabını merak ediyorum.

          Pulse_Count=100000*(bilgi[0]-48);
          Pulse_Count+=10000*(bilgi[1]-48);
          Pulse_Count+=1000*(bilgi[2]-48);     //gelen 6 byte unsigned long int'e çevriliyor(!)
          Pulse_Count+=100*(bilgi[3]-48);
          Pulse_Count+=10*(bilgi[4]-48);
          Pulse_Count+=(bilgi[5]-48);


Bu kısımda sorun yok. Yok derken şöyle yok; bilgi[1] yerine Decimal 55 yazdığım zaman örneğin, bu char '7' ye denk geliyor. Rutinde 55-48=7 'ye karşılık geliyor ve onu alıp 10000'le çarpıyorum. Bu şekilde elle yazınca oluyor. Uart'tan gönderdiğim verinin de char '7' ye karşılık geldiğini test ediyorum-doğru (Lcd'ye char olarak gönderince 7'yi görüyorum, simülasyonda Uart'tan gönderdiğim veriye bakınca bunun 7 olduğunu görüyorum). Fakat çevrimde bir sıkıntım var. yani bilgi[1]='7' iken bunu alıp o rutinde işleme soktuğum zaman her defasında aynı değere karşılık gelecek bir taşma(!) oluyor (Taşma hep aynı değere giderse tabi). Aslında C'nin inceliklerini bilen biri biraz düşünse hatayı bulur.

Bu arada MikroC'nin kendi Help'indeki tabloyu aktarıyorum:

Type Size in bytes Range

bit 1–bit 0 or 1
sbit 1–bit 0 or 1
(unsigned) char 1 0 .. 255
signed char 1 - 128 .. 127
(signed) short (int) 1 - 128 .. 127
unsigned short (int) 1 0 .. 255
(signed) int 2 -32768 .. 32767
unsigned (int) 2 0 .. 65535
(signed) long (int) 4 -2147483648 .. 2147483647
unsigned long (int) 4 0 .. 4294967295            ---------------------> unsigned long 16 bit olarak tanımlı. (!) derken hatayı buldum heh

Teşekkürler @RaMu ve @fatih6761. Bunu nasıl gözden kaçırdım anlamıyorum. Sen kalk MPLAB'tan MikroC'ye geç.... Sonra 70000'i neden basamıyorum diye iki gün düşün :) Benden size naçizane tavsiye; kafayı fazla ısıtmışken arada nefes almanızı öneririm :)

MPLAB farkı:
unsigned long       32 bits  0 4,294,967,295

:)