9999 saydırma ve seri portla okuma

Başlatan rustuuckun, 16 Ekim 2008, 17:42:29

rustuuckun

arkadaşlar ben 9999a kadar sayabilen ve aynı zamanda bu bilgiyi seri portla bilgisayardan okuyabileceğim bir devre örneği arıyorum. 16f84 pic ile yapılan örneği gerçekleştirdim ama bana aynı zamanda seri portla bağlanabilen bir devre lazım. Programlama bilgim çok az olduğu için ve zamanım da çok kısıtlı olduğundan yardıma ihtiyacım var. belki aynı asm kodunu 16f628 e de yükleyip kullanabilirim ama benim devremde tüm port çıkışları kullanılır olduğu için rx ve tx kullanmaya yer kalmıyor. Acaba ne yapmalıyım?

Tagli

Belki daha büyük (daha fazla bacağı olan) bir PIC kullanabilirsin, 16F876 ve 16F877 olabilir. Veya seri iletişimi yazılımsal olarak sağlayabilirsin. Eğer veri alacaksan RB0'a ihtiyacın olacak kesme özelliği için (veya belki B portundaki 4 pinden birinin değişimine bağlı kesmeyi de kullanabilirsin). Sadece veri göndermek istiyorsan herhangi bir bacağı seri iletişim için programlayabilirsin. Sorun şu ki seri iletişim için gereken sürede (9600 baud rate ile yaklaşık 1 ms) PIC başka işlem yapamaz.

Ekleme: Aslında RB0 haricinde de okuma yaptırabilirsin sanırım. Yanlış hatırlamıyorsam PicBasic Pro'da bunu yaptırabiliyorduk ama olayın gerçekte nasıl çözüldüğünü (yani ASM ile) bilmiyorum. Büyük ihtimalle timer kesmesi kullanarak bacağı sürekli yokluyordur değişiklik var mı diye.
Gökçe Tağlıoğlu

rustuuckun

çok sağol verdiğin bilgi için. Yalnız ben 16f84 için yazılmış alım ve verim kodlarını buldum seri port için. yalnız bunları benim sayıcım için nasıl kullanacağımı bilmiyorum. Ayrıca denediğim bilgisayara veri göndermede hyper terminalde anlamsız işaretler görüyorum. Bunları anlamlı hale nasıl getirebilirim bilmiyorum. Bu arada ben sadece pc'ye sayıcımın bilgisini göndermek istiyorum.

lamercik

Aslında formda çok cevap veren birisi olmama rağmen içimden bu soruya cevap vermek geldi birden. Herneyse dönelim konumuza.
seri haberleşmede tek tercih bana göre USART'ı olan işlemciler olmalıdır. bunun nedenlerini ise çok fazla tartışmaya açmak istemiyorum. eğer bir sayıcı yapmak istiyor vede bunu seri porta göndermek istiyor isen  Tagli isimli arkadaşında dediği gibi hem daha fazla bacağı olan hemde USART'ı olan 16F876 veye 16F877 gibi işlemcileri kullanabilirsin. 16F84ün tüm bacakları dolu demişsin, bacaklarda neler bağlı olduğunuda yazmış olsaydın daha da detaylı vermek isterdim.  877 işlemcisinin seri haberleşme rutinlerini ben sana vereyim.

void hatalari_sil(void)
{
               unsigned char d;
   if(OERR)
   {
      TXEN=0;
      TXEN=1;
      CREN=0;
      CREN=1;
   }
   if(FERR)
   {
      d=RCREG;
      TXEN=0;
      TXEN=1;
   }
}

karakter_gonder (unsigned char c)
{
   if(!TXIF)
   {
      hatalari_sil();
   }
   TXREG=c;
}

unsigned char karakter_al(void)
{
   if(!RCIF)  
   {
      hatalari_sil();
   }
   return RCREG;
}



main(void)
{
   TRISC=0X00;

//*************************************************
   SPBRG=25;  
   BRGH=1;    
   SYNC=0;
   SPEN=1;
   CREN=1;
   SREN=0;
   TX9=0;
   RX9=0;
   TXEN=0;
   TXEN=1;
              for( ; ; )
              {    
// bu döngünün içerisinde yapmak istediğin işlemleri sıralandır. örneğin
//seri porta bilgi göndermek için karakter_gonder('1'); yazman kafidir.
//sadece bilgi göndermek istediğine göre bilgi alışının nasıl yapılabileceği
//konusundaki alternatifleri çok fazla açıklamaya gerek görmedim.
//şimdilik söyleyeceklerim bunlardan ibaret. daha açıklamalı soru olmuş
//olsaydı daha açıklayıcı cevap yazmak isterdim  :D
//
               }
}

rustuuckun

verdiğin bilgiler çok sağol zaten sonradan bu sayıcı için şöyle bir değişiklik yapmaya karar verdim. Benim 9999 sayıcı devrem (16f84 ile) olduğu gibi duracak. Bu sayıcı devremde bütün bacaklar dolu ve bu bacaklardan 4 tanesi ondalık bilgisini displaye ve 7 tanesi display ledlerine komut vermekte 3 tanesi de reset, artma ve azalma butonları için ayrılmış durumda. fakat ben bu devremi hiç değiştirmemeye ve şöyle bir çözüme gitmeye karar verdim. Bu 9999 sayıcı devremin reset, artma ve eksilme botunlarını aynı zamanda yapacağım yeni devreme de bağlayacağım. Bu yeni devremde 16f628 kullanarak seri port üzerinden sayıyı bilgisayara göndereceğim böylece hem sayıcı devrem hem de 16f628 devrem ikisi de aynı bilgiyi verecek. Sizce bu çözüm yolu yanlış olur mu?

16f628 ile seri port iletişiminde daha çok yeniyim ve ayrıca her artma butonuna ve eksiltme butonuna basışta gerekli sayıyı seri porttan verecek assembly programını nasıl yazacağımı bilmiyorum. Acaba bana Assembly'de bunu yazabilir misiniz? Çünkü ben sadece assembly kullanıyorum.

Bir de 16f877 ile ilgili seri port iletişim örneği buldum. Sanırım seri port iletişim kodları 16f628 ile uyumludur değil mi? Ama benim bulduğum örnekte 1mhz ayarlanmış oysa bana 4mhz gerekli bunu nasıl kod ile ayarlayabilirim?

Tagli

Genel olarak uyumludur, ama seri iletişim için kullanılan bacaklar farklı. Bu bacakların ikisini de girişe ayarlamalısın (evet bence de saçma ama datasheet çıkış hattının TRIS'ini de 1 yapmamızı söylüyor). Datasheet'teki Tablo 12-4 ve 12-5 farklı kristaller için hız ayarını nasıl yapman gerektiği konusunda fikir verir. BRGH bitini de uygun şekilde ayarlamayı ihmal etme, hangi tabloyu kullanacağın bu bite bağlı.
Gökçe Tağlıoğlu

bigbey

http://www.4shared.com/file/68618459/8955c3ea/seridene.html

bir deneme çalışması vardı onu yukardaki linkte bulabilirsin.
saydırma işinide birileri yapar herhalde bu sıralar çok zamansız kaldım.
TA6R

rustuuckun

ilginiz ve yardımlarınız için çok teşekkür ederim arkadaşlar. Bu işte yavaş yavaş tecrübe kazanmaya başlıyorum sayenizde. Ama tabi biraz daha çalışmam gerektiğini anlıyorum.

Bir de şu saydırma işini nasıl yapacağım konusunda yardımcı olabilir misiniz acaba?

rustuuckun

Uzun uğraşlar sonunda pic16f628'in seri iletişim örneklerini kendi çalışmama uyarlayabildim ya da ilk adımı atabildim sanırım.
Benim amacım 9999 sayıcısı yapmak ve bu sayılan sayıyı her sayma olduğunda seri porttan göndermekti. Elimde (herkesin de kolayca
bulabileceği gibi) pic16f84 ile yapılan 9999 sayıcısı mevcut ve bu devreyi gerçekleştirdim.Fakat bu sayıyı porta göndermek için 628 kullanmak daha
akıllıca bir karar olur dedim. Bu sebebple şöyle bir çözüme gitmeye karar verdim. 628 ile farklı bir sayıcı devre yaparak bu devrenin +(artma) ve
-(Eksilme) ile reset tuşlarını birbirine bağlayarak çözmeye çalışacağım yani iki devre aynı sayıyı verecek fakat ikisi de birbirinden tamamen bağımsız olacak.

BU ARADA SADECE ASSEMBLY İLE PROGRAM YAZABİLİYORUM.

Soru1:   Sizce bu iki bağımsız devrenin yaratılması sorun olur mu?
Soru2:   628 ile yaptığım devrede sayma işlemini hexadecimal olarak 255'e kadar yaptırabiliyorum. Acaba sayma olayını ASSEMBLY ile onluk olarak 9999'a kadar
ayarlayabilir miyiz? Ya da hex olark 255'ten sonra saymaya devam etmesi için nasıl bir değişiklik yapabilirim?
Soru2:   Resimde ve proteusta verdiğim 628sayma uygulamasında max232 bağlandığında çıkıştaki virtual termnalde diğer terminaldeki bilginin aynısını alamıyorum.
Bunun sebebi ne olabilir?
Soru3:   Arkadaşlar benim araştırdığım bütün kaynaklarda picten bilgisayara veri yollarken picin TX ucu max232'nin Tin'den girip Tout'tan çıkarak portun Rx ucuna gidiyor
Ama şekilden ve proteus dosyasından da göreceğiniz gibi bende comun Tx ucuna bağlanırsa sonuç alınabiliyor (iki terminalin çıktısı farklı oluyor). Bunu AÇIKLAYABİLİR MİSİNİZ?

SORU4: Proteusta max232 yerine sadece 10k'lık bir direnç ile comun TX ucuna (RX değil) bağlantı yapılırsa istenilen sonucu alabiliyorum.
Acaba bu uzun ömürlü bir çözüm olur mu? Yoksa uygulamaya geçtiğim anda pic patlar mı?

(Özür dilerim rar dosyasını bir türlü yükleyemedim)

ASM KODU
LIST   P=16F628, R=DEC      ;Pic olarak 16f628 ve Onluk sistem kullanılacaktır.

#include "P16F628.INC"

__CONFIG  _LVP_OFF &_XT_OSC &_WDT_OFF & _PWRTE_ON & _BODEN_ON

CBLOCK   0x20            ;Değişken adreslerinin 0X20'den başladığını bildiriyor
dataL
ENDC
SAYI   EQU   0x35
OYLESINE   EQU   0x36


   ORG   0x00      ;Program 00'da başlıyor
   
;ANALOG/DİJİTAL Giriş olarak PORTA'nın ayarlanması

   movlw   7
   movwf   CMCON         ;Komparatörleri Başlatmak
   
;PORTLARIN BAŞLANGIÇ AYARLARI

   movlw   b'00000000'
   movwf   PORTA
   
   movlw   b'00000100'      ;RB2 (TX)=1 diğerleri 0
   movwf   PORTB
   
   bsf      STATUS,RP0      ;Bank 1'e geçiş
   
   movlw   0xFF
   movwf   TRISA         ;PORTA tüm pinleri giriş
   
   movlw   b'11110010'      ;RB7 ,RB4 ve RB1(Rx) giriş, diğerleri çıkış
   movwf   TRISB
   
;PC ile haberleşmek için BAUD RATE ayarlanması
;9600, No Parity, 1 Stop Bit

   movlw   0x19         ;0x19=9600 bps   (0x0C=19200 bps)
   movwf   SPBRG
   movlw   b'00100100'      ;brgh=high (2)
   movwf   TXSTA         ;Asenkron iletim açık
   
   bcf      STATUS,RP0      ;Bank 0'a geçiş
   
   movlw   b'10010000'      ;Asenkron alım açık
   movwf   RCSTA
   
;Başlamak için sürenin ayarlanması

         clrf   dataL
ayarlama   decfsz   dataL,F
         goto   ayarlama
         
         movf RCREG,W
         movf RCREG,W
         movf RCREG,W    ;Flaşın tamponu alması
         
;ANA DÖNGÜ
      
      clrf   SAYI
      clrw   
      call   gonder


genel   btfss   PORTA,0
      goto   dongu
      btfss   PORTA,1
      goto   azal
      goto   genel

azal   btfsc   PORTA,1
      goto   azal
azal2   btfss   PORTA,1
      goto   azal2
      goto   eksilme
   

dongu   btfsc   PORTA,0
      goto   dongu
yine   btfss   PORTA,0
      goto   yine
      goto   artma
   

artma   incf   SAYI,1
      movf   SAYI,w
      call   gonder
      goto   genel

eksilme   decf   SAYI,1
      movf   SAYI,w
      call   gonder
      goto   genel

;W'daki karakterin Gönderme bitene kadar bekleyerek RS232 yoluyla gönderilmesi

gonder
      movwf   TXREG      ;W'daki veriyi gönder

TransWt   bsf      STATUS,RP0      ;Bank 1'e geçiş
Wthere   btfss   TXSTA,TRMT      ;iletim tamamlanıyor
      goto    Wthere         
      
      bcf    STATUS,RP0      ;Bank 0'a geçiş
      return
      

;MESAJ

mesaj   movlw   'R'
      call   gonder
      movlw  'U'
       call   gonder
       movlw  'S'
       call   gonder
       movlw  'T'
       call   gonder
       movlw  'U'
       call   gonder
       movlw  ' '
       call   gonder
       movlw  ' '
       call   gonder
       movlw  'U'
       call   gonder
       movlw  'C'
       call   gonder
       movlw  'K'
       call   gonder
       movlw  'U'
       call   gonder
       movlw  'N'
       call   gonder
      movlw   0x0D         ;CR
      call    gonder
      movlw   0x0A         ;LF
      call   gonder
      return
   
   END