PIC ile Klavye Yapmak....

Başlatan XErTuX, 03 Kasım 2008, 02:18:33

XErTuX

Arkadaşalar öncelikle herkese merhaba bu forumdaki ilk mesajım...

Konumu tam olarak nereye yazmam gerektiğini bilemedim sanırım burası uygun...

Üniversite için bitirme projesi yapıyorum ve geçen senede heves edip üzerinde biraz araştırma yaptığım bu, pic ile klavye yapımını bu sene bitirmek istiyorum..

Geçen sene sadece assembly bildiğim için pc ile senkron haberleşme beni baya kastı ve bıraktım bu sene pic basic ile ilgilenmeye başladım hala başlangıç seviyesinde olmama rağmen assembly ile arasındaki farkı anlamış bulunmaktayım :)

ilk olarak pic 16f877 ile 28 transistörü ( elimde bulunan klavyenin içinden çıkan kartta 28 adet bağlantı ucu var ) sürüp klavyenin içindeki kartın girişlerine ( tuş takımından gelen mantiks girişler ) bağlayıp şasede kısa devre etme mantığıyla başladım... vede hangi tuşa basılacağını v.s. pice aynı zamanda yazabilmek için devre kartına birde seri portdan pic programlama sistemi ilave edicektim... ( nekadar amatörce )

Daha sonra daha az giriş çıkış portu olan ufak bir pic, ( Pic16f628 ? ) shiftout komutu ile 4 adet shift-register kullanarak 28 adet transistörü kontrol ettim programını yazdım devresini çizdim.....

Daha sonra boot loader denen devrim ile tanıştım nekadarda şahane idi alt+f10 yaptığımda programım direk picimde çalışacaktı bu nedenle bunu destekleyen 16f88 mikrodeneteleyicisine geçtim vede boot loader'a göre devremi tasarladım.....

Daha sonra ben neden bu klavye devre kartını sürüyorum ki? pic-basic bana bu basit seri iletişim imkanlarını sunuyor iken.. ve pic ile direk olarak anakarttaki klavye girişine bilgi göndermeyi hedef aldım....

araştırdım..

http://www.beyondlogic.org/keyboard/keybrd.htm

http://www.pcguide.com/ref/kb/const/op.htm

( alt kısımdaki next'e tıklayarak konu hakkında ilerliyebilirsiniz... )

bu bilgileri buldum...

Herneyse.. gördüğüm kadarıyla klavye ile bilgisayar 11bit seri olarak haberleşiyor fakat ben önceki denemelerimde shift-registerleri sürerken 4 adet register kullanmıştım ve her biri için arka arkada 8er bitlik sinyaller gönderiyordum fakat burda bir seferde 11 bit gödnermem gerekiyor... bunu nasıl yapıcağımı "bilmiyorum"...

Yakın çevrem spi denen birşeyi kullanmamı öneriyor bunun ne olduğunu ne işe yaradığın nasıl çalıştığını benim projemde kullanıp kullanamayacağmı "bilmiyorum"...

Linkleri incelediyseniz kafanızda birtakım şeyler oluşmuşdur muhakkak...

Acaba clk sinyali bilgisayara sürekli gitse vede data ucunda sürekli lojik 1 seviyesinde bir bilgi gitse,... ben sadece bir harf bilgisi göndermek istediğimde data ucuna lojik0 ( başlangıç biti ) ve daha sonrasında bilgimi gönderip daha sonra parity ????? ( bununda ne olduğunu "bilmiyorum" ) bitini göndersem ve daha sorna harfimi bitirmiş olmak için lojik1 ( bitirme bilgisi ) gönderip daha sonra data ucunu hiç sıfıra çekmeden başlangıç konumuna ( data lojik 1, clk sürekli devam etmekte ) getirsem nasıl bir sonuç alırım?...

Saat şuan 2 ve yarın okula gitmem için 6 da kalkmam gerekiyor vize üstüne vizeye giriyorum derslere çalışsam bunu yapamıyorum, kendimce bukadar ilerledim ve şuan beynim bunalmış durumda son çare olarak buraya yazdım.. yardım ederseniz çok sevinirim..

Lütfen xxx'e bak yyy'yi biraz araştır zzz'yi yap v.s. gibi kısa baştan savma bilgiler vericek olan arkadaşlar hiç yazmasın çünkü sıkıldım bıktım. Lütfen cidden yardım etmek isteyen bilgi bencili olmayan ve bildiklerini anlatan arkadaşlar "yorum" ve "yardım" etsinler, yön göstersinler, sanki kendileri yapıyorlarmış gibi düşünsünler..

Proje hakkında öğrenmek istediğiniz bişey olursa sorabilirsiniz "elimden geldiğince" ne yapmaya çalıştığımı anlattım. Bukadar yazdım umarım yardım eden bilirleri çıkar :) iyi geceler...

XErTuX

Parity bitinin ne olduğunu öğrendim...

Dijital haberleşmede doğrulama amaçlı kullanılan bir sistem..

Çift parity ve tek party olarak 2 ye ayrılıyor.

Çift parityde data bilgisi içinde bulunanan 1 bilgileri toplanıyor eğer sayı çift ise partiy biti 1 tek ise 0 yapılıyor. Daha sonra bu data ve parity bilgisini alan sistem aldığı dataya göre kendi parity bilgisini oluşturuyor ve gelen parity ile karşılaştırıyor. Böylece gelen data doğrulanmış oluyor.

sezgin05

Aşağıdaki linkde aynı soruya cevap aranmıştı.Bir bak belki faydası olur.
https://www.picproje.org/index.php/topic,8989

Tagli

Ben senin yapmaya çalıştığının tam tersini denedim: PS/2 klavyeyi PIC'e bağlamak ve gelen şeyleri LCD ekrana bastırmak. "İdare eder" seviyeside bir sonuca da ulaşmayı başardım. Bir çeşit menü sistemi de kurdum şimdi başka özellikler de eklemeye çalışıyorum. (Programı ASM ile yazıyorum)

SPI iletişimi tam bilmiyorum ama sanırım PIC'in içindeki mevcut modül 8 bitlik paketler yolluyor, start stop parity falan yok. Ama klavye bu şekilde çalışmadığı için bu modülü kullanman mümkün olmuyor. Çünkü klavye 11 bitlik paketlerle iletişim kuruyor, ve hatta kendisine gelen emirlere de ACK biti ile cevap veriyor. Ayrıca ben klavyeyi PIC'e bağladığım için clock üretme sorunum olmadı, onun yerine klavyenin ürettiğine göre RB0 kesmesi ile verileri aldım (Klavyeye emir gönderirken de yine onun clock'u kullanılıyor). Sen klavyeyi yapmakta olduğuna göre doğru (veya doğruya yakın) bir frekansta clock ürettirebilmen gerekiyor.

Bir diğer mesele de master durumunda olan bilgisayarın dilinden anlaman. Bilgisayar iletişimi sonlandırmak isterse senin slave olarak bunu yapman ve hat boşta olduğunda yarım kalan bilgiyi tekrar göndermeyi denemen gerek, ki bunun için de buffer'a ihtiyacın var. Baya karışık bir iş, konu hakkında fazla bilgim yok çünkü ben master cihaza göre program yazdığımdan fazla ayrıntısına girmem gerekmedi.

Bir başka mesele de klavyelerde birden fazla (sanırım 3 adet) scan code kümesinin olması. Bilgisayar hangisini kullanıyor emin değilim (büyük ihtimalle 2. kümeyi kullanıyordur), ama hangisini kullanacaksa bununla ilgili bir emir gönderiyor, galiba F0 ve ardından kümenin numarası. Klavye de buna FA (galiba) ile karşılık veriyor ve o andan sonra yeni kümeye göre scan code üretiyor. Sonuçta her ihtimale karşı senin klavyende 3 kümenin de yüklü olması gerekir.

Dediğim gibi, konu karışık. Aklıma gelen bir kaç noktaya değinebildim sadece. Umarım bir faydası olur...
Gökçe Tağlıoğlu

XErTuX



burda 2x 8 bit bilgi gönderdim bulduğum kaynaktaki sinyale benziyor biraz olur mu acaba?

Dediğim gibi bitirme bilgisini gönderdikten sonrada clk sinyalinin belli bir süre devam ediyor bu sorun oluşturur mu?

Sanırım hiç kasmadan shift registerler ile hazır bir klavye devre kartının girişlerini kısa devre etmek ama buda çok amatörce bir çözüm böyle birşey yapıcaksam var olan bir klavye sistemini kontrol edicek isem ne hayrı kalırki :(

Tagli

Clock'un devam etmesi sorun olur. Bilgisayar yeni bir veri geldiğini sanar. Ama clock yarıda (bilgisayarın geleceğini sandığı ikinci ve sahte paketin ortasında) kesilirse bilgisayarın nasıl bir tepki vereceğini bilmiyorum.

Ekleme: Bu arada, clock'un fazla gelmesinin sebebi nedir? Ayrıca grefikte clock'un sonundaki parity ve stop bitinin olduğu bölümde bir boşluk var, sanırım bunun da olmaması gerekiyor.
Gökçe Tağlıoğlu

XErTuX

Tüm sorunlarda burdan kaynaklanıyor; sadece 11 bitlik bir datayı nasıl gönderirim bilmiyorum bu yüzden 2 defa 8 bitlik data gönderiyorum. aradaki boşlukta bu yüzden oluyor pic'in 2. shiftout komutunu işleme süresince..

Ve işime burda yaramaz ama 16 bitlik bir datayıda tek seferde gönderemiyorum acaba ben mi yanlış yapıyorum. Mesela :

A var word
A= %1100110011001100
shiftout porta.1, porta.0, 1, [A/16]

Bu durumda 16 adet clock ile 16 bit veri gönderilmesi gerekemez mi?

benim şuan deneme olarak yapıtğım şey ise:

DEFINE SHIFT_PAUSEUS 10
A Var WORD
B VAr WORD
TRISA=0
ANSEL=0

PORTA= 03                  ;ilkten clock ve data uçlarının 1 olması için
pause 300                    
A= %01100100
B= %11111111
call cikis
goto bitir


cikis:  

PORTA= %01                                      ;başlangıç bitini bu şekilde yapıyorum resimdede gördüğünüz gibi bu komutla ilk clk gelmeden data ucu lojik0 oluyor.
SHIFTOUT PORTA.1, PORTA.0, 1, [A]     ;01100100 bilgisi
SHIFTOUT PORTA.1, PORTA.0, 2,     ;parity ve bitirme bilgisi için 2 adet lojik1 bilgisi.
PORTA= 03  
             
return


Durumum bu.

Tagli

Bence PicBasic Pro'nun SHIFTOUT özelliğini kullanma, çünkü bu şekilde 11 darbe üretemezsin. Bunu kendin yazmalısın. Ben ASM ile yazarken gerekli değerleri birbirinin devamı niteliğinde 2 değişkene (register) yerleştirdim ve bir değişkeni de 11 biti sayması için görevlendirdim. Tabi benim uygulamada clock zaten klavyeden hazır geliyor ve ben kesme ile her clock düşüşü belirlendiğinde en küçük biti data hattına koyup iki register'ı sırayla kaydırıyorum (Bu işlem klavyeye emir yollamak için).

Senin uygulamanda clock'u da sen üreteceğin için araya uygun bir gecikme fonksiyonu yazıp 11 biti benim anlattığıma benzer şekilde "dışarı kaydırma"lısın (shift out, Türkçe'yi parçaladım sanki :)). Elbette işin bitince data ve clock hatlarını serbest bırakmayı unutmaman gerekli.

Bir ayrıntı daha var: Master konumundaki bilgisayar istediği zaman clock hattını (Yoksa data mıydı? Tam hatırlamıyorum...) aşağıda tutarak iletişimi durdurabilir. Senin bunu algılayabilmen lazım. Clock'u (veya data'yı, hangisiyse artık) 1 yaptıktan sonra o bacağı sürekli kontrol edip 0'a düşmüş mü diye bakman gerekiyor. Eğer sen 1 yaptığın halde 0 okuyorsan master o hattı 0'a çekmiş, yani iletişimi kesmiş demektir. Bu durumda göndermeye çalıştığın şeyi hat müsayit olduğunda tekrar göndermek için bir buffer'da saklaman gerekli. Gerçi bazı durumlarda tekrar gönderme işi de farklı olabiliyor.
Gökçe Tağlıoğlu

XErTuX

Assembly'de biraz uğraştım ve 10101010 sinyalini gönderdim sanırım oldu gibi..


Programın şu şekilde:
İlk önce data ve clk uçlarında sürekli lojik1 var,
clk_start ( ilk başlangıç biti için ),
_1 ( lojik1 bilgisi için ),
_0 (lojik0 bilgisi için ),
parity_1 ( parity lojik1 bilgisi için ),
parity_0 ( parity lojik0 bilgisi için ),
clk_end ( bitirme bilgisi için )

şeklinde alt porgamlar oluşturdum mesela _1 alt programı:

_1
   movlw 0x03
   movwf PORTA   
   call timer_clk
   movlw 0x02
   movwf PORTA
   call timer_clk
   return

PortA nin 0. biti clk 1. biti ise data çıkışı, ilk önce ikisindede lojik 1 var çook kısa bi zaman geçikmesi sonra data halen lojik1 de devam ederken clk 0 a düşüyor ve yine çok kısa bir zaman geçikmesi. yani burda clk sinyalinin 1 saykılında datadan lojik 1 gidiyor. diğer alt porgramlarda hemen hemen aynı zaten...
Sorun şuki sadece 10101010 bilgisini göndermek için şunları kullandım:

           call clk_start
   call _1
   call _0
   call _1
   call _0
   call _1
   call _0
   call _1
   call _0
   call parity_0
   call clk_end

Sanırım picbasic'de " asm, endasm " komutlarını kullanarak yine picbasic'e geçmem gerek lookup komutu burda işimi hızlandırabilir?

Vede Tagli ustam yardımlarınız için minnettarım.

XErTuX

Sanırım bir sorunum var.

Picbasic'de clk sinyalinin her bir alternansı arasına koyduğum zaman geçikmesi pause 1 şeklinde ( sanırım en düşük değer bu? :S ( nasıl olur dahada düşük olması gerek )). Sanırım klavyenin bilgilerini göndermesi gereken frekans 20-30khz civarı.

Pause 1 komutu ile ancak pic'i 200mhz de ( :S ) çalıştırırsam 25khz lik saykılı olan clk sinyali alıyorum...

Fakat assembly'de böyle değil pic'e 3mhz çalışma frekansı gönderdiğimde 25khz clk sinyaline ulaşabiliyorum.

Bu konu hakkında ve mümkünse bilgisayardan veri okuma hakkında yardımcı olursanız çok sevinirim.

Yani demek istediğim clk ve data gönderdiğim pinler çıkış olarak ayarlanmış iken nasıl aynı zamanda bilgi alabilirim? Bilgi göndermek istediğim zaman Tris'i 0 normal durumlarda 1 mi yapmam lazım data okumak için?

Peki nasıl okuyabilirim yani hiç bilgim yok bu konuda mantığını kavrayabilmek için bir örnek program gibi birşey ile yardımcı olursanız çok sevinirim.

Vede klavyemin data ve clk çıkış uçlarına paralel olarak benim pic'den çıkan data ve clk'yı bağlayıp bilgiler göndericem ( direk bağlıyamıyacağım çünkü pc ile haberleşme kısımlarını kendi klavyem yapıcak ) bakalım işe yarayacak mı. Yarın yani bugün ( saat 03, yarın vizem var xD ) deniyeceğim sanırım.

Tagli

PicBasic Pro'da "PAUSEUS" diye bir komut var. Bunun yanına yazdığın süre mikrosaniye cinsinden beklenir (yani PAUSE 1 = PAUSEUS 1000). Ben yine de PIC'i mümkün olan en yüksek hızda çalıştırmanı öneririm (20 MHz kristal ile 5 MIPS'a ulaşırsın).
Alıntı yapılan: "XErTuX"Pause 1 komutu ile ancak pic'i 200mhz de ( :S ) çalıştırırsam 25khz lik saykılı olan clk sinyali alıyorum...
Bu arada, zaten PAUSE 1 ile PIC'i hangi hızda çalıştırırsan çalıştır 1 milisaniye bekler çünkü PicBasic Pro senin belirttiğin kristal frekansına göre PAUSE 1'i tam 1 milisaniye bekleyecek şekilde ayarlar.

Alıntı yapılan: "XErTuX"Bilgi göndermek istediğim zaman Tris'i 0 normal durumlarda 1 mi yapmam lazım data okumak için?
Evet, sanırım öyle. Zaten genelde bilgi göndermek istersin... Ama sorun şu ki sen bilgi gönderirken (ve hatta alırken de) clock'u dışarı çıkış olarak verirsin ama bilgisayar bu hattı 0'a çekebilir. Bunun nasıl belirlenebileceğinden pek emin değilim. Belki pin çıkışa ayarlıyken PORT'tan okusan o anki gerçek değerini alabilirsin ama düşük bir ihtimal, çünkü o zaman girişe ayarlamanın pek anlamı kalmazdı. Ama şunu da deneyebilirsin: Hattı PIC'in başka bir bacağına da bağlarsın ve o bacağı girişe ayarlarsın. Hattın 0'da olup olmadığını o bacağa bakarak kontro edebilirsin. Elbette burda dikkat etmen gereken şey "clock'un sen 1 yapmaya çalıştığın halde 0 olması", çünkü zaten normal çalışması sırasında sürekli olarak 1-0 arasında gidip gelecek.
Gökçe Tağlıoğlu

XErTuX

İyi geceler picprojenin yardımsever üyeleri :?  ve tagli ustam ;)

Bugün pic programlayıcımı edindim ve pic16f88'i programladım fakat sonuç olumsuz. Detayları açıklayayım..

Öncelikle, picin tanıtılması aşağıdaki gibi;

@ DEVICE pic16F88
@ DEVICE pic16F88, WDT_OFF 'Watch Dog timer kapali.
@ DEVICE pic16F88, PWRT_OFF 'Power on timer kapali.
@ DEVICE pic16F88, PROTECT_OFF 'Kod Protek kapali.
@ DEVICE pic16F88, MCLR_ON 'MCLR pini kullanılıyor.
@ DEVICE pic16F88, INTRC_OSC_NOCLKOUT 'Dahili osilatör kullanılacak
@ DEVICE pic16F88, FCMEN_OFF 'Fail-Safe clock monitor kapali.
DEFINE OSC 8 '8MHz clock ( picbasic'e pic'in 8mhz'de çalıştığını ve pause gecikmelerini buna göre ayarlamasını belirten kısım bu sanırım??? )

TRISA= %11111111 ( başlangıç için PORTA ( data ve clk uçlarının bulunduğu port ) giriş olarak ayarlı )
TRISB= 0
ANSEL= 0 ( PORTA analog değilde dijital i/o olarak ayarlı )
OSCCON= 11111 ( osilatör 8mhz olarak ayarlandı )
OSCTUNE= 000000  (osilatör hassas ayarı ortada yani 8mhz civari )
PORTB= %11111111 ( ilk durumda pic'in çalıştığını görmek için portb de bulunan herhangi bir led yanıyor )


daha sonra,

pause 1000 ( ilk harf kodunu göndermeden önce biraz bekliyorum )
PORTA= %11111111 ( Porta nin trislerini çıkış olarak ayarlamadan önce data ve clk ucunu lojik1 e çekiyorum, trisi çıkış olarak ayarlamadan önce yapıyorum çünkü trisi ayarlayıp daha sonra lojik1'e çekince data ve clk dahil olmak üzere çok kısa bir süre porta full lojik0 oluyor ve pc bunu start biti olarak görüyor )
call TRIS_0 ( PORTA trisini çıkış yapan alt program )
call harf_q ( q harfini gönderecek alt program )
call TRIS_1  ( tekrar porta giriş olarak ayarlanıyor )
goto bitir


harf_q: ( q harfi alt programı )
   call clk_start
   Call hex_5
   Call hex_1
   call parity_0
   call clk_end
   return

Burada da 10101000 bilgisi gönderiliyor.

Sinyalimiz:


Gördüğünüz gibi sinyal mesajımın sonunda vericeğim linktekiler ile aynı sanırım dahada iyi. Frekans olarak, 5microsaniyede yatay kare sayısı 15 proteusda pic'in çalışma frekansı 6mhz.

T=5x15=75
F=1/75=0,013Mhz = 13Khz
ki olması gerektiği gibi yoksa yanlış mı hesaplıyorum?


http://www.jkmicro.com/documentation/pdf/PS2Keyboard_EN.pdf

Burada Türk bir arkadaş bunu hazırlamış gayet yararlı oldu. Öğrendiğim bilgiye göre pic'in data ve clk ucunu aynı zamanda 10k direnç ile pull-up yaptım bu sayede hep pozitifte, ister ben ister pc sinyal göndersin sadece ozaman negatif'e düşüyor. )

http://www.computer-engineering.org/ps2protocol/

buradada ps2 nin çalışması incelenmiş pek farklı birşey yok, fakat...

The clock frequency is 10-16.7 kHz.  The time from the rising edge of a clock pulse to a Data transition must be at least 5 microseconds.  The time from a data transition to the falling edge of a clock pulse must be at least 5 microseconds and no greater than 25 microseconds.

Dediği gibi clk sinyal frekansı 10-16.7khz arasındadır diyor fakat 2. cümlede anlatılanlar ile benim sinyalim arasında uyuşmazlık var mı?

Birde şunu buldum fakat inceliyecek vaktim yok yatmam gerek;
http://www.atmel.com/atmel/acrobat/doc1235.pdf

Olan şey ise Data ve clk uçlarını aynı anda lojik 0 yaparsam sanki kavyede sapıkça 5-10 tuşa basarsınızda pc dıt dıt öterya o şekilde ses geliyor. Yukarıdaki sinyali gönderdiğimde tık yok. Ve birde kaynaklarda yazanlara göre pc den veri alıp okumam sadece opsiyonelmiş yani okumasamda pc veri göndermediği zamanlarda bilgi göndersem pc bunu alır yani senkronizasyon falan yapmaya gerek yok sanırım.

Şuan tıkanmış durumdayım çünkü devremi boarda kurdum program kendimce gayet sağlıklı çalışıyor proteusda ölçtüğüme göre çıkış sinyalim iyi fakat sorunun nerede olduğunu bilmiyorum.

Yardım ve önerilerinize ihtiyacım iyi geceler ( 04:01 )

XErTuX

Uff neden olmuyor acaba... :?

Yazdığına göre klavye çalışmadan önce klavyenin fonksionlarının aktif olup olmadığına dair bilgi göndermek gerekiyormuş. Klavye çalıştıktan 500-750msn sonra...

pause 600
PORTA= %11111111
call bat_success

bat_success:
   call start_bit
   Call hex_A
   Call hex_A
   call stop_bit_parity_1
   return


kaynak: http://www.computer-engineering.org/index.php?title=PS/2_Keyboard_Interface

Bir satırlık yorum, fikir yazsanız bile yeter :(  ben kurcalar birşey çıkartırım ama cidden tıkandım...

Tagli

Olmayan kısım nedir? Eğer bilgisayar bağladığında çalışmıyorsa belki bilgisayar arada başka komutlar da gönderiyordur ve senin program onlara cevap veremiyordur. Normalde aldığın her komuttan sonra "acknowledge" yollaman gerekli (galiba FA idi).

Ve sanırım 600 ms beklemene gerek yok. Bu süre klavyenin elektrik aldıktan sonra kendi kendini test edip de düzgün çalıştığından emin olması için gerekli, ve sonra da AA gönderir (hatta bunu yaparken ışıklarını yakıp söndürür). Sen zaten klavyenin düzgün çalıştığını varsayıp doğrudan AA yollayabilirsin bence (düzgün çalışmıyorsa bile bunu bilgisayara çaktırmamak lazım di mi?  :lol: )
Gökçe Tağlıoğlu

XErTuX

wow  :) Tagli ustadan başka kimse giriyor mu konuma bilmiyorum ama küfür etseniz yeri  :D

clk ve data uçlarını karıştırmışım data yerine clk, clk yerine data gönderiyormuşum  :mrgreen:

Uçları değiştirdiğim gibi çalıştı...

Fyuuuu bu hafta sonu mutlu geçicek demek ^_^

Bat bilgisi göndermeye gerek yokmuş. :) sanırım sadece pc açılırken biosa klavyenin çalışır olduğunu bildirmek için gerekli.

tekrar:
call harf_q
Pause 200
call harf_a
pause 200
goto tekrar


Gayet stabil qaqaqaqaq şeklinde yazı yazıyor.

Şimdi sıra bütün karakterleri tanımlamaya geldi vede daha sonra amatörce basit mantıkla yazdığım programımı geliştirebilirim. :)

Herşey için teşekkür ederim ciddi gelişmeleri paylaşacağım^_^