CCS-C Encoder okuma ve seri iletişim

gets fonksiyonu girilen stringin sonunda \n var mı diye bakıyor ve varsa okumayı kesip \n olan yere 0 koyuyor. (\n=enter tuşu) Size gönderdiğim program çalışıyor. Sadece lcd.c dosyasında ciddi değişiklikler yapılmış olduğundan maalesef kitapta gördüğünüz yazım çalışmayabilir.
Kod:
#include <16f877.h>     // Kullanylacak denetleyicinin ba?lyk dosyasy tanytylyyor.
#fuses XT, NOWDT,NOBROWNOUT, NOPUT

#use delay (clock=4000000) // Gecikme fonksiyonu için kullanylacak osilatör frekansy belirtiliyor.
#use rs232 (baud=9600, xmit=pin_C6, rcv=pin_C7, parity=N, stop=1) // RS232 protokolünün 9600 bit/sn baud hyzynda olaca?yny ve
                                                                  // TX,RX uçlarynyn hangi pinler olaca?yny tanymlyyor
                                                                  // parity bitinin olmady?yny, stop bitinin 1 bit olaca?y belirtiliyor
//#define use_portd_lcd TRUE   // LCD B portuna ba?ly
#include <lcd.c>   // lcd.c dosyasy tanytylyyor

char   klavye[80];  // klavye isminde 80 üyeli bir dizi tanymlanyyor

#int_rda   // RX ucuna veri gelince meydane gelen kesme
void serihaberlesme_kesmesi ()
{  output_high(pin_c5);  // RC5 çyky?y lojik-1
  // klavye=getch(); // String ifadeyi al ve "klavye" adly dizi de?i?kenine aktar.
   gets(&klavye[0]);
   printf("\n\rYazdiginiz Metin>  %s\n",klavye); // Satyr atla, yeni satyr,RS232 üzerinden klavye string ifadesini gönder,satyr atla
   printf(lcd_putc,"\f%s",klavye);  //LCD'yi temizle ve klavye string ifadesini LCD'de göster
   output_low(pin_c5); // RC5 çyky?y lojik-0
   printf("\n\rKlavyeden bir metin giriniz ve enter tusuna basiniz>"); // Satyr atla, yeni satyr,RS232 üzerinden belirtilen metni gönder
}

/********* ANA PROGRAM FONKSYYONU********/

void main ( )
{
   setup_psp(PSP_DISABLED);        // PSP birimi devre dy?y
   setup_timer_1(T1_DISABLED);     // T1 zamanlayycysy devre dy?y
   setup_timer_2(T2_DISABLED,0,1); // T2 zamanlayycysy devre dy?y
   setup_adc_ports(NO_ANALOGS);    // ANALOG giri? yok
   setup_adc(ADC_OFF);             // ADC birimi devre dy?y
   setup_CCP1(CCP_OFF);            // CCP1 birimi devre dy?y
   setup_CCP2(CCP_OFF);            // CCP2 birimi devre dy?y

   output_low(pin_c5); // RC5 çyky?y ilk anda syfyrlanyyor
   lcd_init();   // LCD'yi hazyrla

   
   printf("\r**************** Merhaba *********************"); // Yeni satyr, RS232 üzerinden belirtilen metni gönder ve satyr atla.
   printf("\n\rKlavyeden girdiginiz bilgiler LCD'de gorunecektir\n\n"); // Satyr atla, yeni satyr, RS232 üzerinden belirtilen metni gönder
   printf("\n\rKlavyeden bir metin giriniz ve enter tusuna basiniz>"); // Satyr atla, yeni satyr,RS232 üzerinden belirtilen metni gönder

   enable_interrupts(int_rda); // int_rda kesmesi aktif
   enable_interrupts(GLOBAL);  // Aktif edilen tüm kesmelere izin ver
   printf(lcd_putc,"\fDeneme");  //LCD'yi temizle ve klavye string ifadesini LCD'de göster

   while(1) // Sonsuz döngü
   {
   }
}
 
Hocam çok teşekkür ediyorum, evet kod çalışıyor sağolunuz.

Benim hatam kodda osilatör frekansını belirtmenin isis için yeterli olduğunu sanmammış.

Sağolun hem siz hem SALIH-46 hocam ikaz edince isiste default olarak pic frekansının 1 mhz olduğunu gördüm, onu 4 yapınca terminalde karakterleri olduğu gibi gördüm lcd'de de.

Sizlere çok teşekkür ediyorum sağolunuz.
 
ze_tr hocam selamlar.

Hocam size bir şey danışmak istiyorum.

Burada denediğim kodda rda kesmesini sürekli aktif yaptığmda (isiste) terminalde bir karaktere bastığım an kesme aktif olduğundan akış duruyor, bu reelde bir sorun oluşturur diye düşünüyorum.

Bu yüzden rda kesmesi içinde disable yapıp, kol dengeye geldiği anda tekrar rda kesmesini enable etmeyi düşünüyorum, sizce bu sağlıklı bir yöntem mi yada başka bir öneriniz olur mu?
 
Kod:
#int_rda   // RX ucuna veri gelince meydane gelen kesme
void serihaberlesme_kesmesi ()
{
...
}

/********* ANA PROGRAM FONKSYYONU********/

void main ( )
{
...
   enable_interrupts(int_rda); // int_rda kesmesi aktif
   enable_interrupts(GLOBAL);  // Aktif edilen tüm kesmelere izin ver
...
   while(1) // Sonsuz döngü
   {
   }
}
Kesme içerisinde kesmeyi disable etmenizin mantığını anlamadım. Yani seri porttan \n karakteri gelmez ise orada takılır kalır mı demek istiyorsunuz? Zaten ana göngüye döndüğünüzde enable ediyorum diyorsunuz. O zaman disble ve enable komutlarınızın hiç bir anlamı kalmıyor. Benim size yazdığım şekilde kod çalışır. Hem kullandığınız PicMicro datasheetine bakın, hem de CCS kullanım kalvuzuna bakın benim yadığım şekil doğrudur. Siz kesmeye gidince gelen bilgiden başka bilgi gelmesin mi istiyorsunuz tam anlayamadım. Yukarıdaki mesajımda da gösterdiğim gibi RDA kesmesinin kullanımı bu şekilde olacak. Siz while döngüsü içerisinde birşeyler yaptırıyorsunuz ve seri porttan bilgi geldiğinde kesmeye gidip ister 1 baytını okutup dönersiniz, ister geri kalan bilgileri de okutursunuz.

Seri porttan göndereceğiniz bilgi herhalde en fazla 5 bayt civarında olacaktır (gets() fonksiyonunu picte kullandığınıza göre sayıları PC den ascii kodla göndereceksiniz ve gönderme bittiğini belirtmek için de \n göndereceksiniz). 9600 bps hızında 5 bayt en fazla 5 ms de gönderilir. 19200 bps te 2.5 ms kadar bir süre. Dolayısıyle bilgi almada bir sorun yaşamazsınız. ISIS'te tabi ki 5 baytı 5 ms de yazabilseydiniz belki de bu soruyu sormayacaktınız. ISIS'te terminal ekranından girdiğinizi karakterlerden sonra enter tuşuna basıyorsunuz değil mi?
 
Merhabalar, öncelikle konu ile ilgili verilen faydalı bilgiler ve düzeyli bilgi alışverişiniz için teşekkür ediyorum, çok faydalı oldu bana bu bilgiler.

Benim yapmak istediğim Enkoderi olan bir DC motorun pozisyon kontrolünü yapmak. Halen araştırıyorum ama kafamda bir şeyler oluşturamadım.

Öncelikle seri porttan pic 'e bir referans pals değeri göndermem gerek. Referans değer - ise motor - yönde değer + ise + yönde dönecek. Motoru L298 ile süreceğim. Yani PC'den pic'e pic'ten de L298 entegresine, motor için "true false" ve sayıcı için "referans pals" değerini aktarmam gerekiyor. Bunu nasıl yapabilirim ?

İkinci olarak picf16877 ile pals sayacağım ve seri porttan göndermiş olduğum referans pals değerine ulaştığımda motoru durduracağım. Bu durumda istediğim pozisyonda durmuş olacak . Yalnız burada hassas konum için pwm kontrol mü yapmam gerekir mi ?

Üçüncü sorum , derleyici olarak PIC C compiler (CCS) kullanıyorum . Pals saydırırken kesme kullanmalı mıyım ? Yoksa TMR0 kullansam pals kaçırma riskim var mıdır?

Şimdiden yardım ve fikirleriniz için teşekkürler. Yapabilirsem devreyi buraya ekleyeceğim.Bu işi çözersek "Pc seri port" üzerinden pozisyon kontrolü adına güzel bir örnek olacağını düşünüyorum.
 
Kesme içerisinde kesmeyi disable etmenizin mantığını anlamadım. Yani seri porttan \n karakteri gelmez ise orada takılır kalır mı demek istiyorsunuz? Zaten ana göngüye döndüğünüzde enable ediyorum diyorsunuz. O zaman disble ve enable komutlarınızın hiç bir anlamı kalmıyor. Benim size yazdığım şekilde kod çalışır. Hem kullandığınız PicMicro datasheetine bakın, hem de CCS kullanım kalvuzuna bakın benim yadığım şekil doğrudur. Siz kesmeye gidince gelen bilgiden başka bilgi gelmesin mi istiyorsunuz tam anlayamadım. Yukarıdaki mesajımda da gösterdiğim gibi RDA kesmesinin kullanımı bu şekilde olacak. Siz while döngüsü içerisinde birşeyler yaptırıyorsunuz ve seri porttan bilgi geldiğinde kesmeye gidip ister 1 baytını okutup dönersiniz, ister geri kalan bilgileri de okutursunuz.

Seri porttan göndereceğiniz bilgi herhalde en fazla 5 bayt civarında olacaktır (gets() fonksiyonunu picte kullandığınıza göre sayıları PC den ascii kodla göndereceksiniz ve gönderme bittiğini belirtmek için de \n göndereceksiniz). 9600 bps hızında 5 bayt en fazla 5 ms de gönderilir. 19200 bps te 2.5 ms kadar bir süre. Dolayısıyle bilgi almada bir sorun yaşamazsınız. ISIS'te tabi ki 5 baytı 5 ms de yazabilseydiniz belki de bu soruyu sormayacaktınız. ISIS'te terminal ekranından girdiğinizi karakterlerden sonra enter tuşuna basıyorsunuz değil mi?

Hocam mesele şu.

Şimdi bizim sistem biraz hassas olacağından belki encoder milisaniyede bir pals üretecek, seri porttan bilgi gönderildiği an kesmeye gidiliyor ve bu sırada üretilecek palsleri kaçıracağım endişesi taşıyorum.

Bu yüzden diyorum acaba bilgisayardan veri gönderildikten sonra, kol istediğim konuma gelinceye dek rda kesmesini pasif mi yapsam.

Ben henüz devreyi kurmadım şu an herşeyi isis üzerinde denemeye çalışıyorum, isiste terminal ekranına rakamı yazmaya başladığım an kesmeye giriliyor ve enter bilgisi bekleniyor, bu arada pic'ten pwm sinyali çıkmaya devam ediyor.

Reelde ben bilgiyi vb ile göndereceğim ama bu esnada da pasl kaçırabilirim diye düşünüyorum, o yüzden size bunu danışmak istedim.

Şu an denediğim kod tam sizin tavsiye ettiğiniz şekilde, main yordamında while döngüsü öncesi rda kesmesini enable ediyorum ve bu kesme için başka da bir işlem yapmıyorum.
 
Pals saydırırken kesme kullanmalı mıyım ? Yoksa TMR0 kullansam pals kaçırma riskim var mıdır?

Arkadaşım merhaba.

Bu konularda henüz yeterli bilgiye sahip değilim, ustalar mutlaka söylediğimde hata varsa düzelteceklerdir.

Şu ana dek pic'ler hakkında yaptığım incelemer neticesi, eğer hassas kontrol yapacaksan pals sayma işini donanıma bırakman yani kesme içinde bu işi yapmanın en garanti yöntem olduğunu söyleyebilirim.

Tabi hatam varsa ustalar düzeltir.
 
Öncelikle seri porttan pic 'e bir referans pals değeri göndermem gerek. Referans değer - ise motor - yönde değer + ise + yönde dönecek. Motoru L298 ile süreceğim. Yani PC'den pic'e pic'ten de L298 entegresine, motor için "true false" ve sayıcı için "referans pals" değerini aktarmam gerekiyor. Bunu nasıl yapabilirim ?
aktaracağınız referans puls değeri en fazla kaç olacak? Eğer 32bin küsür (=65536/2) değerini geçmiyor ise doğrudan 2 bayt sayısal değerini gönderebilirsiniz. ilk 15 bit puls sayısını, 16. bit +,- yönü olarak kullanılabilir. Eğer ASCII kodlarıyla göndermek istiyorsanız işi biraz uzatmış olursunuz.
İkinci olarak picf16877 ile pals sayacağım ve seri porttan göndermiş olduğum referans pals değerine ulaştığımda motoru durduracağım. Bu durumda istediğim pozisyonda durmuş olacak .
Timer1 counter modunda çalışacak şekilde, CCP Compare modunu kullanarak işinizi görebilirsiniz. Puls sayısını CCP1 değerine yüklemeniz gerekir. Yalnız sayı eşit olunca DC motoru durdurmanız durumunda ataletten dolayı istediğiniz konumun ötesine geçebilir. O nedenle hedef puls sayısının atıyorum yarısına kadar hızlı gelin, sonra 3/4 üne kadar daha yavaş bir hızla gelin, en son (dc motor durunca ataletten ilerleme olmayacak hızda hedef puls sayısına kadar gelip durdurun).
Yalnız burada hassas konum için pwm kontrol mü yapmam gerekir mi ?
Evet.
Üçüncü sorum , derleyici olarak PIC C compiler (CCS) kullanıyorum . Pals saydırırken kesme kullanmalı mıyım ? Yoksa TMR0 kullansam pals kaçırma riskim var mıdır?
CCP kesmesini kullanacaksınız. Pulslar tam kare dalgaya yakın olmalı. Sinusoidal ise ve gerilim düşük ise, A portundaki analog comparatorlerden birini (dahili referans voltajını datasheetten seçebilirsiniz), comparator çıkışını timer1 bacağına yönlendirin.
Motorun çok yavaş hareketinde puls oluşmayabilir. Deneyerek bu minimum hızı bulup, bunun altına düşmeyecek şekilde programınızı yazın.
 
Şimdi bizim sistem biraz hassas olacağından belki encoder milisaniyede bir pals üretecek, seri porttan bilgi gönderildiği an kesmeye gidiliyor ve bu sırada üretilecek palsleri kaçıracağım endişesi taşıyorum.

Bu yüzden diyorum acaba bilgisayardan veri gönderildikten sonra, kol istediğim konuma gelinceye dek rda kesmesini pasif mi yapsam...
Sorununuz kesmelerle ilgili değil. Gelen bilgiyi alma ile ilgili. Kesme rutininde gets() fonksiyonu ile değil getc() fonksiyonu ile bilgileri birer birer alıp ana programa döneceksiniz.Yalnız her aldığınız bilgiyi öyle saklayacaksınız ki, gelen bilgi tamam olduğunda (değişken boyutta bilgi ise atıyorum \n karakteri geldiğinde) sakladığınız bilgilerden orjinal bilgiyi elde etmelisiniz. eğer gelen bilgiler sabit sayıda ise (atıyorum 2 bayt ise) ilk gelen bilgiyi aldığınızda bilgi sayacı 0 ise 1 yapın, ikinci gelende (bilgi sayacı 0 dan farklı olduğu için) bu sayacı +1 yapın. Tabi bu arada gelen bilgileri bir dizi içerisine (indisi sayaçla gösterin) saklayın. Toplam gelecek bayt sayısına ulaştığınızda sayacı sıfırlayın. Dizideki bilgileri işleyin. Birer birer bayt okuma işleminde kesmeye gidip gelme zamanı size göre çok çok kısadır (bana göre çok uzun sayılır).

Kesme kullanmadan da işinizi görebilirsiniz. Ben genelde bunu tercih ederim.

Kod:
while(1){
  if(KbHit()){
    // Kesmenin içindekiler buraya
  }
}
 
Öncelikle hızlı cevaplarınız için teşekkürler.
Timer1 counter modunda çalışacak şekilde, CCP Compare modunu kullanarak işinizi görebilirsiniz. Puls sayısını CCP1 değerine yüklemeniz gerekir.

PICF16877'de CCP portu sanıyorum 2 adet var, ben 3 adet motor için bu dediklerinizi bir pic16f877 üzerinde yapabilir miyim? Yoksa compare modunu program içinde halledip
(yani if (pals=x) { motor = 0 ); } gibi yazıp sadece giriş çıkış pinlerini kullansam olur mu ?
 

Forum istatistikleri

Konular
130,111
Mesajlar
933,222
Kullanıcılar
453,175
Son üye
dogukankaragoz

Yeni konular

Geri
Üst