Merhaba arkadaşlar,
Yaklaşık 6 7 ay önce RS232 ile seri port haberleşmeli bir hesap makinesi yapmıştım. O projede bilgisayardan hyperterminal ile bir değer girip ascii kodlarını da kullanarak gercekleyebilmiştim. Ancak şu an önümde cok cabuk halledilmesi gereken başka bir RS232 projesi var. Projeyi 2 kanattan yürütüyoruz. Diğer arkadaş RFiD etiketli kartı kapıda okutuyor. Eğer kart daha önce oluşturulan vertabanında ise bilgisayara eşleşmenin başarıyla gerçekleştiğine dair 5 ya da 6 bytelık bir bilgi geliyor. Buraya kadar olan kısmı arkadaşım CSHARP programlama dili ile gerçekleştirdi. Buradan sonra benim bu bilgiyi RS232 ile bilgisayardan pic'e gönderip eğer gelen bilgi benim istediğim 5 Byte'lık bilgi ise pic'in daha önceden belirlediğim bir cıkıs portuna lojik 1 vermem gerekiyor. Yani kısacası aldığım veri onay ise pic ledi yakacak gibi düşünebilirsiniz. Şimdi benim burdaki sorunum şu: Hesap makinesi yaptığım zaman bilgisayara girilen bir karakter vardı ve getch() komutu ile bu karakteri alabiliyorduk. Ama burda basılan bir tuş olmadığı için getch fonksiyonunu kullanmam mantıksız olur sanırsam. Veriyi direk nasıl alabilirim ve kontrol olabilirim sizce.
NOT: Gelen veri 8 er bitlik 5 paket şeklinde sırayla gelecek yanılmıyorsam. Yani mesela 0xFF, 0x01, 0x01,0x11,0x00 olsun.
Arkadaşlar projeyi böyle yapmak yerine şu duruma indirgedik. Eğer bilgisayardan 00d11 gelirse onay;00y11 gelirse ret cevabı olacak. Onay cevabı: ledin yanması,ret cevabı: ledin yanmaması olarak düşünebilirsiniz. Yazdığım kodda önce char klavye[80] diye bir şey tanımladım daha sonra gets(klavye) dedim.(bunların hepsini rs232 interruptının içinde yapıyorum.) daha sonrada işte if(klavye=="00d11") vs. diyerek programı tamamladım. Ancak program if'li olan satırda hata verdi. Sebebini anlayamadım bir türlü. Sizce hata nerede olabilir? Kod burda:
#include "C:\Documents and Settings\hemso\Desktop\CCS\abc.h"
char klavye[80];
int i;
#int_rda
void serihaberlesme_kesmesi ()
{
disable_interrupts(int_rda);
gets(klavye);
if(klavye=="00d11")
{
output_high(pin_a2);
output_high(pin_a4);
output_high(pin_a3);
delay_ms(1000);
output_a(0x00);
break;
}
if(klavye=="00y11")
{
output_high(pin_a5);
for(i=0;i<3;i++)
{
output_high(pin_a3);
delay_ms(500);
output_low(pin_a3);
delay_ms(200);
}
output_a(0x00);
break;
}
}
void main()
{
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
//Setup_Oscillator parameter not selected from Intr Oscillator Config tab
set_tris_a(0x00);
output_a(0x00);
while(1)
{
enable_interrupts(int_rda);
}
}
CCS bilmiyorum ama if(klavye=="00d11") tırnaklar olacak mı?
Fırat Deveci hitech (soft) kitabında SPI kutuphane hazırlamıs guzel ornegı de var 15 dakıka harcanarak etkın olarak kullanılır dıye dusunuyorum.
Klavye string olacağı için burda bir sorun olmaz diye düşünmüştüm. Hatayı aldıktan sonra değiştireyim diye düşündüm ancak onun alt satırlarında klavye=="00y11" diye bir if li ifade var gene ama orada bir hata görünmüyor. hatta altta çıkan hatayı da yazayım. 1 warning bir de error görünüyor. Hata şöyle:
Warning 203 "rfid.c" line 54(1,1): Condition always true.
Error 44 "rfid.c" Line 12(1,1): Internal Error- Contact CCS LABEL SCR=332
1 Errors, 1 Warnings.
Warning çok önemli değil, muhtemelen while(TRUE) şeklinde bir satır için vermiştir.
Hata içinse; derleyici sürümünü yazmamışsınız ama eski bir sürümse güncelleme yapmanız durumunda sorununuz belki çözülebilir. (rfid.c'de ilgili satır nedir, bilmiyoruz.)
Alıntı yapılan: hemso - 11 Şubat 2011, 01:53:12
Arkadaşlar projeyi böyle yapmak yerine şu duruma indirgedik. Eğer bilgisayardan 00d11 gelirse onay;00y11 gelirse ret cevabı olacak. Onay cevabı: ledin yanması,ret cevabı: ledin yanmaması olarak düşünebilirsiniz. Yazdığım kodda önce char klavye[80] diye bir şey tanımladım daha sonra gets(klavye) dedim.(bunların hepsini rs232 interruptının içinde yapıyorum.) daha sonrada işte if(klavye=="00d11") vs. diyerek programı tamamladım. Ancak program if'li olan satırda hata verdi. Sebebini anlayamadım bir türlü. Sizce hata nerede olabilir? Kod burda:
#include "C:\Documents and Settings\hemso\Desktop\CCS\abc.h"
char klavye[80];
int i;
#int_rda
void serihaberlesme_kesmesi ()
{
disable_interrupts(int_rda);
gets(klavye);
if(klavye=="00d11")
{
output_high(pin_a2);
output_high(pin_a4);
output_high(pin_a3);
delay_ms(1000);
output_a(0x00);
break;
}
if(klavye=="00y11")
{
output_high(pin_a5);
for(i=0;i<3;i++)
{
output_high(pin_a3);
delay_ms(500);
output_low(pin_a3);
delay_ms(200);
}
output_a(0x00);
break;
}
}
void main()
{
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
//Setup_Oscillator parameter not selected from Intr Oscillator Config tab
set_tris_a(0x00);
output_a(0x00);
while(1)
{
enable_interrupts(int_rda);
}
}
Program dili olarak C dilini kullaniyorsunuz değil mi?
O takdirde su iki if dusundugunuz seyi yapmiyor
- if(klavye=="00d11")
- if(klavye=="00d11")
C dilinde arrayler (karakter dizinleride dahil olmak uzere) aslinda pointer'dir. Bu yuzden siz klavye string'inin saklandigin yerin pointer'ini (adresini) "00d11" yada "00y11" stringinin saklandigi yerin adresi ile karsilastiriyorsunuz. Buda herzaman "false" olur. (cunku literal stringler ROMda yada diger degiskenlerden ayri bir segmentda tutulurlar.
iki karakter stringini karsilastirmak icin run-time libraryden strcmp fonksiyonunu kullanmaniz gerekir.
if(1 == strcmp(klavye,"00d11") [veya daha cesursaniz if(strcmp(klavye, "00d11") :)
yada
if(1 == strcmp(klavye,"00y11") [veya if(strcmp(klavye,"00y11")]
seklinde.
Verdiğiniz bilgiler için çok teşekkür ederim. Bu bilgiler ışığında #include string.h kütüphanesini ekleyerek strcmp fonksiyonuyla dediğiniz işlemi yaptım. Bunun üzerine attempt to create..... tarzında bir hata verdi. Bende bunun üzerine strcmp(klavye,"00d11") yapmadım. 2 adet daha string tanımlayıp bu değerleri stringin içine attım(mesela onay[10]="00d11") ve if(strcmp(klavye,onay)) şeklinde iki diziyi karşılaştırdım ve sonuç olarak hiç hata vermedi. Şimdi kod işlevini yerine getiriyormu diye proteusta deneyeceğim. Umarım beklediğim gibi olur. Tüm yardımlarınız için tekrar teşekkürler. Bu siteyi seviyorum:D
Maalesef kod şu an işlevini yerine getiremiyor.gets(klavye) dedikten hemen sonra puts(klavye) dedim rs232 calısıyomu diye kontrol edebilmek için ancak herhangi bir şey cıkmadı ekranda...
if ile yaptığın karşılaştırmayı bytelara böl ayrı ayrı if içinde sınaya bilirsin ben olsaydım bu şekilde yapardım
programda mainin içine acaba rs232 calısıyormu diye deneme amaclı olarak printf("quaresma") yazdım ancak virtual terminal ekranında sacma sapan 3 tane harf cıktı. Önce bu sorunu halletmem gerekiyor sanırsam. Kodumun basında yazan ayarlamaları yaptıgım kütüphaneyi yazmamısım onu da belirteyim belki orada düzeltilmesi gereken bir şey vardır:
#include <16F88.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES EC_IO //External clock
#FUSES NOPUT //No Power Up Timer
#FUSES NOMCLR //Master Clear pin used for I/O
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOPROTECT //Code not protected from reading
#FUSES FCMEN //Fail-safe clock monitor enabled
#FUSES IESO //Internal External Switch Over mode enabled
#use delay(clock=20000000)
#use rs232(baud=19200,parity=N,xmit=PIN_B5,rcv=PIN_B2,bits=8)
Bu arada yukarıdaki xmit ve rcv pinleri yani RS232 aktarımının yapıldığı pinler project wizard dan ayar yaptığımda otomatik olarak a2 ve a3 görünüyordu. Ancak picteki donanımsal olarak görünen usart pinleri(TX ve RX) B5 ve B2 göründüğü için bunları B5 ve B2 pini haline getirdim. Bundan solayı oluşmuş bir sorun da deildir heralde.
Arkadaşlar beklenti cok düştüğünden ve projenin acelesi olduğunda projenin son hali şu. Bilgisayardan d harfi gelirse ledi yakacak, l harfi gelirse yakmayacak diye düşünün. Harflerin yanlış cıkma olayını da çözdüm bu arada. Bir terslik olmasın diye de int_rda kesmesini de kaldırdım. Pic başka birşey için kullanılmayacak çünkü zaten.Kod şöyle:
#include "D:\rflab\rfid_kapi\deneme1\deneme.h"
#include "string.h"
char klavye[10];
int i;
void main()
{
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
//Setup_Oscillator parameter not selected from Intr Oscillator Config tab
printf("quaresma");
while(1)
{
klavye[0]=getc();
putc(klavye[0]);
if(klavye[0]==100)
{
output_high(pin_a2);
output_high(pin_a4);
output_high(pin_a3);
delay_ms(1000);
output_a(0x00);
break;
}
if(klavye[0]==121)
{
output_high(pin_a0);
for(i=0;i<3;i++)
{
output_high(pin_a3);
delay_ms(500);
output_low(pin_a3);
delay_ms(200);
}
output_a(0x00);
break;
}
}
}
Sorun şu virtual terminal ekranında benim printf ile gönderdiğim quaresma yazısı cıkıyor. ancak daha sonra klavyeden yazdığım herhangi bir karakter ekranda yazmıyor. Burada getch ve putch yerine getc ve putc kullanmamın sebebi unexpected identifier hatası vermesiydi. Sizce sorun nerede?
Arkadaşlar sürekli yazıyorum kusura bakmayın ama size elde ettiğim gelişmeleri belirtip daha kolay bir çözüm üretebilmeniz acısından bilgilendirmek istediğimden tamamen. Şimdi anladığıma göre esas problem getchar kısmında. Çünkü proteus ta Pic'in TX ve RX pinlerine led bağladım ancak bir tek RX pinindeki led yanmaktaydı. Bunu nasıl çözebilirim?
bak arkadaş çok güzel anlatmış dostum picte 5 bytelık bir tx -rx registeri yoktur array vardır fakat ben kodunda gelen byteları array haline sıralayan bir yer göremedim bu yüzden 5 bytelık bilgisinin sonuncusunu yada karışık bir şey görebilirsin her neyse bu dikkat eet bu kısım önemli kolay gelsin
Lablarının kapısına rfid sistemi labdaki mühendis adayı öğrenciler tasarlıyor, işte bu! Ahmetcim seri data almanın en temiz yolu kesme ile almaktır, while içinde getch vs. ile almak sağlıklı olmaz. Forumda int_rda diye aratıp çıkan başlıkları okumak çoook faydalı olur. Ben o başlıklardaki bir bilgiyi buraya yapıştırarak devam ediyorum:
//picproje.org
//CCS C seri veri kesmesi örnek kullanımı
#include <16F628A.h>
#fuses NOPROTECT, NOMCLR, NOWDT, NOLVP, INTRC_IO
#use delay(clock=4M)
#use rs232(baud=9600, xmit=PIN_b2, rcv=PIN_b1)
unsigned int veri=0;
void main(){
enable_interrupts(global);
enable_interrupts(int_rda);
while(1){
output_high(pin_b4);
delay_ms(1000);
output_low(pin_b4);
delay_ms(1000);
}
}
#int_rda
void seri_veri_geldi(){
veri=getc();
output_toggle(pin_b0);
}
Bu kodda PIC normal seyrindeyken b4 e bağlı led flash yapıyor, veri geldiğinde değer "veri" değişkenine yazılıyor ve b0 pini toggle ediliyor, veri değişkeni global, main içinde de sorgulatabilirsin.
while(1){
output_high(pin_b4);
delay_ms(1000);
output_low(pin_b4);
delay_ms(1000);
if(veri=='A') //eğer A yazarsam aynıyla cevapla ;)
putc(veri);
}
yapıp deneyebilirsin.
Şimdi bu kod üzerinden devam etmelisin, elinde 1 byte veri geldiğinde kaçırmadan "veri" değişkenine yazan bir kod var başka ne lazım ki! Bu şekilde gelen stringleri de kontrol edebilirsin. CCS C deki gets fonksiyonu da bu mantıkla yazılmış, kütüphanesinde görebilirsin. Mesela seri data olarak gelen GPS cümleciklerinden önce $ karakterine bakan, $ geldiyse cümle GPGGA cümlesi mi diye kontrol eden int_rda rutini şöyle olabilir:
#int_rda
void seri_veri_geldi(){
veri=getc();
output_toggle(pin_d0);
if(veri=='$'){ // $ karakterini gördük
index=0;
out=0;
record=1;
i=0;
return;
}
if(record==1){
c[index]=veri;
index++;
if(index==5) //5 byte alındıysa
record=0;
if(c[0]=='G' && c[1]=='P' && c[2]=='G' && c[3]=='G' && c[4]=='A'){ //GPGGA cümlesi mi kontrol et
out=1; //GPGGA cümlesi, out=1, sıradaki bytle lar lcdye gidecek
i=0;
record=0;
c[0]=0;c[1]=0;c[2]=0;c[3]=0;c[4]=0; //temizle
}
return;
}
//...kod devam ediyor
Bu şekilde siz de kendi int_rda rutininizi yazmalısınız.
#int_rda
void seri_veri_geldi(){
veri=getc();
putc(veri);
output_toggle(pin_b0);
}
Yazarsan klavyeden yazdığını aynen geri alırsın.
İyi çalışmalar, kolay gelsin.
Hocam bunları yazdığım gün bilgisayar başında 7 saat oturduktan sonra durumu hallettim:D Daha sonra da şimdiye kadar foruma girmedim maalesef. Şimdi gördüm yazdıklarınızı. Benim elimde şu an çalışan bir kod var işlevini yapan:D. Bende paylaşım olması açısından diğer arkadaşlar da görsün diye koyuyorum buraya. Ama genede bence esas -işte bu!- denilecek şey sizin öğrencilerinize bu kadar yardımcı oluyor olmanız. Sizi çok seviyoruz hocam:D Kod şöyle:
#include "D:\rflab\rfid_kapi\deneme3(16f877)\deneme3.h"
#include "string.h"
int i;
char klavye[10];
#int_RDA
void RDA_isr(void)
{
disable_interrupts(int_rda);
for(i=0;i<5;i++)
{
klavye[i]=getchar();
putchar(klavye[i]);
}
if(klavye[0]=='0' && klavye[1]=='0' && klavye[2]=='d' && klavye[3]=='1' && klavye[4]=='1')/*bu kısım biraz kazmaca oldu ama artık sinir oldum en son böyle yazdım:D*/
{
output_b(0x0E);
delay_ms(1000);
output_b(0x00);
break;
}
if(klavye[0]=='0' && klavye[1]=='0' && klavye[2]=='y' && klavye[3]=='1' && klavye[4]=='1')
{
output_b(0x05);
for(i=0;i<3;i++)
{
delay_ms(500);
output_b(0b00000001);
delay_ms(200);
output_b(0b00000101);
}
output_b(0x00);
break;
}
}
void main()
{
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
enable_interrupts(GLOBAL);
set_tris_a(0x00);
output_a(0x00);
printf("quaresma");
while(1)
{
enable_interrupts(INT_RDA);
}
}
Başta Fatih hocama olmak üzere yardımını esirgemeyen herkese saygılar..
Rda kesmesinin içindeki şu kısım kafamı karıştırdı;
for(i=0;i<5;i++)
{
klavye=getchar();
putchar(klavye);
}
ilk '0' karakterini geldi klavye stringine atandı. i=1 oldu. 2. karakter alındı ve yine klavye= şeklinde diziye alındı. Dizi indeksi belirtilmeden 2. gelen karakteri klavye[1]'e 3. gelen karakteri klavye[2]'ye yerleştireceğini nasıl biliyor program?
string.h kütüphanesi eklemişsiniz, bununla bir ilgisi var mı?
@50Cal
for(i=5;i<10;i++)
{
klavye=getchar(); //a.
putchar(klavye); //b.
}
yazsanda aynı işi yapar, a. ve b. satır arka arkaya yazılsa 5 defa yıne aynı ısı yapar getchar klavyeden karakterı alıyor putcharda ekrana basıyor(neyse).
bır sonrakı karakter sonrakı haneye basılıyor aynı haneye basmak ıstersen b satırından sonra bırde backsspace koymak lazım.
yani putchar karakter bastıkdan sonra ne sayacı ıse artık bır artırıyor.
Teşekkürler, fakat sanırım sormaya çalıştığım şey yanlış anlaşılmış. For döngüsüyle ilgili bir sıkıntım yok, yani fordaki i değeriyle dizi indeksini karıştırmıyorum.
Anlayamadığım satır; klavye=getchar();
Bir stringimiz var, 2 byte olsun; klavye="xx" klavye[0]='x' ve klavye[1]='x'
klavye=getchar(); ile 'A' karakterini alıp klavyeye atıyoruz.Muhtemelen 0 indeksine atacaktır karakteri, yani: klavye="Ax" olmalı.
sonra bir karakter daha alıyoruz('B' olsun) ve yine klavye=getchar(); Bu satırdan sonra olmasını beklediğim durum şöyle; klavye="Bx" . Fakat arkadaşın uygulamasına göre klavye="AB" olmuş.
Yani öğrenmeye çalıştığım; program, bir stringin en son hangi elemanına karakter ataması yapıldığını ve sıradaki elemanın hangisi olduğunu nasıl biliyor? Stringe yada diziye bir atama yapıldığında dizinin o elemanın indeksi saklanıyor mu bi yerde?
O örnek düzeltilmiş sanırım :). Son halini yukarıda bir kontrol edin:
for(i=0;i<5;i++)
{
klavye[i]=getchar();
putchar(klavye[i]);
}
Teşekkürler hocam, düzeltip kaçmışlar, hiç söylemiyorlar da :P