Seriporttan gelen veriyi ayrıştırma

Başlatan KONYALI, 20 Şubat 2011, 15:15:20

KONYALI

arkadaşlar yaptığım bir projede bilgisayardan seriport aracılığıyla gönderilen bir veri katarından belli kısımları ayırmam gerekiyor.
Bilgisayardan gönderdiğim veri takvim ve saat bilgilerini içeriyor bu bilgileri kullanarak devre üzerindeki DS1307 RTC entegresini ayarlamam gerekiyor. Gelen veri şu şekilde 20021111455
1. ve 2. değer =Gün
3. ve 4. değer =Ay
5. ve 6. değer =Yılın son iki karakteri
7. değer =Haftanın Günü
8. ve 9. değer =Saat
10. ve 11. değer =Dakika

Bu şekilde ayırmam gerekiyor. CCS C içi aşağıdaki kodu kullanıyorum
#include <18F4550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=48000000)
#use rs232(baud=115200, parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#include "HDM64GS128.c"
#include "graphics.c"
#include "string.h"
char   deger[11];  // deger isminde 11 üyeli bir dizi tanımlanıyor
int a_dakika,a_saat,a_gun,a_ay,a_yil,a_haftanin_gunu;
char s_saat[2]="0";
char s_dakika[2]="0";
char s_gun[2]="0";
char s_ay[2]="0";
char s_yil[2]="0";
char s_hgun[2]="0";
#int_rda   // RX ucuna veri gelince meydane gelen kesme
void serihaberlesme_kesmesi ()
{
   disable_interrupts(int_rda); // int_rda kesmesini pasif yap
   gets(deger); // String ifadeyi al ve "deger" adlı dizi değişkenine aktar.
      
    glcd_fillScreen(0);                            //Grafik LCD kullanıma hazırlanıyor
   
  
   glcd_rect(0,0,127,63,NO,ON);              //Dış ekran çerçevesi çiziliyor
   glcd_rect(3,3,124,60,NO,ON);              //İç ekran çerçevesi çiziliyor
   
   glcd_text57(10,13,deger,1,ON);       
   
   s_gun[0]=deger[0];
   s_gun[1]=deger[1];

   s_ay[0]=deger[2];
   s_ay[1]=deger[3];

   s_yil[0]=deger[4];
   s_yil[1]=deger[5];

   s_hgun[0]=deger[6];

   s_saat[0]=deger[7];
   s_saat[1]=deger[8];

   s_dakika[0]=deger[9];
   s_dakika[1]=deger[10];

   //rtc_set_datetime(s_gun,s_ay,s_yil,s_haftanin_gunu,s_saat,s_dakika);
   glcd_text57(10,23,s_gun,1,ON);       
    glcd_text57(10,33,s_ay,1,ON);      
     glcd_text57(10,43,s_yil,1,ON);       
      glcd_text57(10,53,s_hgun,1,ON);       
       glcd_text57(50,40,s_saat,1,ON);       
        glcd_text57(50,50,s_dakika,1,ON);       
   glcd_text57(100,13,deger[0],1,ON);       
/*
   

   s_gun[0]=deger[1];
   s_gun[1]=deger[2];

   s_ay[0]=deger[3];
   s_ay[1]=deger[4];

   s_yil[0]=deger[5];
   s_yil[1]=deger[6];

   s_hgun[0]=deger[7];

   s_saat[0]=deger[8];
   s_saat[1]=deger[9];

   s_dakika[0]=deger[10];
   s_dakika[1]=deger[11];

  
   glcd_text57(10,23,s_gun,1,ON);       
    glcd_text57(10,33,s_ay,1,ON);      
     glcd_text57(10,43,s_yil,1,ON);      
      glcd_text57(10,53,s_hgun,1,ON);    
       glcd_text57(30,23,s_saat,1,ON);     
        glcd_text57(30,23,s_dakika,1,ON);     
 
   */
}
void Donanim_Ayar(){
   setup_psp(psp_disabled);
   setup_spi(spi_ss_disabled);
   setup_timer_0(RTCC_INTERNAL);
   setup_timer_1(t1_disabled);
   setup_timer_2(t2_disabled,0,1);
   setup_adc_ports(AN0|VSS_VDD);
   setup_adc(adc_clock_div_32);   // ADC clock frekansı fosc/32
   setup_adc(ADC_CLOCK_INTERNAL );
   setup_timer_0(RTCC_INTERNAL | RTCC_DIV_256); // Timer0 ayarları yapılıyor
   setup_ccp1(ccp_off);
   setup_ccp2(ccp_off);
   SET_TRIS_A(0b00000101);
   SET_TRIS_B(0b00101110);
   SET_TRIS_E(0b00000000);
   SET_TRIS_C(0b00000111);
   SET_TRIS_D(0b11111111);
}
void main(void) {
   Donanim_Ayar();                           //Donanım ayarları yapılıyor
  
   glcd_init(on);                            //Grafik LCD kullanıma hazırlanıyor
   delay_ms(500);                            //Grafik LCD bekleniyor 
  
   glcd_rect(0,0,127,63,NO,ON);              //Dış ekran çerçevesi çiziliyor
   glcd_rect(3,3,124,60,NO,ON);              //İç ekran çerçevesi çiziliyor
   

 
   setup_timer_0(RTCC_INTERNAL | RTCC_DIV_32); // Timer0 ayarları yapılıyor
   set_timer0(10);   // TMR0 değeri belirleniyor
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);   // Aktif edilen kesmelere izin ver
   
   enable_interrupts(GLOBAL);  // Aktif edilen tüm kesmelere izin ver

   while(1) // Sonsuz döngü
   {
      enable_interrupts(int_rda); // int_rda kesmesi aktif
   }
}


Bu kod ile grafik LCD de şu şekilde çıktı alıyorum

20021111455

2002111 -> s_gun değişkeni
02111 -> s_ay
111 -> s_yil
1 -> s_hgun
14552002111 -> s_saat
552002111 -> s_dakika

yani ilk değerler doğru, diziler zaten 2 şer üyeli ama nasıl oluyorda bu şekilde çıktı alıyorum anlamadım
CCS C string fonksiyonlarından örnek verebilirmisiniz? Ve benim programda hata nerden kaynaklanıyor?
Forumda arama yaptım ama benzer bir konu bulamadım. /* */ arasındaki kod bloğuda istediğim işi yapmıyor kaçırdığım ufak bi nüans var ama aklım durdu bulamıyorum yardımlarınızı bekliyorum



aycan07

Merhaba

Benzer sorun için bende uğraşmaktayım
Seriporttan aldığım veriyi parçalamada sıkıntı yasadım.

CCS de String değerler ile uğrasanlardan yardım bekliyorum.

İyi çalışmalar...

metaltrrocker

Ccs den pek anlamam ama gordugum kadariyla kesme fonksiyonu icerisinde deger atamalari yapiyorsun.     Deger atamalarini ve lcd ye yazdirma kismini main fonksiyonu icerisinde yazip dene belki cozum olur.

Salih

#3
C de stringler (Null Terminated)  özelliklidir.
Yani her stringin sonunda #0 (sıfır) değeri olmalıdır.
Sizin gün ay gibi değişkenler, 2 karakter uzunluğunda tanımlanmış.
3 karakter uzunlukta tanımlarsanız problem çözülür.
Deger isimli değişkeni de 13 karakter tanımla.
Gönderdiğin veri katarının sonuna 0 ve 13  değerlerini ekleyerek gönder.
Çünkü gets komutu gelen katarı sonlandırmak için 0 ve 13 değerli elemanlara bakıyor.

ByTEK

Bende benzer bir çalışma yapmıştım. Delphiden seri port üzerinden saat bilgisii gönderdim ve ds1302yi programladım. Ama ne taklalar attım. Özellikle delphiden gönderdiğim veri hep ascii tipinde oldu ben 20 gönderdim PIC ascii 20 algıladı. sorunu bir türlü çözemedim. en sonunda ayıkladım ve gönderdim. Yani önce S gönderdim kesmeye girdi ve döngüye girerek benden karakter istedi sonra 2 yi gönderdim sonrada 0 gödnerdim ve sonrada G gönderdim. Burada G sonlandırma anlamındaydı. PIC te bunu aldım ascii 2 yi 2 ye ascii 0'ı 0 a çevirdim ve ardından (2*10) +(1*0) = 20 dedim onuda ds1302 ye saat olarak yazdım. Jalv2 dilini kullanmıştım. Açıkçası bu kadar zor ve dönemeçli olacağını düşünemedim. Direkt integer tipinde seri porttan veri gönderseydim hiç sorun yaşamayacaktım.

Senin soruna gelince. Ben olsaydım Saat için yazayım. 2 basamaklı bir dizi oluşturur ve 20 - 54 gönderirdim kesme ile 20 ü 1.eleman 54 ise 2. eleman olarak koyardım ve saatleri ona göre kalibre ederdim. İşte buna benzer birşey yapardım. String işine girmeden.

Salih

#3L3CTRO
Problem delphi ve C dilindeki string yapılarının farkından dolayı oluşmaktadır.
Sırası gelmişken bilmeyenler için bilgi verelim.
Örneğin

"ALİ" isimli bir string imiz olsun.

C dilinde ki bellekte ki yapı şöyledir.   'A'+'L'+'i'+0  bellekte 4 bayt yer kaplar son karakter 0 dır.

Delphi de ise .  3+'A'+'L'+'İ'   yine bellekte 4 bayt yer kaplar. dizideki ilk değer karakter değildir. Stringin uzunluk bilgisini veren
integer tipinde değerdir.

Dolayısı ile PC programı yazarken kullandığınız derleyicinin string yapısını iyi bilmeniz gerekir.
Aynı şekilde CCS deki gets() fonksiyonunun ne istediğini anlamak gerekiyor.

ByTEK

Peki Salih bey o zaman şöyle diyelim. Mesela saat bilgisini delphide comport ile rakam oalrak göndermek istiyoruz. o zaman nasıl yol izlenmeli ?

ComPort1.WriteStr() fonksiyonu ile decimal bir sayı gönderme işlemi nasıl olur ?

Salih

#7
Alıntı yapılan: 3L3CTRO - 21 Mart 2014, 22:08:33
Peki Salih bey o zaman şöyle diyelim. Mesela saat bilgisini delphide comport ile rakam oalrak göndermek istiyoruz. o zaman nasıl yol izlenmeli ?

ComPort1.WriteStr() fonksiyonu ile decimal bir sayı gönderme işlemi nasıl olur ?

Eğer CCS'de gets() komutu ile alacaksan.

Giden : string;

giden := inttostr(saat); saat içeriği 12 olsun

giden := giden + #0 + #13;
ComPort1.WriteStr(giden);

*******************
CCS'de ise

char saat[3];
.
.
.
saat = gets(); Artık saat dizinin içeriği  '1'+'2'+0    olur.

Buraya kadar ASCII olarak göndermiş olduk. Bu yöntem veri alış verişinde daha kolaydır.
Çünkü veri başlangıcı ve bitişi kolay bir şekilde belirtilebilir.
Direk rakam göndermek özellikle veriyi alırken, başlangıç ve bitişini tespit etmek de zorlanılır.

Eğer delphi de saat değerini direk sayı olarak göndermek istersen.
saat içeriğini 12 kabul edelim.
giden : string;
giden[1] : chr(saat); // Saat değerini ascii olarak kabul ettirdik. Giden değişkeninde tek karakter var. ascii değeri 12 olan.

ComPort1.WriteStr(giden); //  12 değeri gönderildi.

CCS tarafında ise. Artık gets() komutu kullanamayız çünkü istediği paket özelliklerini oluşturmadık.

gelen = getc();  Bu durumda gelen değişkenin içeriği 12 olur.

ByTEK

sağolun sayın @salih

Teşekkür ederim. Jalv2 kullanıyorum. onda gelen veri byte tipinde gelip değişkene alıyorum.