Your Ad Here

24 Ocak 2008

SERİ UÇ PROGRAMLAMA TEKNİKLERİ

  • TERMİNALSİZ SERİ UÇLAR İÇİN PROGRAMLAR

    Terminalsiz seri uçlar için yazılan programlar, UNIX ortamına program kontrolunda diğer çevre birimlerini bağlayabilme olanağı getirir. Yazılan program gün başında çok kullanıcılı ortama geçildikten sonra veya bir kullanıcı tarafından istenildiği zaman başlatılabilir. Bu yöntemle işletim sisteminin bir parçası olabilecek sürücü program olmadan, herhangi bir çevre birimini UNIX ortamına bağlamak mümkün olur.

    • UNIX ortamında Seri Uçların tanımlanma biçimi

      UNIX ortamında, işletim sistemi seri uçları iki biçimde tanımlar : Birincisi fiziksel seri uçlar; İkincisi ise pseudo seri uçlardır. Fiziksel seri uçlar kullanılan donanıma ilişkin seri uç sürücü programlarına bağımlı çevre birimi tanımlarıdır ama çoğu kez /dev/ttynn biçiminde tanımlanır. Pseudo seri uçlar gerçekte olmayan ancak TCP/IP ve telnet servisi tarafından üretilen sahte seri uçlardır.

      Seri uçlara ait çevre birimi tanımlarının sahibi çoğu zaman "root" adlı kullanıcıdır. getty programı bir kullanıcı sisteme girdikten sonra bu seri ucun erişim haklarını yalnız ilgili kullanıcıya yönlendirir ve diğer kullanıcıların bu seri uca erişimini kaldırır.

      Seri uca bağlı bir terminal yoksa getty programı kullanılmamalıdır. Bu işlem en güzel, /etc/inittab kütüğündeki ilgili terminal bilgilerinde getty tanımının respawn özelliğini off konumuna almaktır. Böylece aynı seri uca ileride bir terminal bağlanması söz konusu olduğunda /etc/inittab bilgileri bozulmadan off konumu respawn yapılarak terminalden login görüntülenmesi sağlanmış olur.

      Seri uca terminal bağlanmayacak ve buraya bir başka çevre birimi bağlanacaksa, bu çevre biriminde olması gereken en önemli özellik, gönderilen mesajları algılayan bir programın ilgili çevre birimi üzerinde çalışır durumda olabilmesidir.

      UNIX üzerindeki program, ilgili seri ucu kullanabilmek için bu kütüğü open komutu ile açmalıdır. Seri uç kütüğü UNIX için /dev/ttynn biçiminde tanımlanır. Program bu kütüğü açarken hem OKUMA hem de YAZMA işlemi yapacak biçimde koşullandırılır. UNIX ortamında bu kütük daha önce mknod komutu ile yaratılmış olduğundan, kütüğün açılırken yoksa yaratılması söz konusu değildir. Çünkü bu tür kütükleri "root" adlı kullanıcı yaratabilir. Eğer kullanıcının kütüğe erişme yetkisi yoksa kütük açma işlemi başarı ile bitmez.

      Kütük açarken dikkat edilmesi gereken konular :

      1. Eğer seri uca bir modem bağlanmış ise, modemler telefon hattından karşı taraftaki modemi görmeden DTR ve CD sinyalini yakmazlar. Bu durumda program seri uca ait kütüğü açamayabilir. Bu gibi durumlar için open komutunda N_DELAY konumu kullanılmalı, modemle iletişim kurulup mesaj alış verişi tamamlandıktan sonra N_DELAY fcntl komutu ile kaldırılmalıdır.

      2. Seri bağlantıda sistemde tanımlı RS-232 uçlardan TX,RX,CTS,DTR ve Toprak bağlantıları mutlaka bulunmalıdır. Eğer sistemde seri uç çoklayıcı donanım kullanılıyorsa ve bu donanıma ilişkin sürücünün parametrik bilgileri varsa UNIX ortamına uyumlu olmaması olasılığına karşın seri uçların tümünde protokol tanımı "NO PROTOCOL" biçiminde hazırlanmalıdır. Bu özellikler yoksa fcntl komutu ile seri uc, protokolsüz çalışacak biçimde düzenlenmelidir.

      3. Seri uç donanımı UART kurallarına uygun ise seri uc iletişim hızı en çok 38400 olabilir. Bu hızın üzerinde iletişim kurmak söz konusu olduğunda, işletim sisteminin özel komutları varsa kullanılmalıdır. Unutulmaması gereken özellik seri uç iletişim hızı 9600, 19200 ve 38400 olabilir. Diğer ara hızlarda seri uç ile iletişim kurulamayabilir.

    • Seri uç parametrelerini düzenleme

      UNIX ortamında seri uçların kullanım biçimi terminal kullanımına göre düzenlenmiştir. Burada Break tuşu, yazılamayan karakteri çevirme özelliği gibi bazı tanımlar önceden terminal sürücü programı tarafından düzenlenmiş filitreler oluşturulmuştur. Bu düzenleme seri uçtan bir bilgi okuma veya seri uca bir bilgi yazma adımlarında istenilmeyen sonuçlar verebilir. Özellikle çevre birimini kontrol etmeyi amaçlayan karakterler (STX, ETX, NULL gibi), filitrelerden geçmeyebilir. Seri uç programları ham veri işleme konumunda iken işletim sistemi ve sürücü programlar tarafından düzenlenmiş filitrelerin parametrelerini değiştirmelidir. Parametre değiştirme işlemi fcntl komutu ile yapılır.

      fcntl komutu için kullanılacak parametrik bilgilerin alabileceği değerler :

      c_lflag = 0;
      c_iflag = IGNPAR | IXANY | IGNBRK;
      c_oflag = 0;
      
      for(a=0;a < NCCS;a++)
          c_cc[a] = 0;
      
      c_cc[4] = 1; /* karakter sayısı            */
      c_cc[5] = 1; /* zaman asımı bekleme süresi */
      
      c_cflag = CLOCAL | CS8 | CREAD | baud_rate;
      
      olarak tanımlanabilir.

    • Ham bilgi okuma ve yazma kuralları

      UNIX ortamında bir kütükten ham bilgi okuma read komutu, bir kütüğe ham bilgi yazma write komutu ile olur. Seri uçlara ham bilgi (donanım karakter tabanlı olduğu için), bir byte gönderme veya bir byte okuma biçimindedir. Tamponlanmış giriş/çıkış işlemi yapılmamalıdır. Hız açısından (özellikle bilgi gönderirken) tamponlanmış bilgi alış verişi yapılacaksa, tampon alan kontrol edilmeli, tampon alan dolduğunda gönderme durdurulmalı, boşalınca tekrar başlatılmalıdır. Terminal kullanımına ait olan XON/XOFF protokolü ham veri işleme konumunda kesinlikle kullanılmamalıdır. Çünkü bu bilgi (XON veya XOFF), gerçekte karşı taraftaki çevre birimine gitmesi gereken bir bilgi olabilir.

      Bilgi okurken en çok bir byte bilgi tamponlanmalı, mümkünse tampon alan boyu 0 olmalıdır.

      Bilgi okuma işleminde doğrudan read komutu kullanılacak olursa program, okuma işlemi yapılmadan bu komuttan çıkmaz. Ama çevre birimine bilgi gönderen ve çevre biriminden okuma yapan bu tür progamlara sistem içindeki bir başka işlemden bilgi akışı olabilir. Bu durumda çevre biriminden okunacak bilgi yoksa program bir başka işleve geçebilmeli, kendisine gelen bir başka bilgi veya mesaj olup olmadığını anlayabilmelidir.

      UNIX ortamında kesinti (Interrupt) olanağı olmadığından, bu bilgi doğrudan işletim sistemi kontrolu altında olduğundan seri uç okuma programında read komutu yerine select komutu kullanılmalıdır. Bu komut ile açılmış kütüklere ait kütük numaralarından bir küme oluşturulur. Oluşturulan kümeden bilgi gelmesi beklenir. Eğer kümenin hiçbir elemanından bilgi gelmiyorsa belirtilen zaman aşımında işlev, hata kodu ile programa döner. Eğer bir bilgi gelmiş ise, kümedeki kütüğün numarası programa döner. Bu durumda program, ilgili kütükten gelen bilgiyi okur.

    • Örnek program tanımı

      Örnek olarak seri uçtan gelecek bilgi protokol gereği

        <STX><mesaj><ETX><LRC>

      biçiminde olsun. Program bu mesajı alınca önce LRC denetimi yapacak daha sonra mesaj doğru alındı ise ACK gönderecektir. Hata varsa NACK gönderecektir.

    • Örnek program kodu

      #define NACK 0x15
      #define ACK  0x06
      #define ETX  0x03
      #define UPD_NFDS(x) if(nfds<(x))nfds=(x)
      
      main()
      {
      fd_set fdx;
      struct timeval tv;
      struct termios term;
      int nfds = 0;
      char c;
      int  s, fd, sec, msec;
      
      fd = open("/dev/tty00",2);
      
      /* seri uc tanimlarini duzenleme */
      tcgetattr(fp_prt,&term);
      term.c_lflag = 0;
      term.c_iflag = IGNPAR | IXANY | IGNBRK;
      term.c_oflag = 0;
      for(a=0;a < NCCS;a++)
          term.c_cc[a] = 0;
      /* karakter sayısı */
      term.c_cc[4] = 1; 
      /* zaman asımı bekleme süresi */
      term.c_cc[5] = 1; 
      term.c_cflag = CLOCAL|CS8|CREAD|B9600;
      tcsetattr(fp_prt,TCSANOW,&term);
      
      sec = 0; msec = 100;
      tv.tv_sec  = sec;
      tv.tv_usec = msec;
      FD_ZERO(&fdx);
      FD_SET(fd,&fdx);
      UPD_NFDS(fd);
      
      while(1) {
          lrc = 0;
          s = select(nfds+1, &fdx, NULL, NULL, &tv);
          if(s >= 0) {
              /* STX okunur */
              read(s,&c,1);    
              /* mesajin kalani ETX dahil
              okunur ve LRC hesaplanir */
              while(c != ETX) {
                 read(s,&c,1);
                 lrc = lrc ^ c;
                 }
              /* LRC okumak icin */
              read(s,&c,1);
              /* LRC hatasi varsa NACK gonder */
              c = (c != lrc) ? NACK : ACK;
              write(s,&c,1);
              }
          }
      }
      

      Bu örnek programda, kodlamayı kısaltmak için hattan gelen mesajın protokoldaki yapıda sonuna kadar hatasız geleceği varsayılmıştır.

  • TERMİNALLER İÇİN TÜM EKRAN (FULL SCREEN)
    PROGRAM YAZMA TEKNİKLERİ

    Bu bölümde yer alan anlatım için kullandığınız UNIX program geliştirme ortamındaki curses kitaplığı yayınlarına bakmak, varsa diğer özel işlevleri de kullanmak gerekebilir.

    • Karakter tabanlı ekranlarda tüm ekran kullanımı (curses)

      UNIX ortamında karakter ekranlar satır satır kayan komundadır. Tüm ekranı (24 x 80) karakter biçiminde kullanmak. Yazılan her harfi anında algılayabilmek ancak ham bilgi alma ve yazma konumunda geçerlidir.

      Ham bilgiyi ekrandan alma ve ekrana yazma işlemi UNIX program geliştirme ortamında curses kitaplığı ile mümkündür.

      curses gerçek anlamda bir ekranı ham veri işleme konumunda kullanan kitaplıktır. Bu kitaplıkta yer alan işlevlerle uygulama programları ekrandan bir karakter okur, ekrana bir karakter yazabilir. Halbuki komut konumunda yazılan bilgi UNIX tarafından Enter tuşuna basılmadan işleme alınmaz. Komut konumundaki bu mantığa tampon alandan okuma tekniği denir. Ham veri işleme konumunda ise program yazılan her tuşu anında algılar, tuşun gereği olan işlemi anında gerçekleştirir.

      curses önce ekranı ham veri işleme konumuna alır. Daha sonra tüm ekranın iki kopya olarak bilgilerini saklar. Birinci kopya görüntülenen ekran, diğeri ise program tarafından günlenen ekran alanıdır. Her refresh komutu çalıştığında, curses iki kopya arasındaki farklı karakterleri belirler ve yalnız bu karakterleri ekrana gönderir. Bu nedenle curses ekran üzerindeki bir karakterin nereye yazılabileceğini bilmelidir. Her ekranın karakter görüntüleme komutları üretici firmalara göre değiştiğinden, ekran özellikleri termlib veya termcap veri tabanındaki tanımlardan alınır. curses kitaplığının doğru çalışması için kullanılan terminalin özellikleri termlib kitaplığına tanıtılmalıdır. Bu işlem için tic komutu kullanılır. curses UNIX kullanıcısının çevre değişkenlerinden TERM bilgisini kullanarak hangi terminal ile çalıştığını saptar ve ekrana bilgiyi bu terminalin özelliklerine göre gönderir.

    • Ekran tanımlama

      Bir ekranı ham veri işleme konumuna almak için curses kitaplığındaki initscr, cbreak, noecho, nonl işlevleri sıra ile kullanılır. Bu işlemler ekranı ham veri işleme konumuna alır.

      Ekranı tekrar komut işleme konumuna almak için echo ve endwin işlevlerini çalıştırmak gerekir.

      Ekran ham veri işleme konumuna alındığında curses kitaplığı bu ekran için bir gösterge tanımlar. Bu göstergenin adı stdscr olarak belirlenmiştir. Terminal, ham veri işleme konumuna alındığında tuş takımından girilen bilgi iki biçimde algılanabilir. Ya program tuş takımı bilgilerini de ham olarak okur uygulama içinde karakterlerin ne anlama geldiğini belirler, ya da curses kitaplığı basılan bir tuşun termlib kitaplığındaki karşılığını bulup ilgili tuş değerini çevirilmiş olarak programa döndürür. Bu işlem için keypad işlevi çalıştırılır.

      Yukarıda tanımlanan işlevlerle ekran ham veri işleme konumuna alındığında move, getch, addch işlevleri kullanılarak bilgi, ekranın istenilen yerine yazdırılır veya tuş takımından okunur.

      Bir ekrana istenilen bilginin çıkması için refresh işlevinin çalıştırılması gerekir.

    • Pencere tanımlama

      stdscr altında bir veya daha çok pencere açmak, pencerelere hareket ettirmek curses kitaplığı kullanımı ile mümkündür. Pencere açma işlevi newwin ile yapılır. Burada pencerenin ekrandaki (stdscr) başlangıç noktası ve boyutları belirtilir. Açılan pencere werease, delwin gibi işlevlerle kapatılır.

      Bir pencere kapatılınca ekrandan silinmesi için daha önce açılmış pencereler touch işlevi ile yenilenmeli, böylece kapanan pencerenin bıraktığı boşluk değir pencereler ile doldurulmalıdır.

    • Pencereden bilgi okuma, pencereye bilgi yazma

      Pencereye bilgi yazarken pencerenin içindeki imleç adreslemesi pencerenin sol üst kösesine göre (0,0) kabul edilerek hesaplanır. Böylece pencerenin hareket ettirilmesi, yerinin değişmesi programlarda yeniden hesaplama yapmayı gerektirmez.

      Bir pencereden bilgi okurken wgetch işlevi kullanılır. Aynı pencereye bilgi yazmak için waddch işlevi kullanmak gerekir. move işlevi yerine imleç hareketi için wmove işlevi kullanılır.


Ana Sayfaya   Teknik Bilgiler Sayfasina


Aglar Aglink Agteknik C-Kodlama C-Önişleme CRC/LRC DEA etcsrv Çatal (fork) ilet inetd Make Msg Auth Özyinelemeli Robotlar için SDLC Güvenlik Seri uçlar SNA LU0 SNA LU6.2 tcp/ip tcp Programı Unix vi Editör