avatar_Mucit23

İki Pici seri olarak haberleştirme

Başlatan Mucit23, 13 Mayıs 2012, 22:46:50

Mucit23

Merhabalar arkadaşlar.
Bugün 2 işlemciyi seri olarak haberleştirmek istedim. Bir türlü senkronizasyonu yakalayamıyorum her nedense. Aslında iki işlemcininde Uart birimi var fakat gönderici ünitede uartı başka amaçla kullanıyorum. Belki alıcıda kullanılabilir.

Gönderici ünitede Serout2 komutuyla 2400 baund ile gönderiyorum. İki işlemcide 4 mhz de çalışıyor.

Gönderici veriyi göndermek için aşağıdaki gibi bir komut kullanıyorum.


KREDi_GONDER:
   SEROUT2 PORTB.1,396,["MCT",KREDi] 
   SEROUT2 PORTB.1,396,["MCT",KREDi] 
   SEROUT2 PORTB.1,396,["MCT",KREDi] 
RETURN


Belki yakalayamıyordur diye 2-3 defa üst üste gönderiyorum ama oda olmuyor. Problem alıcıda buna eminim.

Basit bir program yazdım gelen veriyi görmek açısından alıcıda işlemci olarak 16F628 kullanıyorum.
DEFINE OSC 4

@ __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _MCLRE_off & _LVP_OFF & _CP_OFF

TRISA=%00000000
TRISB=%00000010
PORTA=0:PORTB=0

CMCON=7

symbol DTA=PORTB.5
SYMBOL CLK=PORTB.7
SYMBOL KLT=PORTB.6

DLY    VAR WORD
SAYI   VAR BYTE
X      VAR BYTE
SYC    VAR BYTE
BIR    VAR BYTE
IKI    VAR BYTE
VERI   VAR BYTE

BASLA:
  SERIN2 PORTB.1,396,[WAIT("MCT"),VERI]
  X=VERI DIG 0:GOSUB AL:BIR=SAYI
  X=VERI DIG 1:GOSUB AL:IKI=SAYI
  SHIFTOUT DTA,CLK,1,[BIR,IKI]
  PULSOUT KLT,1
GOTO BASLA

DELAY5:
   FOR DLY=0 TO 5000:PAUSE 1:NEXT
RETURN

AL:LOOKUP X,[63,6,91,79,102,109,125,7,127,111,64],SAYI :RETURN

END


Veri gönderdiğimde osiloskopla veri akışının olduğunu görüyorum data hattında. Gerçekte ise arada RF modül kullanmayacağım. Direk data hatlarını birleştirerek haberleştireceğim. Zaten arada 2mt bir kablo var.

Problem sizce nerede olabilir.
Bir ulusu yok etmenin En iyi yolu o ulusun dilini yok etmektir.

www.arectron.com/

ete

#1
Bana kalırsa yollanacak bilgiyi 3 defa değil bir defa yolla bu bir. İkincisi bilgiden önce uyandırma yolla .

Aslında bu sistem çok sağlıklı çalışmayacak zira Serxx komutları timeout ile çalışmıyor. Çalışıyor deniliyor ama çalışmıyor maalesef.
Alma yapan program oraya istenenbilgi geinceye kadar çakılıyor ve her 65535 ms sonra bilgi gelmediği için komuttan çıkıyor. Tamda o sırada bilgi gelmiş ise maalesef senkron tutamıyordur. Çözüm uyandırma da yollamak. İşlemci uyandırma ile uğrşırken sen ardından gelen bilgiye yetişebilirsin.

Bu durumda yollama kısmı aşağıdaki şekilde değişecektir;
SEROUT2 PORTB.1,396,[REP$AA\5,REP$00\5,REP$FF\5]
SEROUT2 PORTB.1,396,["MCT",KREDi]

Dikkat edersen alıcı bilgiyi aldıktan sonra ayarlama yapıp shift registere yolluyor. Bu bir zaman kaybıdır. Verici ise muhtemelen bir takım işler yaptıktan sonra yollayacağı bilgiyi aktarıyor. İki tarafın bu şartlarda karşılaşmaları epeyce zor oluyordur. Bu bakımdan öncelikle veri yollama sıklığını bir şekilde artırman gerekiyor. Yada ne yapıp edip alıcı kısmı USART kesmesine bağlaman lazım aksi halde bir takım ayarlamalar yapıp senkron tutturman gerekecek.
Ben olsam TMR1 syacını kullanarak iki veri yollama aralığını bulmaya çalışırdım. Gerçek programda olmayacak bu zaman hesaplama yöntemi ile en azından ne kadar zamanda bir veri yollanıyor onu bulurdum. Sonra alıcının veri alındıktan sonra yeniden veri alma işlemine geçmesi arasındaki süreyide hesaplardım. Sonra bunları bir birine denk getirecek bir çare bulmaya çalışırdım.  Yada haberleşmeyi çift taraflı yapıp hand-shake yani el sıkışma protokolü uygulardım. Kısaca biri bilgi yolladı diğer alıncaya kadar bekler. Bilgiyi alınca aldım diye haber verir. Diğeri o onay gelmeden bir başka bilgi yollamaz. Belirli süre onay gelmemiş ise yeniden eski bilgisini yollar. Onay gelince gider yenisini alır ve yeniden yollar. Buna benzer bir protokol oluşturabilirsin.

ete

Mucit23

Hocam Alıcıyı uart kesmesine sokabilirim ama onuda bir türlü yapamadım. Kesmeyi kuruyorum bilgi gönderdiğimde kesme oluşuyor fakat gelen veriyi alamıyordum. Zaten Data hattını 16F628 in Rx pinine bağlamışım. Yani uart kullanacağımı biliyordum.

Birde şöyle bir problem var hocam .
Uartı açtığım zaman Uart bildiğiniz üzre RX ve TX pinlerini devamlı hıgh konumunda tutuyor. Şimdi ben gönderici ünite ile alıcı üniteyi direk bağladığım zaman arada bir seviye uyuşmazlığı yaşanıyor. Çünkü Göderici ünitede uart kullanılmadığı için devamlı olarak data hattını lowda tutuyor. Bu bir problem olurmu acaba bilmiyorum.

Ben tekrar uarta bir bakayım hocam.
Çok çok zorda kalırsam hocam birtanede uyandırma hattı çekerim. bir kablodaha fazla gidecek. Gönderici ünite veri göndermeden önce uyandırma hattını 1 yapar. Sonra veriyi gönderir. 
Bir ulusu yok etmenin En iyi yolu o ulusun dilini yok etmektir.

www.arectron.com/

Mucit23

Yok hocam kesmede işe yaramıyor. Veri gönderdiğimde kesme oluşuyor buraya kadar tamam fakat kesme oluştuğu zaman kesme alt programında veri alınamıyor.

Programı bu şekilde düzenledim.

@ __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _MCLRE_off & _LVP_OFF & _CP_OFF

TRISA=%00000000
TRISB=%00000010
PORTA=0:PORTB=0

DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 20h ' Enable transmit, BRGH = 0
DEFINE HSER_SPBRG 25  ' 2400 Baud @ 4MHz, 0,17%
DEFINE HSER_CLROERR 1 ' Clear overflow automatically
DEFINE HSER_BAUD 2400 ' BaudRate 9600
DEFINE OSC 4

symbol DTA=PORTB.5
SYMBOL CLK=PORTB.7
SYMBOL KLT=PORTB.6
SYMBOL RCIE =PIE1.5

INTCON=%11000000
ON INTERRUPT GOTO KESME
RCIE=1
CMCON=7

DLY    VAR WORD
SAYI   VAR BYTE
X      VAR BYTE
SYC    VAR BYTE
BIR    VAR BYTE
IKI    VAR BYTE
VERI   VAR BYTE
TEMP   var BYTE

BASLA:

  X=VERI DIG 0:GOSUB AL:BIR=SAYI
  X=VERI DIG 1:GOSUB AL:IKI=SAYI
  SHIFTOUT DTA,CLK,1,[BIR,IKI]
  PULSOUT KLT,1
 
GOTO BASLA

DELAY5:
   FOR DLY=0 TO 5000:PAUSE 1:NEXT
RETURN

AL:LOOKUP X,[63,6,91,79,102,109,125,7,127,111,64],SAYI :RETURN

DISABLE
KESME:
PORTB.0=1
INTCON.7=0
HSERIN ,5,ATLA,[WAIT("MCT"),VERI]
ATLA:
TEMP=RCREG
INTCON.7=1
Resume
enable

END


Kesmeye girip girmediğini anlamak için kesme alt programında hemen RB0 ı 1 yapıyorum. Portb.0=1 komutunu hserin komutuyla atla komutu arasına koysam komut işlenemiyor. Demekki program kesmeye gidiyor ama her nedense kesme alt programında veriyi alamıyor. 5ms verinin gelmesini bekleyip atla isimli etikete dallanıyor.

Bu durumu nasıl yorumlayabiliriz.
Bir ulusu yok etmenin En iyi yolu o ulusun dilini yok etmektir.

www.arectron.com/

ete

#4
5 ms nin senin verilerini almaya yetmediği şeklinde yorumlayabiliriz en başta.
5 ms yerine 50 ms yaz sonrasında haberleşmeyi yakalarsan süre ile oynayarak yavaş yavaş aşağıya çekersin.
Sonrasında programa bakmak lazım belki başka bir etken daha vardır.

Programlarına açılış gecikmesi vermiyorsun . Bu bir eksiklik. En başa başla satırından evvel 250 ms gecikme koy sonra kesmeleri aç. Bunu yapmaz isen başlangıçta registerler rastgele değer alabilir buda programın yanlış çalışmasına sebebp olur. Başlangıç gecikmesini alışkanlık haline getirmelisin.

Ete

Mucit23

#5
Hocam biraz gelişme oldu gibi. Şimdi programı aşağıdaki gibi yaptım.

Gönderici cihazın ilgili alt programı bu şekilde
KREDi_GONDER:
   SEROUT2 PORTB.1,396,[REP$AA\5,REP$00\5,REP$FF\5]
   SEROUT2 PORTB.1,396,[KREDi]  ;PANOYA VERi GÖNDER
;   SEROUT2 PORTB.1,396,[KREDi]
;   SEROUT2 PORTB.1,396,[KREDi]
RETURN


okuyucu programı ise budur.


@ __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _MCLRE_off & _LVP_OFF & _CP_OFF

TRISA=%00000000
TRISB=%00000010
PORTA=0:PORTB=0

DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 20h ' Enable transmit, BRGH = 0
DEFINE HSER_SPBRG 25  ' 2400 Baud @ 4MHz, 0,17%
DEFINE HSER_CLROERR 1 ' Clear overflow automatically
DEFINE HSER_BAUD 2400 ' BaudRate 9600
DEFINE OSC 4

symbol DTA=PORTB.5
SYMBOL CLK=PORTB.7
SYMBOL KLT=PORTB.6
SYMBOL RCIE =PIE1.5

INTCON=%11000000
ON INTERRUPT GOTO KESME
RCIE=1
CMCON=7

DLY    VAR WORD
SAYI   VAR BYTE
X      VAR BYTE
SYC    VAR BYTE
BIR    VAR BYTE
IKI    VAR BYTE
VERI   VAR BYTE
TEMP   var BYTE

PAUSE 100

BASLA:

  X=VERI DIG 0:GOSUB AL:BIR=SAYI
  X=VERI DIG 1:GOSUB AL:IKI=SAYI
  SHIFTOUT DTA,CLK,1,[BIR,IKI]
  PULSOUT KLT,1
 
GOTO BASLA

DELAY5:
   FOR DLY=0 TO 5000:PAUSE 1:NEXT
RETURN

AL:LOOKUP X,[63,6,91,79,102,109,125,7,127,111,64],SAYI :RETURN

DISABLE
KESME:
PORTB.0=1
INTCON.7=0
HSERIN 50,ATLA,[VERI]
HIGH PORTB.3
ATLA:
TEMP=RCREG
INTCON.7=1
Resume
enable
END


Bu şekilde yapınca bir anlıkda olsa veri alınıyor ekranda bir anlık bir kıpırdama oluyor ardından tekrar ekran 00 gösteriyor.

Ne yapmamı tavsiye edersiniz.

Edit;
Hocam biraz düşününce bu şekilde haberleşmenini doğru düzgün yapılamayacağı kanısına vardım. Çünkü senkronizasyonu sağlayacak clock yok.
Acaba tek hattan başka haberleşme yöntemlerini uygulayabilirmiyim. Mesela one wire ile haberleşebilirimiyim.

Yoksa bir tane clock hattı çekip Spi gibi yöntemlerlemi haberleşeyim. Uart beni çok uğraştıracak.

Hocam birde şunu sorayım.
Spi ile haberleştiğimi varsayalım.
Ben clock hattının Alıcıda RB0 a bağlıyayım. Sonra RB0 int kesmesini aktif edeyim. Şöyle düşünüyorum. RB0 değişiklik kesmesinde spi ilk clok palsinde kesme oluşursa eğer ben kesme alt programında geri verinin tamamını Shiftin gibi komutlarla alabilirmiyim.
Bir ulusu yok etmenin En iyi yolu o ulusun dilini yok etmektir.

www.arectron.com/

ete

#6
Bu konuda başka bir şey önermem mümkün değil.
Yapılacak şeyleri daha öncede söyledim. Kendi yolunu kendin bulacaksın çünki programlar senin elinde.

Veri değeri sıfırlanmadığına göre neden sonradan "00" şeklinde gösterim ortaya çıkıyor?
Bu oluyorsa program veri değerini sıfır olarak bir şekilde alıyor demektir bu. Sen asıl verici kısmını incele derim.
Sorun orada gözüküyor.

SPI gibi sistemi kullanmak mümkün. PORTB.0 dan kesme oluşturup programı oraya yönlendirmek ve ardından veriyi seri yoldan yollamak mümkün. Ben denemedim ama benzer uygulamalar görmüştüm.

Ete

Mucit23

Yok hocam veri değeride 0 oluyor. Ben Watch window ile izliyorum olup biteni değişen birşey olmuyor.
Benim anladığım kadarıyla olan biten şöyle aslında

Mesela işlemci Seri olarak sadece 1 verisini gönderirse data bacağından sadece bi clock palsi çıkıyor. Sorn burada bence. uyandırma sinyalinde en  son gönderilen 5 Byte FF bilgisini alıyor. Bir anlık 255 görüyorum gelen veride. Ardından tekrar gelen veri 0 oluyor.

Spi bana daha sağlam bir çözüm olur gibime geliyor. Tek endişem şudur.
Spi haberleşmede 1. Clock verildikten sonra alıcıda kesme oluşması lazım. Program hemen kesmeye gidecek ve tekrar kesme oluşmaması için tüm kesmeleri kapatacak. Ardından hemen diyelim 0. biti alıcak. ardından gelen clocklarla birlikte diğer bitleride alması gerekiyor. Shiftout ile Shiftin komutları çok hızlı çalışıyor. Bu belki problem yaratabilir. Belkide kontrolü ele almak açısından kendim shiftout ve shiftin komutlarını kendim yazarım. Hocam ben SPi üzerine bi uğraşayım.
Bir ulusu yok etmenin En iyi yolu o ulusun dilini yok etmektir.

www.arectron.com/

ete

Veri değeri kendi kendine sıfır olmaz. Senin data paketinin başında işaretçi var. Bu nedenle uyandırma sinyali içinden sistemin veri alması mümkün değil. Yalnızca işaretçi peşinden yollanan veri alınıp VERI isimli değişkene aktarılır. Bu nedenle gelenleri iyi izlemeni tavsiye ederim. Böyle şey ne gördüm nede duydum.

Ete

Mucit23

Arkadaşlar problemi çözdüm. Sorunun sebebi işaretçi kullanmamaktan kaynaklanıyormuş. Data göndermeden uyandrma sinyali ver ardından işaretçi ile birlikte veriyi göndermek gerekiyor. Bu şekilde çalıştırdım.
Bir ulusu yok etmenin En iyi yolu o ulusun dilini yok etmektir.

www.arectron.com/

Burak

İşaretçiden kasıt nedir ?

SerOUT2 OUTPIN,396,["L","B","G",DAT]
  komutunda gördüğümüz "L" , "B" , "G" kısmı gibi mi ?
Ω Gens Una Sumus Ω

gergy

Konu ile direkt alakalı olmayacak ancak kesme (slave'de) kullanarak çalışan spi seri iletişim için örnek var mıdır? Sorma sebebim gerek picbasic pro gerekse protonda basit spi haberleşme örnekleri var ama slave'de kesme kullanarak yapan örnek göremedim.

Powered by EzPortal