Bu başlık, Arm öğreniyoruz ders konusunun C Programlamaya giriş başlığıyla alakalıdır. https://www.picproje.org/index.php/topic,35720.0.html (https://www.picproje.org/index.php/topic,35720.0.html)
C dilinde hiç çalışmamış fakat ARM işlemcilerle henüz uğraşmaya başlayan arkadaşlar, burada C konusuyla ilgili sorularına cevap bulacaklar.
STM32F-Discovery örnek temel programlar (https://www.picproje.org/index.php/topic,35896.msg256518.html#msg256518) https://www.picproje.org/index.php/topic,35896.0.html (https://www.picproje.org/index.php/topic,35896.0.html) başlığında geçen bazı satırlarda gördüğünüz
atama komutlarıyla ilk başlangıcı yapıyorum.
---------------------------------------------------------------------------------------------------
GPIOD->OSPEEDR= 0xFFFFFFFF;
Yukarıdaki kod ne demek?
C programlamaya giriş https://www.picproje.org/index.php/topic,35720.0.html (https://www.picproje.org/index.php/topic,35720.0.html) başlığında structure ve structure pointer yapısını göreceğiz.
Şimdilik GPIOD->OSPEEDR= 0xFFFFFFFF; Satırını, adı GPIOD_OSPEEDR olan registerin içine 0xFFFFFFFF hex sayısını yaz demek olduğunu düşünün.
---------------------------------------------------------------------------------------------------
İşletilen her C satırının sonu muhakkak ; ile sonlandırılmalıdır. (For, while gibi istisna komutlarlarda neden ; olmadığı daha sonra anlaşılacak)
---------------------------------------------------------------------------------------------------
Bir satırın en soluna // konursa o satır komut satırı olmaktan çıkar açıklama satırına dönüşür.
---------------------------------------------------------------------------------------------------
GPIOD->OSPEEDR |= 0xFFFFFFFF;
| OR işlemi demektir. Yukarıdaki komut GPIOD_OSPEEDR registerinde saklanan veri ile 0xFFFFFFFF verisini OR işlemine tabii tutup sonucu gerisin geriye
GPIOD->OSPEEDR registerinin içine yazar.
Aynı satırı GPIOD->OSPEEDR = GPIOD->OSPEEDR | 0xFFFFFFFF; olarak da yazabiliriz.
---------------------------------------------------------------------------------------------------
GPIOD->OSPEEDR &= 0xFFFFFFF0;
& AND işlemi demektir. Yukarıdaki komut GPIOD_OSPEEDR registerinde saklanan veri ile 0xFFFFFFF0 verisini AND işlemine tabii tutup sonucu gerisin geriye
GPIOD->OSPEEDR registerinin içine yazar.
Aynı satırı GPIOD->OSPEEDR = GPIOD->OSPEEDR & 0xFFFFFFF0; olarak da yazabiliriz.
---------------------------------------------------------------------------------------------------
Teşekkürler bunalmış hocam.
hocam şimi neden and kullandık neden or kullandık ?
Ne zaman OR ne zaman AND?
A adında degişkenimiz olsun. Bunun en düşük 2 bitine 10 verisi yükleyelim. Fakat A nın diğer bitleri değişmesin.
A= A & 0xFFFFFFFC; yada A&= 0xFFFFFFFC; En düşük bitleri sil (Diğer bitleri 1 ile AND'lediğimiz için değişmez)
A= A | 0x00000002; yada A|= 0x00000002; Silinmiş bitler 00, bunu 10 ile OR'la ve yerine yaz.
Böylece diğer bitler aynen kaldı fakat en düşük bitler 10 yapılmış oldu.
Eğer A registerine doğrudan A=0x00000002 yazsaydık en düşük 2 bit 10 olacaktı fakat diğerleri de 0 olacaktı. (Bunu istemeyiz)
-----------------------------------
Şimdiye kadar görmediğimiz NOT operatörü ile de aynı işlemi yapabiliriz.
A&= ~0x00000003; En düşük 2 biti (A1 A0) sil (Diğer bitleri 1 ile AND'lediğimiz için değişmez)
A|= 0x00000002; Silinmiş bitler 00, bunu 10 (Decimal 2) ile OR'la ve yerine yaz.
Alıntı YapGPIOD->OSPEEDR |= 0xFFFFFFFF;
| OR işlemi demektir. Yukarıdaki komut GPIOD_OSPEEDR registerinde saklanan veri ile 0xFFFFFFFF verisini OR işlemine tabii tutup sonucu gerisin geriye
GPIOD->OSPEEDR registerinin içine yazar.
hani insanın kafasında ampul yanar ya,
şu ufacık bilgi acayip yol aldırdı bana cok onemli noktalara degindiniz hocam
empatinin anlamını biliyosunuz.
#include "xxx.h"
Sıkı sıkı kalıplaşmış tanımlar yapmadan bazı konuları açıklayacağım.
#include "xxx.h"
Ne demek?
Mesela bir programın içinde aşağıdaki kirmizi ve mavi renkte yazdigim satırlar olsun.
int topla(int a, int b)
{
return(a+b);
}
int cikart(int a,int b)
{
return(a-b);
}
Bu programı böyle yazmak yerine şu şekilde de yazabilirim.
#include "xxx.h"
int cikart(int a,int b)
{
return(a-b);
}
Topla programını sakladım. Nereye sakladım?
Eğer notepad ile xxx.h dosyasını açarsanız içinde aşağıdaki satırları göreceksiniz.
int topla(int a, int b)
{
return(a+b);
}
#include dahil et demek. Neyi dahil edecek iki " içine alınmış dosyayı.
int a;
int b, c;
unsigned int d;
Bunlar ne demek?
ARM CM3 ve CM4 işlemcilerimizde, int, 32 bitlik işaretli tam sayılar demek.
int a; a değişkenim 32 bit uzunlukta ve işaretli tam sayı saklayabilir demek.
int b, c; b ve c değişkeni, 32 bit uzunlukta ve işaretli tam sayı saklayabilir demek.
o halde
int a;
int b, c;
yerine int a, b, c; yazabilirim.
İşaretli sayı ne demek?
İşaretli sayılar asm de de basic de de C de de kullanılmaktadır. Bu nedenle bu soruya cevap vermeyeceğim. Eğer işaretli sayı (2' complement numbers) ne demek bilmiyorsanız ARM kursuna katılabilecek seviyede bilgi birikiminiz yok demektir.
unsigned int a; ne demek?
a değişkeni 32 bit ve işaretsiz sayıları saklayabilir demek.
32 bitlik 0xFFFFFFFF sayısını, int a tanımlı değişkene yazarsam a ya decimal kaç sayısını yazmış olurum?
0xFFFFFFFF -1 demektir. Demekki a değişkenine -1 yazmışım.
32 bitlik 0xFFFFFFFF sayısını, unsigned int a tanımlı değişkene yazarsam a ya decimal kaç sayısını yazmış olurum?
0xFFFFFFFF (2^32) - 1 demektir. Demekki a değişkenine çok büyük bir sayı yazmışım.
Konuya destek olabilecek kaynak:
http://tr.wikipedia.org/wiki/%C4%B0kinin_t%C3%BCmleyeni
short char long ve long long ne demek
short a;
a değişkeni 16 bit ve işaretli tam sayı saklayabilir demek.
unsigned short a;
a değişkeni 16 bit ve işaretsiz tam sayı saklayabilir demek.
char a;
a değişkeni 8 bit ve işaretli tam sayı saklayabilir demek.
unsigned char a;
a değişkeni 8 bit ve işaretsiz tam sayı saklayabilir demek.
long a; a değişkeni 32 bit ve işaretli tam sayı saklayabilir demek.
long ile int aynı fakat ince bir trick varsa bilmiyorum.
long long a; a değişkeni 64 bit ve işaretli tam sayı saklayabilir demek.
unsigned long long a; a değişkeni 64 bit ve işaretsiz tam sayı saklayabilir demek.
hocam baslik yorumlara kapali olsa olmazmi yoksa gene 15-20 30 sayfa sürecek arada bilgielre ulasmak zor olacak ya da ilk 1. sayfada bilgiler olsa 2.sayfadan itibaren de yorumlar ne dersiniz ?
C konusunda anlatımların olacağı başlık ayrı. O kısım yorumlara kapalı. Burada şamata yapacağız.
Soruları olan varsa burda tarışırız.
Eğer, koyu renklı kırmızı yeşil ve siyah karakter kullanımını bana bırakırsanız bu başlıktaki anlatım mesajları bakınca hemen soru cevap mesajlardan ayırtedilir.
Alıntı yapılan: bunalmis - 24 Ekim 2011, 13:46:01
C konusunda anlatımların olacağı başlık ayrı. O kısım yorumlara kapalı. Burada şamata yapacağız.
Soruları olan varsa burda tarışırız.
tamam hocam peki bir soru bir ara c ile azda olsa ugrasmisdim
simdi c programi yazarken basicdeki gibi
goto lcd_yaz veya goto ana_dongu nasil yapilir?
bildigim kadariyla mutlaka main_void olmali ve bu anadongu yani ana programdir
diger fonsiyonlar
fonsiyon_1();
fonsiyon_2();
seklinde peki bu fonksiyonlari ben ana döngüde nasil cagirirm yani goto fonksiyon_1 nasil yaparim acaba?
saygilar
Basicde 5..10 satırlık kısa anlamlı bir kod yaz onu C'ye çevirelim.
Alıntı yapılan: bunalmis - 24 Ekim 2011, 13:51:29
Basicde 5..10 satırlık kısa anlamlı bir kod yaz onu C'ye çevirelim.
uzun zamandir basic ile yazmiyorum ama hemen yazmayi deniyeyim
start:
gosub led_yak
delayms 1000
gosub led_sondur
goto start
led_yak :
portb=%00000001
return
led_sondur :
portb=%00000000
return
end
Basic programın 1/1 C karşılığı
start:
gosub led_yak
delayms 1000
gosub led_sondur
goto start
led_yak :
portb=%00000001
return
led_sondur :
portb=%00000000
return
end
#include "Reglist.h"
void led_yak()
{
Portb=0x01;
}
void led_sondur()
{
Portb=0x00;
}
void delayms(int Dly)
{
.....
.....
}
int main()
{
while(1)
{
led_yak();
delayms(1000);
led_sondur();
}
return(0);
}
yada C ustadlari goto sevmese de
int main()
{
Start:
led_yak();
delayms(1000);
led_sondur();
goto Start;
return(0);
}
include "Delay.h"
void Led_yak(void);
void Led_son(void);
main(void)
{
Led_yak();
DelayMs(250);
Led_son();
}
Led_yak(void)
{
PORTB=1;
}
Led_son(void)
{
PORTB=0;
}
Alıntı yapılan: M_B - 24 Ekim 2011, 14:16:25
include "Delay.h"
main(void)
{
Led_yak();
DelayMs(250);
Led_son();
}
Bunalmış'ında seninde basit yaptığınız bir hata var. Yukarıdaki programda led sürekli yanıyor olcaktır. Bir delay daha gerekiyor.
main(void) un en asagida ve yukarida olmasi sanirim farketmez peki fonsiyorn cagirirken fonksion1(); yapioruzda niye goto kullanamioruz madem goto start diyebiliyorsak :)
Alıntı yapılan: eemkutay - 24 Ekim 2011, 14:39:11
Bunalmış'ında seninde basit yaptığınız bir hata var. Yukarıdaki programda led sürekli yanıyor olcaktır. Bir delay daha gerekiyor.
Bence hata yok. Verilen basic kodda ne varsa onun karsiligini yazdik.
Alıntı Yapmain(void) un en asagida ve yukarida olmasi sanirim farketmez peki fonsiyorn cagirirken fonksion1(); yapioruzda niye goto kullanamioruz madem goto start diyebiliyorsak
main fonksiyonunun asagida yada yukarida olmasi farkeder. Eger main icinden cagrilan fonksiyonlar main'in ustundeki satirlarda yazilmissa sorun yok. Fakat altindaki satirlara yazilmissa bu durumda main satirinin ustundeki satirlarda cagrilan fonksiyonlarin prototipi yazilmali. M_B nin yazdigi koda bakarsan bu prototip tanimlari goreceksin. Goto kullan. Ben bu gune kadar zararini gormedim. Fakat kullanilmamasi istenmesinin de hakli sebepleri var.
main üstte olduğunda altında tanımlayacağımız fonksiyonları en üstte derleyiciye bildirmemiz gerekiyo bildiğim kadarıyla
gotoyu fonksiyon dışına dallanmak için kullanamıyoruz sadece fonksiyon içinde hareket imkanı sağlıyor.
Alıntı yapılan: bunalmis - 24 Ekim 2011, 14:49:36
Bence hata yok. Verilen basic kodda ne varsa onun karsiligini yazdik.
O zaman dikkatte hata var. Gerçi hata bulmayı sevmem ama genel bu tür yanlışlıkları herkes yaptığı için yazmak istedim.
Alıntı yapılan: teknikelektronikci - 24 Ekim 2011, 14:42:20
peki fonsiyorn cagirirken fonksion1(); yapioruzda niye goto kullanamioruz madem goto start diyebiliyorsak
Bir ustteki cevabimda goto ile ilgili sorunu yanlis anlamisim.
function(); gibi bir ifade cagrilirken return adresi stacka atilir. Eger bu fonksiyona Goto ile gitmek mumkun olsaydi geri donus adresi olmayacagindan fonksiyon islenip bittiginde sistem sapitacakti.
Bunun bilincinde olan derleyici yazarlari goto komutu ile fonksiyon cagrilmasi satirina hata mesaji verdirerek derlemeyi sonlandirir.
Zaten sen de Basic de bahsettigin seyi yapamazsin.
Gosub function
end;
function: return
satirlarini
Goto function
end;
function: return
sekline donustursen ne olur?
int topla(int a, int b)
{
return(a+b);
}
Ne demek ?
Bu bir fonksiyondur.
Matematikte Y=A+B gibi ifadelere fonksiyon deriz. Yukarıdaki C kodları da buna benzer.
En solda görülen int, Fonksiyonun sonucunun tipini gösterir. int'ı yukarılarda bir yerlerde söylemiştik. 32 bit işaretli tam sayı demekti.
topla, fonksiyonumuzun adıdır.
Fonksiyon adından sonra muhakkak parantez olur.
Bu parantezin içinde fonksiyonda kullanılacak girdi verileri bulunur.
Bizim örneğimizde bu veriler int a ve int b imiş.
Gelelim fonksiyon ne yapıyormuş.
return(a+b);
Fonksiyon a+b işlemini yapıyor. Yani int a ile int b değerini topluyor.
Buradaki return ne demek?
int topla(int a, int b)
Burada en soldaki int, fonksiyonun geri döndüreceği sonucun integer olduğunu bildiyordu ya,
işte a+b işlemi sonucunda bulunan sayisal değer return içinde döndürülür.
return(geri dönecek değer)
eemkutay hocam;
Doğrusu şöyle olsa
include "Delay.h"
main(void)
{
Led_yak();
DelayMs(250);
Led_son();
DelayMs(250);
}
int topla(int a, int b)
{
return(a+b);
}
Gibi bir fonksiyonla toplama işlemi yapmak.
int sonuc;
sonuc=topla(3,5);
şeklinde toplama fonksiyonun çağırabiliriz.
bir başka örnek;
int sonuc,K;
K=5;
sonuc=topla(3,K);
bir başka örnek;
int sonuc,K,a;
K=5;
a=3;
sonuc=topla(a,K);
prototip dediginiz sanirsam
Led_yak(void) buradaki void ifadesidir öyle değilmi
daha dogrusu en üstteki
void Led_yak(void);
void Led_son(void);
ifadelerdir
Alıntı yapılan: eemkutay - 24 Ekim 2011, 15:12:07
O zaman dikkatte hata var. Gerçi hata bulmayı sevmem ama genel bu tür yanlışlıkları herkes yaptığı için yazmak istedim.
hocam basic kodu öylesine ornek yazdim yanip yanmamasi önemloi degil ;)
void Led_yak(void); // Bu bir prototip, yani adı sanı belli fonksiyonun girdisi ne çıktısı ne hepsi belli fakat içinde ne var belli değil
void Led_son(void); // Bu bir prototip, yani adı sanı belli fonksiyonun girdisi ne çıktısı ne hepsi belli fakat içinde ne var belli değil
Biraz eziyet olur fakat, programınızdaki tüm fonksiyonların prototipini tanımlarsanız daha sonra derlemede çok rahat edersiniz, kim kimin altında kim kimin üstünde arayışına yada yer değiştirmelere girmezsiniz.
yani () içinde ne var önemli toplada a ve b vardı burada void var parantez içinde void varsa programa fonksiyona gir neyapacağını orada gör diyoruz diğertürlü bunları götür topla getir diyoruz doğrumudur
....function(void) ile ....function() ayni anlama geliyor.
Buradaki void, fonksiyonun hiç parametre istemediğini anlatıyor.
------------------------
void function(....)
Buradaki void, fonksiyonun sonuç üretmediğini söylüyor.
int main()
{ .....
.....
}
Bu C kodlarimizin calismaya baslayacagi ana (ilk) fonksiyon.
ARM CM3 ve CM4 islemcilerde main fonksiyonunun donusu int tanimlanmalidir. Yani, int main() olmali.
En son satira return(0) yazabilirsiniz. Yazdigimiz programlarda mainden hic cikmayiz. Dolayisi ile return degeri olarak istediginizi yazabilirsiniz.
Su ana kadar yazilanlardan sonra asagidaki programi anlamis ve Y degerinin ne olacagini bulabilmeniz gerekiyor.
int f1(int i);
int f2(int i);
void main()
{
int A,Y;
A=f1(1);
Y=f2(A);
return(0);
}
int f1(int i)
{
return(2*i);
}
int f2(int i)
{
int k;
k=5+i;
return(3*k);
}
Eger Y yi dogru bulabiliyorsaniz C nin gerisi corap sokugu gibi gelir.
Tabiki cevap yazacaklarin C ile hic ugrasmamis arkadaslar olmasini bekliyorum.
Alıntı yapılan: bunalmis - 24 Ekim 2011, 23:27:46
En son satira return(0) yazabilirsiniz. Yazdigimiz programlarda mainden hic cikmamayiz. Dolayisi ile return degeri olarak istediginizi yazabilirsiniz.
Hocam return() yazmanın bize ne tur bir avantajı olurki. Benim duşuncem hiç bir faydası olmayacağı yonunde.
Program ana donguye (main) girdimi daha cıkmayacaktır. cıksa bile gittiği yerden geri donecektir. Tabi gittiği yerde kısır donguye girmediyse.
21 sanıyorum umuyorum galiba
yanlış yaptım sanıp düzelttim ama son kararım 21
hocam biraz c ile çalışmıştım ama olanda gitti.şimdi main fonsyonundan önce belirtilen fonsiyonlar bir nevi alt program.?main içinde onları dahil edebiliriz.tıpkı #include gibi.dosya değiilde komut dizilerini çağırıyoruz.peki örneğin int f1() nedir?gördüğüm kadarıyla fonksiyon için void oluyor.birde
Alıntı Yapf1(int i);
int f2(int i);
f1(int i) olayı nedir?
Alıntı yapılan: eistain_54 - 25 Ekim 2011, 00:36:49
hocam biraz c ile çalışmıştım ama olanda gitti.şimdi main fonsyonundan önce belirtilen fonsiyonlar bir nevi alt program.?main içinde onları dahil edebiliriz.tıpkı #include gibi.dosya değiilde komut dizilerini çağırıyoruz.peki örneğin int f1() nedir?gördüğüm kadarıyla fonksiyon için void oluyor.birde f1(int i) olayı nedir?
Eğer bir fonksiyon
f1(int i); şeklinde tanımlanmışsa başına
otomatik olarak
int belirleyicisi eklenir ve şu anlama gelir;
int f1 (int i);Dışarıdan
int türünde bir parametre al ve geriye de
int türünde bir değer döndür.
void f1 (int i); Dışarıdan int türünde bir parametre al ve geriye değer döndürme
Yani i türünde bir veri al.buda ana fonksiyonda bir yerdemi?birde geri değer döndürme işlemi nedir?
Geri değer döndürme
return() konutu ile yapılır ve () içine yazılan değer geri döndürülür.
şimdi int f1(int i) gibi bir fonksiyon tanımlamışsa bu fonksiyon çalışıp bittiğinde geriye bir değer döndürecek demektir. Örneğin
int f1(int i)
{
return(2*i);
}
bu fonksiyon gibi. Bu fonksiyon görüldüğü gibi return komutu aracılığı ile parametre olarak girilen değerin 2 katını geriye döndürmektedir. Ama bir de
void f1(int i) gibi bir fonksiyon olsun bu fonksiyonsa geriye hiç bir değer döndürmez. Buna bir örnek verirsek.
void delay(int i)
{
int a;
for(a=0;a<i;a++);
}
bu fonksiyon çağırıldığında girilen parametreye kadar for döngüsü aracılığı ile sayılır ve böylelikle program da bekleme yapmış olurruz.Tıpkı led in yanıp sönmesinde kullanılan delay gibi.
Alıntı yapılan: M_B - 25 Ekim 2011, 00:07:42
Hocam return() yazmanın bize ne tur bir avantajı olurki. Benim duşuncem hiç bir faydası olmayacağı yonunde.
Program ana donguye (main) girdimi daha cıkmayacaktır. cıksa bile gittiği yerden geri donecektir. Tabi gittiği yerde kısır donguye girmediyse.
Fonksiyonun geri donusunu belirleyen tanimlayici void değilse, derleyici, fonksiyonda return komutunu gormeyi ister, bulamazsa da ve en azindan warning mesaji verir.
main fonksiyonundan hic cikmayacak olsak bile usulen icine return koymak gerekir.
Kaydirma operatorleri
a=1<<4 a ya 0x10 yukle demek. 1 degerini 4 kere sola kaydirdi.
a=3<<4 a ya 0x30 yukle demek. 3 degerini 4 kere sola kaydirdi.
a=0x80>>1 a ya 0x40 yukle demek. 0x80 degerini 1 kere saga kaydirdi.
a=0x80>>7 a ya 0x01 yukle demek. 0x80 degerini 7 kere saga kaydirdi.
Ornegin neden a ya 0x10 yuklemek icin a=0x10 degil de a=1<<4 yazariz?
Bir registerin adi REG olsun ve buna ait aciklamalarinin bulundugu dokumanda PortClkOn adindaki bitin sira numarasi 4 olsun.
Yani; 0. degil, 1. hic degil, 2. de degil, 3. de degil 4. bit
Reg=1<<4 yazinca bir bakista regin 4. bitini 1 yaptigimiz anlasilir. reg=0x10 yazarsak da anlasilir.
Fakat Reg=3<<4 yapinca Reg'in 5 ve 4 nolu bitlerinin 1 oldugu daha sempatik anlasilir. Siz isterseniz Reg=0x30 da yazabilirsiniz.
Fakat kaydirma operatorlerinde kayma miktarini hep sabit deger vermek zorunda degilsiniz. Reg=a<<b; de yazarak parametrik deger verebilirsiniz.
C ile hic ama hic ugrasmamis fakat su ana kadar yazdiklarimizi harfi harfine okumus bir arkadas ben surayi anlamadim diyebilirmi? Elestiri bekliyorum.
@Bunalmis hocam yazılarınız net ve anlaşılır (askeri tabirle :) )
birinci sorum..
a=1<<4 ile diyelim ki "a" registerinin 4'üncü bitini set ettik. bu işlemi önce 0 biti set edip sonra 4 defa sola mı kaydırıyor?
eğer böyle ise "a" registerinin 0,1,2,3'üncü bitlerinin önceden barındırdıkları durumlar ne oldu? eğer siliniyor ise bu işlemi belirli bir sıra ve usule göre mi yapmamız gerekiyor?
ikinci sorum..
bir fonksiyondan birden fazla değer ile dönebilirmiyiz?
üçümcü sorum..
işaretli sayı olarak tanımladığımız bir sayıda içerik hangi noktadan sonra (-) değer alır? yada bunun bir kuralı mı var?
dördüncü sorum..
adresiniz nedir? (24 Kasımda size çiçek göndericem :) )
Hocam fonksiyon olayını kapattım ancak bu kezde yazılan sayılar canımı sıkmaya başladı.Şimdi yazdığımız sayılar hiçde bit düzeyinde gibi gelmedi bana. 0x080 kaydırınca 0x040 oldu.bu kaç bitlik sayı ki hex hali 80 iken kaydırınca 40 oluyor. Birde sanırım Arm işlemcilerde bu değerlerde farklı oluyor.
Alıntı yapılan: eistain_54 - 25 Ekim 2011, 06:34:17
Hocam fonksiyon olayını kapattım ancak bu kezde yazılan sayılar canımı sıkmaya başladı.Şimdi yazdığımız sayılar hiçde bit düzeyinde gibi gelmedi bana. 0x080 kaydırınca 0x040 oldu.bu kaç bitlik sayı ki hex hali 80 iken kaydırınca 40 oluyor. Birde sanırım Arm işlemcilerde bu değerlerde farklı oluyor.
0x80>>1 bir kere sağa kaydırmak demek o sayıyı ikiye bölmek demektir.
0x80<<1 bir kere sola kaydırmak demek o sayıyı ikiyle carpmak demektir.
0x80 desimel olarak 128 eder
128/2=64
64 desimel sayısıda hex olarak 0x40 eder.
bu olayı catpat asm ile alakalı bir durumda görmüştüm şimdi osc ayarlarını biraz çalışırsam anlaşıldı
type casting
Gene örneklerle açıklayacağım.
int a;
short b;
a=0x12345678; // olsun;
b=(short)a; // dersek b, 0x5678 değerini alır
(short)a demek, biliyorum sen short değilsin fakat kendini şu an için short'dan say demek
-----------------------------------
int a;
short b;
a=0x12345678; // olsun;
b=(short)a>>16; // dersek b, 0x1234 değerini alır
-----------------------------------
int a;
short b;
b=0x1234; // olsun;
a=(int) b; // dersek a, 0x00001234 değerini alır
-----------------------------------
char a;
short b;
b=0x1234; // olsun;
a=(char) b; // dersek a, 0x34 değerini alır
Alıntı yapılan: papsukkal - 25 Ekim 2011, 05:24:55
birinci sorum..
a=1<<4 ile diyelim ki "a" registerinin 4'üncü bitini set ettik. bu işlemi önce 0 biti set edip sonra 4 defa sola mı kaydırıyor?
eğer böyle ise "a" registerinin 0,1,2,3'üncü bitlerinin önceden barındırdıkları durumlar ne oldu? eğer siliniyor ise bu işlemi belirli bir sıra ve usule göre mi yapmamız gerekiyor?
ikinci sorum..
bir fonksiyondan birden fazla değer ile dönebilirmiyiz?
üçümcü sorum..
işaretli sayı olarak tanımladığımız bir sayıda içerik hangi noktadan sonra (-) değer alır? yada bunun bir kuralı mı var?
dördüncü sorum..
adresiniz nedir? (24 Kasımda size çiçek göndericem :) )
1.Cevap : Soruyu sorarken yaptığın yorumun kısmen yanlış olduğunu görebilirsin.
a=1<<4;
a =00000001 ; //a=1
a =00010000 ; //a=16
a=3<<1;
a=00000011; //a=3
a=00000110;//a=6
edit: Sağa kaydırma
a=3>>1;
a=00000011; //a=3
a=00000001;//a=1
2.cevap: Aslında 1 değer döner. Ama fonksiyon içinde global olarak tanımladığın değişkenlerin içeriğini değiştirebilirsin. Yada STRUCT yapı oluşturabilir bu sayede geriye döndürdüğün bir STRUCT altında birden fazla değer döndürebilirsin.
Örneğin kompleks bir sayının imajinel ve reel bileşenlerini fonksiyondan birini geri döndürebilirsin. Ama COMPLEX.reel ve COMPLEX.imag şeklinde oluşturacağın yapıyı direk COPMLEX olarak fonsiyondan geri döndürebilirsin.
3.cevap : bunu sayıların binary gösterimi için mi sordunuz anlamadım? Yoksa kaydırma işlemi için mi anlamadım ?
if karşılaştırması
Karşılaştırma amacıyla if komutunu kullanıyoruz.
if den sonra parantez içinde karşılaştırma ifadesini yazıyoruz.
if (a==1) // a, 1 mi
if (a!=1) // a, 1 den farklımı
if (a>0) // a, sıfırdan büyükmü
if den sonra gelen parantez içindeki ifade ya yanlıştır (0) yada doğru (0 dan farklı)
if (a&2) // a AND 2 sonucu 0 dan farklımı
if karşılaştırmasından sonra ; konmaz. Eğer koyarsanız bu komut öylesine zaman kaybetmek adına çalışır
if karşılaştırmasından sonra sadece 1 komut yazarak bu komutun karşılaştırma sonucuna göre çalışıp çalışmamasını sağlarsınız.
if (a==1) b=2; // eğer a, 1 ise b'ye 2 yükle
if karşılaştırmasının sonucuna göre birden fazla komut işletmek istiyorsanız
bu durumda komutları blok (dantelli parantez) içine alırız.
if (a==1)
{
b=2;
c=0;
}
Yukaridaki komut; eğer a, 1 ise b'ye 2, c'ye de 0 yukle demek
-----------------
else komutu
if karşılaştırmasında karşılaştırma sonucu beklenenin aksi olması durumunda kod çalıştırmak istersek else komutundan yararlanırız.
if (a==1)
{
b=2;
c=0;
}
else
{
b=5;
c=7;
}
Yukarıdaki komut, a=1 ise, b=2, c=0 yapar.
a 1'e eşit değilse, b=5, C=7 yapar.
----------------------------
A=1 ise ve B=5 ise Ledyak fonksiyonunu cağırmak
if ((A==1) && (B==5)) Ledyak();
Yada
if (A==1) if (B==5) Ledyak();
Yada
if (A==1)
{
if (B==5)
{
Ledyak();
}
}
A=1 ise veya B=5 ise Ledyak fonksiyonunu cağırmak
if ((A==1) || (B==5)) Ledyak();
Yada
if (A==1) Ledyak();
else if (B==5) Ledyak();
A 1 degilse ve B=5 ise Ledyak fonksiyonunu cağırmak
if ((A!=1) && (B==5)) Ledyak();
gibi...
for döngüsü
Döngü kurmak için kullandığımız komutlardan birisi for komutudur.
for komutunu () takip etmelidir.
Parantez içine yazabileceğimiz ifadeleri örnekler vererek açıklayacağım.
for (a=0; a<10; a++)
{
}
a=0 ile başla,
eğer a<10 ise dantelli parantez içindeki komutları işlet, a yı 1 artır. (a++ a=a+1 demek) kırmızı renkli satıra git
------------------------
for (a=10; a!=0; a--)
{
}
a=10 ile başla,
eğer a 0 değilse ise dantelli parantez içindeki komutları işlet, a yı 1 artır. (a-- a=a-1 demek) kırmızı renkli satıra git
-----------
for (a=0; a<10; a++)
{
}
a=0;
for (; a<10;)
{
a++;
}
Yukarıdaki yazım şekilleri aynı işi yapar.
for komutu ile sadece tek komut işletecekseniz aşağıdaki örnekteki gibi dantelli parantezlere ihtiyaç kalmaz.
for (a=0; a<10; a++) Komut
Yukarıdaki kodu aşağıdaki gibi de yazabilirsiniz
for (a=0; a<10; a++) { Komut }
Yukarıdaki kodu aşağıdaki gibi de yazabilirsiniz
for (a=0; a<10; a++)
{
Komut
}
while döngüsü
Döngü kurmak için kullandığımız komutlardan birisi while komutudur.
while komutunu () takip etmelidir. () içine koyacağımız şart doğru olduğu sürece while döngüsü çalışır. Şart sağlanmadığında while dan çıkılır.
while(1) yazdığımızda sonsuz bir döngü kurmuş oluruz ve asla while döngüsünden çıkılmaz.
Parantez içine yazabileceğimiz ifadeleri örnekler vererek açıklayacağım.
a=0;
while (a<10)
{
}
eğer a<10 ise dantelli parantez içindeki komutları işlet
------------------------
a=0;
while (a<10)
{
a=a+1; gibi bir komut yazmazsak sonsuz döngü olur.
}
goto komutu
Tanımladığınız bir etikete goto komutu ile zıplayabilirsiniz.
Örneğin;
n=0;
Dongu: .......
.......
if (k>50) goto Cik;
n++;
if (n<10) goto Dongu;
Cik: ........
........
& | ^ ~ (Bitwise)
& AND operatoru
| OR operatoru
^ XOR operatoru
~ NOT operatoru
A = 0x0A & 0x03; A nin sonucu 0x02
A = 0x0A | 0x03; A nin sonucu 0x0B
A = 0x0A ^ 0x03; A nin sonucu 0x09
A = ~0x0A; A nin sonucu 0x05
Array Dizi
Örneğin A adında bir değişkenimiz olsun. Fakat bu değişkenimizin bireyleri olsun.
Yani A0, A1, A2..... şeklinde.
Bu tip değişkenler için hafızada yer açmamız gerekir.
Örneklere bakınız.
int A[10]; // 11 tane integer elamani olan A dizisi
int B[2]={4,5,6} // B[0]=4, B[1]=5, B[2]=6 demek
char Mesaj[128]={"Merhaba",0};
char Msg[128]={'M','e','r','h','a','b','a',0};
-----------------
int B[2]={4,5,6} // B[0]=4, B[1]=5, B[2]=6 demek
if (B[1]==5) LedYak(); // Eger Bnin 1.elemaninin degeri 0x00000005 ise LedYak fonksiyonunu cagir.
pointer kavramina bakalim.
pointere neden ihtiyac varla baslayalim.
Asagidaki gibi bir fonksiyon dusunelim.
void hesapla(int a, int b)
{
int x,y,z,w;
x=a+b;
y=a-b;
z=a*b;
w=a/b;
}
peki hesaplanan x,y,z,w degerlerini cagiran fonksiyona nasil iletebiliriz? (malesef int int int int hesapla(int a, int b) yazamiyoruz)
Cozum 1. Global degisken kullanmak
int x,y,z,w;
void Hesapla(int a,b)
{
x=a+b;
y=a-b;
z=a*b;
w=a/b;
}
Cozum 2
void Hesapla(int a, int b, int* x, int* y, int* z, int* w)
{
*x=a+b;
*y=a-b;
*z=a*b;
*w=a/b;
}
Burada int *x, gelen veri, x degiskeninin degeri değil adresidir demek.
*X = a+b; demek a+b islemini yap ve sonucu adresi verilen alana yaz demek.
Peki bu fonksiyonu cagirirken nasil adres verecegiz?
main void() // burada parantez icine void yazacaksak yazmayabilme serbestligimiz var
{
int a,b,c,d;
Hesapla (4, 5, &a, &b, &c, &d)(http://picproje.org/Smileys/default/wink.gif) // Buradaki &a, a degiskeninin adresinin sayisal degeri demektir.
}
-------------------------------------------------------------------------------
pointeri anlamak icin bir baska ornek
void main()
{
int a,b; // a ve b integer iki degisken
int* p // p, integer degiskenlerin adresini saklayabilen bir degisken, yani bir pointer
p=&a // a degiskeninin adresini p ye yukledik
a=1; // a=1 yaptik
b=*p; // p degiskenindeki adresdeki veriyi b ye yazdik. (b=a oldu)
}
Pointer denen sey de bundan ibaret.
O halde bir fonksiyondan istedigimiz kadar sonuc geri dondurebiliriz. Daha dogrusu, bir fonksiyondan, istedigimiz kadar degiskenin icine deger yazmasini isteyebiliriz.
structure ve union
Standart veri tiplerinin disinda veri tipleri olusturmak icin struct deyimiden yarlaniyoruz.
Mesela A degiskeninin bir integer bir de karakter bileseni olsun.
A nin integer bilesenine 1234 hex degeri aktaralim, karakter bilesenine de 'Z' olsun diyebiliriz.
Bunun icin tanimlanmasi gereken structure;
struct Ozel
{
int IntBileseni;
char CharBileseni;
};
Boyle bir tanim ardindan mesela A degiskenine bu ozelligi atayalim.
struct Ozel A;
Artik A degiskenimizin icine deger atayabiliriz.
void main()
{
A.IntBileseni=0x1234;
A.CharBileseni='Z'
// A nin CharBileseni 'Z' mi diye bakmak istersek
if (A.CharBileseni=='Z')
{
// Anin Char bileseni Z imis
}
}
Simdi de union tanimlamasina bakalim.
Bunun icin bir ornek yapacagim.
struct Ozel_Integer{
char H;
char L;
};
// Burada yaptigim, adlari H ve L olan char tipinde 2 tane bilesenden olusan, Ozel_Integer adini verdigim char bir degisken tanimlamak oldu.
union Ister16_Ister8_8 {
int Bir_Kerede_16_Bit_Yukle;
struct Ozel_Integer Sekiz_Bit_Yukle;
};
// Burada yaptigim ise Bir kerede 16 bit deger yuklenebilen integer tipinde ve adini Bir_Kerede_16_Bit_Yukle koydugum degisken ile;
// Daha once tanimladigim Ozel_Integer adindaki structurla ayni yapidaki Sekiz_Bit_Yukle degiskenimi ayni adrese oturtmak oldu.
// Bu ozellige de Ister16_Ister8_8 adini verdim.
union Ister16_Ister8_8 Ozel_Degiskenime;
// Burada ise adini Ozel_Degiskenime koydugum bir degisken tanimlamak ve buna da Ister16_Ister8_8 adini koydugum union ozelligi vermek oldu.
void main (void)
{
Ozel_Degiskenime.Bir_Kerede_16_Bit_Yukle=0x7890;
Ozel_Degiskenime.Sekiz_Bit_Yukle.H=0x12;
Ozel_Degiskenime.Sekiz_Bit_Yukle.L=0x34;
}
Alıntı yapılan: fatihinanc - 25 Ekim 2011, 00:51:37
Eğer bir fonksiyon f1(int i); şeklinde tanımlanmışsa başına otomatik olarak int belirleyicisi eklenir ve şu anlama gelir;
int f1 (int i);
Dışarıdan int türünde bir parametre al ve geriye de int türünde bir değer döndür.
void f1 (int i);
Dışarıdan int türünde bir parametre al ve geriye değer döndürme
int ile void arasındaki temel farkı hala anlayamadım
hep void kullanırım
dondürmek istedigim değeri global bi değişkene atarım
sonra istediğim heryerde kullanırım
peki int kullanmanın avantajı nedir siz hangisini daha cok kullanıyorsunuz
iyi bilen arkadaşlar tabikide ikisininde yeri ayrı diyecektir fakat neden oldugunu soylerlerse cok makbule geçer
teşekkürler
Alıntı yapılan: gambit1244 - 25 Ekim 2011, 16:27:20
peki int kullanmanın avantajı nedir siz hangisini daha cok kullanıyorsunuz
Global değişkenler programın başından sonuna kadar hafızada tutulurlar. Bu sebeple programın başından sonuna kadar -hafızada- bulundukları bölgeyi işgal ederler.
Fakat bir fonksiyon içerisinde tanımlanan değişkenler(
Örn : int f1(int i) fonksiyonu)
stack alanını kullanırlar. Bu değişkenlerin ömürleri fonksiyonun başından sonuna kadar tanımlıdır.
Yani fonksiyon bitince stack alanında işgal ettikleri o bölge başka amaçlar için de kullanılabilir durumda olur.
Bu sebeple genellikle local değişkenler üzerinden işlem yapmak programı daha efektif çalışır hale getirir.
Global değişkenler kullanılarak void tipinde tanımlanabilir.
İllaki int olması gerekmiyor.Float f1() de olabilirdi.
Bu geri döndürülen verinin tipi ile alakalı.
Eğer geri dönecek değer int tipinde ise;
int f1();
float tipinde ise;
float f1();
geri dönüş değeri yoksa void olur.
C nin bu kadarcık özeti ile https://www.picproje.org/index.php/topic,35896.0.html (https://www.picproje.org/index.php/topic,35896.0.html) de verdiğimiz örnek programları çok rahat anlamanız gerekiyor.
Alıntı yapılan: bunalmis - 25 Ekim 2011, 16:56:21
C nin bu kadarcık özeti ile https://www.picproje.org/index.php/topic,35896.0.html (https://www.picproje.org/index.php/topic,35896.0.html) de verdiğimiz örnek programları çok rahat anlamanız gerekiyor.
Hocam elinize sağlık. Ben baştan sona kadar okudum. Anlatımınız ve renklendirmeler bence çok yerinde.
arkadaşlar degerli bilgiler için cok teşekkür ederim
sormak istedigim bişey daha var
mesela
RCC->AHB1ENR
boyle bir register kayıt işlemi var
buradaki -> işlemini c kitabında hiç gormedim
gordüysemde hatırlayamadım
bu işlem asm komutumu yoksa sadece register için kullanılan bi komutmu
eğer oyleyse bunun gibi c de olmayan komutlar nelerdir yada bilmemize gerek varmı sizce
Şimdi daha önceleri hiç C ile uğraşmamış olanları değil de uğraşanları davet edelim.
#include "STM32F4xx.h"
void SystemInit()
{
RCC->AHB1ENR |= 0x00000008; // GPIOD donanımının clock sinyalini uygulayalım
GPIOD->MODER = 0x55000000; // GPIOD nin 15, 14, 13, 12 pinleri cikis tanimlandi (Ledler bu pinlerde)
GPIOD->OSPEEDR= 0xFFFFFFFF; // GPIOD nin tum cikislari en yuksek hizda kullanacagiz
}
int main()
{
while(1)
{
GPIOD->ODR= 0x0000F000; // Ledler yansin
GPIOD->ODR= 0x00000000; // Ledler sonsun
}
}
// Programın sonudur.
Yukarıdaki programda;
#include "STM32F4xx.h" satırını kaldırıp atalım. Programımızda header dosya vs kalmasın.
Programda aşağıda adıgeçen registerleri structure pointer yapısından kurtarıp structure yapısına dönüştürelim.
Sözkonusu register adreslerini STM32F4xx.h dosyasından öğrenebilirsiniz.
RCC->AHB1ENR
GPIOD->MODER
GPIOD->OSPEEDR
GPIOD->ODR
GPIOD->ODR
Sorumuz budur.
Yukarıdaki soruyu çözdünüzmü C de kod yazmayla ilgili hiç bir sıkıntınız kalmaz ve C de ilerlemeye başlarsınız.
Hocam şu satıra dikkat etmemişsin.
Programda aşağıda adıgeçen registerleri structure pointer yapısından kurtarıp structure yapısına dönüştürelim.
Alıntı yapılan: gambit1244 - 25 Ekim 2011, 17:21:39
arkadaşlar degerli bilgiler için cok teşekkür ederim
sormak istedigim bişey daha var
mesela
RCC->AHB1ENR
boyle bir register kayıt işlemi var
buradaki -> işlemini c kitabında hiç gormedim
gordüysemde hatırlayamadım
bu işlem asm komutumu yoksa sadece register için kullanılan bi komutmu
eğer oyleyse bunun gibi c de olmayan komutlar nelerdir yada bilmemize gerek varmı sizce
Eğer struct ya da Union; pointer ise , yapının elemanlarına ulaşmak için bu "->" işaret kullanılır.
Örneğin.
typedef struct{
char hasan;
int mehmet;
float ali;
} structtest;
// fonksiyona geçilen parametre struct
void struct_param_normal ( structtest prm_normal){
prm_normal.ali = prm_normal.mehmet * prm_normal.hasan;
}
// fonksiyona geçilen parametre struct pointer
void struct_param_ptr( structtest *prm_ptr){
prm_ptr->ali = prm_ptr->mehmet * prm_ptr->hasan;
}
Açıklamayı unuttugumuz bazı C komut / terimlerini şimdi ele alalım.
#define Tanım yapmak için kullanırız.
Ornekleri inceleyin.
#define AlarmLediniYak 0x10
GPIO.PORTA.ODR |=AlarmLediniYak;
Yukarıdaki ifade GPIO.PORTA.ODR |=0x10; komut satırına eştir.
Ancak GPIO.PORTA.ODR |=AlarmLediniYak; okunaklığı ve anlaşılırlığı yüksektir.
Yada aşağıdaki örneğe bakın
#define Yan GPIOD->ODR= 0x0000F000
#define Son GPIOD->ODR= 0x00000000
if (LedFlag) Yan; // Ledler yansin
else Son; // Ledler sonsun
Yukarıdaki iki satır aşağıdaki satırlarla aynı anlama gelir.
if (LedFlag) GPIOD->ODR= 0x0000F000; // Ledler yansin
else GPIOD->ODR= 0x00000000; // Ledler sonsun
volatile
Bazı ARM registerlerinin özelliği gereği, okunduğunda register içeriğinde bazı bitler silinir.
RegX böyle bir register olsun.
void Sifirla()
{
int A;
A=RegX
}
gibi bir fonksiyon derleyici tarafından optimize edilip çağrılmayabilir. Çünkü RegX okunmuş ve A içine yazılmış fakat A hiç bir yerde kullanılmamıştır.
Dolayısı ile derleyici bu fonksiyonu işe yaramaz olarak görecektir.
Fakat bu durumda biz Sıfırla fonksiyonunu çağırmakla, RegX registerinin okuyup içeriğini silmek istediğimizden, derleyici de bu fonksiyonu es geçtiğinden, RegX de bazı bitler silinmeyeceğinden programımız düzgün çalışmaz.
Bu duruma engel olmak için A değişkeninin tanımını aşağıdaki gibi yaparız.
void Sifirla()
{
volatile int A;
A=RegX
}
Sonuç olarak volatile, derleyiciye kardeşim volatile tanımlı değişkenlerimi kaldırıp atma ben ne diyorsam sen onu yap emri vermeye yarar.
Global alanda tanımlı değişkenler
Ramın Global alanında tanımlı değişkenler RAMda sürekli olarak yer kaplarlar.
Global bir değişken tanımlamak için değişkenin fonksiyon dışında tanımlanması yeterlidir.
Örnegin int A değişkenini global alanda tanımlayalım.
int A;
void Say()
{
......
......
}
Bir değişken fonksiyon içinde tanımlanırsa o değişken local değişken olur.
void Say()
{
int A;
......
......
}
Local değişken fonksiyon çağrıldığında oluşan, fonksiyon içi işlemler bittiğinde kendisi dolayısı ile içeriği yok edilen değişkendir.
static
Local değişkeni statik değişkene çevirir.Yani fonksiyon içi işlemler bitse de var olmaya devam eden değişkenlerdir.
void Say()
{
static int A;
......
......
}
Bu açıdan Global Tanımlama ile Statik aynı anlama gelebilir mi ?
Aynı şey değil.
Global değişkene her fonksiyondan erişilebilir. Fakat static tanımlı değişkene sadece tanımlı olduğu fonksiyondan erişilir.
Kritik bir soru
int a;
void main()
{
static int a;
a=1;
// Global a değişkeninin içeriğini nasıl öğrenirsiniz?
....
}
Fonksiyonun dışından Başka bir fonksiyonda sorarım
Başka yolu?
Alıntı yapılan: bunalmis - 25 Ekim 2011, 22:34:32
Başka yolu?
Evet hocam cok guzel bir soru sordunuz?
az once piclede denedim global tanımda a olarak gozukuyor.
static tanımda ıse main@a gozukuyor.
Bende soruyorum hocam baska cozumu var mı?
hocam aslında buna pc programlamadan cevap vereceğim ama yanlış olacak korkusu çeken öğrenci gibim hissediyorum kendimi
Form_Mk
Global A
function zzz
int A
......
Static A
end Function
En Form
gibi bir yapıdan bahsediyoruz aslında.
Burada Global A ya
Form_Mk.A
statik değişkene (buda nasıl bir çeviriyse)
Form_Mk.zzz.A olarak erişilir
Alıntı yapılan: bunalmis - 25 Ekim 2011, 22:25:27
Kritik bir soru
int a;
void main()
{
static int a;
a=1;
// Global a değişkeninin içeriğini nasıl öğrenirsiniz?
....
}
Galiba static değişkenin ilk değerlerine bakmak gerekiyor.Yanlış hatırlamıyorsam eğer static olarak tanımladığımız değişkene ilk değer ataması yapmışsak bu data segmentte, yapmamışsak bss segmentte tutuluyor.
Bu örnekte static değişkene ilk değer ataması yapılmadığı için bss segment içerisine erişerek static a değişkenin, data segmente erişerek de global a değişkenin içeriğini öğrenebiliriz diye düşünüyorum.
Ama denemedim, olmayabilir...
Alıntı yapılan: GreeN - 25 Ekim 2011, 11:57:29
1.Cevap : Soruyu sorarken yaptığın yorumun kısmen yanlış olduğunu görebilirsin.
a=1<<4;
a =00000001 ; //a=1
a =00010000 ; //a=16
a=3<<1;
a=00000011; //a=3
a=00000110;//a=6
edit: Sağa kaydırma
a=3>>1;
a=00000011; //a=3
a=00000001;//a=1
kaydırma işlemini anladım
aslında sorduğum şuydu...
registerin 0. bitinde 1 değeri var ve biz bunu korumak istiyoruz
a=1<<4; ile değer yüklersek anladığım kadarı ile işler karışır
Alıntı yapılan: GreeN - 25 Ekim 2011, 11:57:29
3.cevap : bunu sayıların binary gösterimi için mi sordunuz anlamadım? Yoksa kaydırma işlemi için mi anlamadım ?
bu sorumun cevabını buldum.
en soldaki bit 1 ise değer " - " dir.
Alıntı yapılan: bunalmis - 25 Ekim 2011, 22:25:27
Kritik bir soru
int a;
void main()
{
static int a;
a=1;
// Global a değişkeninin içeriğini nasıl öğrenirsiniz?
....
}
A değişkeninin adresini B değişkenine kaydedip, içerik gerektiğinde de adresi kontrol ederek olabilir mi?
Alıntı yapılan: papsukkal - 26 Ekim 2011, 00:32:29
kaydırma işlemini anladım
aslında sorduğum şuydu...
registerin 0. bitinde 1 değeri var ve biz bunu korumak istiyoruz
a=1<<4; ile değer yüklersek anladığım kadarı ile işler karışır
bu sorumun cevabını buldum.
en soldaki bit 1 ise değer " - " dir.
register ın herhangi bi bitindeki verinin değişmesini istemiyosanız.or işlemi ile register a yükleme yapmalısınız.
Örnek:
GPIOD->MODER |=1<<4; bu şekilde yüklendiğinde sadece 4. bit 1 yaparsınız geri kalan bitler değişmez.
GPIOD->MODER=1<<4; deseydiniz registerın değeri bu işlem sonunda 16 olur.
Bu işlemin adı maskelemedir.
OR la yada AND le yapılabilir. OR yaparsanız 0 la maskelemeniz AND le yaparsanız 1 ile maskelersiniz.
Yukarda (Eğer Yanlışsam Lütfen Düzeltiniz) 32bitlik bit sayıda 1 i 4 kez sola kaydırıp Orlayarak registerin içerisine atıyorsunuz. Buna bağlı olarak (Or işleminde 1 yutan dır sonuç da devamlı 1 çıkar) 4. bit lojik 1 oluyor.
Alıntı yapılan: muhittin_kaplan - 26 Ekim 2011, 00:45:16
Bu işlemin adı maskelemedir.
OR la yada AND le yapılabilir. OR yaparsanız 0 la maskelemeniz AND le yaparsanız 1 ile maskelersiniz.
Yukarda (Eğer Yanlışsam Lütfen Düzeltiniz) 32bitlik bit sayıda 1 i 4 kez sola kaydırıp Orlayarak registerin içerisine atıyorsunuz. Buna bağlı olarak (Or işleminde 1 yutan dır sonuç da devamlı 1 çıkar) 4. bit lojik 1 oluyor.
Evet doğru söylüyorsunuz ancak 4. biti 0 yapmak istediğimiz zaman AND kullanmak daha mantıklı
mesele anlaşıldı. teşekkür ederim
Global değişkenlerle ilgili birşey eklemek istiyorum: Globalleri el bombasına benzetebiliriz. Birçok işinizi yapmaya yarayan güçlü araçlardır ama aynı zamanda tehlikelidirler. Elinizde de patlayabilirler. Kullanırken dikkatli olmak lazım.
Biraz acabilirmisin? Neden patlar?
Bende merak ettim neden "patlar" sonuçta kullandımız basic derleyicilerinin nerdeyse hepsi global değişkenle çalışmak zorunda bırakıyo kullanıcıları..
Patlar'dan şunu kastettim: Global değişkenlere herkes her yerden ulaşabildiği için hatalara yol açma olasılığı yüksektir. Özellikle multitaskin uygulamalarda...
Global değişkenler duyuru panosuna asılmış kağıt parçası gibidir.
Her önüne gelen kağıttaki yazıyı silip yenisini yazabilir. Bu açıdan bakınca, şakacı çocuklar varsa tabiki tehlikelidir.
Hocam Sorunuzun Cevabı nedir? yani statik ile global tanımlamalar a ulaşımla alakalı olan.
Alıntı yapılan: bunalmis - 25 Ekim 2011, 22:25:27
Kritik bir soru
int a;
void main()
{
static int a;
a=1;
// Global a değişkeninin içeriğini nasıl öğrenirsiniz?
....
}
Pointer kullanarak 2 değişkeninde adresleri yine global 2 farklı adreste tutulur , dilediğimiz yerde tuttukları değerleri kullanabiliriz.
Alıntı YapPointer kullanarak 2 değişkeninde adresleri yine global 2 farklı adreste tutulur , dilediğimiz yerde tuttukları değerleri kullanabiliriz.
Bu iki a değişkeninin adreslerini main fonksiyondan nasıl öğreniriz?
Eğer harici bir fonksiyon yardımıyla öğrenirim derseniz sorunun anlamı kalmaz.
Sonuçta Static A nın yaşam alanında Global A ya ulaşlmasını istiyorsunuz. mu ? :S
Soruda o isteniyor. C++ da bu öğrenilebilir mi?
Alıntı yapılan: bunalmis - 26 Ekim 2011, 12:10:31
Soruda o isteniyor. C++ da bu öğrenilebilir mi?
C++'ta bu mümkün görünüyor: http://bytes.com/topic/c/insights/737451-case-against-global-variables
int data = 10;
int main()
{
double data = 25.0;
cout << data << endl; //You see 25
cout << ::data << endl; //You see 10
}
Sanırım C de bunu ek bir işlem olmadan yapamıyoruz.
Zaten bu durumdan her zaman kaçınılmalı. Yani global ve lokalde kullanılan değişken adları farklı olarak verilmeli.
Ne kadar az global kullanırsak bu da o kadar iyidir ayrıca.
C++ da :: operatörü kullanılarak global değişkene ulaşılabilir fakat C de bunun bir karşılığı yok...
#include <stdio.h>
main(t,_,a)char *a;{return!0<t?t<3?main(-79,-13,a+main(-87,1-_,
main(-86,0,a+1)+a)):1,t<_?main(t+1,_,a):3,main(-94,-27+t,a)&&t==2?_<13?
main(2,_+1,"%s %d %d\n"):9:16:t<0?t<-72?main(_,t,
"@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l,+,/n{n+,/+#n+,/#\
;#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l \
q#'+d'K#!/+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# \
){nl]!/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#n'wk nw' \
iwk{KK{nl]!/w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c \
;;{nl'-{}rw]'/+,}##'*}#nc,',#nw]'/+kd'+e}+;#'rdq#w! nr'/ ') }+}{rl#'{n' ')# \
}'+}##(!!/")
:t<-50?_==*a?putchar(31[a]):main(-65,_,a+1):main((*a=='/')+t,_,a+1)
:0<t?main(2,2,"%s"):*a=='/'||main(0,main(-61,*a,
"!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m .vpbks,fxntdCeghiry"),a+1);}
birde yukarıdaki gibi bir şamata var. anlayabilen bana da anlatsın. programı derlediğinizde
On the first day of Christmas, my true love gave to me...
A Partridge in a Pear Tree.
On the second day of Christmas, my true love gave to me...
2 Turtle Doves
And a Partridge in a Pear Tree.
On the third day of Christmas, my true love gave to me...
3 French Hens
2 Turtle Doves
And a Partridge in a Pear Tree.
On the twelfth day of Christmas, my true love gave to me...
12 Drummers Drumming
11 Pipers Piping
10 Lords-a-Leaping
9 Ladies Dancing
8 Maids-a-Milking
7 Swans-a-Swimming
6 Geese-a-Laying
5 Gold Rings
4 Colly Birds
3 French Hens[8]
2 Turtle Doves
And a Partridge in a Pear Tree.
şeklinde bişeyler yazıyor... :)
Pointerler üzerine konuşmaya devam edelim.
Çipinizin dokumanında, adresi atıyorum 0x42345678 olan bir register gördünüz.
Fakat #include ile programınıza dahil edilmiş olan çipin register tanımlamalarının bulunduğu dosyada her nedense bu 0x12345678 adresli register yer almamış.
Sizin de bu registeri kullanmanız gerekiyor. Ne yapacağız?
---------------------------------------------------------------
Programlarda int A yada char A vs bir tanım yaptığınızda, A değişkenin adresi derleme aşamasında C tarafından belirlenir.
Halbuki registerlerin adreslerini çip üreticisi belirler. Dolayısı ile bu gibi durumlarda adres belirleme işini derleyicinin inisiyatifinden almamız gerekir.
---------------------------------------------------------------
Şimdi daha önceki pointer anlatımımızı hatırlayın ve aşağıdaki satırları takip edin.
int A; // Ben integer bir değişkenim
int *P; // Ben integer değişkenin adresini saklayabilirim
P=&A; // Pointer'a A değişkeninin adresini yazdık
*P=0x12; // pointerin gösterdiği int alana 0x12 değerini yani 0x00000012 yükleyeceğiz demektir.
// Yukarıdaki satırlar A=0x12 demekle aynı şeydir.
---------------------------------------------------------
Yukarıdaki örnekte pointera A değişkeni, hangi adresde ise o atandı ve kullanıldı. Şimdi yok kardeşim A nın adresini değil benim vereceğim sayısal adresi kullan diyelim.
Sonrada bu adrese örnek olarak 0x12345678 değerini yazalım.
int *P;
P=(int*) 0x42345678;
*P=0x12345678;
----------------------------------------------------------------
Fakat ben P nin önüne her defasında * koymak istemiyorum.
#define P (*((int*) 0x42345678)) tanımlarsak
P=0x12345678;
yazarız.
Eğer yakışıklı görünmesi şart değil derseniz
(*((int*) 0x42345678))=0x12345678; de yazabilirsiniz.
Verilen örnekler 0x42345678 adresine 0x12345678 sayısını yazar.
----------------------------------------------------------------------------
Yukarıdaki örneklerde pointeri integer tanımladık.
Bir portu, bu şekilde pointer ile kullanmak için portu int tanımlamak sakıncalıdır. unsigned int tanımlanmalıdır. Neden?
Alıntı yapılan: bunalmis - 25 Ekim 2011, 22:25:27
Kritik bir soru
int a;
void main()
{
static int a;
a=1;
// Global a değişkeninin içeriğini nasıl öğrenirsiniz?
....
}
Eğer verdiğiniz kodun başına da birşeyler ekleyebiliyorsak { } içerisinde tanımlayarak yapılabilir. Aşağıdaki kodu gcc ile derleyip kontrol ettim :
#include <stdio.h>
int a=0;
void main()
{
{
static int a;
a=1;
printf ("\nLocal a : %d", a);
}
printf ("\nGlobal a : %d\n", a);
}
Sonuç :
Local a : 1
Global a : 0
Bu şekilde çalışması normal zaten.
Çünkü static değişkeni farklı bir blok içerisinde tanımlamışsınız.
Soruda main fonksiyonu içerisinde..
Alıntı yapılan: bunalmis - 26 Ekim 2011, 14:00:09
Bir portu, bu şekilde pointer ile kullanmak için portu int tanımlamak sakıncalıdır. unsigned int tanımlanmalıdır. Neden?
Hocam portlar fiziki olarak vardır. Adresleri signed olamaz. yani hiçbir zaman negatif olamaz. Daima pozitif olmalıdır.
int tanımlarsak olur fakat sakıncası var. Bu sakıncayı söylemizi istiyorum.
#define P (*((int*) 0x42345678)) Sakıncalı
#define P (*((unsigned int*) 0x42345678)) Olması gereken
sanırım bu işe yarar ?
int a=1; // global değiken
int *pt1,*pt2;
int main(){
pt1 = &a; //bu satırı static a değişkenini tanımlamadan önce yazdığım için global a değişkeninin adres değerini aldı
static int a=10;
pt2 = &a; //bu satırda da static a değişkeninin adres değerini aldım
printf("Global a = %d",*pt1);
printf("Static a = %d",*pt2);
.....
}
Pek C bilgim Yoktur Yalnız. Pointer ile çalışmanın nasıl bir sistem olduğunu ASM deki Dolaylı Adresleme olarak kavradığımı düşünüyorum.
ohalde Global değişkenin Pointer (Hazfıza Adresi) Değerini Bir değişkende Saklarım Main Fonksiyonu içerisinde Bu adresdeki değeri okurum. Statik değere zaten ulaşıyoruz. Problen Her ikisininde "A" olarak tanımlanması idi.
Olurmu ?
Baktımda green de dediğimi yazmış
#define P (*((int*) 0x42345678)) Sakıncalı
#define P (*((unsigned int*) 0x42345678)) Olması gereken
şimdi 0xffffffff adresini düşünürsek bu int olamaz, unsigned olur. Sakıncalı olma sebebi bu mudur?
Statik tanımı kodlar arasına sıkıştığı için Green'in örneğini Keil derlemiyor.
Alıntı yapılan: bunalmis - 26 Ekim 2011, 14:55:15
Statik tanımı kodlar arasına sıkıştığı için Green'in örneğini Keil derlemiyor.
Bildirimlerin atamalardan önce gelmesi gerekiyor.
Alıntı yapılan: jeopardy - 26 Ekim 2011, 14:54:48
#define P (*((int*) 0x42345678)) Sakıncalı
#define P (*((unsigned int*) 0x42345678)) Olması gereken
şimdi 0xffffffff adresini düşünürsek bu int olamaz, unsigned olur. Sakıncalı olma sebebi bu mudur?
0xFFFFFFFF, integerda da unsigned integerda da tanımlı dır.
Dolayısı ile sakınca bu değil. Başka bir şey.
Öyle bir örnek verin ki, integer pointer üzerinden tanımlanmış porta eriştiğimizde sorunu tüm çıplaklığı ile görelim.
Alıntı yapılan: fatihinanc - 26 Ekim 2011, 14:06:05
Bu şekilde çalışması normal zaten.
Çünkü static değişkeni farklı bir blok içerisinde tanımlamışsınız.
Soruda main fonksiyonu içerisinde..
Değişkeni main fonksiyonunda tanımlarsak da olur, bu şekilde de aynı çıktıyı veriyor, ama bu sefer de "extern" kısmını farklı blokta tanımlamış oldum :P
#include <stdio.h>
int a = 0;
void main()
{
static int a = 1;
{
extern int a;
printf("Global a %d\n", a);
}
printf("Local a %d\n", a);
}
Alıntı yapılan: bunalmis - 26 Ekim 2011, 14:55:15
Statik tanımı kodlar arasına sıkıştığı için Green'in örneğini Keil derlemiyor.
Aynı isimli değişkenler için her değişken kendi tanımlandığı alanda çalışıyor , birlikte kullanılamazlar , bende bir hile yapayım dedim (@CoşkuN'nun dediği gibi değişkenlerin önce deklare edilmesi şartı problem olabilirdi) ama c++ da çalıştı.
örneğin c++ 'da ;
for(int a;a<10;a++) {.......} // a' değişkenini hemen kullanacağım yerde tanımlayabilirken
c'de bunu yapamıyorum . (mplap c30 'da ansi c standartlarına uygun değil şeklinde hata veriyordu.)
bunun gibi farklar mevcut.
Peki ozaman;
integer verilere erişen pointer kullanarak adı Reg olan registere, aşağıdaki satırdaki komutu uygularsam ne olurdu? Nasıl bir sakınca olur?
#define Reg (*((int*) 0x42345678))
Reg=Reg>>1;
Şimdi anladınızmı?
Sanırım bellek işlemlerinde (özellikle bellek bölümleriyle uğraşırken) bellek adres numarasıyla oynamamız gereken (shift mesela) durumlar olabilir. Böyle durumlarda int olarak tanımlayıp ardından işaret bitini işleme dahil etmek işleri arap saçına dönüştürebilirdi. Bu yüzden bellek adreslerindeunsigned int i tek geçmeli ;)
Hayır. Belleğin adres değeriyle işim yok. Adresi kaydırmıyorum. Belleğin içeriği ile işim var. Soruyu bir daha kontrol edin.
#include <stdio.h>
int a=10;
const int *ap=&a;
void main(void){
static int a=20;
const int *sap=&a;
char c;
printf("\n global %d, static %d \n", *ap, *sap);
{
int a;
a=30;
printf("\n global %d, static %d auto %d\n", *ap, *sap, a);
}
c=getchar();
}
==================================
program ciktisi:
global 10, static 20
global 10, static 20 auto 30
@Bunalmis
hocam sorunuz cevabı int in negatif değerler alması değil mi?Mesela biz bi registera 0xfffff000 değerini verecez eğer bu değeri int tipli bi değişken aracılığı ile register a yüklmeye çalışırsak bu sayının değer -4096 olacaktı ama unsigned int tipli bi değişken ile yüklemeye çalışırsak istediğimiz değeri yüklemiş oluruz.
siz de "Reg (*((int*) 0x42345678))" işlemiyle belleğin 0x42345678 numaralı adresini int tipli olarak belirliyosunuz.
Alıntı yapılan: mufitsozen - 26 Ekim 2011, 18:43:07
#include <stdio.h>
int a=10;
const int *ap=&a;
void main(void){
.....
Bunu derleyebildinizmi?
const int *ap=&a;
bu satırda c++ hata vermişti bende.
Alıntı yapılan: M_B - 25 Ekim 2011, 08:06:09
0x80>>1 bir kere sağa kaydırmak demek o sayıyı ikiye bölmek demektir.
0x80<<1 bir kere sola kaydırmak demek o sayıyı ikiyle carpmak demektir.
0x80 desimel olarak 128 eder
128/2=64
64 desimel sayısıda hex olarak 0x40 eder.
hocam bence bu mantık yeni başlayan birisi için anlaşılması zor olabilir bunun yerine olayı derinine açarak;
(a=0x80>>1 a ya 0x40 yukle demek. 0x80 degerini 1 kere saga kaydirdi. )
yani 80hexemal sayısını binary e çevirip ( 80h = 1000 0000 demektir)
bu rakamların hepsini birer satır sağa kardırırsak 0100 0000 = 40hexemal olur.
Not hex - decimal - binary translateyi bilgisayarlarımızdaki hesap makinesini görünmden programcı olarak seçerek yapabiliriz
Ben Soruyuda Kaçırdırdım Cevabıda
Konuşulmak İstenen işaretli sayılar ile İşaretsiz sayılar mı ?
Alıntı yapılan: yamak - 26 Ekim 2011, 19:02:42
@Bunalmis
hocam sorunuz cevabı int in negatif değerler alması değil mi?Mesela biz bi registera 0xfffff000 değerini verecez eğer bu değeri int tipli bi değişken aracılığı ile register a yüklmeye çalışırsak bu sayının değer -4096 olacaktı ama unsigned int tipli bi değişken ile yüklemeye çalışırsak istediğimiz değeri yüklemiş oluruz.
siz de "Reg (*((int*) 0x42345678))" işlemiyle belleğin 0x42345678 numaralı adresini int tipli olarak belirliyosunuz.
pointeri isaretli de tanimlasaniz isaretsiz de tamislasaniz 0xFFFFF000 yazdinizmi porttan 0xFFFFF000 cikar. Sorun okumada.
Asağıdaki proğram parçacıgı porttaki 0x80000000 verisini okuyup sağa kaydırıp tekrar porttan çıktığında porta yazilan veri 0xC0000000 olacaktır.
Halbuki pointeri unsigned int tanımlasaydık porttaki 0x80000000 verisini okuyup sağa kaydırıp tekrar porttan çıktığında porta yazılan veri 0x40000000 olacaktı.
#define Reg (*((int*) 0x42345678))
Reg=Reg>>1;
Aksi takdirde her defasinda type casting yapmak gerekirdi.
Peki aşagıdaki satirda neden volatile ön eki getirme ihtiyacı duyarız? #define Reg (*((volatile unsigned int*) 0x42345678))
Hocam volatile eğer kesme içinde bir değişken değer alıp sonra o değişkeni main içinde kullanacaksak kullanırız.Yani derleyiciye kod optimizasyonu yapma diyoruz.Eğer volatile kullanmazsak o değişkenin eski değerini okuyabiliriz.
Bu arada hocam bir önceki soruda benim kastettiğim farklı birşeydi.Tamam unsigned da tanımlasak signed ta tanımlasak adres yine yazdığımız adres olur fakat daha sonra okuyacağımız zaman eğer register ın değeri 0xFFFFF000 gibi bi değerse bunu -4096 olarak okumaz mıyız?Ya da bu değeri o register a yazarken sorun oluşmaz mı ?
Optimizasyon sonucunda uretilen kodlarda, registeri okuyan kod parcasinin neden koda dahil edilmeyip kaldirilip atildigini aciklamak lazim. En azindan bir ornekle.
Alıntı yapılan: yamak - 27 Ekim 2011, 01:26:42
Bu arada hocam bir önceki soruda benim kastettiğim farklı birşeydi.Tamam unsigned da tanımlasak signed ta tanımlasak adres yine yazdığımız adres olur fakat daha sonra okuyacağımız zaman eğer register ın değeri 0xFFFFF000 gibi bi değerse bunu -4096 olarak okumaz mıyız?Ya da bu değeri o register a yazarken sorun oluşmaz mı ?
(integer uzunluk icin) -4096 ile 0xFFFFF000 in farki varmiki?
Bir sonraki konumuz ARM registerlerini structure yapısında tanımlama hakkında.
Ön hazırlık yapmak isterseniz Rehber'de örneğin GPIOx port adreslerine bir göz atın.
Bi farkı yok hocam. Ama benim bahsettiğim sorun örneğin bi değişkeni int olarak tanımladık daha sonra bit kaydırma operatörünü kallanarak 0xFFFF0000 değerini aştık bunu aştıktan sonra sorun oluşmaz mı?Ya da farklı şeylerden bahsediyor olabiliriz :)
....
Derleyici, optimizasyon yaparken yazdığınız bazı satırları hiç işleme almayabilir.
Örneğin
int a;
a=1;
a=2;
örneğinde a=1; gereksiz görünmektedir.
Fakat burada a bir register ise
a=1;
a=2;
satırlarının her ikisi de işletilmelidir.
Zira, bazı registerlere veri yazmak aynı zamanda bir başka registerde bilmem ne bitinin otomatik sıfırlanmasına neden olur.
Bu durumda yukarıdaki kod optimize edilip sadece a=2 koduna çevrilirse program hatalı çalışacaktır.
Bu gibi durumlara engel olmak için veri tipinin tanımlandığı satırın başına volatile ekinin getirilmesi yeterli olur.
#define Reg (*((unsigned int*) 0x42345678)) // sorun oluşturacak tanımlama şekli
#define Reg (*((volatile unsigned int*) 0x42345678)) // sorunsuz tanımlama şekli
Alıntı yapılan: GreeN - 26 Ekim 2011, 22:10:53
Bunu derleyebildinizmi?
const int *ap=&a;
bu satırda c++ hata vermişti bende.
BORLAND C 4.5 ile denedim calisti
c++ yerine c compiler secenegi ile deneyin. C++ daha 'strong typed' bir derleyicidir.
Alıntı yapılan: yamak - 27 Ekim 2011, 01:23:24
Hocam volatile eğer kesme içinde bir değişken değer alıp sonra o değişkeni main içinde kullanacaksak kullanırız.Yani derleyiciye kod optimizasyonu yapma diyoruz.Eğer volatile kullanmazsak o değişkenin eski değerini okuyabiliriz.
volatile, eger program calisirken kendi kendine degisen (buyuk olasilikla donanimdan dolayi) sayaclar vb icin kullanilir. Bunlarin kesme ile bir alakasi yoktur.
Aslinda volatile ile derleyiciye optimizasyon sirasinda program icinde degeri degismeyen degiskenleri optimize etme diyoruz yoksa ornegin seri data gelmismi diye bir registerin bir bitine surekli bakan bir while dongusunu derleyici bu degiskeni dongu icerisinde degeri hic degismiyorki der ve onun icin gerekli kodu uretmeyebilir.
onun icin donanimi kontrol eden butun registerlar program icinden volatile diye tanimlanir.
Merak ettiğim bir konu var.
#define Reg (*((volatile unsigned int*) 0x42345678))
Kullanılan işlemcinin derleyicisinde unsigned integerin 32 bit olduğunu biliyoruz. Buna rağmen çipin register tanımlamalarının yapıldığı dosyalarda #define Reg (*((volatile unsigned long*) 0x42345678)) tanımı yapılıyor.
Öte yandan hangisini kullanırsak kullanalım aynı kod üretiliyor.
Buradaki espiri nedir?
O zaman ARM işlemciler için yazdığımız kodları ileride çok farklı bir işlemciye taşırken sorun çıkmasın diye düşünebiliriz.
Geçen gün veri tiplerinin tanımlanması hususunda baya uzun bir mesaj yazdım. Ancak tam yollayacakken şimdi yeri değil diye iptal ettim. Keşke etmeseymişim. Bilmeyen arkadaşlar için söylüyorum. Yazdığınız kodları başka platformlar içinde kullanmak istiyorsanız eğer; @gerbay' ın dediği gibi stdint.h dosyasını iyice bir inceleyin. Bu kütüphane C99 Standartlarına göre düzenlenir.
Eğer kodunuzu taşıdığınız platformda veri tiplerinizin kaç byte ile ifade edileceğini belirlemek istiyorsanız bu tanımlamaları göz önünde bulundurmanız yeterli.
Keil stdint.h'den alıntıdır
/* minimum values of exact-width signed integer types */
#define INT8_MIN -128
#define INT16_MIN -32768
#define INT32_MIN (~0x7fffffff) /* -2147483648 is unsigned */
#define INT64_MIN __ESCAPE__(~0x7fffffffffffffffll) /* -9223372036854775808 is unsigned */
/* maximum values of exact-width signed integer types */
#define INT8_MAX 127
#define INT16_MAX 32767
#define INT32_MAX 2147483647
#define INT64_MAX __ESCAPE__(9223372036854775807ll)
/* maximum values of exact-width unsigned integer types */
#define UINT8_MAX 255
#define UINT16_MAX 65535
#define UINT32_MAX 4294967295u
#define UINT64_MAX __ESCAPE__(18446744073709551615ull)
C dilini hiç bilmeyen arkadaşlar için C derneğinin hazırlamış olduğu ders notları
dökümanın şifresi cdernek
http://hotfile.com/dl/133447593/03cab39/cdersi_cdernek.pdf.html
Alıntı yapılan: mufitsozen - 27 Ekim 2011, 13:38:18
volatile, eger program calisirken kendi kendine degisen (buyuk olasilikla donanimdan dolayi) sayaclar vb icin kullanilir. Bunlarin kesme ile bir alakasi yoktur.
Aslinda volatile ile derleyiciye optimizasyon sirasinda program icinde degeri degismeyen degiskenleri optimize etme diyoruz yoksa ornegin seri data gelmismi diye bir registerin bir bitine surekli bakan bir while dongusunu derleyici bu degiskeni dongu icerisinde degeri hic degismiyorki der ve onun icin gerekli kodu uretmeyebilir.
onun icin donanimi kontrol eden butun registerlar program icinden volatile diye tanimlanir.
Hocam kesme örneğini şu yüzden verdim:
Örneğin kesme içinde benim "a" adında bi değişkenim var ,ben bu değişkeni main fonksiyonu içinde kullanıyorum ve "a" nın değeri seri porttan okunan değerlere göre değişebiliyo.ben bu "a" nın değerini main fonksiyonu içinde kullanacağım zaman derleyici bu değişkenin herhangi bir zamanda değişmeyeceğini kabul edip hep başlangıçtaki değerini bu değişkenin içinde tutabilir.Yani derleme yaparken bu değişkenin yerine sabit bir sayı ya da string koyabilir.Fakat ben bu değişimi kesme içinde değil de main içinde yapmış olsaydım örneğin:
while(1)
{
a=uart_register;
}
bu durumda derleyici a nın değerini uart_derleyicisini bağlı olduğunu bileceği için optimizasyon yapmayacaktı. Bu söylediklerimde haksız mıyım?
Hocam anlamadıım iki konu var...
structure ve union
pointer
Alıntı yapılan: yamak - 28 Ekim 2011, 14:15:05
Hocam kesme örneğini şu yüzden verdim:
Örneğin kesme içinde benim "a" adında bi değişkenim var ,ben bu değişkeni main fonksiyonu içinde kullanıyorum ve "a" nın değeri seri porttan okunan değerlere göre değişebiliyo.ben bu "a" nın değerini main fonksiyonu içinde kullanacağım zaman derleyici bu değişkenin herhangi bir zamanda değişmeyeceğini kabul edip hep başlangıçtaki değerini bu değişkenin içinde tutabilir.Yani derleme yaparken bu değişkenin yerine sabit bir sayı ya da string koyabilir.Fakat ben bu değişimi kesme içinde değil de main içinde yapmış olsaydım örneğin:
while(1)
{
a=uart_register;
}
bu durumda derleyici a nın değerini uart_derleyicisini bağlı olduğunu bileceği için optimizasyon yapmayacaktı. Bu söylediklerimde haksız mıyım?
Evet, haksizsiniz maalesef. :o Cunki verdiginiz ornek yanlis. (buna eski dilde sui-misal emsal olmaz diyoruz :-\). Diyelimki seri_port_status_reg diye bir (HW) register var ve bunun 1inci biti seri bilgi geldiginde 1 oluyor. Sizde bir yerden seri bilgi gelip gelmedigini programinizda anlamaya calisiyorsunuz.
Bunun icin suna benzer bir kod yazdiniz diyelim:
while( (seri_port_status_reg & 1) == 0); /* seri_port_status_reg 1.biti 0 ise bekle */
/* gelen seri datayi oku */
.......
compiler bu while icinde bu degiskenin degeri hic degismiyor diye bu donguye ait hic bir kod yaratmayabilir (optimizasyon secimine bagli olarak) ama volatile derseniz programin islemesinden bagimsiz olarak bu deger degisebilir diye while dongusune ait kod yaratilir.
Su anda cok vaktim olmadigindan daha guzel bir ornek veremiyorum ama, @gerbay'in vakti varsa cok daha guzel bir sekilde bunlari anlatabilir.
Alıntı YapEvet, haksizsiniz maalesef. Cunki verdiginiz ornek yanlis. (buna eski dilde sui-misal emsal olmaz diyoruz ). Diyelimki seri_port_status_reg diye bir (HW) register var ve bunun 1inci biti seri bilgi geldiginde 1 oluyor. Sizde bir yerden seri bilgi gelip gelmedigini programinizda anlamaya calisiyorsunuz.
Bunun icin suna benzer bir kod yazdiniz diyelim:
while( (seri_port_status_reg & 1) == 0); /* seri_port_status_reg 1.biti 0 ise bekle */
/* gelen seri datayi oku */
.......
compiler bu while icinde bu degiskenin degeri hic degismiyor diye bu donguye ait hic bir kod yaratmayabilir (optimizasyon secimine bagli olarak) ama volatile derseniz programin islemesinden bagimsiz olarak bu deger degisebilir diye while dongusune ait kod yaratilir.
Su anda cok vaktim olmadigindan daha guzel bir ornek veremiyorum ama, @gerbay'in vakti varsa cok daha guzel bir sekilde bunlari anlatabilir.
Aslında benim anlatmaya çalıştığım şey buna benzer bir şey.
Ama tamam gerbay'dan ya da bunalmis'tan yanıt bekliyorum. :)
Alıntı yapılan: eistain_54 - 28 Ekim 2011, 17:13:56
Hocam anlamadığım iki konu var...
structure ve union
pointer
Neresinde takıldın?
konuyu anlamadım.komple yokbnde
@Yamak
Bir satirda a=Port; gibi bir atama yapilmis ve daha sonraki satirlarda
....
c=Port;
....
....
e=Port;
benzeri atamalar yapildiysa derleyici, nasil olsa Port degerini a=Port atamasinda okumus ve ogrenmistik artik tekrar okumama gerek yok diyebilir. Ilk okudugu Port degerini c ve e nin de icine yazabilir. Halbuki Port donanima aittir ve ilk okundugu andan sonra farkli degerler icerebilir.
Yada;
Ornegin interrupt rutininde
a=Port atamasi yapildiktan sonra a degiskeni, bu rutinde hic kullanilmamamissa bu bos yere yazilmis bir satir diyebilir. Bu satiri komple kaldirarabilir.
Yada;
bir program parcasinda
Port=1;
.....
.....
Port=2; gibi
atama yapildiysa ve .... satirlarinda Port okuma amacli kullanilmadiysa bu durumda Port=1 gereksiz bir atama olarak gorulebilir.
Bu gibi durumlarda bu komut satirlari, yazdiginiz program satirlarinda var olan fakat cipe ait kodlara eklenmeyen komutlardir.
Volatile eki bu gibi durumlari engeller.
Alıntı yapılan: eistain_54 - 28 Ekim 2011, 18:26:22
konuyu anlamadım.komple yokbnde
Tamam dert etme. Ilk asamalarda zaten bunlarla isimiz olmayacak.
tmm simdi ne yapmk gerekio?
Evet şimdi de C gibi dillerde goto komutu kullanmak hoş değil diyenlerden;
Neden hoş olmadığını açıklamalarını bekliyorum.
Mümkünse örneklerle.
Hocam C deyince benim aklıma ilk olarak WHILE döngüleri gelir. C ' de GOTO görmeye pek alışık olmadığım için böyle düşünüyorum.
Alıntı yapılan: bunalmis - 29 Ekim 2011, 20:38:23
Evet şimdi de C gibi dillerde goto komutu kullanmak hoş değil diyenlerden;
Neden hoş olmadığını açıklamalarını bekliyorum.
Mümkünse örneklerle.
Hocam Konuyu Oradan Oraya Geçiyoruz.
Başlık Diğeri değilmiydi ?
C programlama dili yada Türevlerinde Fonksiyon ve Alt program vardır. (Bunların İçerisinde c#, VB.net ve PIC için olan Swordfish de var)
Fonksiyonlarda tanımlanan değişkenler sadece o fonksiyon altında yaşarlar ve fonksiyon sonunda kaybolurlar. (Yukarda Bahsedildi.)
Ayrıca Bu Fonksiyonlardan Oluşturulmuş Dosyaları esasen yazdığımız program dosyasına "INCLUDE" edebiliriz. bu bize okunurluluk ve taşınabilirlilik sağlar. (PC programlamadaki DLL dosyalar gibi)
Alıntı yapılan: muhittin_kaplan - 29 Ekim 2011, 21:05:59
Hocam Konuyu Oradan Oraya Geçiyoruz.
Başlık Diğeri değilmiydi ?
Yok orada 3 kişi yazışıyoruz ya o yüzden burada tartışalım dedim.
Şimdi
a=a+1 yerine a++ kullan
a=a+5 yerine a+=5 kullan
goto kullanma denince
iyi C program yazıldığı sanılıyor.
Bana bunu söyleyecek adamın bu kodların altındaki asmlerde neler olduğunu izah edebilmesi lazım.
Keil optimizasyonunu açtığınızda yukarıdaki önerilerin çok ötesinde akla bile gelmeyecek optimizasyonlar yapılıyor.
Label ları güzel yerlere oturttuktan sonra goto ile son derece anlaşılır ve çok kısa kodlar yazabilirsiniz.
Aksini söyleyen varsa buyursun.
Gavur böyle diyor şurda şöyle yazmış demeyin. Yazdığı şeyi tartışmaya getirin.
Alıntı yapılan: muhittin_kaplan - 29 Ekim 2011, 21:10:43
Fonksiyonlarda tanımlanan değişkenler sadece o fonksiyon altında yaşarlar ve fonksiyon sonunda kaybolurlar. (Yukarda Bahsedildi.)
void fonksiyon() {
static int degisken = 0;
degisken = degisken + 1;
}
C ye başlayanlar, bu koddaki gibi bazı istisnalara dikkat edin.
Alıntı yapılan: bunalmis - 29 Ekim 2011, 20:38:23
Evet şimdi de C gibi dillerde goto komutu kullanmak hoş değil diyenlerden;
Neden hoş olmadığını açıklamalarını bekliyorum.
Mümkünse örneklerle.
Ben bazen goto kullanırım işin uzmanı da değilim ancak, bir fonksiyon ya da lib yazdığımızı düşünelim bu fonksiyonun içinde return yerine goto ile main e dallanırsak,fonksiyonun taşınabilirliği zorlaşır, vede stack dan yediğimiz bir alanı geri boşaltmamış oluruz diye aklıma geldi ilk olarak.
Alıntı yapılan: mcan - 29 Ekim 2011, 22:26:50
Ben bazen goto kullanırım işin uzmanı da değilim ancak, bir fonksiyon ya da lib yazdığımızı düşünelim bu fonksiyonun içinde return yerine goto ile main e dallanırsak,fonksiyonun taşınabilirliği zorlaşır, vede stack dan yediğimiz bir alanı geri boşaltmamış oluruz diye aklıma geldi ilk olarak.
ASM derleyicide deseydin anlardım fakat C derleyici, böyle bir şey yapmana izin vermez. Bu satıra hata verir ve düzeltmeni ister.
Alıntı yapılan: bunalmis - 29 Ekim 2011, 22:35:18
ASM derleyicide deseydin anlardım fakat C derleyici, böyle bir şey yapmana izin vermez. Bu satıra hata verir ve düzeltmeni ister.
Bunu bilmiyordum biraz önce denedim ,evet izin vermiyor label yokmuş gibi hata veriyor.Bunu da bu arada fark etmiş oldum karlıyım :)
Alıntı yapılan: mcan - 29 Ekim 2011, 22:26:50
Ben bazen goto kullanırım işin uzmanı da değilim ancak, bir fonksiyon ya da lib yazdığımızı düşünelim bu fonksiyonun içinde return yerine goto ile main e dallanırsak,fonksiyonun taşınabilirliği zorlaşır, vede stack dan yediğimiz bir alanı geri boşaltmamış oluruz diye aklıma geldi ilk olarak.
aynen arkadasımın dedigi gibi biliyorum bende
mantıklı düşününce
kendi yazdıgınız veya hazır fonksiyonları bolca kullanacagınız bir program yazıyorsanız
goto kullanmak nerede oldugunuzu kaybetmenize sebep olabilir.
programa 2 3 ay sonra birşey eklemek gerektiginde tüm yapıyı tekrardan gözden geçirmek gerekebilir
nereye ne eklersem neyin nasıl değişeceğini kestirmek daha zorlaşır
ama yeri geldigindede hiçbişey goto nun yerini tutmuyor
Alıntı yapılan: bunalmis - 29 Ekim 2011, 20:38:23
Evet şimdi de C gibi dillerde goto komutu kullanmak hoş değil diyenlerden;
Neden hoş olmadığını açıklamalarını bekliyorum.
Mümkünse örneklerle.
Harbiden goto sanki c++ içinde bir komut değil gibi.. Benim kafamda sizin sorduğunuz soru şöyle şekillendi ;
"C dilinde GOTO hangi durumlarda kullanılır"Bence c'dilinin ruhuna aykırı , yani c dilinde her komut disiplinli birer asker , GOTO 'da sanki disiplinsiz , DİSKO'dan çıkmayan 1 aylık bir asker gibi.
Ama goto'yu nerede kullandın derseniz , iç içe bir iki döngüden acilen çıkmam gereken bir durum olursa (bir değişken izleniyor mesela) program akışında döngilerin bir anlamı kaymıyordur , programın artık başkabir yerden devam etmesi gerektiğinde goto kullanabilirim.
Goto yüksek düzeyli bir komuttur. İstediğiniz kadar karmaşık algoritmalar kurun, istediğiniz noktadan Goto ile ayrılabilirsiniz. Alt seviyede bir şeyler staka atılmış registerler değer almış bu sizin sorununuz değil. Komut listesine goto konduysa derleyici gotonun kullanımından doğacak sorunları da çözmüş demektir.
while, for vs komutlarını goto ile uzun yoldan da yapabilirsiniz. Fakat bazı durumlarda goto ile yapacağınız basit işlemleri, while vs de uzun yolan yaparsınız.
En basitinden while dögüsünü break ile kırdığınızı varsayın. Break sizi while'ın çıkışına atar. Fakat ben goto ile çok farklı yere uçabilirim.
C nin doğası dediğiniz ne oluryor ki goto buna aykırı oluyor?
Sebep?
Alıntı yapılan: bunalmis - 03 Kasım 2011, 12:27:56
Sebep?
@gerbay "ben şahsen goto kullanmıyorum" demis. Bu kararin subjektif bir oldugunun gostergesidir, dolayisi ile tartismak abestir.
Musaadelerinizle konuyu bir Nasrettin hoca fikrasi ile baglarsak, adamin biri kosa kosa Nasrettin hocanin yanina gelmis, "hoca hoca" demis, "3 adam ellerinde tepsi tepsi baklava gidiyorlar!" Nasrettin hocada "Bundan banane?" demis, adam onun uzerine aciklamis, "ama" demis "sizin eve gidiyorlar!" Hocada bunun uzerine karsilik vermis "o zaman sanane?".
Yani subjektif bir deger yada kararin elestirisi olmaz. Karari alan sonucunada katlanir. Dermisim! :-[
Ne zaman C yada Delphi kodlama ve Goto kelimesi bir arada geçse, goto, C nin doğasına aykırı söylemini duymaktan bıktığım için Gerbay'ın bu konudaki bu tercihinin gerekçesini öğrenmek isterdim.
goto komutunu bende kullanmıyorum hocam,
kullanmama sebebim kodu okumayı zorlaştırıyor,
bir de pipeline'ın boşalmasına sebep oluyormuş diyorlar ama bu konuda süphelerim var goto pipeline'ı nasıl etkiliyor tam bilmiyorum
http://techtrain.microchip.com/x14/arch/Slides/5.swf
Alıntı yapılan: bunalmis - 03 Kasım 2011, 11:47:11
C nin doğası dediğiniz ne oluryor ki goto buna aykırı oluyor?
C'nin doğası dediğim olay şudur ;
C'nin yapısından bahsederken içerisindeki kodların belli bir sıraya göre yürütüldüğü , alt yapıların yer aldığı(for vs..) , ve bu yapıların bir girişi bir çıkışının olduğundan olduğundan bahsedebilirmiyiz? Ama goto bu yapılara 2 adet çıkış verir. Bir programcı bir for döngüsü içeriğinden sonra gelen kodları , sonrada diğerlerini , sonra ondan sonra gelenleri alt alta yazdıktan sonra bunların arasında goto ile gezmenin ne kadar takip edilebilir olduğunu sorgular.
Alıntı Yap....bir de pipeline'ın boşalmasına sebep oluyormuş ....
Bakın bu cevap, en ama en mantıklı cevap. Fakat bu bile goto kullanımından vageçmeyi gerektirmiyor.
Çünkü goto nun getireceği avantaj (fazladan karşılaştırma vs nin kalkması durumu) pipeline bufferın boşalması durumunda kaybedilecek zamandan daha avantajlı olabilir. Üstelik siz istediğiniz kadar C de goto komutu kullanmayın, yazdığınız C kodların arka planında goto komutları oluşur. (Gerçi ARM CM3 çiplerinin komut setine bazı durumlar için goto ihtiyacını kaldıran yeni komutlar eklenmiştir.)
Fakat her fonksiyon çağrımında, while, for, do benzeri yapılarda siz istesenizde istemesenizde C derleyici goto opcode'unu kullanır. Bu da pipeline mekanizmasının sıfırlanmasına neden olur.
Goto ve türevleri komutlar, pipeline mekanizmasını nasıl kötü etkiler? Trafikte otobüs gibi yüksekçe bir araç kullandığınızı varsayın.
Yolda giderken önünüzdeki 3...4 aracı yukarıda oturduğunuz için görebilirsiniz.
En öndeki yada aradaki araç frene bastığında erken tepki verip gerekiyorsa sizde hızınızı düşürürsünüz. Böylece gereksiz yavaşlamalar yapmayabiliyorsunuz.
Bu durumda gözünüzü önünüzdeki 3 araçtan ayırmazsınız.
Fakat siz bir kavşaktan dönünce artık o 3 araç farklı yöne gitmektedir ve siz hafızanızdan bu araçların markasını rengini vs unutup (pipeline bufferi boşaltıp) yeni döndüğünüz yolda önünüze çıkacak yeni üç aracı sırayla hazfızanıza kazımanız gerekecektir.
Bire bir bir örnek olmasa da goto neden pipeline mekanizmasının performansını düşürüre fikir verecektir.
Alıntı yapılan: bunalmis - 03 Kasım 2011, 14:19:19
Ne zaman C yada Delphi kodlama ve Goto kelimesi bir arada geçse, goto, C nin doğasına aykırı söylemini duymaktan bıktığım için Gerbay'ın bu konudaki bu tercihinin gerekçesini öğrenmek isterdim.
Bu konuda en detayli aciklama "Code Complete" kitabindaki "goto" ile alakali bolum.
Ben sahsen goto kullanmanin program yapisini daha karisik ve kontrol edilemez hale getirdigini dusunuyorum. O yuzden goto kullanmamaya calisiyorum. Fakat bazi dongu ve bilhassa hata durumlarini kontrol ederken goto kullanmamak cok daha kotu, okunmasi ve anlasilmasi zor ayni zamanda gereksiz kod yazimini gerektiriyor. O yuzden gerekirse goto'da kullaniyorum. Fakat bazi modern dillerdeki "exception handling" (raise,throw, catch vb) mekanizmalari gotosuzda program yazilmasini sagliyor ornegin python'da goto yok!
yinede C icin konusursak, @gerbayda dahil birisi setjmp ve longjump gibi ozel "goto"lar kullanilmadan ic ice 8 tane fonksiyondan hata oldugunda nasil geri cikarlar anlatabilse cok iyi olurdu :-)
benim bu konudaki 3 kurusluk fikirlerim bu kadar.
Alıntı YapBen sahsen goto kullanmanin program yapisini daha karisik ve kontrol edilemez hale getirdigini dusunuyorum. O yuzden goto kullanmamaya calisiyorum. Fakat bazi dongu ve bilhassa hata durumlarini kontrol ederken goto kullanmamak cok daha kotu, okunmasi ve anlasilmasi zor ayni zamanda gereksiz kod yazimini gerektiriyor. O yuzden gerekirse goto'da kullaniyorum. Fakat bazi modern dillerdeki "exception handling" vb mekazizmalari gotosuzda program yazilmasini sagliyor ornegin python'da goto yok!
İşte bu açıklamaya şapka çıkartıyorum.
Python ne iş yapar?
(Kritik exception rutinlerimi asla C ile yazmam paytonu da bilmem)
Alıntı yapılan: bunalmis - 03 Kasım 2011, 15:23:32
İşte bu açıklamaya şapka çıkartıyorum.
Python ne iş yapar?
(Kritik exception rutinlerimi asla C ile yazmam paytonu da bilmem)
sayin @bunalmis bir takim saglik ve is ile isler cok fazla vaktimi almakta oldugundan python konusuna bayramdan sonra daha detayli bir cevap yazmak isterim. Ama kisaca python ve Ruby gibi modern diller program yazmak ve sahip olduklari application libler vasitasi ile cok cabuk, cok detayli ve cok hizli kosan programlar yazmaya firsat verir. Kisaca Wikipediaya bakarsak soyle der"
Python is a general-purpose, high-level programming language[5] whose design philosophy emphasizes code readability.[6] Python claims to "[combine] remarkable power with very clear syntax",[7] and its standard library is large and comprehensive. Its use of indentation for block delimiters is unique among popular programming languages.
Python supports multiple programming paradigms, primarily but not limited to object-oriented, imperative and, to a lesser extent, functional programming styles.
Benim icin en cekici kismida C ile yazilmis olmasi ve C (ve C++) ile cok kolay ve cok dogal ve kolay bir sekilde birlikte calisabilmesidir.
Mikroişlemci üzerinde Exception Handling nasıl oluyor acaba bu konuda biraz bilgi verebilir misiniz?
buna sonra değinilecek denmişti ama konuda geçtiğinden biraz yüzeysel de olsa birşeyler anlatırsanız çok sevinirim
Alıntı yapılan: ErsinErce - 03 Kasım 2011, 15:35:52
Exception Handling nasıl oluyor acaba bu konuda biraz bilgi verebilir misiniz?
buna sonra değinilecek denmişti ama konuda geçtiğinden biraz yüzeysel de olsa birşeyler anlatırsanız çok sevinirim
Insallah bayramdan sonra birseyler yazmaya calisirim ama, vaktiniz var ise "Code Complete" kitabi 2ed "Exception handling: Section 8.4" okunabilir.
mikroislemcilerde ortami exception handling icin hazirlamak icin en kolay yol, Cdeki setjump ve longjump mekanizmalarini kullanmaktir (bunlar genellikle MACRO olarak yapilirlar) yada signal ve catch gibi sw interruptlar ve stack manipulasyonuda olabilir vs. Isteyenler ASM kullanarakta kendi exception mekanizmalarini kurabilirler. Tabii RTOs ve/veya Multithreaded ortamlarda bu konu cok karisik olabilir.
Aslinda gercekci bir elestiri yapmak gerekirse, program yaziyorum deyipte Code Complete http://www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670/ref=sr_1_1?ie=UTF8&qid=1320327636&sr=8-1 (http://www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670/ref=sr_1_1?ie=UTF8&qid=1320327636&sr=8-1) kitabini okumamis, ve okuyupda kutuphanesi (dahada iyisi masasinda) tutmayan birisi benim gorusume gore profesyonel bir programci olmak yolunda daha cok yol kadetmesi lazim gelir.
Exception için interrupt konusunu öncelikle işlemek bitirmek lazım.
Fakat exception ile interrupt arasındaki keskin çizgi, şöyle özetlenebilir;
Interrupt faydalı işler, Exceptionlar tehlikeli ve hatalı durumlar için üretilir. Buna rağmen System Tick Timer bir interrupt olmasına rağmen exception sınıfına sokulmuştur. Çünkü OS yapıları için Tick Timer referansdır ve timer interrupt ürettiyse bunun bir hata gibi algılanması gerekir.
Örnek vermek gerekirse
Exceptionlar: Hard fault, Memory Manegement fault, Bus fault, Usage fault.
Exceptionların yönetimi CPU dadır. NVIC bunlara karışmaz.
Fakat bu farklarının önemli olmadığı durumlar için ortak açıklamalar yapılırken interrupt ve exceptionların her ikisine birden exception da deniyor.
Exceptionlara bulaşmak için interrupt mekanizmasını iyice kavramış olmak ardından da ARM Core registerlere değinmemiz gerekiyor.
Bu nedenle bu aşamada amacımızdan uzaklaşmamalıyız.
bu konu için ne kadar sabırsızlandığımı anlatamam, Exception yapılarının sebeplerini az çok anladım gibi
Ama nasıl işliyor, işledikten sonra neler oluyor, bu işlemleri ne kadar etkileyebiliyoruz gibi sorular hazırda bekliyor hocam :)
Cortex M3 Basics diye bir kitap var. PDF linki forumda da olacak.
Merak ettiğin soruların cevabını şimdiden bu kitapta bulabilirsin.
http://en.wikipedia.org/wiki/Setjmp.h bu fonksiyon gerçekten çok kullanışlıymış, bilmek iyi oldu çok sağolun mufitsozen hocam
bahsettiğiniz kitap bu mu bunalmis hocam?
http://books.google.com.tr/books?id=mb5d_xeINZEC&printsec=frontcover&hl=tr#v=onepage&q&f=false
Alıntı yapılan: ErsinErce - 03 Kasım 2011, 16:18:20
bu konu için ne kadar sabırsızlandığımı anlatamam, Exception yapılarının sebeplerini az çok anladım gibi
Ama nasıl işliyor, işledikten sonra neler oluyor, bu işlemleri ne kadar etkileyebiliyoruz gibi sorular hazırda bekliyor hocam :)
Bu kısımları açıkcası yüzeysel biliyorum.
Mesela CM3(4) işlemciye yüklediğiniz kod bir noktada işlemciyi ARM moduna sokup bu şekilde kod koşturumu yapacak olsun. Böyle bir kodu rahatlıkla yazabiliriz.
CM3(4) işlemciye yüklenmiş böyle bir fonksiyon işletilip processor, ARM moduna geçmeye zorlandığında derhal usage exception oluşur.
Bu aşamada port çıkışlarını güvenli konumlara çekmek, interrrupları yasaklamak ve ardından win deki gibi mavi ekran üzerinde uygulamanın sona erdirilildiğini işletilen kodun bu işlemciye uygun olmadığını duyurmaktan başka çok da fazla bir seçeneğimiz yok görünüyor.
Alıntı yapılan: ErsinErce - 03 Kasım 2011, 16:37:46
bahsettiğiniz kitap bu mu bunalmis hocam?
http://books.google.com.tr/books?id=mb5d_xeINZEC&printsec=frontcover&hl=tr#v=onepage&q&f=false (http://books.google.com.tr/books?id=mb5d_xeINZEC&printsec=frontcover&hl=tr#v=onepage&q&f=false)
Evet.
Ben bu kitabı paylaşmıştım forumda lik var.
ulaşamazsanız yenide upload ederim.
bahsettiğiniz kitap exceptionları biraz hızlı geçmiş interruptlar üzerine yönelmiş daha çok,
bulduklarım arasında son kaynak genel ARM yapısından bahsediyor bizim çipi kapsıyor mu tam emin değilim ama diğer pdf biraz daha geniş yer vermiş bu konuya
http://infocenter.arm.com/help/topic/com.arm.doc.dui0056d/DUI0056.pdf
http://vatly.ucoz.com/_ld/0/36_Elsevier-ARM_Sy.pdf
dikkati daha fazla bu yöne çekmeyeyim, kaldığımız yerden devam edelim hocam
Selam arkadaşlar aranıza yenikatıldım, ARM'lerede yeni bulaştım...:) Elimde stm32f100rb kart var, Keil kullanıyorum, C yi dde örnekleri inceleyerek ve kaynaklarla öğreniyorum, C# biliyorum birazda picbasic ama C kodlarınıda okuyabildiğimi de fark ettim burayıda keşfettim iyi oldu açıkcası...
Şimdi elimde 2x16 paralel LCD var, sheetler yardımıyla bağlantılarıyaptım, şimdi örnekleri veyayazdıklarımı derleme vakti geldi, denemelere başlamam gerek artık, ama Keil'de derleyemiyorum "Please select first the target STM32F10x device used in your application (in stm32f10x.h file)" hatası alıyorum...
Ama Keil'in örneklerinde kit üzerinde gelen yazılımın aynısı var, onu ise istediğim değişiklikleri yapıp derleyebiliyorum, sanırım bir yerde hatam var, yardımcı olabilirsinizsanırım, şimdiden teşekkürler...
https://www.picproje.org/index.php/topic,35719.0.html (https://www.picproje.org/index.php/topic,35719.0.html)
Sorunun cok acik degil. Belki yukaridaki link yardimci olur.
Projeyi olustururken linkteki anlatimlari izle.
Keil ile çalışırken __IO tanımlamasını nasıl kullanıyoruz ,tanımını- açıklamasını bulamadım. sadece ilgili işlemcinin .h dosyasının içinde görüyorum,ancak kesin tanımını okumak istiyorum.
Buldum buymuş ;
#define __IO volatile
Yeni sorum var;
Keilde bir structure tanımlayalım ve bu structure yapısında bir pointer tanımlayalım ve bu pointerin adresini tanımlama aşamasında belirleyelim;
Buşekilde yapabiliyorum ;
Alıntı Yaptypedef struct {
uint32_t fg ;
}output_;
#define df ((output_ *) (GPIOC_BASE+(uint32_t)0x0C))
Ancak benim istediğim
Alıntı Yaptypedef struct {
uint32_t fg ;
}output_;
output_ *yu=(GPIOC_BASE+(uint32_t)0x0C);
Yani adresi tanımlama yapılırken belirlenmiş pointer elde etmek istiyorum ancak hata veriyor.
Ne oldu şimdi?
Basic ve ASM kullananan arkadaşlar C de bir şeyler karalayabilir hale geldilermi?
Keil'de proje dosyası açıp, derleyip debug edebiliyorlarmı?
Yoksa Mevlam kayıra saldım çayıra durumları mı?
proje ve derlemede sıkıntı yok. bunalmış hocam. sadece datasheeti biraz daha incelemek lazım kendi adıma.
@bunalmiş hocam,
Merak etme, kitler milletin eline geçince başını baya bi ağrıtacak herkes :)
Yazılanları okudum emeğinize sağlık bir kaç tane sorum var.
S1-)GPIOD->OSPEEDR= 0xFFFFFFFF;
Daha önce bir kişi daha sormuş ama verilen cevaplardan pek bir şey anlamadım.
Bu komuttaki "
->" operatörün görevi tam olarak nedir, ne iş yapar, neyi sağlar ?
Örnek verebilir misiniz?
S2-)Alıntı Yap
Eğer bir fonksiyon f1(int i); şeklinde tanımlanmışsa başına otomatik olarak int belirleyicisi eklenir ve şu anlama gelir;
int f1 (int i);
Dışarıdan int türünde bir parametre al ve geriye de int türünde bir değer döndür.
void f1 (int i);
Dışarıdan int türünde bir parametre al ve geriye değer döndürme
Bu ifadede "int f1 (int i);" fonksiyonu geriye bir değerle dönüyor denmiş.
Geriye dönen değeri nasıl kontrol ediyoruz, fonksiyon dışında geriye dönen değeri nasıl kullanıyoruz bir örnekle açıklayabilir misiniz?
S3-)Mesela c#'da değişkene karakter yüklemek istidiğimizde değişkeni
string olarak tanımlıyorduk. Bu platformda değişkene karakter atamak için nasıl tanımlamalıyım ?
Soruya soruyla cevap vereyim.
Once sen cevapla.
Siradan bir degiskene nasil erisirsin? Bu degiskene pointer ile nasil erisirsin?
Structure nedir?
Structure'a dogrudan nasil erisirsin? Bir structure'a pointer ile nasil erisirsin?
Alıntı yapılan: bunalmis - 22 Aralık 2011, 23:06:52
Siradan bir degiskene nasil erisirsin? Bu degiskene pointer ile nasil erisirsin?
Hocam bu sorunun cevabı gene sizin yazdığınız kodlar olabilir mi ?
void main()
{
int a,b; // a ve b integer iki degisken
int* p // p, integer degiskenlerin adresini saklayabilen bir degisken, yani bir pointer
p=&a // a degiskeninin adresini p ye yukledik
a=1; // a=1 yaptik
b=*p; // p degiskenindeki adresdeki veriyi b ye yazdik. (b=a oldu)
}
Alıntı yapılan: bunalmis - 22 Aralık 2011, 23:06:52
Structure nedir?
Bunu da siz öğrettiniz.
Standart veri tipleri dışında veri tipi oluşturmamıza yarayan yapı.
Alıntı yapılan: bunalmis - 22 Aralık 2011, 23:06:52
Structure'a dogrudan nasil erisirsin? Bir structure'a pointer ile nasil erisirsin?
Gene sizin örneklerinizden cevaplamaya çalışayım.
struct Ozel
{
int IntBileseni;
char CharBileseni;
}
int* k;
int* l;
struct Ozel A;
A.IntBileseni=0x1234;
A.CharBileseni='Z'
*k=A.IntBileseni;
*l=A.CharBileseni;
Ben Pointer olayını halen tam olarak olarak kavramış değilim.
Pointer hakkında bişeyler yapıyorum ama ezbere. :-\
@EMG81
soyle oturakli islemcilerden birisi icin assembly biliyormusun.
@Sayment
Yazdigin cevaplari keil de derlemeyi denedinmi? Bu cevaplari bilerek mi yazdin yoksa cut-copy mi?
Pointerin canina okumanin vakti geldi demekki.
Hayır keilde denemedim.
Sorulardan ne anladıysam konu anlatımlarınız içerisinden cevap vermeye çalıştım. Cevap olarak yazdığım kodları anlayabiliyorum.
Hata mı yaptım ?
Gerbay
Hocam ne yaptin? C den sogutacagiz milleti.
Sayment sorun yok, sadece structure ile olan kisimda structure icerigini pointerin gosterdigi yere tasimissin. Ben bunu degil, structure'a pointer ile ulasmani istemistim.
Alıntı yapılan: bunalmis - 22 Aralık 2011, 23:50:13
@EMG81
soyle oturakli islemcilerden birisi icin assembly biliyormusun.
Hayır ne yazıkki bilmiyorum. Kısaca hayat hikayem şöyle;
6-7 yıl kadar 8 bit işlemciler ve asembly ile çalıştım. Assembly artık beni yormaya başlayınca bir ara Basic ile tanıştım ::) bu serüven birkaç ay kadar sürdü. Şimdi C ile çalışıyorum. Mutluyum :)
Hangi 8 bit islemcilerle index registeri olan bir islemci ile calistinmi?
@gerbay
Hocam açıklama için teşekkür ederim fakat bu biraz üst düzey olmuş. Bilgi eksiği çok bende :(
@bunalmis
"Structure'a pointer ile ulaşmanı istemiştim." derken; Structure'nin içeriğine ulaşmamı istemediniz mi ?
Yok fark yok elbette de, burada anlatilmasi gereken konu yandaki yazim seklinde kirmizi renkli kisim. GPIOD->OSPEDR
Alıntı yapılan: bunalmis - 23 Aralık 2011, 00:07:52
Hangi 8 bit islemcilerle index registeri olan bir islemci ile calistinmi?
Pic ve ATmel ile çalıştım.
Alıntı yapılan: gerbay - 23 Aralık 2011, 00:11:54
arkadaşlar arka planda neler olduğunu göstermek için biraz detay gösterdim ama size bu karışık gelip gözünüzü korkutmasın.
sizin için tek bilmeniz gereken GPIO-D nin OutputSpeed registerına 0xFFFFFFFF değerinin atandığı bilgisi..
Bunu anladım hocam sağolun.
Alıntı yapılan: bunalmis - 23 Aralık 2011, 00:12:34
Yok fark yok elbette de, burada anlatilmasi gereken konu yandaki yazim seklinde kirmizi renkli kisim. GPIOD->OSPEDR
Sormak istediğim tam olarak buydu.
Hocam pointer tam olarak ne iş yapar bunu tam kavrayamamışım okudukça kafam karışıyor.
Evet oncelikle pointer isleminin canina okumamiz gerekiyor cunku pek cok kisi pointeri ezbere kullanmaya calisiyor.
Fakat -> icin ben de kisa bir aciklama yapacagim.
Keilde ornek bir proje olusturun. (Bunu ARM ogreniyoruz bolumunde Keil basliginda anlattik)
ardindan optimizasyon seviyesini 0 yapin. ve asagidaki kodlari main satirinin icine kopyalayin.
Derleyin ve debug moduna gecin. Memory window da adresi 0x20000000 e set edin.
Kodlari satir satir isletin ve her satir isletimi ardindan memory window da 0x20000000 den itibaren ilk bir kac degeri gozleyin.
void SystemInit()
{
}
typedef struct
{
int x;
short y;
} MyStruct; // MyStructure adinda structure tanimi yaptik
MyStruct A; // A, MyStructure yapisinda olsun.
int main()
{
MyStruct* Z; // Z bir pointer olsun ve MyStructure tipindeki verilere ulasmaya yarasin
A.x=1; // A structurunda x elemanina 1 degerini yukle
A.y=2; // A structurunda y elemanina 2 degerini yukle
Z=&A; // Z pointerimize A structure'inin adresini yukleyelim
Z->x=3; // Z pointerinin, point ettigi structure'in x elemanina 3 degerini yukle
Z->y=4; // Z pointerinin, point ettigi structure'in y elemanina 4 degerini yukle
while(1);
}
Pointer icin sabah anlasilir bir yazi yazacagim.
Yani "adaminBiri" değişkenin içeri 0x12345678 adresinde tutuluyor diyelim.
adaminBirineIsaretci = &adaminBiri;
Bu işlemden sonra "adaminBiriIsaretci" değişkeninin içeriği 0x12345678 mi oluyor ?
@gerbay
Teşekkür ederim hocam anladım. Ama bu aşamadan sonra bir kaç sorum daha olacak onları da yarın sorayım :)
@bunalmis
Hocam bu yazdıklarınızı sabah dinç kafa ile anlamaya çalışayım bende. Emeğiniz için teşekkür ederim.
Pointer hakkında
char A; // 1 Byte alan kaplayan bir değişken
A=1; gibi bir atamada yapılan işlem RAMda A için ayrılan 1 bytelık alana 0x01 verisini yerleştirmek demektir.
Bu işlem CPU tarafından şu şekilde yapılır.
Yukle32 Register1, A_Adres A nın adresini Register1 içine yükle
Yukle8 Register2, 1 0x01 sayısal değerini Register2 içine yükle
Sakla8 Register2,[Register1] Register2 içeriğini Register1 içeriği olan adrese yerleştir.
Alt seviye bu işlemde Register1, Anın adresini saklamakta yani A registerini göstermekte yani A registerini point etmektedir.
Makine kodlarıyla C dilindeki A=1 atamasını yapmanın en sık kullanılan ve en yalın hali budur.
Örneğin
int A;
ardından A=1; gibi program parçacığı derlendiğinde derleyici derhal A nın adresi olan sayısal değeri belirler (diyelimki A nın adresi 0x20000000) ve
Yukle32 Register1, 0x20000000
Yukle8 Register2, 0x01
Sakla8 Register2,[Register1]
program parçaçığını oluşturur.
Görüldüğü üzere burada derleyici, A değişkenine değer atılacağını bildiği için derhal A değişkeninin adresini daha derleme aşamasında hemen kodların arasına sıkıştırmıştır.
-------------------------------
Peki programımızda hangi değişkene değer atılacağını yazım aşamasında değilde kodların işlenmesi aşamasında bildirmek istersek bu nasıl yapılır?
Örneğin A ve B adında 8 bitlik iki değişkenimiz olsun.
char A, B;
Bu durumda hangi değişkenle uğraşacaksak bu değişkenin adresini tutacak aracı bir değişkene (pointer) ihtiyaç duyarız.
bu aracı değişken char *P gibi tanımlanır. Burada * pointerdan bahsedildiğini yani *P, P bir pointer demektir anlamına gelir.
char *P ise P nin 8 bitlik verilere ulaşmak için tanımlanmış bir pointer olduğunu söyler.
Her hangi bir değişkenin adresini bilirsek pointer ile bu değişkenin Ramda kapladığı alana ulaşabilir buraya istediğimiz veriyi yazabilir yada tersine okuyabiliriz.
Bir değişkenin adresini öğrenmek istediğimizde değişkenin hemen önüne & sembolü koyarız.
Bu durumda P=&A yazdığımızda Anın adresi P pointerine yazılmış olur. Şimdi bu adrese 0x01 değerini yerleştirmek istersek
*P=0x01; dememiz yeterlidir.
tekrar edecek olursak;
P=&A; A değişkeninin adresini P ye yaz.
*P=0x01; P de saklı olan adresin gösterdiği yere 0x01 değerini yerleştir.
-----------------------------------------------------------------------------------------
8 bitlik A , 16 bitlik B, 32 bitlik C değişkenimiz olsun.
Bunların her birisine 1 sayısını yüklemek isteyelim.
char A;
short B;
int C;
char* PA;
short* PB;
int* PC;
*PA=1;
*PB=1;
*PC=1;
Neden pointerleri char, short yada int tanımlama ihtiyacı duyuyoruz?
8 bitlik 1 sayısı 01
16 bitlik 1 sayısı 0001
32 bitlik 1 sayısı 00000001
Örneğin int pointerin gösterdiği adrese 1 sayısı yazılacaksa ramda bu adrese 0x00 takip eden bir sonrakine 0x00 bir sonrakine 0x00 bir sonrakine ise 0x01 yerleşir. (Aslında tam tersi)
Bu nedenle point edilecek değişken adresinin uzunluğunu pointer tanımında net şekilde belirleriz.
-----------------------------------------------------------------------------
Peki CPU pointer ile çalışırken nasıl kod işletir.
Örneğin aşağıdaki kod, yazımın en başında yazdığım koddan alıntıdır.
Yukle8 Register2, 1 0x01 sayısal değerini Register2 içine yükle
Sakla8 Register2,[Register1] Register2 içeriğini Register1 içeriği olan adrese yerleştir.
Burada Register1 içine hangi 8 bitlik değişkenin adresi yazılırsa o değişkene 0x01 değeri yazılmış olur.
P=&A gibi bir C komutu, alt seviyede
Yukle32 Register1, A_Adres şeklinde makina kodlarına dönüşür.
-------------------------
P=&A ;
*P=0x01;
iki satırlık C kodu ise, makine dilinde aşağıdaki koda dönüşür. Bu da yazımızın en başındaki kırmızı kodların ta kendisidir.
Yukle32 Register1, 0x20000000 // P=&A ;
Yukle8 Register2, 0x01
Sakla8 Register2,[Register1]
Yukarıdaki kodda derleyicinin RAMda 0x20000000 adresini A değişkene reserve ettiğini görüyoruz.
Pointer sonuçta postacıdır. Postacıya bir paket ve bunun teslim edileceği adresi verirseniz, postacı paketi alıcısına teslim eder.
P=&Ahmet; Postacı, Ahmetin adresi bu
*P=0x01; 0x01 i bu adrese teslim et.
Pointer kullanmasaydık
Ahmet=0x01 ; Ahmet bu 0x01 senin.
int A;
short B;
char C;
char D;
int* P;
A=0x02;
P=&A;
P++;
*P=0x01;
Bu soruya kafa yorunuz. Sorum bu program ne yapar?
Bu soruyu çözen pointeri anladı demektir.
A=0x02; // A değişkenine 2 sayısını yükle(A=2)
P=&A; // A değişkeninin adresini pointere kaydet
P++; // A değişkeninin içeriğini 1 arttır (A=3)
*P=0x01; // A değişkenine 1 sayısını yükle (A=1)
Doğru mudur ?
Hocam Şurada Bir Yanlışınız mı var Benmi Yanlış Anlıyorum.
Yukle8 Register2, 1 0x01 sayısal değerini Register2 içine yükle
Sakla8 Register2,[Register1] Register2 içeriğini Register1 içeriği olan adrese yerleştir.
Sakla8 Reg2,[Reg1]
burada Reg1 içeriğindeki bilgiyi Adress olarak kabul et ve o adrese giderek içeriği al ve Reg2 ye kaydet değilmidir. (Dolaylı adresleme)
A=0x02; // A değişkenine 2 sayısını yükle(A=2)
P=&A; // A değişkeninin adresini pointere kaydet
P++; //Adres bilgisini bir arttır
*P=0x01; // A adresinden Sonraki adrese 0x01 degerini yaz
Sanırım
void SystemInit()
{
}
typedef struct
{
int x;
short y;
} MyStruct; // MyStructure adinda structure tanimi yaptik
MyStruct A; // A, MyStructure yapisinda olsun.
int main()
{
MyStruct* Z; // Z bir pointer olsun ve MyStructure tipindeki verilere ulasmaya yarasin
A.x=1; // A structurunda x elemanina 1 degerini yukle
A.y=2; // A structurunda y elemanina 2 degerini yukle
Z=&A; // Z pointerimize A structure'inin adresini yukleyelim
Z->x=3; // Z pointerinin, point ettigi structure'in x elemanina 3 degerini yukle
Z->y=4; // Z pointerinin, point ettigi structure'in y elemanina 4 degerini yukle
while(1);
}
Anladım "A.x=y" ile "Z->x=y" aynı anlama geliyor. Ama neden "A.x=y" yazmak yerine "Z->x=y" yazıyoruz?
Bunun avantajı ne bize ne sağlıyor?
Alıntı Yapint A;
short B;
char C;
char D;
int* P;
A=0x02;
P=&A;
P++;
*P=0x01;
Bu soruya kafa yorunuz. Sorum bu program ne yapar?
Bu soruyu çözen pointeri anladı demektir.
öncelikle: int ve short aynı anlama gelir,
hatta
int A;
short A;
short int A;
bu üçü aynı anlamdadır.
soruya gelince:
A=0x02; // A'nın değerini 2 yap
P=&A; // A'nın adresini P pointerine ata
P++; // P pointerinin gösterdiği adresi 1 arttır. yani P, önceden A'nın adresini gösterirken, şimdi A'dan 1 sonraki adresi göstersin. P artık bellekte A'nın değil, A'dan sonraki bellek adresini göstermektedir. bu da (muhtemelen) B'nin adresidir.
*P=0x01; // B'nin değerini 1 yap
Nasıl Aynı Anlama Geliyor.
Alıntı Yap
Type Bytes Bits Range
short int 2 16 -32,768 -> +32,767
unsigned short int 2 16 0 -> +65,535
unsigned int 4 16 0 -> +4,294,967,295
int 4 32 -2,147,483,648 -> +2,147,483,647
long int 4 32 -2,147,483,648 -> +2,147,483,647
signed char 1 8 -128 -> +127
unsigned char 1 8 0 -> +255
float 4 32
double 8 64
long double 12 96
C dilinde şamata yapıyoruz desek de aslında CM4 işlemcimiz için Keil kullanarak C dilinde şamata yapıyoruz.
Bu şartlarda
int 32 bit
short 16
char da 8 bit değişken anlamına geliyor.
@Bocek pointer sorusuna verdiğin cevabın doğru değil.
@Muhittin Kaplan
Sakla8 Reg2,[Reg1]
Reg2 registerindeki değeri Reg1 registerinde adresi saklı alana yaz anlamına geliyor.
int A;
short B;
char C;
char D;
int E;
int* P;
A=0x02;
P=&A;
P++;
P++;
*P=0x01;
Birde bu soruya kafa yorunuz. Sorum bu program ne yapar?
Bu soruyu çözen pointeri tam anladı demektir.
MOV A,30h mu yani (30h adresinde bulunan bilgiyi A ya Taşı) 8051
int A;
short B;
char C;
char D;
int E;
int* P;
A=0x02; //A=0x02
P=&A; //P=A nın Adresi
P++; //P=P+1
P++; //P=P+1
*P=0x01; //P nin gösterdiği adrese 0x01 yaz
Yani E ye
Hocam E yemi C yemi :) ben C diye hesapladım ama..
Alıntı yapılan: muhittin_kaplan - 23 Aralık 2011, 17:18:10
MOV A,30h mu yani (30h adresinde bulunan bilgiyi A ya Taşı) 8051
MOV tarzi komutlarda işlem yönü firmadan firmaya değişir. Örneğin İntel ve TI da zıtdır.
Fakat benim örneğimde Sakla8 Reg1,[Reg2] yazinca fazla kafa yormaya degmez.
Cunku Bir onceki komutta Yukle8 diye hayali bir komut yazmisim. Bununla register icine 0x01 gibi deger atamisim.
Hemen ardindan da Sakla8 di'ye hayali komut kullanmisim.
Bu durumda Yukle8 MOVE, Sakla8 de STORE anlamina geliyor.
STORE komutunda STORE Reg1,[Reg2] ye bahsettigimden daha farkli anlam veremezsin.
(http://img191.imageshack.us/img191/9492/adszkvt.png)
olmaz mı ?
char *a;
char b;
b= *a++;
ile
b=*a;
a++;
ayni mi calisir ?
@Muhittin Kaplan
Evet aynen dedigin gibi E ye 0x01 yukler.
Yalniz bu soruda derleyicinin alt alta tanimladigimiz degiskenleri RAM'da da ardisil adreslere yerlestirdigini varsaydik.
Bu soru icin ardisil adresler olsa da daha farkli sorular icin durum degisir.
Neden degisir sorusunun cevabini merak edenler varsa kafa yorun biraz. Neden degisir?
Alıntı yapılan: muhittin_kaplan - 23 Aralık 2011, 17:12:46
Nasıl Aynı Anlama Geliyor.
@muhittin hocam öyle diyorsun da bunca yıldır (epey bi yıl;) ben int ve short'u aynı bilirdim. şurdaki kaynaklar beni destekliyor:
http://s2.hubimg.com/u/978945_f496.jpg
http://www.exforsys.com/tutorials/c-language/c-programming-language-data-types.html
senin verdiğin tabloda int ve long int aynı uzunlukta.
benimkinde int ve short int aynı uzunlukta.
şurda da demiş ki öyle de olur böyle de:) sistemine göre değişir.
http://cprogramminglanguage.net/c-data-types.aspx
Aslında ben "Hangi derleyiciye Göre" Diyecektim (Ansi C data types -Google)ama bakınca Bunu gördüm.
@Bocek
32 Bit islemci ile calisiyoruz. Bu durumda short 16 bit anlama geliyor.
Senin verdigin tablo belliki 16 bit islemciler icin duzenlenmis.
char <= short <= int <= long
Unutmadan chardan küçük nibble dediğimiz 4 bitlik veri vardır ancak bunu derleyiciler BCD dışında pek irdelemez. Semioctet diyede geçer.
Alıntı yapılan: sayment - 23 Aralık 2011, 15:02:17
void SystemInit()
{
}
typedef struct
{
int x;
short y;
} MyStruct; // MyStructure adinda structure tanimi yaptik
MyStruct A; // A, MyStructure yapisinda olsun.
int main()
{
MyStruct* Z; // Z bir pointer olsun ve MyStructure tipindeki verilere ulasmaya yarasin
A.x=1; // A structurunda x elemanina 1 degerini yukle
A.y=2; // A structurunda y elemanina 2 degerini yukle
Z=&A; // Z pointerimize A structure'inin adresini yukleyelim
Z->x=3; // Z pointerinin, point ettigi structure'in x elemanina 3 degerini yukle
Z->y=4; // Z pointerinin, point ettigi structure'in y elemanina 4 degerini yukle
while(1);
}
Anladım "A.x=y" ile "Z->x=y" aynı anlama geliyor. Ama neden "A.x=y" yazmak yerine "Z->x=y" yazıyoruz?
Bunun avantajı ne bize ne sağlıyor?
Mystructure tipinde A, B, C, D, ..... structurelar tanimlamis olalim.
Tek bir fonksiyon yazarak istedigim structurla veri alisverisinde bulunmak isteyelim.
Iste burada siradan degiskenlerde pointer ne avantaj sagliyorsa structure pointer de structure yapisindaki degiskenlerde ayni avantaji saglar.
int A;
short B;
char C;
char D;
int E;
int* P;
A=0x02;
P=&A;
P++;
*P=0x01;
Sorularım var ,
1- bunalmis hocam peşisıra yapılan tanımlamalarda , tanımladığımız değişkenlere ram'de ardı ardınamı yer alırlar. bu istisnasız değişmez öylemi ?
2- A 32 bit , ve B 16 bit ise bunların ram'de tuttukları yerler ;
(http://i1114.photobucket.com/albums/k538/lordex06/1Ram.jpg)
Böylemidir ? (Adres misal vermek için yazıldı ) böyle ise P=&A; satırında A'nın bulunduğu adres olarak P hangi değeri alır ?
3- P++; satırında adres değeri bir mi artırılır ? Yoksa int *P; ile 32 bit tanımlandığı için 32 eklenerek mi artırılır?
4- Eğer değer 32 artıyorsa *P=0x01; ile değer D'ye mi yazılır yani D=0x01 mi olur? (B 16 bit C 8 bit D 8 bit)
Green
1 nolu soruya cevap vermistik.
Veriler ardisil adreslere yerlesmez. İstisnai olarak aşağıdaki örnekte ardışıl çünkü veri tiplerine özenle seçtim.
Diğer sorularına gelmeden önce ilk soruma tekrar gözatmanızı istiyorum.
int A;
short B;
char C;
char D;
int* P;
A=0x02;
P=&A;
P++;
*P=0x01;
Bu soruya cevaplar geldi. Fakat sonradan farkettim. Henüz doğru cevap gelmedi.
burada da 0x01 değerini B ye yükler
(http://img207.imageshack.us/img207/7717/adszjck.png)
Pointerin dikkatsiz kullanımı kazalara yol açar.
Birşeyler eziliyor. Pointerle uğraşmanın tehlikesi de bu. Hangi değişkene ne oluyor?
Big endian ve little endian durumu için aynı soruya bir daha kafa yorun.
@Muhittin kaplan Verdiğin resim yanlış.
ARM işlemcilerde ram adresleri 1 bir artarken sadece 8 bit ilerlersin.
0 adresinde int değer varsa adresi 4 artırırsan bu int değişkeni takip eden değişkene ulaşırsın.
Alıntı yapılan: bunalmis - 23 Aralık 2011, 18:13:25
Green
1 nolu soruya cevap vermistik.
Veriler ardisil adreslere yerlesmez. İstisnai olarak aşağıdaki örnekte ardışıl çünkü veri tiplerine özenle seçtim.
Diğer sorularına gelmeden önce ilk soruma tekrar gözatmanızı istiyorum.
int A;
short B;
char C;
char D;
int* P;
A=0x02;
P=&A;
P++;
*P=0x01;
Bu soruya cevaplar geldi. Fakat sonradan farkettim. Henüz doğru cevap gelmedi.
Eğer ram adresimiz 0x20000000'den başlıyorsa
A'nın adresi 0x20000020 olur. A =0x02 değerini alır (32 bit)
P=&A; //A'nın adresi 0x20000020 olur. P A 'nın adresini alır.
P++; //P 32 bit artırılır , 0x20000040 olur buda D nin adresidir.
*P=0x01; //pointer tuttuğu adrese 0x01 değerini yazar. Yani D ye 0x01 değeri atılır.
Alıntı yapılan: muhittin_kaplan - 23 Aralık 2011, 18:28:37
(http://img207.imageshack.us/img207/7717/adszjck.png)
Muhittin hocam o zaman senin gösterdiğin ram yapısında pointeri öyle artır ki D'yi yada C'yi işaret etsin ?
Alıntı YapEğer ram adresimiz 0x20000000'den başlıyorsa
A'nın adresi 0x20000020 olur. A =0x02 değerini alır (32 bit)
P=&A; //A'nın adresi 0x20000020 olur. P A 'nın adresini alır.
P++; //P 32 bit artırılır , 0x20000040 olur buda D nin adresidir.
*P=0x01; //pointer tuttuğu adrese 0x01 değerini yazar. Yani D ye 0x01 değeri atılır.
Anlaşıldı. Bu böyle olmayacak.
Adres hesaplaması bu şekilde değil. Yanlış yapıyorsunuz.
Arm işlemcilerde memory kullanımı, değişkenlerin ramda tanımlanması konusuna bakmanız gerekecek.
Tabiki big ve little endian yapısına da.
Alıntı yapılan: bunalmis - 23 Aralık 2011, 18:13:25
Veriler ardisil adreslere yerlesmez. İstisnai olarak aşağıdaki örnekte ardışıl çünkü veri tiplerine özenle seçtim.
Diğer sorularına gelmeden önce ilk soruma tekrar gözatmanızı istiyorum.
int A;
short B;
char C;
char D;
int* P;
A=0x02;
P=&A;
P++;
*P=0x01;
Bu soruya cevaplar geldi. Fakat sonradan farkettim. Henüz doğru cevap gelmedi.
C D 0 olurken B 1 değerini alması gerekiyor (little endian)
B C 0 olurken D 1 değerini alması gerekiyor (big endian)
hocam Cortex-M3 M4 serisinde adresler ardışıl yerleşiyor diye biliyorum ???
sf:10-11 ben mi yanlış anladım acaba?
http://www.arm.com/files/pdf/IntroToCortex-M3.pdf
arada yazılanları sonradan gördüğümden edit fazla oldu kusura bakmayın
Alıntı yapılan: bunalmis - 23 Aralık 2011, 18:30:47
ARM işlemcilerde ram adresleri 1 bir artarken sadece 8 bit ilerlersin.
0 adresinde int değer varsa adresi 4 artırırsan bu int değişkeni takip eden değişkene ulaşırsın.
8 bit ilerlersek B = 0x0100 olur sanırım (bu sefer doğru olsun .... :) )
Alıntı yapılan: GreeN - 23 Aralık 2011, 18:51:27
8 bit ilerlersek B = 0x0100 olur sanırım (bu sefer doğru olsun .... :) )
Adres ile değer kavramlarını karıştırıyorsun hocam
biri evin kapı numarası diğeri içindeki kişi sayısı
windows olsaydı çoktan mavi ekran vermişti :D
Peki M4 chip Big mi little mi?
Little ve big olursa ne olur ?
Alıntı yapılan: ErsinErce - 23 Aralık 2011, 18:48:06
hocam Cortex-M3 M4 serisinde adresler ardışıl yerleşiyor diye biliyorum ???
sf:10-11 ben mi yanlış anladım acaba?
http://www.arm.com/files/pdf/IntroToCortex-M3.pdf (http://www.arm.com/files/pdf/IntroToCortex-M3.pdf)
Ardışıl yerleşmez. Adress Align işlemi var. Byte tipi veriler herhangi bir adrese yerleşirken 16 bit word tipi (short) veriler çift adreslere yerleşir. integer tipi 32 bit veriler ise sadece 0 ve 4 ün tam katlarına yerleşir.
Eğer C de ard arda tanımladığınız karmaşık veriler varsa (int chat char int short) bu durumda sıralamayı bozan verinin adresi yeniden hesaplanır ve arada boşluklar oluşur.
Align edilmemiş yerleşimde işlemcinin veriye ulaşım performansı düşer hatta bazı komutlar hizalanmamış verilere erişmeye kalktığında exceptiona neden olur. C derleyici buna engel olmak için verileri kendisi hizalar.
Birde eğer verileriniz arasında structure, array vs durumlar varsa hangi değişken nereye yerleşmiş bunu tahmin edemezsiniz.
ARM Cortex - M çekirdeğini her iki türlü (Big ve Little) tasarlıyor. Slikon üreticisi hangisini isterse onu tercih ediyor. Bunu için silkikon üreticisinin dökümanlarına bakmak gerekli.
Alıntı yapılan: muhittin_kaplan - 23 Aralık 2011, 19:09:18
Peki M4 chip Big mi little mi?
Little ve big olursa ne olur ?
CM3 işlemciler little endian çalışır. İstisnai olarak big endian çalışabilen çipler de varmış. (TI Stellaris little edndian çalışıyor)
CM4 işlemcimiz de little endian çalışıyor. Fakat bunu reset yada system init aşamasında değiştirebiliyoruz diye bir yazı okuduğumu hatırlamıyorum. Little endian bana daha mantıklı geldiği için hiç değiştirme ihtiyacı duymadım.
Çipi bigendian moduna geçirdiyseniz peripheral registerlere erişimde tekrardan little ednian moduna geçmeniz gerekir.
Fakat bu dediklerim C ile program yazanları nerede ise hiç ilgilendirmez.
Alıntı yapılan: muhittin_kaplan - 23 Aralık 2011, 19:09:18
Peki M4 chip Big mi little mi?
Cortex™-M4 Devices Generic User Guide ( 2-10 sf:23 ) dediğine göre
Alıntı Yapmanages all data memory accesses as little-endian or big-endian. Instruction memory and
Private Peripheral Bus (PPB) accesses are always performed as little-endian.
hafıza erişimi değişebiliyor fakat diğer bölümler her zaman little endian olarak çalışıyor
@bunalmis anladım hocam teşekkürler
Little tamam. Yani LSB ile MSB ters.(Google dan aratınca çıkıyor hepsi de Tarihe not düşmek gerek)
1.peki bu hafıza adresleme yaparken ne olay yaratıyor?
2.her memory adresi 8 bitten oluşuyor dediniz.
peki int* P; tanımlaması yapıp A nın adresini yüklediğimizde p++ yaparsak anın adresine 1 eklemiş olacagız ve oraya 0x02 yazacağız MI ? (Yani A=0x00000201 mi olacak)
kafam iyice karıştı bildiğimi de unuttum :D
Alıntı yapılan: muhittin_kaplan - 23 Aralık 2011, 19:42:14
Little tamam. Yani LSB ile MSB ters.(Google dan aratınca çıkıyor hepsi de Tarihe not düşmek gerek)
1.peki bu hafıza adresleme yaparken ne olay yaratıyor?
2.her memory adresi 8 bitten oluşuyor dediniz.
peki int* P; tanımlaması yapıp A nın adresini yüklediğimizde p++ yaparsak anın adresine 1 eklemiş olacagız ve oraya 0x02 yazacağız MI ? (Yani A=0x00000201 mi olacak)
Diyelimki int A değişkeni 0x20000000 adresinde.
Bunu point eden int* P pointerine 0x20000000 yükledik.
Eğer p++ derseniz Pointerimiz 0x20000004 değerini alır.
-----------------
Diyelimki char A değişkeni 0x20000000 adresinde.
Bunu point eden char* P pointerine 0x20000000 yükledik.
Eğer p++ derseniz Pointerimiz 0x20000001 değerini alır.
-----------------
Diyelimki short A değişkeni 0x20000000 adresinde.
Bunu point eden short* P pointerine 0x20000000 yükledik.
Eğer p++ derseniz Pointerimiz 0x20000002 değerini alır.
-----------------
Diyelimki char A değişkeni 0x20000000 adresinde.
Bunu point eden int* P pointerine 0x20000000 yükledik.
Eğer p++ derseniz Pointerimiz 0x20000004 değerini alır.
P nin ne zaman 1 nezaman 2 ne zaman 4 artacağına derleyici karar verir. Bunu nasıl belirler pointer tanımlanırken ne diye tanımlandığına bakar.
(http://b1112.hizliresim.com/s/r/19lpp.jpg) (http://bit.ly/c25MCx)
Dataların bu şekilde yerleştirileceği planlandı, yerleri reserve edildi.
0x0000 0000 nolu adrese 0x02 sayısını yazdı. A integer oldugu icin
0x0000 0001
0x0000 0002
0x0000 0003 nolu adreslerde şu an 0x00 var
Pointere A nın adresini yani 4 byte yer kaplayan A verisinin ilk adresi yükledi. Pointer da 0x0000 0000 var.
P nin değerini 1 arttırdı. P integer oldugu için 4 byte lık alana dokunmadan bir sonraki 4 byte lık alanın ilk adres değerini aldı. Yeni P değeri 0x0000 0004
Bu adres alanına 0x01 yükleyecek. Aslında yükleyeceği sayı 0x00000001. Bu 32 biti resimdeki ilk 4 byte lık bölüme A yı yerleştirdiği gibi (değersiz bitler değerli 8 er bitlik gruplardan once) yerleştirilecek. Dolayısıyla 0x0000 0004 nolu adrese 0x01 yüklenecek, 5,6 ve 7 nolu adreslere 0x00.
Tabloya bakılırsa B degeri 0x0001 olur. C ve D değerleri 0x00. A değişmez.
yani sonuç olarak P++ dediğimizde önceden tanımlamamız aşağıdakilerden biri olduğunda
char *P yazarsak byte
Short *P yazarsak 2 Byte
int *P yazarsak 4 byte
Long *P yazarsak 8 Byte
olarak işlem yapar.
Ozaman Yukardaki sorunu cevabı B ye yazar olacak sanırım.
Peki bir soruda benden.
int A;
short B;
char C;
char D;
int* P;
A=0x02;
P=&A;
P++;
*P=0xA501;
yazarsam ne olur
int A;
short B;
char C;
char D;
int* P;
A=0x02;
P=&A; A yi point ediyoruz.
P++; P 4 artti
*P=0x0101; P, integer bir pointer olduguna gore 0x00000101 verisini A nin 4 byte otesina yazazacak
Bu durumda B ye 0x0101, C ve D ye de 0x00 yazilacaktir.
konuyla çok alakalı değil ama c ile noktalı sayıları nasıl kullanıyoruz
bascomavr ile eproma single bir değişkeni yazdığımda 4byte yazıyor (7,50) gibi
tabi basicde ne olup bitiyor bilmdiğimiz çok nokta var
birde bunalmış hocamın haricinde konuya hakim biri spi,I2C bunları temelden anlatabilse süper olurdu
pnin gösterdiği adrese 16 bit yadık B yi doldurdu.
peki 32 yazsaidirk ozaman C ve D de yazılmış olacaktı bu haliyle.
int A;
short B;
char C;
char D;
int* P;
A=0x02;
P=&A; A yi point ediyoruz.
P++; P 4 artti
*P=0xAFB8Ad55; P, integer bir pointer olduguna gore 0xAFB8AD55 verisini A nin 4 byte otesina yazazacak
Bu durumda B ye 0xAD55, C ye B8 ve D ye de 0xAF mi yazacaktı ?
ama anlaşına şudur ki AFB8 "B" ye diğerleri sırasıyla. big ve little olayı burada mı devreye giriyor ?
Alıntı yapılan: muhittin_kaplan - 23 Aralık 2011, 21:14:55
pnin gösterdiği adrese 16 bit yadık B yi doldurdu.
peki 32 yazsaidirk ozaman C ve D de yazılmış olacaktı bu haliyle.
Hayir. *P=0x0101; yazmakla aslinda siz 16 bitlik 0x0101 degil 32 bitlik 0x00000101 yazdiniz. Cunku P integer bir pointer.
Dolayisi ile C ve D her zaman ezilecek. Daha once de dedigim gibi dikkatsizce pointer kullanimi sistemi crach edecek kadar tehlikelidir.
Little endianda
0x20000000 adresine 0x12345678 yazarsak
byte larin yerlesimi su sekilde olur.
0x20000000 adresine 0x78
0x20000001 adresine 0x56
0x20000002 adresine 0x34
0x20000003 adresine 0x12
Big endian yerlesim yapilsaydi
0x20000000 adresine 0x12345678 yazarsak
byte larin yerlesimi su sekilde olur.
0x20000000 adresine 0x12
0x20000001 adresine 0x34
0x20000002 adresine 0x56
0x20000003 adresine 0x78
Hocam Bir Karışıklılık yaşıyorum.
P aslında integer bir değişken. Biz bunu Adress saklaması için Tanımlıyoruz (Pointer)
Adres 32 bitlik olabilir. Ama o adresin değeri Char,Short,Int olabilir.
int olarak tanımladığımızda P nin içereceği adres bilgisimi yoksa içeriğindeki adrese kaydedilecek bilgiyimi tanımlamış oluyoruz.
Sizin Yukarda Yazdığınıza Göre Pointer tanımı Adrese yüklenecek Değerdir.
Short *P yazacak olsaydım. yine 32 bitlik adress değerini alırmıydı ?
Alıntı yapılan: muhittin_kaplan - 23 Aralık 2011, 21:29:06
Hocam Bir Karışıklılık yaşıyorum.
P aslında integer bir değişken. Biz bunu Adress saklaması için Tanımlıyoruz (Pointer)
Adres 32 bitlik olabilir. Ama o adresin değeri Char,Short,Int olabilir.
int olarak tanımladığımızda P nin içereceği adres bilgisimi yoksa içeriğindeki adrese kaydedilecek bilgiyimi tanımlamış oluyoruz.
Sizin Yukarda Yazdığınıza Göre Pointer tanımı Adrese yüklenecek Değerdir.
Short *P yazacak olsaydım. yine 32 bitlik adress değerini alırmıydı ?
Her zaman icin adres 32 bittir. int de olsa short da olsa char da olsa adres 32bit.
Eger pointerimiz int* P tanimlandiysa *P=blabla yazilirsa blabla herzaman 32 bit demektir.
Eger pointerimiz short* P tanimlandiysa *P=blabla yazilirsa blabla herzaman 16 bit demektir.
Eger pointerimiz char* P tanimlandiysa *P=blabla yazilirsa blabla herzaman 8 bit demektir.
Siz
int A;
short B;
char C;
char D;
tanimini bosverin. short B tanimi B nin 16 bit oldugunu soyler. Fakat int* P bir sekilde B nin adresini gosteriyorsa P, B nin short tanimini dinlemez B nin ne olduguna bakmaz bile. Cunku P integer veri pointeridir. Point ettigi yere 32 bit yazar yada point ettigi yerden 32 bit okur. Popint edilen yerdeki verinin tipi hic mi hic onemli degildir.
Zaten taa en basindan bu ornegi ozellikle verdim. Kafalar karissin gercek gorunsun diye.
konuyu cok ortadan bolmeden bir soru sormak isterim:)
Diyelim ki bir struct tanimliyoruz, bu struct'un icinde bir buffer var. buffer'in veri tipi duruma gore unsigned char da olabilir, unsigned short da. struct'u typedef ile tanimlarken run time bir deklarasyon yapamiyoruz diye biliyorum, her iki durum icinde gecerli bir struct nasil olusturulur, veya nedir bunun cozumu? ayni sekilde bu buffer'in boyutu (buffer dedigim array yani) da run time da gelecek bir degiskene gore ayarlanmali. bu arada, bu bufferi kullanacak fonksiyonlarin arguman ve return degiskenleri da gayri ihtiyari ile unsigned char veya unsigned short olacak. Siz nasil bir yontem izlerdiniz?
Bunu bilse bilse Gerbay bilir.
Ben tüm gün şehir dışındaydım. Yeni geldim ve 1 solukta tüm yazılanları okudum.
Üzülerek söylüyorum ki ben halen pointer ı anlıyamadım. Nedeni şu
Asm kısmında neler oluyor bilmiyorum ama
int a;
A=0x01;
Dediğimizde a nın içerisine 0x01 değeri yerleşmiyormu ? (Tabiki şu şekilde 0x00000001 )
Derleyici bizim yerimize A nın adresini bulup yeni değeri A nın içerisine yüklemiyormu ? Derleyiciye pointer vasıtası ile değişkenin saklandığı adresi neden hatırlatmak zorunda kalıyoruz ?
Aslında minik bir makro oluşturuyoruz. Öyle değilmi ?
int* p; // diyerek adres saklayıcı pointer tanımlayıp
int x;
*p=&x // makro oluştu.
@Bunalmis
Bana ARM assembly öğrenebileceğim E kitap önerebilirmisin ? Arka Planda neler oluyor bilmek lazım.
Assembly ye ARM ile dalmak yüzmeyi bilmeden okyanusa atlamaya benzer. 8 bit bir işlemci (Bülent hocamın dediği gibi index registerli) ile ASM öğrenmek iyi bir başlangıç olur. Böyle bir MCU da Memory Map, ROM,RAM alanı, Stack alanı vs gibi kavramların çabuk oturmasına yarayacaktır. Uygulama geliştirme aşamasına geçerken C ile hızlı ve mantığa dayalı yol almak kolaylaşacaktır.
ARM ve assembly ikilisi bana ürkütücü geliyor gerçekten:S
Sordugun soruyu pointerin canina okuyalim kisminda cevaplamistim.
Evet A=0x01 dediginde derleyici, dogrudan A nin adresini buluyor ve koda gomuyor. Islemci bu satiri isletirken Anin adresi ne diye arayışa girmiyor ekstradan kod işletmiyor çünkü o satirda ornegin R0 registerine zaten A nin adresini atayan kodlar derleme + link asamasinda yazilmisti.
William Hohl'un ARM Assembly Language kitabini oneririm. (CRC Press.) Malesef e-kitap değil.
Bu arada "CM3 islemciler icin Assembly" diye bir kitap denemem var ve yarisini bitirmis durumdayim. Icerik olarak bu haliyle bile (84 sayfa) yeterli ve baskiya verilebilecek durumda ancak, kitaba ornek kodlar diye bir bolum ekleyerek sayfa sayisini 150 yapmak istiyorum.
Gel gelelim yurt disinda oldugum icin baski ve satis isleri ile ugrasmam kolay değil. 2010 yazinda bir iki matbaa ile gorustugumde gayet makul fiyatlar verildi.
Kendi kitabimin baskisi bitmis olsaydi onerirdim.
Alıntı yapılan: EMG81 - 23 Aralık 2011, 22:48:27
*p=&x // makro oluştu.
Bu arada anlatamamışsınız derdinizi...
p=&x; diyecektiniz sanırım :)
Hocam simdi sorun soyle vuku bulmakta, stm32 ailesinden bir cm3 icin driver yaziyorum. Spi portu data registeri 8 bit de olabiliyor, 16 bit de. Tum yazilimi katmanlar halinde yaziyorum. HAL/Driver/API/ en sonunda kullanici uygulamasi seklinde katmanlar var.
biraz kulagi tersten tutmus gibi olduk, ama misal ben usart icin soyle bir sey yazdim:
typedef struct
{
unsigned char portNumber;
unsigned char *usartTransmitBuffer;
unsigned char *usartReceiveBuffer;
unsigned char usartTransmitStatus;
unsigned char usartReceiveStatus;
unsigned short int usartTransmitBufferIndex;
unsigned short int usartReceiveBufferIndex;
} UsartPort, *ptrUsartPort;
typedef struct
{
unsigned char portNumber;
unsigned char usartBaudrate;
unsigned char usartStopBit;
unsigned char usartWordLength;
unsigned char usartHwFlowControl;
unsigned char usartParity;
unsigned short int usartTransmitBufferLength;
unsigned short int usartReceiveBufferLength;
unsigned char (*ptrUsartReceiveCallback) ( unsigned char *ptrBufferPointer, unsigned short int bufferLength );
unsigned char (*ptrUsartTransmitCallback) ( void ); /* does it really needed? think again*/
} UsartPortConfiguration, *ptrUsartPortConfiguration;
typedef struct
{
unsigned char (*initUsart) ( ptrUsartPortConfiguration usartConfig );
unsigned char (*writeUsartFIFO) ( unsigned char *data, unsigned short int dataLength );
unsigned char* (*readUsartFIFO) ( unsigned short int dataLength );
unsigned char (*openUsart) ( unsigned char portNumber );
unsigned char (*closeUsart) ( unsigned char portNumber );
ptrUsartPortConfiguration config;
} UsartDriver, *ptrUsartDriver;
ust katmanda api'yi yazan amca, bu UsartDriver'dan olusturacak bir tane. icindeki config structunu da doldurup initUsart(); fonksiyonunu cagiriyor. bu fonksiyonda gidip constructor cagiriyor, ve bir usartPort olusturuyor. driver structu icindeki open/close/read/write benim driver katmaninda tanimladigim fonksiyonlar, init kisminda bunlarin adreslerini yukluyorum. kullanici sadece tanimladigi driver icinden bunlari cagiriyor, istedigini yapiyor. config struct'inda 1-2 callback fonksiyonu var, bunu ust katmanda driveri kullanan eleman yaziyor. ben gerektiginde cagiriyorum (orn. arkadasim bufferin doldu, al sen bu bufferin pointerini yaz bi kenara seklinde).
bir nevi cakma object oriented (javadan c#dan kalma aliskanlik iste)
simdi 2 sorun var (ilk mesaji yazdigimda birdi, simdi kodlari tekrar okuyunca 2 oldugunu farktim:P )
1.soru: usart driverin icindeki writeFIFO fonksiyonunu cagirdi eleman. hangi usart'a yazmam gerektigini nasil ogrenebilirim? (parametre olarak usart_no gecmeden).
ornegin javada/c#da super diye bisi var. C de boyle bisi olsa, super.portNumber dedigim an kut diye run time da parametresiz alirdim. sizce bu yapida bunu parametre kullanmadan saglamanin yolu varmidir? yada siz nasil yapardiniz?
2.sorum: SPI da hem 16 hemde 8 bit data kullanilabiliyor demistim, yukardaki yapiyi aynen SPI'a da tasimak istiyorum, fakat donen degerler ve parametreler degisiyor (unsigned shor ve unsigned char gibi). bunu void* pointerla asarim, ancak islem yaparken typecast yapmam lazim. yukardaki sorunda oldugu gibi, hangi type oldugunu bilmeden (portConfiguration icinde SpiType diye bir degisken oldugunu dusunun) nasil type cast yaparim ki?
sanirim zorla parametre olarak gececem bu type olayini, ama onu da istemiyorum sahsen.
bunun yaninda birde soyle bisi var;
UsartPort structundan aynisi olarak SpiPort olarak da var. ancak 8/16bit hadisesi yuzunden iki tane var, Spi8bit Spi16bit gibi. amacim, tek bir struct olsun, ben bu struct icindeki bufferin tipini ve size'ini run time ayarlayabileyim. (sanirim mumkun degil gerci de) siz olsaniz nasil yapardiniz?
evet hocam, C ile object oriented ancak bu kadar oluyor iste:) yardimlariniz icin cok tesekkur ederim, gayet aciklayici oldu:)
yalniz kafama takilan bisi oldu, su UsartDriver struct'unda fonksiyonlarin argumanlarina struct'in pointerini gecmissiniz, tam olarak orayi kacirdim sanirim. Ben ilk dusundugum yapida misal init fonksiyonu, icerden bir constructor cagiriyordu, o da bana bir port aciyordu. o portun write/read/open/close gibi islemlerini de tanimlanan driver'a geciyordum, ana 1sn.. salak ben, arguman olarak driverin kendisini gecmezsem zaten nasil set edecem degerlerini offf.. insan yazarken anliyor bazen hatalarini :)
Ama write/read vb. seylere illaki bir port number argumani gececez, baska cikis yolu yok gibi. gerci ben sizden yanit beklerkene inanilmaz amele bir sey yaptim, ama calisti :) object collection vari birsey yaptim, kesinlikle inefficient bir yapi ama merak iste.. sanirim ben bu kaybettigim vakti yarin dum duz kodlar yazarak telafi edecem :')
incelemek isterdim de iste zaman kisiti oldugu icin abuk sabuk yaziyoruz boyle.. gonul bir yandan cok katmanli guzel mimari oturt, sonra rahat et der, ote yandan proje yetismeyecek yusuf yusuf der..
@gerbay hocam benimde bir sorum olacak fonksiyonlarda dizi geri döndürme imkanımız var mı? bu tarz birşey istersek illa union ve structure ile mi yapmak zorundayız?
hocam zahmet verdim size, gerçekten çok faydalı oldu, çok teşekkür ederim
Pointer dan sapmamak her zaman en iyisi, iyice netleşti =)
malesef CPP konusuna biraz korkak bakıyorum şu an için, ama okul bitince üzerine eğilmek istiyorum
notlarımı aldım hocam :)
Daha önce böyle bişey ile uğraşmıştım. Bir değişkenin değerini fonksiyon içinde değiştirmeye çalıştığımda hi-tech hata vermişti. O zaman sorup soruşturduğumda eğer böyle bişey yapılmak isteniyosa ve eğer C kullanılıyosa fonksiyonun parametresinin pointer olması, C# da ise referans tipli olması zorunlu diye söylenmişti bana.Acaba sizin yazdığınız fonksiyonda hata vermemesinin nedeni girilen parametrenin struct olmasından mı kaynaklanıyo?
Alıntı Yapvoid func(cont int a)
@gerbay hocam, cont yerine duk yada sansolye filan gibi unvanlarda olabilirmi? :P :-[
saka bir yana @gerbay hocam, ben C gibi dillerde pass by value diye bilirdim, dolayisi ile a degiskenine bir deger verilse bile bunun fonksiyon disinda bir hukmu yoktur. yani const yazarak aslinda bildigimizi bir kere daha teyid ediyoruz. bunada malumun ilami denirki geregi yoktur.
----edit --- @gerbay zaten a degiskenin degismeyecegini ornekde yazmissiniz, benim gozumden kacmis, ozur. Fakat yinede Demirelin deyimiyle malumun ilami abesle istigaldir, "pass by value" gectigini bildigmiz parametreler fonksiyon icinde degisirse haberim olsun diye kod yazilmasida buna ornek teskil edermi acaba? Tabiiki "int a" yerine "int *a" denmis olsa (yada struct x *a) ve bu pointer degerinin gosterdigi yerin degistilmemesi gerekiyorsa o zaman const ifaesinin kullanilmasi guzel bir ornek olur. Ama soruda cevapda bu olmadigindan ben daha fazla yazmadan ufak ufak gideym :-[
yani sui misal emsal olmaz arkadaslar. ;)
sevgili gerbay "nereden girdim bu konulara?" demissin, ben soyliyeyim. Program yaziyorum derken degisken tanimla, pointer nedir, syntax hatasi vs almadan program yazmak bu isin ilk adimi. daha bunun ikinci seviyesi, sonra ucuncu, sonra dorduncu sonra...
boylece hitech mi ccs mi diyen arkadaslarda aslinda ne kadar anlamsiz bir soru sorduklarinida anlarlar. :-)
yani bu detayli aciklamalarinla aslinda bir farkindalikta yaratiyorsun okuyucularda.
iyi geceler vede tesekkurler.
Alıntı yapılan: mufitsozen - 24 Aralık 2011, 20:17:24
sevgili gerbay "nereden girdim bu konulara?" demissin, ben soyliyeyim. Program yaziyorum derken degisken tanimla, pointer nedir, syntax hatasi vs almadan program yazmak bu isin ilk adimi. daha bunun ikinci seviyesi, sonra ucuncu, sonra dorduncu sonra...
boylece hitech mi ccs mi diyen arkadaslarda aslinda ne kadar anlamsiz bir soru sorduklarinida anlarlar. :-)
yani bu detayli aciklamalarinla aslinda bir farkindalikta yaratiyorsun okuyucularda.
iyi geceler vede tesekkurler.
baktım bu işin sonu yok. gittim aldım bir c kitabı hatta hızımı alamadım 2 tane aldım.
farklı kitaplarda farklı yorumlar var.eğem amacım öğrenmek ise illa gözle göreceğim elle de tutacağım bir kitap olmalı.
Alıntı yapılan: omereliusuk - 25 Aralık 2011, 01:29:33
baktım bu işin sonu yok. gittim aldım bir c kitabı hatta hızımı alamadım 2 tane aldım.
farklı kitaplarda farklı yorumlar var.eğem amacım öğrenmek ise illa gözle göreceğim elle de tutacağım bir kitap olmalı.
En iyisini yapmışsınız. Hangi kitapları aldınız? Bende de Serdar ÇİÇEK'in "CCS C" kitabı var. Yararlı olur mu acaba ?
Alıntı yapılan: gerbay - 25 Aralık 2011, 01:33:46
hocam şu deitel lerin renkli, cicili bicili kitabı vardı net de, para vermeseydiniz. net den o kitabı bulurdunuz..
Hangi kitap hocam.Link vs paylaşmanız mümkün mü?
http://www.pandora.com.tr/urun/c-how-to-program-6e-pie/191946
tavsiyem budur :) Ben C++ kitabını alıcam param tam olunca :) Tek eksik yanı ingilizce olması :) Ama ingilizcede sıkıntı yok diyorsanız bence şahane bir kaynak .
Alıntı yapılan: gerbay - 24 Aralık 2011, 13:05:50
hayır.
sizin kodunuzu hatırlıyormusunuz?
mesela şunu da yazabilirsiniz;
void func(int a)
{
a = 1;
}
ama fonksiyon çağırılırken a parametresinin kopyası yapılır ve "a = 1" ataması o kopya ya yapılır yani giren parametre etkilenmez.
eğer
void func(cont int a)
{
a = 1;
}
şeklinde yapmaya çalışırsanız o kopya parametre const olacağından "a = 1" atamasına derleyici izin vermez hata verir.
bu tarz pointer ya da referans olmayan parametrelerin her zaman kopyası yapılır ve o kopya fonksiyon içinde kullanılır. ister native veri tipi olsun isterseniz bir kayıt deseni (struct vs) olsun. bu kopyalama da hem daha fazla kod üretir, hem daha fazla ram tüketir hem de daha fazla clock tüketir..
Evet hocam haklısınız. Ben yanlış hatırlamışım. Şimdi denedim de hata vermedi ama program istediğim gibi çalışmadı.
SERDAR ÇİÇEK'in CCS C kitabını almıştım zaten. ama bundan daha ötesi gerekiyor.
kitap sadece toplamda 30-40 sayfa anlatmış C dilini.#ilk 200 sayfa içerisinde # gerisi hep bilindik şeyler. yalnız pic bölümü ile ilgili olanlar neyle nasıl bağlantı kurulur onu anlatıyor.
aldığım kitaplar:
1- Programlamayı C ile Öğreniyorum, Palme Yayincilik, Muhammet Yorulmaz, Seher Yorulmaz 23TL
" Programlamaya giriş, Problem Çözme, Algoritma tasarımı .... gibi bir sürü alt başlık var. "
2- C Programlama ve Programlama Sanatı, Beta Yay., Dr. M. Sabih AKSOY, Dr. Ömer AKGÖBEK 12 TL
"Genel Programlama Teknikleri, Menu Hazırlama<sırf bunun için değil ama bu da elimin altında olsun diye aldım.>
veri yapıları, dosyalama, grafik fonksiyonlari, port kullanımı" gibi bir sürü alt başlık var.
her iki kitapta
neyi nasıl yaptığını matematiksel işlemlerin C ile nasıl yapılabileceğini anlatıyor. bilmiyorum ben tatmin oldum. hoş benim evde kendimin ürettiği menü yapımı ile okuduktan sonra yaptığım menü arasında neredeyse hiçbir fark olmadığını görünce kendimle biraz övündüm ama neyse...
--------------------------------------------------------------------
Bir de ccs c de math.h yi ekleyip kareal=Pow(sayi,us);yazdım bir de baktım ki direkt 2kb kod artmış. 16f877a ile uğraşınca 2kb ciddi bir rakam. :o
"C Programlama ve Programlama Sanatı"
Kütüphanede varmış oradan alırız artık.
Alıntı yapılan: Seçkin ALAN - 25 Aralık 2011, 13:31:48
http://www.pandora.com.tr/urun/c-how-to-program-6e-pie/191946
tavsiyem budur :) Ben C++ kitabını alıcam param tam olunca :) Tek eksik yanı ingilizce olması :) Ama ingilizcede sıkıntı yok diyorsanız bence şahane bir kaynak .
hocam altaki link te slayt halinde bolumleri var.
http://ube.ege.edu.tr/~cinsdiki/webpages/cprog.html
Paul Deitel and Harvey Deitel, "C++ How to Program (8th Edition)"
Pre ntice | 2011 | ISBN: 0132662361 | 1104 pages | PDF | 56 MB
http://www.filesonic.com/file/2031942841/0132662361CProgram.pdf
Asagidaki iki satir ne is yapar?
while(A&2==2);
while((A&2)==2);
while(A&2==2);
A sıfırdan farklı ise while döngüsüne gir
while((A&2)==2);
(A&2) işlemi 2ye eşitse while döngüsüne gir
Evet bahisler acildi.
Gene mi yanlış :(
Hocam;
while(A&2==2); // Burda işlem önceligi nedir bilmiyorum. hatalı yazımda olabilir.
while((A&2)==2); // satırında A ve 2 yi ve işlemine alıp sıkan sonuc 2 ye eşitse alt satıra gecer.
@Sayment Cevaplarinin dayandigi noktayi acikla.
Asagidaki satir ne is yapar?
while(A++==2);
while((A&2)==2);
(Ave2) işleminin sonucu ikiye eşit ise while parantezi doğru olur diye düşündüm
while(A&2==2);
Bu soruda da 2==2 doğru olduğundan A 0dan farklı olan değerlerde while parantezinin içerisi doğru olur dedim.
İşlemler sağdan sola doğru yapılır diye biliyorum o yüzden böyle dedim.
while(A++==2);
A'yı 1 arttır değer 2ye eşit ise parantez içi doğru olur diyeceğim ama bu seferde işlemler sağdan sola olmamış oluyor. Söylediğim ile çelişiyorum.
Yanlış biliyorum doğrusu nedir ?
inşallah doğrudur.
bu şuna döndü
a+++b
ne oldu şimdi?
arada bir boşluk bıraksaymışız neyin ne olduğunu daha iyi anlayacaktık ama neyse:)
önce
while(a==2)
doğruysa içeri giriyor.
sonra
a zaten 1 değer armıştır. (a+1)==2 değerine bakıyor.
a++==2;
Bu ne anlama gelir?
Hocam yanlışımızı söyleseniz de düzeltsek
Keille de baktigimda;
while(A&2==2) ile while (A&1) ayni
2==2 true yani 1 o halde A&1
--------------------
while (a|2==3);
2 farkli 3 olduguna gore false yani 0
a|0=a
o halde
while (a|2==3) ile while (a!=0) ayni anlama geliyor
---------------
a+=3==3; a=a+1 demek
----------------
Asagidaki kodlara en azindan warning almayi beklerdim.
a++==2 ile a++ ayni
a++==3 ile a++ ayni
a++==4 ile a++ ayni
verildimi hatırlamıyorm. kitap kucalarken adres döndüren fonksiyonlar dan bahsediyordu.
*Adres(* Int a,* Int b)
böyle bir fonkisyon nasıl çalışır ?
Soruldumu bilmiyorum şöyle bir sorum var. C dilinde
typedef struct _A{
DWORD x;
DWORD y;
} BT;
Şeklinde struct yapımız olsun
Bir başka yapımızda bu şekilde olsun
typedef struct _TLE {
BT* xyz_;
DWORD abc;
}zte;
Programda bir tane pointer degisken olusturalim
zte *degisken;
Şimdi başlangıcda her değişkeni initial ettik diyelim. Degiskenin icindeki xyz nin x ine nasıl ulaşırız?
*(degisken->xyz_.x) = 0 ; desek olmuyor . Calismiyor...
Simdi aklima geldi degisken->xyz_->x = 0 ; gibi bir kullanim dogrumudur?
Bu pointerlari kullanmadan once baslangic degerlerinin atandigini nerden anlariz? NULL kelimesini 0 olarak tanimlarsak pointer degeri de sifir ise bu pointer daha baslangic degeri atanmamis diyebilirmiyiz? Peki ya gercekden pointer remin ilk adresini point ediyorsa bu iki olayi nasil ayird ediyorlar?
Evet -> şeklinde kullanım doğrudur.
Eğer işaretçi statik veya global tanımlı ise, muhtemelen derleyici ona ilk değer olarak null verecektir. Ama işaretçi yerel ise ilk değer ataması yapılmaz. Bu yüzden kendimiz yapmalıyız. Bir işaretçiye değer atanıp atanmadığını kontrol etmenin benim bildiğim tek yolu null olup olmadığına bakmak. İşaretçi gerçekten 0 adresini mi gösteriyor? yoksa değer atanmamış mı? anlamanın bir yolu yok bildiğim kadarıyla.
Cevap icin sağolun hocam...
Arkadaşlar bir bilgi vermek istiyorum keil ile ilgili yada c ile ilgili.
Bir fonksiyon oluşturdum ve bu fonksiyonun değişkenleri structure pointer. Örneğin fonksiyon(PTR* X) gibi olsun.
Bu fonksiyonun kendisini yazmadan önce deklare etmedim, Main içinde bu fonksiyona PTR* değilde INT türünde pointer girdim.Sonuçda warning ile işlem bitti.Şans eseri okuyacağım datanın boyutu tam olarak int kadar dı ki bir süre sorunu anlamadım.Ancak warningi yok etmek için fonksiyonu deklare ettiğimde fonksiyona yanlış türde pointer atadığım için error mesajı aldım ve program derlenmedi.Sizde karşılaşabilirsiniz.
Alıntı Yapint *P;
P=(int*) 0x42345678;
*P=0x12345678;
Merhabalar;
Pointer konusunda anlamadığım bir şey var; yukarıdaki int ' lerin manasını anlayamadım:
Bu
int ne demek?
Bu
int ne demek?
(birisi bu gösterici 32 bitlik adres gösterebilir, birisi de buraya 32 bit tam sayı yüklenebilir demek mi yoksa?)
Alıntı yapılan: -Hasan- - 20 Ocak 2012, 14:02:11
Merhabalar;
Pointer konusunda anlamadığım bir şey var; yukarıdaki int ' lerin manasını anlayamadım:
Bu int ne demek?
Bu int ne demek?
(birisi bu gösterici 32 bitlik adres gösterebilir, birisi de buraya 32 bit tam sayı yüklenebilir demek mi yoksa?)
Birinci int , int tipi değişkeni point eden bir pointer oluşturuyor. Diğer int ise sabiti int tipinde bir pointer ile işaretliyor.
c dosyayı import ediyoruz hazır yazılmış fonksiyonu vs kullanmak için peki "H" dosya nedir
lütfen header dosya demeyin. neden h include yapıyoruz ?
aklıma şu geliyor;
c yukardan aşağıya derleniyor, çağrılan bir fonksiyon yukarıda olması gerekiyor. bunu aşmak için fonksiyonlara ön tanımlama yapılıyor. bu header dosya bunun için mi kullanılıyor ?
Source kodlarinda gorunmesini istemedigin, kafa karistiracak satirlari, tanimlamalari, degiskenleri, hatta alt programlari gozonunden uzaklastirmak icin kullaniyoruz.
Istiyorsan header dosya icerigini C kodlarinin tepesine yapistir ve header dosyayi include etme.
biraz açarmısın hocam konuyu incelikleri nedir
Alıntı Yapint *P;
P=(int*) 0x42345678;
Alıntı Yap
*P=0x12345678;
Alıntı yapılan: -Hasan- - 20 Ocak 2012, 14:02:11
Merhabalar;
Pointer konusunda anlamadığım bir şey var; yukarıdaki int ' lerin manasını anlayamadım:
(birisi bu gösterici 32 bitlik adres gösterebilir, birisi de buraya 32 bit tam sayı yüklenebilir demek mi yoksa?)
Aslında bu iki satır birleştirilerek yazılabilir.
int *p = (int *) 0x42345678;
Bu ilk iki satırda 2 şey gerçekleşiyor.
1) p'nin 'int*' olarak tanımlanması. p senin de tahmin ettiğin gibi 32 bitlik bir tamsayı göstergesidir.
2) p'ye ilk değer atanması. p'nin değeri 0x42345678 dir. p göstergesi 0x42345678 adresindeki tamsayıya 'int' işaret etmektedir.
İlk verdiğin koddaki gibi p'yi ilk değersiz bırakmak yerine ona 0 veya NULL ile ilk değer vermek daha iyidir.
int *p; // <-- KOTÜ; çünkü p'nin değeri belirsiz; yanlışlıkla kullanırsak HATA!
p = (int *) 0x42345678;
Tanımladığımız yerde uygun bir ilk değer yoksa onu 0'la ilklendiririz.
int * g = 0;
/* ... */
// daha sonra:
g = &bir_int;
En son satırdaki artık bir gösterge tanımladığımız için göstergenin gösterdiği anlamına geliyor. Yani göstergenin gösterdiği int tamsayısına bir değer ata anlamına geliyor. 0x42345678 adresindeki tamsayıya 0x12345678 değerini atıyoruz.
*p = 0x12345678; // göstergenin gösterdiği eşittir 0x...
Alıntı yapılan: -Hasan- - 20 Ocak 2012, 14:02:11
Merhabalar;
Pointer konusunda anlamadığım bir şey var; yukarıdaki int ' lerin manasını anlayamadım:
Bu int ne demek?
Bu int ne demek?
(birisi bu gösterici 32 bitlik adres gösterebilir, birisi de buraya 32 bit tam sayı yüklenebilir demek mi yoksa?)
aslında hepsi aynı boyutta adres gösterir.sadece gösterdiğinin boyutu hakkında bir bilgi vardır.
bu bir dizi üzerinde çalışırken anlaşılabilecek bir konu.diyelim dizi 32bitlik int elemanlaran oluşuyor,ilk elemanının adresini pointer ile gösterdik.
int dizi[50];
int *sPtr;
hafızada 50*4 bytelık bir alanı dizi için ayırdık ve int gösterecek bir pointer tanımladık.diyelim adreste 32 bit ,misalen dizinin başlangıç adresi 0x12F0 olsun(adres bus 16 bit olsun data ile karışmasın diye)
hafıza
0x12f0 -> dizi[0]
0x12f4 ->dizi[1]
..
..
sPtr=dizi;
bu kod ile sPtr=0x12f0 ile yüklenir,*sPtr ise dizinin ilk elemanıdır.
diyelim sıralı bir işlem yapılacak.eğer sPtr yi bir arttırırsak 32 bitlik bir ing gösterdiği için değeri 4 byte artar,0x12f4 olur.normalde +1 olunca 0x12f1 olması beklenir aritmetik olarak ama gösterdiği değer int olduğundan dolayı (kapladığı alandan dolayı) böyle olur.yani verinin türünün tanımlanması buna yarar.umarım anlatabilmnişmdir.
Alıntı yapılan: z - 27 Ekim 2011, 01:06:42
pointeri isaretli de tanimlasaniz isaretsiz de tamislasaniz 0xFFFFF000 yazdinizmi porttan 0xFFFFF000 cikar. Sorun okumada.
Asağıdaki proğram parçacıgı porttaki 0x80000000 verisini okuyup sağa kaydırıp tekrar porttan çıktığında porta yazilan veri 0xC0000000 olacaktır.
Halbuki pointeri unsigned int tanımlasaydık porttaki 0x80000000 verisini okuyup sağa kaydırıp tekrar porttan çıktığında porta yazılan veri 0x40000000 olacaktı.
#define Reg (*((int*) 0x42345678))
Reg=Reg>>1;
Aksi takdirde her defasinda type casting yapmak gerekirdi.
Peki aşagıdaki satirda neden volatile ön eki getirme ihtiyacı duyarız?
#define Reg (*((volatile unsigned int*) 0x42345678))
bu başlığın 8. sayfasına geldim ve şurada takıldım, bilen birisi açıklayabilir mi acaba;
*Halbuki pointeri unsigned int tanımlasaydık porttaki 0x80000000 verisini okuyup sağa kaydırıp tekrar porttan çıktığında porta yazılan veri 0x40000000 olacaktı <-----> bu kısmı anladım
*Asağıdaki proğram parçacıgı porttaki 0x80000000 verisini okuyup sağa kaydırıp tekrar porttan çıktığında porta yazilan veri 0xC0000000 olacaktır. <-----> burasını anlamadım 0x80..... verisi bir sağa kayarsa neden 0xC0....olur?
teşekürler...
Eger isaretli bir degisken tanimladiysak bu degiskende pozitif yada negatif sayilar saklayabiliriz.
Negatif sayilar icin 2 ye tumleyen modu kullaniliyor. Bu gosterim seklinde en yuksek konumdaki bit isaret bitidir.
Ornegin 8 bit icin 0x80 hex sayisi decimal -128 demek. Bunun yarisi 0xC0 hex sayisi ise decimal -64 demek.
Isaretli sayilar aritmetik olarak saga kaydiriliyorsa isaret biti aynen yerinde kalir isaret biti dahil saga kaydirilir.
Alıntı yapılan: z - 03 Mart 2012, 10:10:02
Eger isaretli bir degisken tanimladiysak bu degiskende pozitif yada negatif sayilar saklayabiliriz.
Negatif sayilar icin 2 ye tumleyen modu kullaniliyor. Bu gosterim seklinde en yuksek konumdaki bit isaret bitidir.
Ornegin 8 bit icin 0x80 hex sayisi decimal -128 demek. Bunun yarisi 0xC0 hex sayisi ise decimal -64 demek.
Isaretli sayilar aritmetik olarak saga kaydiriliyorsa isaret biti aynen yerinde kalir isaret biti dahil saga kaydirilir.
cevap için teşekür ederim @bunalmış.
8. sayfadan devam ediyorum.
Alıntı yapılan: gerbay - 22 Aralık 2011, 23:55:39
1. soru için;
Hocam bu tür şeyleri en iyi anlamanın yolu kodu yazıp üretilen kodu ya da preprocessor output dosyasını incelemektir. Şöyle ki;
GPIOD->OSPEEDR= 0xFFFFFFFF;
kodunda GPIOD ve OSPEEDR var ve "->" 'point' işareti ile bir pointer erişimi olduğu belli. Şimdi GPIOD ve OSPEEDR neymiş ona bakmak lazım;
GPIOD yi ilgili header larda ararsanız şöyle bir tanım bulursunuz;
#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE)
burada yine bilinmeyenler var. GPIOD_BASE e de bakalım;
#define GPIOD_BASE (AHB1PERIPH_BASE + 0x0C00)
karşımıza AHB1PERIPH_BASE çıktı birde, onun tanımı;
#define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000)
PERIPH_BASE in tanımı ise;
#define PERIPH_BASE ((uint32_t)0x40000000)
yani interpret ederseniz GPIOD_BASE şöyle oluyor;
((uint32_t)0x40000000 + 0x00020000 + 0x0C00)
GPIOD ise;
((GPIO_TypeDef *) 0x40020C00)
şeklinde birşeye dönüşüyor. Yani memory mapped IO da GPIO-D portunun base adresini işaret ediyor.
O base adresten itibaren offset ler de GPIO_TypeDef tanımı içerisinde var. Şöyle ki;
/**
* @brief General Purpose I/O
*/
typedef struct
{
__IO uint32_t MODER; /*!< GPIO port mode register, Address offset: 0x00 */
__IO uint32_t OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */
__IO uint32_t OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */
__IO uint32_t PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */
__IO uint32_t IDR; /*!< GPIO port input data register, Address offset: 0x10 */
__IO uint32_t ODR; /*!< GPIO port output data register, Address offset: 0x14 */
__IO uint16_t BSRRL; /*!< GPIO port bit set/reset low register, Address offset: 0x18 */
__IO uint16_t BSRRH; /*!< GPIO port bit set/reset high register, Address offset: 0x1A */
__IO uint32_t LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */
__IO uint32_t AFR[2]; /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */
} GPIO_TypeDef;
bu structure tanımında OSPEEDR yi de bulduk. Offset adresi olarak 0x08 adresinde. Base adres üzerine OSPEEDR için offset adresini de ilave edeceğiz. Bu durumda kodumuzdaki;
GPIOD->OSPEEDR = 0xFFFFFFFF;
kısmı şuna dönüşüyor; özellikle OSPEEDR nin tip tanımına dikkat;
*((__IO uint32_t*) 0x40020C08 ) = 0xFFFFFFFF;
yani memory de ki 0x40020C08 adresine 0xFFFFFFFF değeri atanıyor..
Zaten preprocessor dosyası üretip incelerseniz derlenmeden önce kodun preprocess aşamasında
((GPIO_TypeDef *) ((((uint32_t)0x40000000) + 0x00020000) + 0x0C00))->OSPEEDR= 0xFFFFFFFF;
şeklinde dönüştürüldüğünü görürsünüz.
derlenmiş kodda da göreceğiniz kod şudur;
kaynak kod:
int main()
{
GPIOD->OSPEEDR= 0xFFFFFFFF;
for (;;);
}
üretilen kod:
.text:00000008 EXPORT main
.text:00000008 main
.text:00000008 02 49 LDR R1, =0x40020C08
.text:0000000A 4F F0 FF 30 MOV.W R0, #0xFFFFFFFF ; Rd = Op2
.text:0000000E 08 60 STR R0, [R1] ; Store to Memory
.text:00000010
.text:00000010 loc_10 ;
.text:00000010 FE E7 B loc_10 ; Branch
.text:00000010 ; End of function main
.text:00000010
.text:00000010 ; ---------------------------------------------------------------------------
.text:00000012 00 00 ALIGN 4
.text:00000014 08 0C 02 40 dword_14 DCD 0x40020C08 ; DATA XREF: mainr
açıklama;
ilk satırda R1 registerına 0x40020C08 değeri aktarılıyor.. tam olarak GPIO-D nin OSPEEDR registerının adresi,
ikinci satırda R0 registerına 0xFFFFFFFF değeri aktarılıyor,
üçüncü satırda ise R0 da bulunan değer R1 ile işaret edilen adrese yazılıyor..
olay bundan ibaret..
@gerbay emeğine sağlık çok güzel bir cevap hazırlamışsın.
kendi adıma söylüyorum; kafamda bir sürü sorunun cevbaını bulmuş oldum.
keilde projenin içindeki dosyaları kurcalarken, orada yazılanların artık yabancısı olmam.
teşekürler...
mrb arkadaşlar bende bu stm32f4-discovery kartını yeni aldım formu sürekli takip ediyorum ama kafam bayağı karıştı daha önce ccs c ile program yazıyordum bu çok farklı geldi bana ya da olayın özünü anlayamaış olmamdan da kaynaklanabilir. örneğin size şöyle bir soru soracağım
while(TRUE)
{
output_b(0xff);
delay_ms(1000);
output_b(0x00);
delay_ms(1000);
}
acabaa bu tip komutlarla keilde program yazamazmıyız.
merhaba
CCS ye yakın program yazabılmen ıcın
http://www.st.com/internet/evalboard/product/252419.jsp (http://www.st.com/internet/evalboard/product/252419.jsp) linkinden
FIRMWARE indirip bu kutuphaneyi kullanman gerekir.
Ornek:
GPIO_InitTypeDef GPIO_InitStructure;
static __IO uint32_t TimingDelay;
void Delay(__IO uint32_t nTime);
uint8_t k,l;
int main(void)
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
SysTick_Config(SystemCoreClock/ 1000);
GPIO_SetBits (GPIOE, E);
GPIO_ResetBits (GPIOE,E);
void init_port (void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD , ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(LCD_PORT, &GPIO_InitStructure);
.......
gibi..
ilgin için teşekkürler mb neyse bu daha karmaşık diğeri daha anlaşılır :(
int *p;
p=(int*) 0x42345678;
*p=0x12345678;
Bu şekilde bir kullanımda 0x42345678 adresindeki bir register a 0x12345678 değeri atıyoruz tamam. Anlamadığım kısım neden "p=(int*) 0x42345678; " ifadesinde (int*) parçasına ihtiyaç duyuyoruz.
Integer tipinde bir pointer tanımladık, neden bu pointer a direk olarak "p=0x42345678;" şeklinde adresini veremiyoruz ?
Veremiyor muyuz? Denemedim ama bana sanki verebilirmişiz gibi geldi. Derleyici hata veriyorsa eğer bunun sebebi olası mantıksal hataları derleme anında bulabilmek içindir. Yani senin ne yaptığının farkında olmanı istiyor olabilir.
Ama bence kendin 0x42345678 gibi rasgele bir adres tanımlayamazsın. Adresler önceden tanımlı değişkenlerden veya malloc() gibi fonksiyonlardan gelmeli.
Alıntı yapılan: Engineer Jr. - 08 Haziran 2012, 05:44:02
Anlamadığım kısım neden "p=(int*) 0x42345678; " ifadesinde (int*) parçasına ihtiyaç duyuyoruz.
Integer tipinde bir pointer tanımladık, neden bu pointer a direk olarak "p=0x42345678;" şeklinde adresini veremiyoruz ?
Çünkü dikkat ederseniz göstergenin türü int* dir. Direkt olarak göstergeye o değeri veremeyiz çünkü göstergenin türü int* sağ taraftaki değer int olduğu için hata verecektir.
İkinci kullanımda da göstergenin önüne gelen asteriks işareti göstergenin gösterdiği anlamına gelmektedir. Yani *gosterge gibi .. Göstergenin gösterdiği değer de bir tamsayı olacağı için burada bir sıkıntı yok.
Ancak ilk kullanımda 0x42345678 adresinin geçerli bir bellek adresi olduğunu biliyormuyuz. Eğer bu adres geçerli bir bellek adresi değilse programımız hatalı olacaktır.
Evet şu an çok fena dank etti desem yeridir :) int tipinden int* tipine bildiğimiz type casting yapıyoruz. Pointer a int tipi atarsak olmayacaktır elbette. Bunu okudğum sırada saat sabaha karşı bir vakitti artık beyin ne kadar sulanmışsa : D
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
unsigned char* fonk(unsigned const char* const str1,unsigned const char* const str2)
{
unsigned char* temp=(unsigned char*)(malloc(strlen(str1)+strlen(str2)+1));
memcpy(temp,str1,strlen(str1));
memcpy(temp+strlen(str1),str2,strlen(str2));
return temp;
}
int main(void)
{
unsigned char* addr;
unsigned const char *str1 =(unsigned char*)"yusuf ";
unsigned const char *str2 =(unsigned char*)"YAMAK";
addr=fonk(str1,str2);
printf("%s\n",addr);
free(addr);
return 0;
}
Böyle bi programda eğer printf() 'ten sonra free kullanmazsam stack te ayrılmış olan yer yine boşalmış olur mu? Bu soruyu sormamın nedeni bildiğiniz gibi fonksiyon içindeki değişkenler normalde dinamik ömürlü oluyo. tamam temp değişkeni siliniyordur. ama temp in gösterdiği adres tekrar serbest bırakılıyo mu?
hayır aldığın memory otomatik olarak geri verilmez.
free fonksiyonu malloc, calloc ile ayrılan belleği serbest bırakır, lokal değişkenler üzerinde etkisi olmaz sanırım.
Hocam sorunun cevabını buldum aslında. Ayrılan bellek otomatik geri bırakılmıyo. Bırakılması için free kullanılması gerekiyo. Eğer geriye bırakılsaydı, temp adresinin içeriğini printf ile yazdırmazdım. Aslında sorduğum soru mantıksız. Eğer öyle bişey olsaydı fonksiyonlardan geriye fonksiyonun içinde ayrılan yeri adresi hiçbir zaman döndürülmesini bi manası kalmazdı :)
Çökmesede güzel bir örnek değil aslında fonksiyon içinde yer alıp onun adresini döndürmek. Yeri dışarıda alıp fonksiyona adresini sokup içerisini fonksiyon içinde doldursanız daha güzel olur. Fonksiyonunuzu çağıran biri sizin içeride memory aldığından haberdar olmayıpgeri iade etmeyebilir. Herkes kendi aldığını kendi bıraksın.
Aslında her iki durumda da bellek sızıntısı olur diye düşünüyorum. Yukarıdaki örnekte fonk işlevinden çıkılmadan önce free ile dinamik olarak ayrılan bellek alanının geri verilmesi gerekiyor.
int foo0() { char * p0, *p1;
p0 = malloc(1);
if (birSeylerYap(p0))
{
free(p0);
return 1;
}
p1 = malloc(1);
baskaSeylerYap(p0, p1);
free(p1);
free(p0);
return 0;
}
Yukarıdaki 'foo0' işlevinde bellek sızıntısı olmaması, programcının dikkatine kalmıştır. İşlevden çıkılan her noktada bellekten ayrılan bütün alanların geri verilmelerinin unutulmaması gerekir.
Dinamik değişkenler için C'de malloc'la yer ayrılır, ve free ile geri verilir.
C++'da new ile değişken için hem yer ayrılır hem kullanıma hazırlanır, ve delete ile hem sonlandırılır hem bellek geri verilir.
Çöp toplayıcı bulunan bir ortamda ise new ile kurulan bir değişkenin delete ile sonlandırılması gerekmez; çöp toplayıcı ilerideki belirsiz bir zamanda hem değişkenin bozucusunu (destructor) çağırır, hem de belleği geri verir.
C++'da belleğe güvenli bir şekilde erişmek için akıllı göstergeler (smart pointers) veya daha genel ismiyle RAII yöntemleri kullanılır.
http://acehreli.org/turkcecpp/akilli_gostergeler.html (http://acehreli.org/turkcecpp/akilli_gostergeler.html)
D C++'nin getirdiği RAI gibi yöntemleri desteklerken ek olarak otomatik bellek yönetimin (çöp toplayıcısını) da kullanabiliriz. Buna rağmen D gibi sistem dillerinde alt düzey bellek işlemlerini elle de yönetebiliriz.
http://ddili.org/ders/d/bellek_yonetimi.html (http://ddili.org/ders/d/bellek_yonetimi.html)
http://ddili.org/makale/bellek.html (http://ddili.org/makale/bellek.html)
HOCAM BÜYÜK BİR ZEVKLE TAKİP EDİYORUM ELİMDE KALEM KAĞIT :) AMA BEN YAPTIĞINIZ BİR İŞLEMİ ANLAMADIM ANLAYAN VARSA CEVAP VERİRSE ÇOK SEVİNİRİM..
& | ^ ~ (Bitwise)
& AND operatoru
| OR operatoru
^ XOR operatoru
~ NOT operatoru
A = 0x0A & 0x03; A nin sonucu 0x02
A = 0x0A | 0x03; A nin sonucu 0x0B
A = 0x0A ^ 0x03; A nin sonucu 0x09
A = ~0x0A; A nin sonucu 0x05
HOCAMIZIN VERDİĞİ BU ÖRNEKLERDE SONUNCU ÖRNEĞİN CEVABINI BEN SÜREKLİ 0XF5 BULUYORUM ANCAK HOCAMIZ 0X05 DEMİŞ NEREDE HATA YAPIYORUM?
Alıntı yapılan: cooldoubtless - 21 Temmuz 2012, 18:32:03
A = ~0x0A; A nin sonucu 0x05
HOCAMIZIN VERDİĞİ BU ÖRNEKLERDE SONUNCU ÖRNEĞİN CEVABINI BEN SÜREKLİ 0XF5 BULUYORUM ANCAK HOCAMIZ 0X05 DEMİŞ NEREDE HATA YAPIYORUM?
Ben de senin çözümünün doğru olduğunu düşünüyorum. ~A 0xF5 oluyor. Eğer sayı işaretli olsaydı sonuç şu şekilde olurdu.
-128 64 32 16 8 4 2 1
~A 1 1 1 1 0 1 0 1
= -128 + 64 + 32 + 16 + 0 + 4 + 0 + 1 == -11
0x0A= b0000 1010
~b1111 0101
Alıntı yapılan: cooldoubtless - 21 Temmuz 2012, 18:32:03
HOCAM BÜYÜK BİR ZEVKLE TAKİP EDİYORUM ELİMDE KALEM KAĞIT :) AMA BEN YAPTIĞINIZ BİR İŞLEMİ ANLAMADIM ANLAYAN VARSA CEVAP VERİRSE ÇOK SEVİNİRİM..
& | ^ ~ (Bitwise)
& AND operatoru
| OR operatoru
^ XOR operatoru
~ NOT operatoru
A = 0x0A & 0x03; A nin sonucu 0x02
A = 0x0A | 0x03; A nin sonucu 0x0B
A = 0x0A ^ 0x03; A nin sonucu 0x09
A = ~0x0A; A nin sonucu 0x05
HOCAMIZIN VERDİĞİ BU ÖRNEKLERDE SONUNCU ÖRNEĞİN CEVABINI BEN SÜREKLİ 0XF5 BULUYORUM ANCAK HOCAMIZ 0X05 DEMİŞ NEREDE HATA YAPIYORUM?
Hata yok çözümün doğru...
derslerin devam etmemesinin bir nedeni var mı acaba? bunalmış hocam uzun süredir yazmamış
O zaman ben haftanın sorusu tadında bir soru yazayım.
Soru şu : Aşağıdaki program öğrencilerin final notunun %40'ını, arasınav notunun %20'sini, ödevlerin ortalamasının %40'ını alarak bitirme notunu buluyor ama programda bir hata var. Bu hata ne?
Not : Ödev girişini linux altında Ctrl-D ile sonlandırabiliyorsunuz.
#include <iomanip>
#include <ios>
#include <iostream>
#include <string>
using std::cin; using std::setprecision;
using std::cout; using std::string;
using std::endl; using std::streamsize;
int main ()
{
// Ogrencinin adini sor ve oku
cout << "Lutfen isminizi giriniz: ";
string isim;
getline (cin, isim);
cout << "Merhaba, " << isim << "!" << endl;
// ara sinav ve final notlarini oku
cout << "Lutfen ara sinav ve final notlarinizi giriniz: ";
double arasinav, final;
cin >> arasinav >> final;
// odev notlarini ogren
cout << "Tum odev notlarinizi giriniz\n";
cout << "Girisi sonlandirmak icin dosya-sonu (CTRL-D) tuslarina basiniz: ";
// simdiye kadar okunan not sayisi ve toplami
int sayac;
double toplam;
double x;
while (cin >> x) {
++sayac;
toplam += x;
}
// sonucu yaz
streamsize sonuc = cout.precision ();
cout << "Bitirme notunuz " << setprecision (3)
<< 0.2 * arasinav + 0.4 * final + 0.4 * toplam / sayac
<< endl;
return 0;
}
toplam sifirlanmamis. Yani baslangic degeri atanmadan kullanilmis.
bu aslında C şamatası değil de C++ şamatası olmuş.
toplam değişkeninden başka sayac değişkeni de sıfırlanmamış. ancak bazı derleyiciler kendiliğinden ilk değer olarak 0 veriyor diye biliyorum. böyle bile olsa ilk değeri kendimiz vermeliyiz.
bir de sonuc isimli değişkene atama yapılmış ama kullanılmamış. yapılan atama da ondalık sayılarda noktadan sonra gösterilecek hane sayısı.
belki de precision değerini eski haline getirmek için kullanılacaktı ama unutulmuş.
cout.precision(sonuc);
Alıntı yapılan: bocek - 26 Temmuz 2012, 16:37:33
toplam değişkeninden başka sayac değişkeni de sıfırlanmamış. ancak bazı derleyiciler kendiliğinden ilk değer olarak 0 veriyor diye biliyorum.
Evet buradaki hata
ilklendirilmemiş yerel değişkenlerin kullanılması.Yerel değişkenler açık olarak ilklendirilmezse varsayılan ilklendirme yapılır. Ancak burada derleyicinin verdiği ilk değer tanımsızdır. Ama hangi değişkenler için tanımsızdır. Hazır veri tipleri için.
Tanımsız değişkenlerle yapılabilecek tek geçerli işlem de giriş akımından bir değer okutmaktır. Burada
arasinav ve
final değişkenlerinde olduğu gibi. Hatta iyi bir programlama alışkanlığı olarak ben bu değerleri de ilklendirerek kullanmayı tercih ediyorum.
Kullanıcı tanımlı türlerde ise, açık ilklendirme yapılmadığı zaman sınıfın varsayılan kurucu işlevi çağrılır. Örneğin burada string ilklendirilmediği için string sınıfına ait varsayılan kurucu (
default constructor) çağrılır.
Programı ilk haliyle denediğimizde notlar 100 100 100 olarak girilse bile ortalamayı 60 olarak veriyor. gcc üzerinde denedim.
Programın düzeltilmiş hali:
#include <iomanip>
#include <ios>
#include <iostream>
#include <string>
using std::cin; using std::setprecision;
using std::cout; using std::string;
using std::endl; using std::streamsize;
int main ()
{
// Ogrencinin adini sor ve oku
cout << "Lutfen isminizi giriniz: ";
string isim;
getline (cin, isim);
cout << "Merhaba, " << isim << "!" << endl;
// ara sinav ve final notlarini oku
cout << "Lutfen ara sinav ve final notlarinizi giriniz: ";
double arasinav, final;
cin >> arasinav >> final;
// odev notlarini ogren
cout << "Tum odev notlarinizi giriniz\n";
cout << "Girisi sonlandirmak icin dosya-sonu (CTRL-D) tuslarina basiniz: ";
// Programlama hatasi !
// Ilklendirilmemis yerel degiskenler
int sayac = 0; // <--
double toplam = 0; // <--
double x;
while (cin >> x)
{
++sayac;
toplam += x;
}
// sonucu yaz
streamsize sonuc = cout.precision ();
cout << "Bitirme notunuz " << setprecision (3)
<< 0.2 * arasinav + 0.4 * final + 0.4 * toplam / sayac
<< endl;
return 0;
}
mesaj birleştirme:: 26 Temmuz 2012, 23:38:18
Evet bir soru daha :D
Soru : Verilen bir sayının 2'nin üssü olup olmadığını bulan bir işlev yazınız.
Bu sorunun cevabı da şu şekilde olacak:
bool ussuMu (int sayi)
{
return !((~(~0 >> 1) | sayi) & (sayi - 1));
}
Başlık çok güzel olmuş elinize sağlık.
Alıntı yapılan: z - 23 Aralık 2011, 23:03:52
Bu arada "CM3 islemciler icin Assembly" diye bir kitap denemem var ve yarisini bitirmis durumdayim. Icerik olarak bu haliyle bile (84 sayfa) yeterli ve baskiya verilebilecek durumda ancak, kitaba ornek kodlar diye bir bolum ekleyerek sayfa sayisini 150 yapmak istiyorum.
Hocam kitap ne durumda , bitirebildin mi ? CM3'ün mimarı ve ASM yapısı 18f'den sonra çok ilgimi çekti açıkcası.. İstersen yayınlamadan önce baştan sonra okuyup bitirip yorumlayabilirim sana : ))
Alıntı yapılan: z - 25 Ekim 2011, 18:05:32
Hocam şu satıra dikkat etmemişsin.
Programda aşağıda adıgeçen registerleri structure pointer yapısından kurtarıp structure yapısına dönüştürelim.
Alıntı yapılan: z - 27 Ekim 2011, 01:48:15
Bir sonraki konumuz ARM registerlerini structure yapısında tanımlama hakkında.
Ön hazırlık yapmak isterseniz Rehber'de örneğin GPIOx port adreslerine bir göz atın.
Bunalmış hocam , İlk başlarda bahsetmişsiniz ancak sanırım arada kaynamış . Donanım registerlarına pointer kullanmadan nasıl değer atabiliyoruz ?
Sanki bir yerde , GPIOD.ODR.PB0=1 yada GPIOD.ODR = 0x00000F00 gibi bir kullanım görmüştüm sizin ancak bulamadım şimdi. Nasıl kullanıyoruz bu şekilde.
Aşağıdaki şekilde de yada klasik header dosyası ile erişebiliyorum,burada sorun yok:
#define GPIOC_ODR (*((volatile unsigned long*) 0x4001100C))
main()
{☺
char dizi[]="dizi";
printf("%c",for(i=0;i<4;i++)(*dizi+i));
}
bu şekilde bir kullanımı yapılabilirmi?
burdaki amacım dizi elemanlarını tek seferde bu şekilde basmak.
Alıntı yapılan: sseedat - 21 Aralık 2012, 22:50:35
main()
{☺
char dizi[]="dizi";
printf("%c",for(i=0;i<4;i++)(*dizi+i));
}
bu şekilde bir kullanımı yapılabilirmi?
burdaki amacım dizi elemanlarını tek seferde bu şekilde basmak.
main()
{☺
char dizi[]="dizi";
printf("%s",dizi);
}
tşk printf ten çok şey istiyorum sanırsam:D
Öyle olmaz ama şöyle olur istediğin şeyle hemen hemen aynı sayılır.
#include <stdio.h>
#include <string.h>
int main(void)
{
int i=0;
unsigned char f[]="dizi";
for(i=0;i<strlen(f);printf("%c\n",f[i]),i++);
}
Alıntı yapılan: yamak - 21 Aralık 2012, 23:04:53
Öyle olmaz ama şöyle olur istediğin şeyle hemen hemen aynı sayılır.
#include <stdio.h>
#include <string.h>
int main(void)
{
int i=0;
unsigned char f[]="dizi";
for(i=0;i<strlen(f);printf("%c\n",f[i]),i++);
}
Bu kadar uğraşmaya gerek yok "printf("%s",dizi);" mutlu eder arkadaşı kanımca :)
evt printf kütüphanesiyle oynayıp yapılabilir diye ddüşünüyorum.
Alıntı yapılan: AsHeS35 - 21 Aralık 2012, 23:21:22
Bu kadar uğraşmaya gerek yok "printf("%s",dizi);" mutlu eder arkadaşı kanımca :)
Ama karakter dizisi olmazsa ne olacak? :)
Alıntı yapılan: yamak - 21 Aralık 2012, 23:25:45
Ama karakter dizisi olmazsa ne olacak? :)
Şimdi %s li gönderim için kütüphaneyle oynamaya gerek yok.Karakter dizisini sormuş arkadaş ha long integer olursa artık onu da bırakalım kendi halletsin .
Ben kütüphaneyle oynanacak demedimki.Eğer dizi karakterlerden değildi integer tipli verilerden oluşursa sizin söylediğiniz yöntemle nasıl yapılacak dedim.Eğer dediğiniz gibi yaparsanız tüm değerler karakter olarak ekrana basılacaktır.Çün %s kullanımından dolayı tür dönüşümü yapılacak.Yani ben ekrana 97 yazmasını istiyoyorum ama ekranda a harfi çıkacak.
bir değişkeni global tanımlamakla, fonksiyon içerisinde static tanımlamak arasında ne fark vardır ?
C nin ASM karşısında en güzel kolaylığıdır bu.
Değişkeni global tanımladınmı olur olmaz rutinler bu değişkene erişebilir. Fakat Fonksiyon içine koydunmu bu değişkeni sadece fonksiyondan erişirsin. En azından yazdığın kodda abuk sabuk yerlerden bu değişkene erişmek istediğinde derleyici kızar.
ASM de bu iş biraz mide bulandırıcı. Stackda relatif adreslerin hesaplamaları ile boğuşmak durumunda kalırsın.
Bu extern nedir nerede nicin kullanilir
Ben kullandığım şekliyle örnek vereyim. Bir proje açıp, program yaz. Bu programın değişkenleri olsun.
Programın bağlı olduğu proje içinde bir program daha yaz. Bu program ilk programdaki değişkenleri kullanmak istesin.
Bu durumda değişkenleri tanımlar ve bunların başına extern ifadesi eklersin. Bu durumda derleyici bu değişkenlerin dışarıdaki bir yerden alınacağını anlar.
extern char a; // gibi.
İlk programda tanımladığın değişkenin ise export edilmesi gerekir. (Değişkenlerimi C den değil de asm tarafından export ettiğim için C de export etmeyi hatırlamıyorum)
aynı değişkene farklı dosyalardan erişmek istediğinde kullanırsın.harici değişken olarak bilirim bellekte yer ayırmaz sadece derleme zamanında linker devreye girip olayları birbirine bağlar
Sunumu anlamiyim?
main.c dosyasinin icerisindeki degisken eger extern int a olarak tanimlarsam, mhk.c dosyasindan da ulasabilirim
Arkadaşlar merhaba , aşağıdaki dizi ile ilgili örneği anlayamadım.
- bir döngü oluşturuyorum . 4 kez tektarlanacak.
- daha sonra strncmp fonksiyonu kullanılıyor , ama neden Rec '&' şeklinde gönderiyoruz. Rec adresini mi göndermiş oluyoruz ?
http://www.csystem.org/kaynak-kod-arsivi/strncmp-fonksiyonu (http://www.csystem.org/kaynak-kod-arsivi/strncmp-fonksiyonu)
- Döngüde n sürekli artıyor 1,2,3'e kadar.
- Rec[0]=B ,Rec[1]=Y ,Rec[2]=E .... eşit değilmidir. Aşağıda if kısımda ki sorgulama nasıl gerçekleşiyor ?
unsigned char Rec[]={"BYE---"};
for(n=0; n<4 ; n++)
{
if (!strncmp( &Rec[n],"BYE",3 ))
{
//event
}
else if (!strncmp( &Rec[n],"OK",2 ))
{
//event
}
}
Eğer bir işaretçiye dizinin ismini, başında & karakteri ve eleman numaras olmadan geçersen , dizinin başlangıç adresini vermiş olursun.
örn
char dizi[]="klllkjlklklk"
char *ptr;
ptr = dizi; ptr işaretçisine dizinin başlangıçadresini attık.
ptr= &dizi[3] şeklinde atama yaparsak , dizinin 4. karakterinin adresini atamış oluruz.
strncmp() fonksiyonu 2. parametrede verilen string ile, 1. parametrede verilen stringin 3.parametre ile belirlenen kadar uzunluktaki kısmını karşılaştırır.
Muhtemelen dizideki verinin ilk karakteri her zaman aranan karakter olmuyor. Bu yüzden programcı aranan ilk karakterin başladığı yeri bulmak için döngüde adresi artırıyor.
Yanıt için çok teşekkürler. Benimde kafamı karıştıran nokta o oldu. Tamda anlamış değilim.
Aşağıda komut satırında &Rec[n] = Rec[0] = "BYE" ------> mı oluyor ?
if (!strncmp( &Rec[n],"BYE",3 ))
unsigned char Rec[]={"BYE---"};
if (!strncmp( &Rec[n],"BYE",3 ))
Rec[0] = 'B'
Rec[1] = 'y'
Rec[2] = 'e' olur.
Kafanı karıştıran sanırım for döngüsü.
unsigned char Rec[]={"Bye---"}
Buradaki gibi dizimizin içeriği kesin belli ise , for döngüsü anlamsız.
if (!strncmp( Rec,"Bye",3 ))
sonucu verecektir.
İçeriğimiz "xxBye---" şeklinde olsaydı ve biz bu düzeni kesin biliyor olsaydık ,
if (!strncmp( &Rec[2],"Bye",3 ))
karşılaştırmaya dizinin 3. elemanından başla diyebilirdik.
Fakat dizimizin içeriği her zaman aynı değilse, yani bazen "xBye--" , bazen "xyzBye----" , bazen "Bye---" şeklinde geliyorsa, o zaman belediğimiz sözcüğün ilk karakterinin yerini araştırmamız gerekir.
Bu programda da yapılan o.
Önce Rec[0] dan başla karşılaştır diyor. baktı sonuç yok, n değerini 1 artırıp Rec[1] den başla diyor... böyle devam ediyor.
Bunun yerine
strchr(....) fonksiyonu ile B karakterinin başladığı yer bulunup sonra bu adresten başlayan karşılaştırma yapılabilir.
veya
strstr(....) fonksiyonuyla dizi içerisinde "Bye" kelimesi aratılır. eğer bu dizi içerisinde aradığımız kelime varsa başlangıç adresi döner.
hımmm dostum çok teşekkürler şimdi anladım.
stm32f4 kitinde keil ile şu kodu yazdım. Olay o kadar ilginç ki kafayı yedim >:(
en alttaki for döngüsü sorunlu. 2 kez ledleri yakıp söndürüp, sonra for'dan çıkıp tamamen ledler yanmalı. Bu arkadaş 6 kez led yak söndür yapıyor.
Ben 4 yap dersem 12 yapıyor, 5 dersem 15 hep üç katı. Uğraştım uğraştım bi türlü nulamadım çok ufak bi yeri atlıyorum ama kafayı yedirtti bana gerçekten. Bi el atıverin hocalar :(
#include "STM32F4xx.h"
void SystemInit()
{
unsigned int i;
for (i=0;i<0x00100000;i++); // OSC oturtma ve kurtarma rutini
RCC->CFGR |= 0x00009400; // AHB ve APB hizlarini max degerlere set edelim
RCC->CR |= 0x00010000; // HSE Xtal osc calismaya baslasin
while (!(RCC->CR & 0x00020000));// Xtal osc stabil hale gelsin
RCC->PLLCFGR = 0x07405408; // PLL katsayilarini M=8, N=336, P=2 ve Q=7 yapalim
// RCC->PLLCFGR = 0x07402A04; // PLL katsayilarini M=4, N=168, P=2 ve Q=7 yapalim
RCC->CR |= 0x01000000; // PLL calismaya baslasin (Rehber Sayfa 95)
while(!(RCC->CR & 0x02000000)); // Pll hazir oluncaya kadar bekle
// FLASH->ACR = 0x00000705; // Flash ROM icin 5 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55)
FLASH->ACR = 0x00000605; // Flash ROM icin 5 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55)
RCC->CFGR |= 0x00000002; // Sistem Clk u PLL uzerinden besleyelim
while ((RCC->CFGR & 0x0000000F) != 0x0000000A); // Besleninceye kadar bekle
RCC->AHB1ENR |= 0x0000000F; // GPIO A,B,C,D clock'u aktif edelim
GPIOD->MODER = 0x55000000; // GPIOD nin 15, 14, 13, 12 pinleri cikis tanimlandi (LEDler icin)
GPIOD->OSPEEDR= 0xFFFFFFFF; // GPIOD nin tum cikislari en yuksek hizda kullanacagiz
}
void delay_ms(int bekle) // 168 mhz'de 1cyc=6ns
{
int i=0;
int j=0;
for(j=0;j<bekle;j++)
{
for (i=0;i<33500;i++); // 166600*6ns=1ms
}
}
int main()
{
int m=0;
for(m=0; m<2; m++)
{
GPIOD->ODR= 0x0000F000; // Ledler yansin
delay_ms(500);
GPIOD->ODR= 0x00000000; // Ledler sonsun
delay_ms(500);
}
GPIOD->ODR= 0x0000F000;
} // Programin sonu
Alıntı yapılan: Deli_Nedym - 10 Ocak 2013, 07:53:39
stm32f4 kitinde keil ile şu kodu yazdım. Olay o kadar ilginç ki kafayı yedim >:(
en alttaki for döngüsü sorunlu. 2 kez ledleri yakıp söndürüp, sonra for'dan çıkıp tamamen ledler yanmalı. Bu arkadaş 6 kez led yak söndür yapıyor.
Ben 4 yap dersem 12 yapıyor, 5 dersem 15 hep üç katı. Uğraştım uğraştım bi türlü nulamadım çok ufak bi yeri atlıyorum ama kafayı yedirtti bana gerçekten. Bi el atıverin hocalar :(
#include "STM32F4xx.h"
void SystemInit()
{
unsigned int i;
for (i=0;i<0x00100000;i++); // OSC oturtma ve kurtarma rutini
RCC->CFGR |= 0x00009400; // AHB ve APB hizlarini max degerlere set edelim
RCC->CR |= 0x00010000; // HSE Xtal osc calismaya baslasin
while (!(RCC->CR & 0x00020000));// Xtal osc stabil hale gelsin
RCC->PLLCFGR = 0x07405408; // PLL katsayilarini M=8, N=336, P=2 ve Q=7 yapalim
// RCC->PLLCFGR = 0x07402A04; // PLL katsayilarini M=4, N=168, P=2 ve Q=7 yapalim
RCC->CR |= 0x01000000; // PLL calismaya baslasin (Rehber Sayfa 95)
while(!(RCC->CR & 0x02000000)); // Pll hazir oluncaya kadar bekle
// FLASH->ACR = 0x00000705; // Flash ROM icin 5 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55)
FLASH->ACR = 0x00000605; // Flash ROM icin 5 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55)
RCC->CFGR |= 0x00000002; // Sistem Clk u PLL uzerinden besleyelim
while ((RCC->CFGR & 0x0000000F) != 0x0000000A); // Besleninceye kadar bekle
RCC->AHB1ENR |= 0x0000000F; // GPIO A,B,C,D clock'u aktif edelim
GPIOD->MODER = 0x55000000; // GPIOD nin 15, 14, 13, 12 pinleri cikis tanimlandi (LEDler icin)
GPIOD->OSPEEDR= 0xFFFFFFFF; // GPIOD nin tum cikislari en yuksek hizda kullanacagiz
}
void delay_ms(int bekle) // 168 mhz'de 1cyc=6ns
{
int i=0;
int j=0;
for(j=0;j<bekle;j++)
{
for (i=0;i<33500;i++); // 166600*6ns=1ms
}
}
int main()
{
int m=0;
for(m=0; m<2; m++)
{
GPIOD->ODR= 0x0000F000; // Ledler yansin
delay_ms(500);
GPIOD->ODR= 0x00000000; // Ledler sonsun
delay_ms(500);
}
GPIOD->ODR= 0x0000F000;
} // Programin sonu
Hiç sistem fonksiyonlarına bulaşmadan söyleyebilirim ki şunu bir dene
while(1) {
for(m=0; m<2; m++)
{
GPIOD->ODR= 0x0000F000; // Ledler yansin
delay_ms(500);
GPIOD->ODR= 0x00000000; // Ledler sonsun
delay_ms(500);
}
GPIOD->ODR= 0x0000F000;
}
Sonsuz döngüye giriyor böyle
for yapıs....
{
GPIOD->ODR= 0x0000F000; // Ledler yansin
delay_ms(500);
GPIOD->ODR= 0x00000000; // Ledler sonsun
delay_ms(500);
}
GPIOD->ODR= 0x0000F000;
while(1);
Programı durdurmazsan flash üzerinden devam edebilir derleyiciye bağımlı olarak.
Son şekilde çalıştı ama o while(1) nasıl bunu sağladı hiç anlamadım :-X
Sonsuz döngüye girdi orda ama daha evvel oraya gelmiyordu ki bu kodlar for'un içinde dönüp duruyordu çıkınca da tekrar başa dönüyordu bunu 3 kez tekrarlıyordu , biz şimdi o bi kere yapınca sonsuz döngüye sokuyoruz o nedenle başa dönmüyor. Bir çözüm bu tamam kabul ama ne bileyim for'un kendi yazılış sistemini değiştirmedi maalesef
Alıntı yapılan: Deli_Nedym - 10 Ocak 2013, 08:14:16
Son şekilde çalıştı ama o while(1) nasıl bunu sağladı hiç anlamadım :-X
Sonsuz döngüye girdi orda ama daha evvel oraya gelmiyordu ki bu kodlar for'un içinde dönüp duruyordu çıkınca da tekrar başa dönüyordu bunu 3 kez tekrarlıyordu , biz şimdi o bi kere yapınca sonsuz döngüye sokuyoruz o nedenle başa dönmüyor. Bir çözüm bu tamam kabul ama ne bileyim for'un kendi yazılış sistemini değiştirmedi maalesef
Dediğinizi yanlış anladıysam düzeltirsiniz beni de benim gönderdiğim kodda for döngüsünü bitirip ledleri yakıp programı durduruyor.Sizin düşünceniz ise aynı for döngüsüne dallandığınızı düşünüyorsunuz işin aslı öyle değil for döngüsünü bitirip ledleri set ettikten sonra programınız durmadığı veya bir döngüde kalmadığı için devam ediyor devamında ki kodları siz göremezseniz artık flash memory de ne varsa onu çalıştırır sizin de şansınıza ledler yanıp sönüyor :).
mesaj birleştirme:: 10 Ocak 2013, 08:21:13
Ayrıca siz bu döngünün durmadan olmasını istiyorsanız benim dediğimi yazmanız gerekiyor
while(1){
//sizin kodlarınız
}
Bu şekilde yazarsanız programınız hep aynı işlevi yapar siz elektriği kesinceye kadar.
Anladım hocam eyvallah for'a tekrar dallanmamasına rağmen aynı for'daki işlemleri yapması kafamı karıştırdı. Satır satır nasıl izleyebiliriz programı ? Debug yapınca daha sistem ayarlarının olduğu kodlardan çıkamıyoruum da alt satırlara direkt geçemez miyim ?
mesaj birleştirme:: 10 Ocak 2013, 17:18:47
For döngüsünün end ile bitmiyor olması da beni şaşırttı. C dillerinde öyle değil mi ? Burda neden değil ? Atıyorum ben for döngüsü içindeyken mavi butona basınca for'dan çıksın ve kaçıncı döngüdeyse bana o döngünün sayısını versin istiyorum napıcam ? Keil beni bitirdin ya >:(
Alıntı yapılan: Deli_Nedym - 10 Ocak 2013, 16:47:56
Anladım hocam eyvallah for'a tekrar dallanmamasına rağmen aynı for'daki işlemleri yapması kafamı karıştırdı. Satır satır nasıl izleyebiliriz programı ? Debug yapınca daha sistem ayarlarının olduğu kodlardan çıkamıyoruum da alt satırlara direkt geçemez miyim ?
mesaj birleştirme:: 10 Ocak 2013, 17:18:47
For döngüsünün end ile bitmiyor olması da beni şaşırttı. C dillerinde öyle değil mi ? Burda neden değil ? Atıyorum ben for döngüsü içindeyken mavi butona basınca for'dan çıksın ve kaçıncı döngüdeyse bana o döngünün sayısını versin istiyorum napıcam ? Keil beni bitirdin ya >:(
for(int i=0;i<10;i++)
{
}// burada for döngüsüne tekrar dallan diyor aslında. şart bitersede end for işlevini yerine getir.
Döngüden çıkmak için break; komutu kullanılır. Kaçıncı döngü sayısını bir değişkende tutabilirsiniz.
1- end for yazınca end tanımsız diyor.
2- for bitince tekrar main'e dönüyor kodlar ve bir kere daha main işliyor yani for döngüsü bi daha gerçekleşmiş oluyor. Acaba işlemci kodun bitttiğini mi anlamıyor ? Ama öyle olsa her kod bitiminde tekrar main'in başına dönmez mi ? Bu iki kere main okuyup bi daha başa dönmüyor. İlle de en son while(1); diyerek sonsuz döngüye mi sokmam gerek yani ?
int main()
{
int m;
GPIOD->ODR= 0x00000000; // Ledler sonsun
delay_ms(2000);
for(m=1; m<10; m++)
{
GPIOD->ODR= 0x0000F000; // Ledler yansin
delay_ms(m*100);
GPIOD->ODR= 0x00000000; // Ledler sonsun
delay_ms(m*200);
if (GPIOA->IDR & 0x000000001)
break;
}
GPIOD->ODR= 0x00005000;
delay_ms(1000);
GPIOD->ODR= 0x0000A000;
delay_ms(1000);
GPIOD->ODR= 0x00003000;
delay_ms(1000);
GPIOD->ODR= 0x0000C000;
delay_ms(1000);
}
önce ledler iki saniye sönük duruyor. Ardından for'a giriyor. Eğer mavi butona basarsam for'dan çıkıyor. Ardından ledleri değişik şekillerle 1'er saniye yakıyoruz. Normalde main'in sonuna geliyoruz programın bitmesi gerek fakat program en baştan ledleri iki saniye sönük tutup tekrar for'a girip çıkınca yine ledleri değişik şekillerde 1'er saniye yakıyor. Sonra bitiyor program.
mesaj birleştirme:: 10 Ocak 2013, 19:22:06
if (GPIOA->IDR & 0x000000001) // Mavi butona basınca
Alıntı yapılan: Deli_Nedym - 10 Ocak 2013, 19:18:29
1- end for yazınca end tanımsız diyor.
2- for bitince tekrar main'e dönüyor kodlar ve bir kere daha main işliyor yani for döngüsü bi daha gerçekleşmiş oluyor. Acaba işlemci kodun bitttiğini mi anlamıyor ? Ama öyle olsa her kod bitiminde tekrar main'in başına dönmez mi ? Bu iki kere main okuyup bi daha başa dönmüyor. İlle de en son while(1); diyerek sonsuz döngüye mi sokmam gerek yani ?
önce ledler iki saniye sönük duruyor. Ardından for'a giriyor. Eğer mavi butona basarsam for'dan çıkıyor. Ardından ledleri değişik şekillerle 1'er saniye yakıyoruz. Normalde main'in sonuna geliyoruz programın bitmesi gerek fakat program en baştan ledleri iki saniye sönük tutup tekrar for'a girip çıkınca yine ledleri değişik şekillerde 1'er saniye yakıyor. Sonra bitiyor program.
mesaj birleştirme:: 10 Ocak 2013, 19:22:06
if (GPIOA->IDR & 0x000000001) // Mavi butona basınca
1.soru için
Arkadaş orada end for diyerek bir pseudo(okunur yalancı) kodla anlatmaya çalışmış for döngüsünün bittiğini.Yani @Seçkin ALAN ın anlatttığı şey size bildiğiniz dile göre özet geçmiş C'de for döngüsünde bir end komutu yoktur.break ve continue yapıları vardır.
2.soru için for bitince tekrar main e dönmüyor burada anlaşalım bir kere for bitince programın kontrolden çıkıyor.O yüzden while(1); yazıp programı main içerisinde tutuyorsun.
Ayrıca kardeş senin şu anki ihtiyacın Deitel&Deitel C ve C++,yeni C ye başlıyorsan o kitaptan başla en iyi Türkçe kitaplardan biridir.
Teşekkürler AsHE.
Aslında kod sizin dediğiniz dışında birşey yapmaz. Adım adım gitiğimizi varsayalım. Mavi butona basınca döngüden çıkıyor. Aslında mavi butona basmasanız bile for döngüsündeki şart sona erdiği vakit döngüden çıkıcak. Sonra kaldığı yerden! yani GPIOD->ODR= 0x00005000; buradan devam edecek. Kod bloğunun sonunda ise programı sonlandıracak. Burada herhangi bir sıkıntı yok. Kod yazdığınıza göre çalışıyor.
Fakat siz led toggle işlemini sürekli yapsın ben butona basana kadar derseniz şöyle bir kod yazmanız gerekiyor
int main()
{
int m;
GPIOD->ODR= 0x00000000; // Ledler sonsun
delay_ms(2000);
// eski kodunuz for(m=1; m<10; m++)
while(1)
{
GPIOD->ODR= 0x0000F000; // Ledler yansin
delay_ms(m*100);
GPIOD->ODR= 0x00000000; // Ledler sonsun
delay_ms(m*200);
if (GPIOA->IDR & 0x000000001)
break;
}
GPIOD->ODR= 0x00005000;
delay_ms(1000);
GPIOD->ODR= 0x0000A000;
delay_ms(1000);
GPIOD->ODR= 0x00003000;
delay_ms(1000);
GPIOD->ODR= 0x0000C000;
delay_ms(1000);
}
while içindeki şart sağlandığı sürece dönecek. İçinde 1 var yani true. İçindeki şart sağlanıyor. Bir nevi kısır döngü. Siz enerjiyi kesmediğiniz veya butona basmadığınız sürece koddan çıkmaz.
Butona basıldığında ise şöyle okuma yapmak daha mantıklı gibi;
if (GPIOA->IDR & 0x000000001){
//butona basıldı
delay_ms(100);
if (GPIOA->IDR & 0x000000000) { // butondan el çekildiği vakit. Son bitin 0 olduğunu düşünüyorum.PDF okumadım
break; // döngüden çık
}
}
Aşağıdaki kod mantığı, butona basılmadığı sürece daim olarak LED'i yakar ve söndürür.
Butona basıldığı sürece hiçbir şey yapmadan durur.
Butondan el çekildiği anda blink döngüsünden çıkar.
main
{
bool IS = true;
while(IS)
{
OnLED();
Delay();
OffLED();
Delay();
while (Button)
IS = false;
}
}
Öncelikle teşekkürler herkese.
Alıntı YapAslında kod sizin dediğiniz dışında birşey yapmaz. Adım adım gitiğimizi varsayalım. Mavi butona basınca döngüden çıkıyor. Aslında mavi butona basmasanız bile for döngüsündeki şart sona erdiği vakit döngüden çıkıcak. Sonra kaldığı yerden! yani GPIOD->ODR= 0x00005000; buradan devam edecek. Kod bloğunun sonunda ise programı sonlandıracak. Burada herhangi bir sıkıntı yok.
İşte tam burada sıkıntı var hocam. Bunları ben de biliyorum ve buraya kadar aynen çalışıyor sıkıntı yok. Fakat sizin de dediğiniz gibi kod bloğunun sonunda program sonlanmıyor işte, main'in başından ititbaren yapmış olduğu ne varsa aynen onları yapıyor. Benim derdim o. Kod bloğu bitmesine rağmen bu program nasıl bi kez daha baştan itibaren bir kez daha çalışır ? ille de sona while(1); diyerek sonsuz döngü mü yapıcaz yani böyle bir şeyin olması mı gerek ? Çok sinir bozucu bi durum dünden beri main sonlanmasına rağmen programın tekrar çalışması beni delirtti >:(
@Deli_Nedym
Örnek olarak verdiğim kod işine yaramadı mı?
Hocam benim derdim led yak söndür veya flash eden program değil. Örneğin için teşekkürler. Benim derdim kod döngüsü bittikten sonra programın durmaması
Ben zaten kodu LED yak/söndür diye yazmadım.
Senin sorununa bir çare olabilir mi diye yazdım.
Sorununu yanlış anlamış da olabilirim.
Acaba bir kez daha açıklayabilir misin?
Ben de elimden geldiği kadar yardımcı olmaya çalışayım.
Öncelikle senin verdiğin kod keil'de hata verdi hocam.
En basitinden kodumuz şu olsun
int main()
{
int m;
for(m=1;m<10; m++)
{
GPIOD->ODR= 0x0000F000; // Ledler yansin
delay_ms(500);
GPIOD->ODR= 0x00000000; // Ledler sonsun
delay_ms(500);
}
} // Programin sonu
Bu program normalde 9 kez led yak söndür yapmalı ve ardından bitmeli değil mi ? Ancak bizim programımız 18 defa falan yapıyor. Yani main bir kere değil iki defa çalışıyor. Bunu başka kod ekleyerek de test ettiim. Main'e ne yazarsak, kod son bulması gerektiği yerde tekrar main de ne varsa onşları yapıp sonra bitiyor. Acaba keil de veya stm32f4 kitinin options kısmında mi bir sorun var ?
wdt açık kalmasın ?
keilde hata vermesi sıkınt değil illaki açıklama satırı vardır buraya yazarsan bir yolunu bulmaya çalışırız.
int main()
{
int m;
for(m=1;m<10; m++)
{
GPIOD->ODR= 0x0000F000; // Ledler yansin
delay_ms(500);
GPIOD->ODR= 0x00000000; // Ledler sonsun
delay_ms(500);
}
while(1);//Bunu yazınca çalışıyor mu 9 kez yanıp sönme işlemi.
} // Programin sonu
Kodda ki eklenti de çalışıyorsa WDT kaynaklı değildir ayrıca WDT olsa sabaha kadar reset yer program 18 değil 118 bile yapar.Koda yapacağın eklentiyi yukarıda verdim.
Ayrıca önce ki mesajımda
Alıntı yapılan: AsHeS35 - 11 Ocak 2013, 04:42:56
2.soru için for bitince tekrar main e dönmüyor burada anlaşalım bir kere for bitince programın kontrolden çıkıyor.O yüzden while(1); yazıp programı main içerisinde tutuyorsun.
demişim.
Yani demem o ki kod bitmez assembly biliyorsan diyeceğim şu ki PC+1 yaparak yoluna devam eder.
Verdiğim kod sadece taslaktı.
Algoritma açısından örnek olsun diye.
Normalde main içerisinde yazılan kodlar sonsuz döngü [ for( ;;; ), while(1) gibi ] içerisinde değilse, bir kez çalışırlar.
Ancak kullandığın denetleyicinin ayarları ile ilgili bir sorun vardır muhakkak.
Bunun başka bir açıklaması olabileceğini sanmıyorum.
Bir de denetleyiciyi değiştirip, öyle dene.
Hata şüphelerinin sayısını düşürmek her zaman için iyidir.
Zira yazdığım her kod fazladan tekrarlıyor diyorsun.
Kod sonuna while(1) yazarak sorun çözülebilir de.
Bu sorun olmaz senin için. :)
Herkese teşekkürler beyler. En sona while(65); yazıp sonsuz döngüye sokacağım kalsın orda dallanmasın bir yere. Yoksa tam sonuca ulaşamayacağız gibi keil ve işlemci ayarlarına pek yatkın değilim. Şimdilik sonsuz döngüyle çözelim biz bu sorunu. Herkese emeklerinden ötürü teşekkürler kolay gelsin iyi çalışmalar...
Alıntı yapılan: AsHeS35 - 11 Ocak 2013, 16:11:59
int main()
{
int m;
for(m=1;m<10; m++)
{
GPIOD->ODR= 0x0000F000; // Ledler yansin
delay_ms(500);
GPIOD->ODR= 0x00000000; // Ledler sonsun
delay_ms(500);
}
while(1);//Bunu yazınca çalışıyor mu 9 kez yanıp sönme işlemi.
} // Programin sonu
Kodda ki eklenti de çalışıyorsa WDT kaynaklı değildir ayrıca WDT olsa sabaha kadar reset yer program 18 değil 118 bile yapar.Koda yapacağın eklentiyi yukarıda verdim.
Ayrıca önce ki mesajımda demişim.
Yani demem o ki kod bitmez assembly biliyorsan diyeceğim şu ki PC+1 yaparak yoluna devam eder.
while 1 e gelince kısır döngüye neden girmiyor?
kısır döngüye giriyor zaten. Yani program oraya kadar çalışıp sonra sonsuz döngüde kalıyor. Çalışıyor diyebiliriz program böylelikle de
Alıntı yapılan: ULAGA - 11 Ocak 2013, 16:15:52
Verdiğim kod sadece taslaktı.
Algoritma açısından örnek olsun diye.
Normalde main içerisinde yazılan kodlar sonsuz döngü [ for( ;;; ), while(1) gibi ] içerisinde değilse, bir kez çalışırlar.
Ancak kullandığın denetleyicinin ayarları ile ilgili bir sorun vardır muhakkak.
Bunun başka bir açıklaması olabileceğini sanmıyorum.
Bir de denetleyiciyi değiştirip, öyle dene.
Hata şüphelerinin sayısını düşürmek her zaman için iyidir.
Zira yazdığım her kod fazladan tekrarlıyor diyorsun.
Kod sonuna while(1) yazarak sorun çözülebilir de.
Bu sorun olmaz senin için. :)
Bu bahsettiğiniz derleyiciden derleyiciye değişir.Hi-Tech C de bunu bir hata kodu olarak verir mesela programı döngüye sokmadınız diye mesela C51 de kod yazıp debug butonuna basarak disassembly sine baktığınızda gördüğünüz programın bittiği değil programın NOP larla doldurularak durdurulmaya çalıştığı ya da (edit:startup dosyasına dallanarak kendini döngüye de sokuyor neye göre belirlediğini bilmiyorum) 0xFFFF adresine geldiğinde 0x0000 dan başlayarak sizin programınızı tekrar çalıştırdığı olur.
Bilgisayar için Dev-C++ derleyicisi için konuşursak onda program bitirilir durdurulur ve console kapatılır.
Kısacası gömülü C'de kapatma dediğiniz işlem sonsuz döngü olur.
mesaj birleştirme:: 12 Ocak 2013, 04:08:37
Alıntı yapılan: Seçkin ALAN - 11 Ocak 2013, 16:21:38
while 1 e gelince kısır döngüye neden girmiyor?
Programı durduruyor sadece, tüm işlemleri döngüye sokmuyor.
uzun zaman sonra ödünç verdiğim stm32 kitim geri geldi ve keili kurdum stlink driverinide keil kurulum ve kullanım konusundaki linkten indirip kurdum fakat keil bana stlink driverimin eski olduğu gibi bir hata veriyor bu sorunu nasıl aşabilirim
stlink utiliy kullanarak firmware uptade yapabilirsin hocam.
hocam hata veriyor
st-link is not in the dfu mode
please restart it.
diye bir hata veriyor.
hocam stlink util programından yükleme silme işlemi yapabiliyormusunuz ?
hocam şu an kitte ilk gelen o ışık oyonları yüklü
target-connect dediğimde ld1 kırmızı yeşil flash yapıyo yürüyen pogram duruyor ama disconnect dediğimde yine eski program devam ediyor
debug nasıl yaacaz hocam :'(
st utily ile karta bağlantını kurabiliyorsunuz yani
mesaj birleştirme:: 13 Ocak 2013, 19:53:41
C:\Program Files (x86)\STMicroelectronics\STM32 ST-LINK Utility\ST-LINK Utility
nin altınaki
STLinkUSBDriver.dll
dosyasını
C:\Keil\ARM\STLink
altına kopyalayın
mesaj birleştirme:: 13 Ocak 2013, 19:55:29
keil ile sonrasında deneyiniz bakalım ne olcek
yyappmım ama hala aynı hatayı veiyor timewiever tarzı birşeyle zamanınız varsa ayalara falan bir bakabilirmisiniz
mesaj birleştirme:: 13 Ocak 2013, 20:45:18
hocam şifreyi attım ama geldimi
http://www.sonsivri.to/forum/index.php?topic=42239.0 (http://www.sonsivri.to/forum/index.php?topic=42239.0)
bu linkteki ks108 header vs dosyalarını bir proje oluşturup hepsini target1 altına ekledim
şimdi bunları mainde yine include etmem gerekiyormu gerekiyorsa neden
ekranın x=5 y=5 kordinatarına "blabla" nasıl yazarız
-
hocam yazdıramadım gldcyi led yaksönler oluyorda. glcd için sanırım daha benim için çok erken.
bu meredi bir türlü dfu moduna sokamadım mcu türkiyede biri sağolsun vermiş işe yaramadı .
çinli amcamın birinin resimlerine bakarak yaptım yok.
kactane driver denedim sayısını unuttum olmuyor :'(
1
Merhaba arkadaşlar, biraz lodoslama olacak ama, konu "C" olunca benimde şöyle bir sorunum var, yardımcı olabilirseniz memnun olurum...
https://www.picproje.org/index.php/topic,44756.msg329973.html#msg329973 (https://www.picproje.org/index.php/topic,44756.msg329973.html#msg329973)
Soruları teker teker cevaplayarak gitsek.
float deger;
deger=10/3;
yapınca degerin ne olması gerekir?
deger=10*0.333333
de doğru sonuç alıyorum. 10/3 ün 3.333 olması gerekirken neden 3 tamsayısını alıyorum ?
(10/3.0 mı yapmak gerekiyor)
Alıntı yapılan: muhittin_kaplan - 22 Ocak 2013, 15:40:28
deger=10*0.333333
de doğru sonuç alıyorum. 10/3 ün 3.333 olması gerekirken neden 3 tamsayısını alıyorum ?
(10/3.0 mı yapmak gerekiyor)
c dilinde mixed type hesap yada expression kullanildiginda degisik tipler (int, unsigned ve double) arasinda type promotion kurallari isler.
Ayrica bazi compilerlar bunlara kullanilan islemcinin 8/16/32/64 bit olmasina gore ek anlamlar ekler. (yani int yazinca her MCU icin bu farkli sayida bit icerebilir!)
kullandiginiz compilerin dokumanlari icinde "type promotion" bahsine bakmanizda fayda olur.
hocam ben bir soru sorayım..
Tuş takımını sürekli tarıyorum. Tuş takımından bir tuşa basıldığı zaman bu tuşun bırakılmasını beklemem lazım.
her bir tuşa basıldığını algıladığımda gerekli işlemleri yapıp ardında şöyle bir komutla bekletiyorum
while (int_tus==!45){}
Normalde hiçbir tuşa basılmazsa bana 45 verisi geliyor. Basılmışsa basılan tuşun ascii karşılığı geliyor. Böyle bir kullanım yanlışmı olur acaba. Burada demek istediğim int_tus verisi 45 den farklı olduğu sürece program while içerisinde dönsün. Ama bu komutla program while içerisinde beklemiyor
!= olacak.
@Mucit23
Eğer tuş okurken tuşa basıldığı anda tuşun bırakıldığını öğrenmek için bir döngüye girersen;
O anda başka bir işlem yaptıramazsın işlemciye kesmeler hariç.
Yine de kodunun tümünü bilmediğim için pek bir yorum yapamayacağım.
Teşekkürler JKramer...
Alıntı yapılan: ULAGA - 22 Ocak 2013, 16:17:18
@Mucit23
Eğer tuş okurken tuşa basıldığı anda tuşun bırakıldığını öğrenmek için bir döngüye girersen;
O anda başka bir işlem yaptıramazsın işlemciye kesmeler hariç.
Yine de kodunun tümünü bilmediğim için pek bir yorum yapamayacağım.
Hocam menü ayakları. Durumun farkındayım, sakıncalarınıda biliyorum ama zaten tuşa basılı olduğu zamanlarda işlemcinin başka birşey yapmasına gerek yok. Kesmeler çalışıyor. Tuş bilgisini sürekli okuyorum o yeter.
Alıntı yapılan: Mucit23 - 22 Ocak 2013, 16:27:49Hocam menü ayakları. Durumun farkındayım, sakıncalarınıda biliyorum ama zaten tuşa basılı olduğu zamanlarda işlemcinin başka birşey yapmasına gerek yok. Kesmeler çalışıyor. Tuş bilgisini sürekli okuyorum o yeter.
Yaptığın sistemin çalışması açısından bir sorun teşkil etmiyorsa, dediğin gibi önemli değil. :)
Mufit hocam teşekkür ederim.
Alıntı yapılan: gerbay - 22 Ocak 2013, 15:44:30
float sa 10.0f/3 yapmanız gerekiyor, double sa 10.0/3 ...
Yukardaki Cevabe istinaden devam edeyim.
#define Z 64
int A;
float Sonuc;
a=5;
Sonuc=a/Z yi nasıl yapacağım ?
Derleyici olarak GCC arm (CoIDE ile) Kullanıyorum.
mesaj birleştirme:: 22 Ocak 2013, 17:10:40
@Mucit
while (int_tus != 45)
{
.........
}
yaparsan 45 dışındaki tüm değerlerde while içerisine girer.
Alıntı yapılan: muhittin_kaplan - 22 Ocak 2013, 17:07:25
Mufit hocam teşekkür ederim.
Yukardaki Cevabe istinaden devam edeyim.
#define Z 64
int A;
float Sonuc;
a=5;
Sonuc=a/Z yi nasıl yapacağım ?
Derleyici olarak GCC arm (CoIDE ile) Kullanıyorum.
sonuc=((float)a)/Z;
konunun başını okumadım yanlış birşeye de cevap vermiş olabilirim.
Not:Derleyiciniz küçük-büyük harf duyarlı olabilir.
ona takılmayın.
sonuc=((float)A)/Z;
şunu denedim (VB den kalma alışkanlık)
Sonuc=float(A/Z); olmadı. Çözüm Önerinizi Deneyeceğim. Teşekkür ederim.
float sonuc;
sonuc = (float)a/Z;
Alıntı yapılan: muhittin_kaplan - 22 Ocak 2013, 17:35:04
ona takılmayın.
sonuc=((float)A)/Z;
şunu denedim (VB den kalma alışkanlık)
Sonuc=float(A/Z); olmadı. Çözüm Önerinizi Deneyeceğim. Teşekkür ederim.
önce parantez içi işletiyor zaten oradan a=5 z=64 dolayısıyla integer olarak 0 geliyor sonra floata çevriliyor ve sonuç sizi tatmin etmiyor sıfır çıkıyor yani.Önce type-casting yapın sonra bölme işlemini okunaklık artsın diye çift parantez kullandım.
hiç biri olmadı.
bende
#define DENEME 64.0 yaptım.
Alıntı yapılan: muhittin_kaplan - 23 Ocak 2013, 15:28:43
hiç biri olmadı.
bende
#define DENEME 64.0 yaptım.
Size söylerken de Dev-C++ ile denedim siz söyledikten sonra da onun üzerinde de GCC var ama demek ki arm gcc derleyicisi farklı çalışıyor.
#include <stdio.h>
#define Z 64
int main(void)
{
int a=4;
float sonuc;
sonuc=((float)a)/Z;
printf("%f\n",sonuc);
system("PAUSE");
}
Şu kod parçacığı bende 0.062500 gösteriyor.
Her iki şekilde de sonuç, 0.0625
AsHeS35'in de dediği gibi ARM derleyicisi ile ilgili bir sorun olabilir.
sonuc=((float)a)/Z;
sonuc=(float)a/Z;
Kodları deşmeye devam ozaman, Bakmadım Ama Global ve yerel aynı tanımlama yapılmışsa
int Deger;
fonction()
{
float Deger;
Deger=Z/A;
}
Yaparsam benim mantığım fonksiyon içerisindeki ni işleme koyar diyor. Yarın Biraz daha deşeleyip bakayım.
Alıntı yapılan: muhittin_kaplan - 23 Ocak 2013, 17:49:19
Kodları deşmeye devam ozaman, Bakmadım Ama Global ve yerel aynı tanımlama yapılmışsa
int Deger;
fonction()
{
float Deger;
Deger=Z/A;
}
Yaparsam benim mantığım fonksiyon içerisindeki ni işleme koyar diyor. Yarın Biraz daha deşeleyip bakayım.
Fonksiyon içerisinde fonksiyonda ki Deger değişkenini kullanır fakat fonksiyon dışında mesela main gövdesinde Deger değişkeni çağrılırsa global tanımlanan kullanılır.
kalın bir main dosyam var, tüm fonksiyonları yazdım buraya. bunu bölmek istiyorum dosyalar halinde yapmam gereken adımlar nelerdir.
int topla(int a, int b)
{
int z=a+b;
return z;
}
int cikart(int a, int b)
{
int z=a-b;
return z;
}
int carp(int a, int b)
{
double z=a*b;
return z;
}
main()
{
int deger;
deger=Topla(1,2);
int DigerDeger=cikart(3,2);
double carpim=carp(2,3);
}
yapmak istediğim matematik.c ve matematik.h adında iki dosya oluşturup bu işlemleri oraya atmak ve main e oradan çağırmak.
matematik.c
#include stdint.h
#include matematik.h
int topla(int a, int b)
{
int z=a+b;
return z;
}
int cikart(int a, int b)
{
int z=a-b;
return z;
}
int carp(int a, int b)
{
double z=a*b;
return z;
}
matematik.h
#ifndef MATEMATIK_H_
#define MATEMATIK_H_
extern int topla(int a, int b);
extern int cikart(int a, int b);
extern int carp(int a, int b);
#endif //MATEMATIK_H_
1. matematik rutinlerini matematik.c dosyasına at.
#include "matematik.h"
int topla(....)
{
..
..
}
long carp(...)
{
..
..
}
..
..
vs..
vs...
matematik rutinleri için header dosya hazırla
matematik.h
#ifndef __MATEMATIK_H //(çakışma kilidi)
#define __MATEMATIK_H
#incude "xxxxxx" // ihtiyacın olan dosyaları include et
#include"yyyyyy"
int topla(...);
long carp(..);
..
..
#endif
matematik.c dosyasını projeye dahil et.
main içinde "matematik.h" dosyasını include et.
#ifndef __MATEMATIK_H //(çakışma kilidi)
#define __MATEMATIK_H
Bunun amacı nedir hocam
"Header guard" olarak bilinir. Aynı header'ın iki kez include edilmesini engeller. Yani program içinde hiç düşünmeden istenildiği kadar #include "matematik.h" yazılabilir, çünkü sadece bir kez include işlemi yapılacaktır.
O kısım ilk çalıştığında __MATEMATIK_H tanımlı mı diye bakar. Tanımlı değilse bu ifadeyi tanımlar ve altındaki işlemleri yapar. İkinci eklemede __MATEMATIK_H zaten önceden tanımlanmış olduğundan dosyadaki herşey atlanır.
Son satırdaki #endif ifadesini unutmamak lazım tabi. #ifndef bloğunu o kapatıyor.
Diyelim ki birden fazla dosyada "matematik.h" include edilmiş.
Şöyle bir kurgumuz olsun.
adc.h
#include "matematik.h"
pwm.h
#include "matematik.h"
main.c (veya main.h)
#include "adc.h"
#include "pwm.h"
main.c derlenirken matematik.h içerisindeki tanımlamalar dosyaya iki kez eklenecekti. Önce adc.h çözümlenirken, sonra da pwm.h çözümlenirken "matematik.h" içerisindeki tanımlar dosyaya eklenecekti.
bunu çözmek için çakışma kilidi koymamız gerekecek.
nasıl?
eğer derleme esnasında bir dosya bir kez include edilmiş ve buradaki tanımlar alınmışsa, bir daha bu tanımların alınmasına engel olarak.
#ifndef __MATEMATIK_H
#define __MATEMATIK_H
..
..
#endif
#ifndef eğer tanımlanmamışsa (no define) anlamına geliyor.
bu kodparçacığı ise
eğer __MATEMATIK_H tanımını daha önce görmedi isen, bu bloğu derlemeye dahil et. yoksa bu bloğu hiç görmemişsin say anlamına geliyor. Eğer bu tanım daha önce görülmemişse , bu blok derlemeye dahil edileceği için, #define __MATEMATIK_H ile artık tanımlı hale getiriyoruz. Yani derleyiciye sen bu tanımlamaları daha önce gördün diyoruz.
burada tanımın __MATEMATIK_H olmasının bir nemi yok. #ifndef _MERHABA_DUNYALI_ diyebilirdik. hiç bir şey farketmezdi. dosya adı ile uyumlu olması, anlaşılırlık nedenyle gelenek olmuş.
derleyici "adc.h" dosyasını işlerken "matematik.h" dosyasının içeriğini okudu. baktı ki __MATEMATIK_H diye bir tanım daha önce yapılmamış. Bloğu derlemeye dahil etti.
sonra "pwm.h" dosyasını işlemeye baladı. baktı ki "matematik.h" dosyası include edilmiş. hemen dosyayı açtı.
#ifndef __MATEMATIK_H satırına geldi. __MATEMATIK_H dite bir tanım daha önce yapılmış mı diye baktı listesine. Gördü ki bu tanım daha nce yapılmış, bu bloğa eleşmeden #endif satırını aradı ve yoluna oradan devam etti.
Bu konularda eksiğim.
Bazı Sormak istediklerime de cevap olmuş.
main.c nin içeriği
adc.h
pwm.h
matematik.h
----------
pwm.h içeriği
include matematik.h
--------------------
adc.h içeriği
include matematik.h
şeklinde olduğundan aslında main.c tarafından matematik.h dolayısıyla matematik.c fonksiyonları defaten çağrılmış ve derlenmiş oluyor. Bu Hatayı düzeltmek için matematik.h dosyasına
#ifndef __MATEMATIK_H //(çakışma kilidi)
#define __MATEMATIK_H
#include dosyalar
prototipler......
#endif
yapıyoruz. Buraya kadar tamam.
Şimdi birşey daha sorabilirmiyim, Bir dosyayı include ettiğimde kullandığım fonksiyonumu yoksa tümünümü derler ? Birsürü fonksiyondan oluşmuş bir dosyada bir fonksiyon kullanıyorsa diğrelerinin derlenmesi sistemde fazladan yer kapsamasına neden olmaz mı ?
Tüm fonksiyonlar derlenir. Ancak link esnsında ve sonrasında sadece kullanılan fonksiyonlar hex koda dönüşür.
Alıntı YapŞimdi birşey daha sorabilirmiyim, Bir dosyayı include ettiğimde kullandığım fonksiyonumu yoksa tümünümü derler ? Birsürü fonksiyondan oluşmuş bir dosyada bir fonksiyon kullanıyorsa diğrelerinin derlenmesi sistemde fazladan yer kapsamasına neden olmaz mı ?
olur. Her obj(ect) dosyasinin icindekiler birlikte yuklenir/yerlestirilir.
bunu engellemek icin her fonksiyonu ayri bir dosyaya yerlestirin ve derlenmis object dosyalarini bir lib(rarye) koyun. Link asamasinda bu library kullanilarak referans edilen ama daha yuklenmemis butun fonksiyonlarin obj'leri lib(rary)den aranir ve eklenir.
bu stm32 ile sin(x) olayına basit bir örnek verebilirmisin.
Keilde tanımladığım bir fonksiyonun sonunda bir etiket tanımlıyorum.
fonksiyon içerisinde farklı yerlerden bu etikete goto ile dallanmam gerekiyor.
Böyle yaptığımda kod çalışıyor ama bir uyarı veriyor
src\main.c(2720): warning: #127-D: expected a statement
Bu uyarının sebebi nedir. Benden ne gibi bir açıklama bekliyor?
Keil C anlayamadığım bazı komut satırları var konu hakkında yardımlarınızı bekliyorum.
# define IAP_LOCATION 0X7ffffff1
unsigned long command[5];
unsigned long result[2];
typedef void (*IAP) (unsigned long[],unsigned long[]);
typedef eski_adi yeni_adi şeklinde kullanılıyor ama yukarıda tam olarak ne yapılmak istenildiğini anlayamadım *IAP diye bir pointer mı var ?
IAP iap_entry
Burada IAP nesne olarak kabul edilip çoğaltılıyor mu ?
iap_entry =(IAP)IAP_LOCATION;
Anlamadım
iap_enrty(command,result);
typedef void (*IAP) (unsigned long[],unsigned long[]);
Hocam buna "Function Pointer" deniyor. Yani nasıl "int" bir tipse, "void" bir tipse, fonksiyonlar da tip olarak tanımlanabiliyor.
Burada IAP "tipi", dönüş değeri "void" olan, unsigned long[] cinsinden iki parametre alan fonksiyon -aslında tip- anlamına geliyor.
C dili nesne yönelimli bir dil değildir. Dolayısıyla nesne olarak yorumlamaz.
IAP iap_entry;
iap_entry =(IAP)IAP_LOCATION;
Bu kod, bellekte IAP_LOCATION adresinde, parametre olarak iki adet unsigned long[] alan bir fonksiyon olduğu anlamına geliyor ve bu fonksiyonun adresi iap_entry değişkenine atılıyor. IAP'ı da bir tip olarak düşünün.
void foo(void);
nasıl bir fonksiyon belirtiyorsa
IAP iap_entry;
de bir fonksiyon belirtiyor. Kullanılmasının tek sebebi dinamik olarak bellekte herhangi bir adresi taşıyabilmesi.
Bu fonksiyon işaretçileri nerede kullanılır derseniz, en basitinden sıralama algoritmaları kullanır.
void qsort(void *base, size_t nmemb, size_t size,
int(*compar)(const void *, const void *));
Burada compar parametresi bir değişkendir ve algoritma karşılaştırmayı bu değişkenin işaret ettiği fonksiyona yaptırır.
int compare_values(int *a, int *b)
{
return a > b;
}
int main()
{
qsort(siralanacak_dizi, eleman_boyutu, dizi_boyutu, compare_values);
}
Burada qsort'a karşılaştırmaları yapan fonksiyonumuzun adresi yollanıyor.
Gerçek fonksiyonlar da aslında pointer'larıyla aynı şekilde ele alınır.
Function pointer, bir işaretçi ise işaret ettiği değeri çağırmak için '*' önekini kullanmalısınız. Ancak fonksiyonlar da aynı şekilde ele alındığından;
void my_funcion(int n)
{
printf("n is %d", n);
}
void (*foo)(int);
foo = &my_function;
foo(1); // doğrudan fonksiyon olarak çağır
(*foo)(2); // işaretçi mantığıyla çağır
iki kullanımda aynı işi yapar ve ikisi de doğrudur.
Dkkat ettiyseniz foo'ya fonksiyonun adresi atanmıştır ('&' karakteri ile). Derleyici, foo(..) ve (*foo)(..) kullanımlarının her ikisini de fonksiyona çağrı olarak yorumlar. İşaretçi olarak bakarsak, foo, void döndüren ve int parametre alan bir fonksiyona işaret eden bir pointer'dır. *foo değeri otomatik olarak void döndüren ve parametre olarak int alan bir fonksiyonun ta kendisidir. Her iki türlü de çağrılır. İşlemci bu satırlarda Program Counter adresini yedekler, işlemciyi foo'nun içeriğine atlatır ve fonksiyon çalışmış olur.
C++ 'ta funcion pointer yerine virtual fonksiyonları kullanmak daha uygundur(diye biliyorum).
Umarım açıklayabilmişimdir. İyi çalışmalar...
teşekkürler!!!!
128x64 Grafik LCD de bölgesel resim basmaya çalışıyorum. Bu iş için bir fonksiyon yazayım dedim ama kafam durdu.
void ks0108_pixelimage(u8 x,u8 y,const unsigned char img[], u16 size){
u16 i=0;
u8 z=0,yz=0,temp=0,data=0;
u8 ux=0,uy=0;
for (yz=0;yz<size/8;yz++) // Yatay Tarama Yapiliyor..
{
for (i=0;i<size/2;i++) //Dikey Tarama Yapiliyor
{
data=img[i];
for (z=0;z<8;z++)
{
temp=(data>>z)&0x01;
ks0108_pixel(ux,uy,temp);
}
}
}
}
Şimdilik yazdıklarım bunlar.
Kafamdaki düşünce şöyle, 8x8, 16x16, 32x32 gibi boyutlarda hazırlanmış resimlerim var. Bu resimleri ekranın istediğim bir kordinatına basmak istiyorum.
Fonksiyondaki Size Parametresi Resmin boyutunu belirliyor. Normalde 16X16 bir resim için 16*2 den 32 byte eder, Yani Size parametresi 32 gönderilmesi gerekir.
Bu Gönderilen resmin boyutuna ve kordinatlarına göre ekrana uygun şekilde basacağım
Bunu optimize bir şekilde nasıl yaparım.
Edit;
Tamam Hallettim
void ks0108_pixelimage(u8 x,u8 y,const unsigned char img[], u16 size){
u16 i=0;
u8 z=0,ux=0,uy=0;
for (i=0;i<size;i++)
{
if(i==((size/2)))
{
uy=uy+8;
ux=0;
}
for (z=0;z<8;z++)
{
ks0108_pixel(x+ux,y+uy+z,((img[i]>>z)&0x01));
}
ux++;
}
}
@Mucit23 hocam pixel basarken ux uy kullanmışsınız. Bunlar değerlere ilk başta offset olan x ve y eklenmeli. Sonrasında taramanın her adımında ux ve uy bir arttırılmalı. Bunların üstüne tarama sırasındaki x y koordinatlarını da eklemelisiniz. İki boyutlu bir resmin Genişlik ve yükseklik olmak üzere iki ölçüsü vardır. Fonksiyona bir parametre eklemek birşey kaybettirmez. Fonksiyonu:
void ks0108_pixelimage(u8 x,u8 y,const unsigned char img[], u8 width, u8 height)
olarak tanımlarsanız daha kolay olur.
void ks0108_pixelimage(u8 x,u8 y,const unsigned char img[], u8 width, u8 height) {
u8 ix, iy, i;
u8 data_byte, data_bit;
for(iy = 0; iy < (height / 8); iy++){
for(ix = 0; ix < width; ix++){
/* (satır) x (bir satır uzunluğu) + sütun */
data_byte = img[iy * width + ix];
for(i = 0; i < 8; i++){
data_bit = (data_byte >> i) & 0x1;
ks0108_pixel(x + ix, y + iy + i, data_bit);
}
}
}
}
Şimdilik böyle birşey yazdım. Resmin diziye nasıl atıldığını da açıklarsanız ona göre yazabiliriz.
İyi çalışmalar...
Hocam Sanırım üst üste yazdık. Ben şu şekilde hallettim.
void ks0108_pixelimage(u8 x,u8 y,const unsigned char img[], u16 size){
u16 i=0;
u8 z=0,ux=0,uy=0;
for (i=0;i<size;i++)
{
if(i==((size/2)))
{
uy=uy+8;
ux=0;
}
for (z=0;z<8;z++)
{
ks0108_pixel(x+ux,y+uy+z,((img[i]>>z)&0x01));
}
ux++;
}
}
İlk yazdığım zaman sağlıklı düşünemiyordum sanırım. Şu haliyle çalışıyor. Belki daha optimize bir şekilde yazılabilir.
----
Sizin yazdığınızıda deneyeyim. Sanırım sizinkinde resmin illa 8x8 ve katı şeklinde olması gerekmiyor. 8*32 gibi bir değerde olabiliyor. İnceleyelim bakalım
Hallettiyseniz tamamdır hocam. Şunu fark ettim ki benim yazdığımda küçük bir hata var. Neyse siz kendinizinkini kullanın ben onu düzelteyim.
Hocam mutlaka bir sebebi vardır, Ama eğer kullandığım değişkenler 8 bit dışına çıkmayacaksa dediğiniz şekilde yapmak boş yere ram tüketim miktarını arttırmazmı?
Anladım Hocam. Verdiğiniz bilgi için teşekkürler..
arkadaşlar merhaba,
Bir tabloda char karakterler tutmak istiyorum. Bunu nasıl yaparım
Örneğin şöyle birşey yapmaya çalıştım..
const *char_data[]={"PicProje\n\r"};
Ben bu tablodan aldığım karakterleri usart ile göndereceğim. Amacım örneğin char_data[0] dediğim zaman bana tablo içerisindeki 0 karakter yani P harfini versin. Yukarıdaki gibi bir kullanıma müsade etmiyor keil. Doğrusu nasıl olmalı
Tabloda çok fazla karaker olacak.
Alıntı yapılan: Mucit23 - 26 Şubat 2013, 10:49:36
arkadaşlar merhaba,
Bir tabloda char karakterler tutmak istiyorum. Bunu nasıl yaparım
Örneğin şöyle birşey yapmaya çalıştım..
const *char_data[]={"PicProje\n\r"};
Ben bu tablodan aldığım karakterleri usart ile göndereceğim. Amacım örneğin char_data[0] dediğim zaman bana tablo içerisindeki 0 karakter yani P harfini versin. Yukarıdaki gibi bir kullanıma müsade etmiyor keil. Doğrusu nasıl olmalı
Tabloda çok fazla karaker olacak.
const char data[]={"PicProje\n\r"};
olarak dener misin? Sonra da data[0] olarak çağıracaksın...
evet hocam sanırım dizi türünü belirtmediğim için hata alıyormuşum. Bu şekilde çalışıyor
mesaj birleştirme:: 26 Şubat 2013, 12:43:18
Hocam bir problem var fakat
Dizi içerisine satır başı alt satıra geçmek için kullandığım \n\r karakterleri alınamıyor herhalde
normalde şöyle birşey yapmaya çalışıyorum.
const char char_data[]={"/*************************************************************************************************************************************************/\n\r"};
while(1){
for (x=0;x<151;x++)
{
Send_Data(char_data[x]);
}
}
Burada yanlış saymadıysam dizi içerisinde 0 dahil olmak üzere 150 karakter var bende 150 döngü oluşturup diziden alıp usarta gönderiyorum. Bilgisayarda terminalde baktığımda datalar geliyor fakat düzenli bir şekilde gelmiyor. Normalde \n\r karakterleri terminale gttiği zaman alt tan satır başı yapması lazım ama bu haliyle çorbaya dönüyor program..
const char data[]={"PicProje\n\r"};
şeklinde yaptıysan tanımı
Send_Data(data[x]);
kullanmalısın.
"zzz" problem bu değilmiş. pardon .
mesaj birleştirme:: 26 Şubat 2013, 13:50:03
enter komutu göndersen satır başı için. 13 dü galiba .
Hocam Teşekkür ederim o kısmıda hallettim sayenizde. şuan seri iletişimde sıkıntı yok, Satır başı felan güzel çalışıyor.
Yanlız tablo yapamıyorum, Const Char şeklinde bir karakter tablosu oluşturabilirmiyim. Dizi içerisinde tahminimce 2000,3000 eleman olur.
const char char_data[]={"/***********************************************/\n\r
/***********************************************/\n\r
/***********************************************/\n\r};
Şöyle birşey yapmak istiyorum. Bunu acaba iki boyutlu dizi olarakmı tanımlamak gerekir böyle bir tabloyu nasıl oluştururum
Alıntı yapılan: Mucit23 - 26 Şubat 2013, 14:02:39
Hocam Teşekkür ederim o kısmıda hallettim sayenizde. şuan seri iletişimde sıkıntı yok, Satır başı felan güzel çalışıyor.
Yanlız tablo yapamıyorum, Const Char şeklinde bir karakter tablosu oluşturabilirmiyim. Dizi içerisinde tahminimce 2000,3000 eleman olur.
const char char_data[]={"/***********************************************/\n\r
/***********************************************/\n\r
/***********************************************/\n\r};
Şöyle birşey yapmak istiyorum. Bunu acaba iki boyutlu dizi olarakmı tanımlamak gerekir böyle bir tabloyu nasıl oluştururum
Hocam tablodan kastınız string'lerden oluşan bir dizi ise iki boyutlu dizi gerekiyor. Ama sadece birkaç satırdan oluşan bir string ise alt satıra tekrar çift tırnak koyarak devam edebilirsiniz.
const char *text =
"Bu uzun bir metin ama"
"cok satirda parcalanabilir. "
"Her satira tirnak koymayi unutmayin.";
veya
const char *text2 =
"Bu ise diger yontem\
Her satiri tamamen ele alinacagindan
bosluklara, tab'lara dikkat edin";
İkinci yöntemde her satırın tamamı alındığından satırlar sol yana bitişik şekilde yazılacak. Örneği satırları tab ile kaydırmak istediğinizde yazılacak olan metne de tab eklenir.
İyi çalışmalar.
const char srv_globalmenu_title[][22]={
"İlk satır \n\r\0",
"İkinci satır \n\r\0",
"Üçüncü satır \n\r\0",
"Dördüncü satır\n\r\0",
"Beşinci satır \n\r\0"
}
Alıntı yapılan: Klein - 26 Şubat 2013, 18:00:59
const char srv_globalmenu_title[][22]={
"İlk satır \n\r\0",
"İkinci satır \n\r\0",
"Üçüncü satır \n\r\0",
"Dördüncü satır\n\r\0",
"Beşinci satır \n\r\0"
}
Prof.
Teşekkürler arkadaşlar.
Arkadaşlar merhaba , aşağıdaki yapıyı tam olarak anlamadım.
Burada bir yapı tanımlanıyor ok !
typedef struct
{
value....
} yapi1
Yeni yapi olarak coğaltıyorum .Burada da problem yok.
yapi1 yeniyapi1
aşağıda problem yok
unsigned char bfr[11];
fonksiyon(bfr,yeniyapi1);
yeniyapi1 tekrarmı coğaltıyoruz yeniyapi2 ?? anlamadım.
void fonksiyon (unsigned char * buf , yapi1 yeniyapi2)
{
event.....
}
Bu işin mantığı nedir.
Ne sorduğunuzu tam anlamadım. Biraz daha açar mısınız?yeniyapi1 tekrar mı çoğaltıyoruz ne demek?
fonksiyon(bfr,yeniyapi1);
Burda yaptığınız fonksiyonu çağırmak
void fonksiyon (unsigned char * buf , yapi1 yeniyapi2)
{
event.....
}
Bu ise çağırdığınız fonksiyonun implement edilmesi. Burdaki "yeniyapi2" sadece argüman adi.
Çoğaltma ile kastteğiniz sanırım değişken oluşturma.
Dostum kusura bakma kelimeleri yanlış seçmişim
<struct> <yap isimi> <nesne ismi>;
Anlamadığı tarafı ----> yapi1 yeniyapi2 neden ?
void fonksiyon (unsigned char * buf , yapi1 yeniyapi2)
{
event.....
}
Orada yapılan tek şey fonksiyona yapi1 türünden bir parametre göndermek.
fonksiyon(bfr,yeniyapi1);
burada yapılan şey prototip tanımlama.Bir nevi derleyiciyi uyarıyosun. Aşağıda bir yerlerde böyle bi fonksiyon var diye.Eğer bunu yapmazsan fonksiyonu çağırdığın zaman linker hata verecektir.Böyle bi fonksiyon yok diye.Eğer prototip tanımlamak istemiyosan fonksiyonu main fonksiyonundan önce tanımlamalısın.
typedef struct
{
value....
} yapi1
yapi1 yeniyapi1
1. FONKSİYON
void fonksiyon (unsigned char * buf , yapi1 yeniyapi2)
{
event.....
}
2. FONKSİYON
void fonksiyon (unsigned char * buf , yeniyapi2)
{
event.....
}
1. fonksiyonla 2. fonksiyon arasında ne fark var.
Alıntı yapılan: yamak - 01 Mart 2013, 19:14:01
Orada yapılan tek şey fonksiyona yapi1 türünden bir parametre göndermek.
fonksiyon(bfr,yeniyapi1);
burada yapılan şey prototip tanımlama.Bir nevi derleyiciyi uyarıyosun. Aşağıda bir yerlerde böyle bi fonksiyon var diye.Eğer bunu yapmazsan fonksiyonu çağırdığın zaman linker hata verecektir.Böyle bi fonksiyon yok diye.Eğer prototip tanımlamak istemiyosan fonksiyonu main fonksiyonundan önce tanımlamalısın.
Yanlış anlaşılma olmasın diye söylüyorum.
fonksiyon(bfr,yeniyapi1); fonksiyonun prototip tanımlaması değil. fonksiyon çağrısıdır.
prototipi void fonksiyon(unsigned char *, yapi1) şeklinde olur.
Ayrıca yine prototip tanımlaması derleyici içindir, linker için değil.
Eğer fonksiyonun prototip tanımlaması yapılır ancak implement edilmezse linker aşamsında hata verir.
@armsistem
Sanırım kafasını karıştıran neden ikinci bir yapi1 değişkeninin tanımlanması.
Onun sebebi ise kullanıcı bu fonksiyonu çağırdığında derleyici yeniyapi1 değişkeninin bir shallow kopyasını oluşturur.
İşte bu kopya yeniyapi2 değişkenidir. yani sen fonksiyonunun içinde yeniyapi1 nesnesinin kopyası üzerinde işlem yapmış olursun.
Bunun yerine yapi1 türünden pointer kullanman daha efektif olur.
Ayrıca değişken isimleri çok kötü onlarda kafanı karıştırabilir.
Sonradan eklediğin mesaj için:
1. fonksiyon unsigned char * ve yapi1 türünden 2 parametre alır
2. fonksiyon derlenmez çünkü yeniyapi2 diye bir tür tanımı yok.
İlk verdiğin örnekteki yeniyapi2 bir tür değil değişkendir.
Dediğim gibi isimler çok kötü. aslında yeniyapi2 yapi1 türünden bir değişken.
Haklısınız ben yanlış gördüm.Onu bi an prototip tanımalası olarak.Evt o kısım fonksiyon çağrısı.
Arkadaşlar C de Negatif bir sayıyı pozitif bir sayıya nasıl çeviririm. Mesela sayı -100 olsun. Bir işlemden geçirdikten sonra bu sayıyı Signed char olarak tanımlı bu değer. Yani +-127 alabilir.
Bilmiyorum ama nedense br ses
şunu aramamı söylüyor
absolute value in ansi c
mesaj birleştirme:: 07 Mart 2013, 15:19:22
http://publib.boulder.ibm.com/infocenter/iadthelp/v7r0/index.jsp?topic=/com.ibm.etools.iseries.langref.doc/rzan5mst68.htm (http://publib.boulder.ibm.com/infocenter/iadthelp/v7r0/index.jsp?topic=/com.ibm.etools.iseries.langref.doc/rzan5mst68.htm)
Hocam Sağolun Hallettim. Açıkçası mutlak değer hiç aklıma gelmedi.
Ben gidip 7. biti 0 yapmaya çalışıyorum..
Matematik doğada varmıdır, yoksa bizmi matematik yaparız.
(Aman Fractal duymasın. :-X)
Espiri Yapmayada gelmiyor arkadaş.
hiç bi yerde göremediysen bari eline bak
c ile ilgili bu bölümü geyik bölümüne çevirmesek.
Arkadaşlar merhaba işlemcinin Flash memory'sini okurken problem yaşıyorum (C diline tam hakim olmamamdan kaynaklanıyor)
Aşağıdaki diziyi flash memory yazıyorum.
unsigned char const demo_messg[] =
{
0x70, 0x40, 0x2D, 0xE9, 0x00, 0x40, 0xA0, 0xE1, 0x01, 0x50, 0xA0, 0xE1, 0x05, 0x10, 0xA0, 0xE1
} ;
Okumak için aşağıdaki kodları kullanıyorum.
char *oku; // 8 bit değişken
oku = (char*)0x7000; // flash memory yazılı olduğun adresi
u1_string_gonder(oku); // çıktı 70 40 2D E9
Buraya kadar problem yok.
Adresleme mantığı aşağıdaki gibi midir ?
0x7000 ---- 70
0x7001 ---- 40
0x7002 ---- 2D
0x7003 ---- E9
......................
Kodları aşağıdaki gibi değiştirdiğimde
oku = (char*)0x7003; // flash memory yazılı olduğun adresi
u1_string_gonder(oku); // çıktı E9
7000-7001-7002-7003 ----- bir hücremidir ?
7000-7001-7002-7003 = char mıdır ?
adres arttırma yoluyla oku=oku+4; şeklinde mi olur ?
Aşağıdaki bloklar halinde nasıl okurum.
7000-7001-7002-7003
7004-7005-7006-7007
demo_messg zaten dizinin başlangış adresini tutar. Yani adrestir. Siz bunun adrsinin 7000 olduğunu nerden biliyorsunuz? Bilseniz bile derleyici bu adresi kendi atadığı için sabit adres üzerinden gitmek doğru olmaz. Kısaca bu işi derleyiciye bırakın. Siz dizinin adresini alın.
Örnek:
char dizim[]={0x01,0x02,0x03,0x04};
char *a;
a= dizi;
a=&dizi[0] gibi... dizinin adresini karakteri gösteren a göstericisine yüklüyoruz. Böylece a içerisinde dizinin adresi tutuluyor.
*a dersek, a nın gösterdiği adresteki(dizi[0], 0x01) eleman kastedilmiş olur.
Merhaba , 7000 olduğunu nereden biliyorum , çünkü o adrese ben yazıyorum orası işlemcinin flash memory adresi. Okumaya çalıştığım ve kısmen okuduğum yer flash memory.
Ekrana içi dolu bir daire çizmek istiyorum. Elimde sadece nokta koyma fonksiyonum var. verdiğim X ve Y koordinatlarına Nokta koyuyor.
İnternette çok fazla kod var. Çember çizebiliyorum ama içini nasıl doldururum. Örnek bir kod parçacığı verebilirmisiniz.
Alıntı yapılan: Mucit23 - 18 Mart 2013, 22:01:15
Ekrana içi dolu bir daire çizmek istiyorum. Elimde sadece nokta koyma fonksiyonum var. verdiğim X ve Y koordinatlarına Nokta koyuyor.
İnternette çok fazla kod var. Çember çizebiliyorum ama içini nasıl doldururum. Örnek bir kod parçacığı verebilirmisiniz.
Şimdi hocam ben bir algoritma önereyim elinde merkezin olsun,bir d diye bir açı değişkeni olsun x=r*cos(d);ve y=r*sin(d) olarak pixel noktalarını tarayabilirsin.Tabii ki döngünün değişkeni r ve d olmak üzere.
EDİT:Şimdi ekranın göbek noktasının 0,0 olarak kabul etmişim ama diyelim ki 50,50 olsun x=r*cos(d)+50; y=r*sin(d)+50; olur.
Evet hocam o kodlarla çember çiziyorum. Fakat Çemberin içi dolu olmasıni istersem ne yapmam gerekir.
Alıntı yapılan: Mucit23 - 18 Mart 2013, 22:19:45
Evet hocam o kodlarla çember çiziyorum. Fakat Çemberin içi dolu olmasıni istersem ne yapmam gerekir.
E tamam işte daire dediğin şey iç içe geçmiş çemberlerdir tabii senin kullandığın GLCD ya da TFT pixellerden oluşuyor dolayısıyla r yi sabit tutarsan 1 çember r yi değişken yaparsan ve maksimum değeride istediğin sayıya eşitlersen oldu sana içi dolu daire :)
anladım. yarı çap kadar iç içer geçmiş çember çizmek gerekiyor sanırım.
Alıntı yapılan: Mucit23 - 18 Mart 2013, 22:31:19
anladım. yarı çap kadar iç içer geçmiş çember çizmek gerekiyor sanırım.
Aynen hocam mesela yarıçap ve derecenin değişim miktarını en iyi deneyerek görebilirsiniz,mesela r aralıkları geniş olursa aralıklarla çemberler çıkar daha sıkı olursa daire olur eğer derece değişkeninin aralıkları dar olursa daire kesik kesik çıkar mesela bunları optimize edebilirsiniz.
Tamam Hocam. Aklıma bir iki yöntem geldi. Yarın deneyeceğim
Alıntı yapılan: Mucit23 - 18 Mart 2013, 22:56:03
Tamam Hocam. Aklıma bir iki yöntem geldi. Yarın deneyeceğim
Hocam mesela çember çizdirmek için değişik bir algoritmanız varsa onu da kullanabilirsiniz aralıklarla çoklu çember çizdirerek.
Hocam yaptım birşeyler hem oldu hemde oldu.
Bu iş için şöyle bir fonksiyon yazdım.
void GLCD_Point(unsigned int x, unsigned int y, unsigned int size)
{
int pointx=0, pointy=0;
int angle, temp;
for(temp=1;temp<size+1;temp++)
{
for(angle=0;angle<360;angle++)
{
pointx = x + (temp * cos((pi * angle)/180));
pointy = y + (temp * sin((pi * angle)/180));
GLCD_PutPixel(pointx,pointy);
}
}
}
Çalıştı bu şekilde. Çember çizip içini doldurabiliyorum. Lakin bu kodlar çok yavaş çalıştı. Yani Size değerini 10 verirsem eğer ekranda bir dairenin çizilmesi 700-800 ms yi buluyor. Dairenin içinin dolduğunu görüyorum. TFT ekranda bunu yapmaya çalışıyorum. Kullandığım işlemci STM32, 64Mhz de çalıştırıyorum.
@mucit23 bir de bunu dener misin?
/**************************************************************************************************
* File name : graphic.c
* Programmer : jaruwit supa
* Web presence : [url=http://www.thaibestlink.com]www.thaibestlink.com[/url]
* Note : lcd graphic support
* Language : avrGCC
* Hardware : atmega16
* Date : 01/05/2009
************************************************************************************************/
/* _____STANDARD INCLUDES____________________________________________________ */
#include <avr/io.h>
#include <stdlib.h>
/* _____PROJECT INCLUDES_____________________________________________________ */
#include "graphic.h"
/* _____LOCAL DEFINE_________________________________________________________ */
/* _____LOCAL VARIABLES______________________________________________________ */
/* _____LOCAL FUNCTIONS______________________________________________________ */
/* _____PUBLIC FUNCTIONS_____________________________________________________ */
/*********************************************************************
* Function : void Line(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2)
* Description : Draw a line on a graphic LCD using Bresenham's
* PreCondition : SetColor()
* Input : x1,y1 - starting coordinates
* : x2,y2 - ending coordinates
* Output : none
* Note : none
********************************************************************/
void Line(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2)
{
signed int x, y, addx, addy, dx, dy;
signed long P;
int i;
/*
if (x1>x2)
{
dx = x1; x1 = x2; x2 = dx;
dy = y1; y1 = y2; y2 = dy;
}
// vertical line
if ((x1 == x2) || (y1 == y2))
{
FillRectangle(x1, y1, x2, y2);
return;
}
*/
dx = abs((signed int)(x2 - x1));
dy = abs((signed int)(y2 - y1));
x = x1;
y = y1;
addx = addy = 1;
if(x1 > x2)
addx = -1;
if(y1 > y2)
addy = -1;
if (dx >= dy)
{
P = 2L*dy - dx;
for (i=0; i<=dx; ++i)
{
DrawPixel(x, y);
if(P < 0)
{
P += 2*dy;
x += addx;
}
else
{
P += 2*dy - 2*dx;
x += addx;
y += addy;
}
}
}
else
{
P = 2L*dx - dy;
for(i=0; i<=dy; ++i)
{
DrawPixel(x, y);
if(P < 0)
{
P += 2*dx;
y += addy;
}
else
{
P += 2*dx - 2*dy;
x += addx;
y += addy;
}
}
}
}
/*********************************************************************
* Function : void Rectangle(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, unsigned int rad)
* Description : Draws a beveled figure on the screen.
* PreCondition: None
* Input : x1, y1 - coordinate position of the upper left center
* : x2, y2 - coordinate position of the lower right center
* : rad - defines the redius of the circle,
* Output : None
* Note : None
********************************************************************/
void Rectangle(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, unsigned int radius)
{
signed int a, b, P;
signed int bx, ay;
// adjust size
x1 = x1 + radius;
x2 = x2 - radius;
y1 = y1 + radius;
y2 = y2 - radius;
DrawRect(x1 , y1-radius, x2 , y1-radius); // top
DrawRect(x1 , y2+radius, x2 , y2+radius); // bottom
DrawRect(x1-radius, y1 , x1-radius, y2 ); // left
DrawRect(x2+radius, y1 , x2+radius, y2 ); // right
if (radius == 0)
return;
// draw broder
a = 0; // increment by 1
b = radius; // decrement by 1 using P
P = 1 - radius;
bx = b;
ay = a;
do
{
if (a && (a != b))
{
DrawPixel(x1-b, y1-a);
DrawPixel(x1-b, y2+a);
DrawPixel(x2+b, y1-a);
DrawPixel(x2+b, y2+a);
}
DrawPixel(x1-a, y1-b);
DrawPixel(x2+a, y1-b);
DrawPixel(x1-a, y2+b);
DrawPixel(x2+a, y2+b);
if(P < 0)
P+= 3 + 2*a++;
else
P+= 5 + 2*(a++ - b--);
} while(a <= b);
}
void RectangleFill(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, unsigned int radius)
{
signed int a, b, P;
signed int bx, ay;
if (radius == 0)
{
DrawRect(x1, y1, x2, y2);
return;
}
// adjust size
x1 = x1 + radius;
x2 = x2 - radius;
y1 = y1 + radius;
y2 = y2 - radius;
a = 0; // increment by 1
b = radius; // decrement by 1 using P
P = 1 - radius;
bx = b;
ay = a;
DrawRect(x1, y1-radius, x2, y2+radius);
do
{
if (bx != b)
{
DrawRect(x1-bx, y1-ay, x1-bx, y2+ay); // left in
DrawRect(x2+bx, y1-ay, x2+bx, y2+ay); // right in
bx = b;
}
ay = a;
if (a != b)
{
DrawRect(x1-a, y1-b, x1, y2+b); // left out
DrawRect(x2 , y1-b, x2+a, y2+b); // rigth out
}
if(P < 0)
P+= 3 + 2*a++;
else
P+= 5 + 2*(a++ - b--);
} while(a <= b);
if (bx != b)
{
DrawRect(x1-bx, y1-ay, x1-bx, y2+ay); // left in
DrawRect(x2+bx, y1-ay, x2+bx, y2+ay); // right in
}
}
/*********************************************************************
* Function : void Circle(unsigned int x, unsigned int y, unsigned int radius, unsigned char fill)
* Description : Draw a circle on the screen.
* PreCondition: None
* Input : x,y - the center of the circle
* : rad - defines the redius of the circle,
* : fill - fill yes or no
* Output : None
* Note : None
********************************************************************/
void CircleFill(unsigned int x, unsigned int y, unsigned int radius, unsigned char fill)
{
signed int a, b, P;
a = 0;
b = radius;
P = 1 - radius;
do
{
if(fill)
{
DrawRect(x-a, y+b, x+a, y+b);
DrawRect(x-a, y-b, x+a, y-b);
DrawRect(x-b, y+a, x+b, y+a);
DrawRect(x-b, y-a, x+b, y-a);
}
else
{
DrawPixel(a+x, b+y);
DrawPixel(b+x, a+y);
DrawPixel(x-a, b+y);
DrawPixel(x-b, a+y);
DrawPixel(b+x, y-a);
DrawPixel(a+x, y-b);
DrawPixel(x-a, y-b);
DrawPixel(x-b, y-a);
}
if(P < 0)
P+= 3 + 2*a++;
else
P+= 5 + 2*(a++ - b--);
} while(a <= b);
}
tabii uyarlaması sana kalmış.
Alıntı yapılan: bocek - 19 Mart 2013, 10:34:04
@mucit23 bir de bunu dener misin?
/**************************************************************************************************
* File name : graphic.c
* Programmer : jaruwit supa
* Web presence : [url=http://www.thaibestlink.com]www.thaibestlink.com[/url]
* Note : lcd graphic support
* Language : avrGCC
* Hardware : atmega16
* Date : 01/05/2009
************************************************************************************************/
/* _____STANDARD INCLUDES____________________________________________________ */
#include <avr/io.h>
#include <stdlib.h>
/* _____PROJECT INCLUDES_____________________________________________________ */
#include "graphic.h"
/* _____LOCAL DEFINE_________________________________________________________ */
/* _____LOCAL VARIABLES______________________________________________________ */
/* _____LOCAL FUNCTIONS______________________________________________________ */
/* _____PUBLIC FUNCTIONS_____________________________________________________ */
/*********************************************************************
* Function : void Line(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2)
* Description : Draw a line on a graphic LCD using Bresenham's
* PreCondition : SetColor()
* Input : x1,y1 - starting coordinates
* : x2,y2 - ending coordinates
* Output : none
* Note : none
********************************************************************/
void Line(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2)
{
signed int x, y, addx, addy, dx, dy;
signed long P;
int i;
/*
if (x1>x2)
{
dx = x1; x1 = x2; x2 = dx;
dy = y1; y1 = y2; y2 = dy;
}
// vertical line
if ((x1 == x2) || (y1 == y2))
{
FillRectangle(x1, y1, x2, y2);
return;
}
*/
dx = abs((signed int)(x2 - x1));
dy = abs((signed int)(y2 - y1));
x = x1;
y = y1;
addx = addy = 1;
if(x1 > x2)
addx = -1;
if(y1 > y2)
addy = -1;
if (dx >= dy)
{
P = 2L*dy - dx;
for (i=0; i<=dx; ++i)
{
DrawPixel(x, y);
if(P < 0)
{
P += 2*dy;
x += addx;
}
else
{
P += 2*dy - 2*dx;
x += addx;
y += addy;
}
}
}
else
{
P = 2L*dx - dy;
for(i=0; i<=dy; ++i)
{
DrawPixel(x, y);
if(P < 0)
{
P += 2*dx;
y += addy;
}
else
{
P += 2*dx - 2*dy;
x += addx;
y += addy;
}
}
}
}
/*********************************************************************
* Function : void Rectangle(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, unsigned int rad)
* Description : Draws a beveled figure on the screen.
* PreCondition: None
* Input : x1, y1 - coordinate position of the upper left center
* : x2, y2 - coordinate position of the lower right center
* : rad - defines the redius of the circle,
* Output : None
* Note : None
********************************************************************/
void Rectangle(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, unsigned int radius)
{
signed int a, b, P;
signed int bx, ay;
// adjust size
x1 = x1 + radius;
x2 = x2 - radius;
y1 = y1 + radius;
y2 = y2 - radius;
DrawRect(x1 , y1-radius, x2 , y1-radius); // top
DrawRect(x1 , y2+radius, x2 , y2+radius); // bottom
DrawRect(x1-radius, y1 , x1-radius, y2 ); // left
DrawRect(x2+radius, y1 , x2+radius, y2 ); // right
if (radius == 0)
return;
// draw broder
a = 0; // increment by 1
b = radius; // decrement by 1 using P
P = 1 - radius;
bx = b;
ay = a;
do
{
if (a && (a != b))
{
DrawPixel(x1-b, y1-a);
DrawPixel(x1-b, y2+a);
DrawPixel(x2+b, y1-a);
DrawPixel(x2+b, y2+a);
}
DrawPixel(x1-a, y1-b);
DrawPixel(x2+a, y1-b);
DrawPixel(x1-a, y2+b);
DrawPixel(x2+a, y2+b);
if(P < 0)
P+= 3 + 2*a++;
else
P+= 5 + 2*(a++ - b--);
} while(a <= b);
}
void RectangleFill(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, unsigned int radius)
{
signed int a, b, P;
signed int bx, ay;
if (radius == 0)
{
DrawRect(x1, y1, x2, y2);
return;
}
// adjust size
x1 = x1 + radius;
x2 = x2 - radius;
y1 = y1 + radius;
y2 = y2 - radius;
a = 0; // increment by 1
b = radius; // decrement by 1 using P
P = 1 - radius;
bx = b;
ay = a;
DrawRect(x1, y1-radius, x2, y2+radius);
do
{
if (bx != b)
{
DrawRect(x1-bx, y1-ay, x1-bx, y2+ay); // left in
DrawRect(x2+bx, y1-ay, x2+bx, y2+ay); // right in
bx = b;
}
ay = a;
if (a != b)
{
DrawRect(x1-a, y1-b, x1, y2+b); // left out
DrawRect(x2 , y1-b, x2+a, y2+b); // rigth out
}
if(P < 0)
P+= 3 + 2*a++;
else
P+= 5 + 2*(a++ - b--);
} while(a <= b);
if (bx != b)
{
DrawRect(x1-bx, y1-ay, x1-bx, y2+ay); // left in
DrawRect(x2+bx, y1-ay, x2+bx, y2+ay); // right in
}
}
/*********************************************************************
* Function : void Circle(unsigned int x, unsigned int y, unsigned int radius, unsigned char fill)
* Description : Draw a circle on the screen.
* PreCondition: None
* Input : x,y - the center of the circle
* : rad - defines the redius of the circle,
* : fill - fill yes or no
* Output : None
* Note : None
********************************************************************/
void CircleFill(unsigned int x, unsigned int y, unsigned int radius, unsigned char fill)
{
signed int a, b, P;
a = 0;
b = radius;
P = 1 - radius;
do
{
if(fill)
{
DrawRect(x-a, y+b, x+a, y+b);
DrawRect(x-a, y-b, x+a, y-b);
DrawRect(x-b, y+a, x+b, y+a);
DrawRect(x-b, y-a, x+b, y-a);
}
else
{
DrawPixel(a+x, b+y);
DrawPixel(b+x, a+y);
DrawPixel(x-a, b+y);
DrawPixel(x-b, a+y);
DrawPixel(b+x, y-a);
DrawPixel(a+x, y-b);
DrawPixel(x-a, y-b);
DrawPixel(x-b, y-a);
}
if(P < 0)
P+= 3 + 2*a++;
else
P+= 5 + 2*(a++ - b--);
} while(a <= b);
}
tabii uyarlaması sana kalmış.
Uyarlıyorum hocam. Yanlız çok eksiğim var. Sadece elimde plot(x,y) fonksiyonu var. Bunu kullanıp sizin verdiğiniz kodları benim yazılıma uyarlıyarak çember çizdim. Bayağıda hızlı çizdi.
Yanlız DrawRect fonksiyonuda lazım. Bunuda verebilirmisiniz. Veyahut başka hızlı çalışabilecek Rectangle fonksiyonuda olur.
seninkinden daha hızlı rectangle çizen bir algoritma olacağını zannetmiyorum. çünkü algoritma belli, sol üstten sağ üste çizgi çek, sağ üstten sağ alta vs.. diye gider. yine de vereyim kodları.
gerekli 'define' lar şöyle:
#define DrawRect(x1,y1,x2,y2) LCD_Rect(x1, y1, x2, y2, GetColor())
#define LCD_OPEN_WRITE() LCD_CLR_CS();\
LCD_SET_RS();
#define LCD_FAST_WRITE(val) LCD_SET_DBH((val)>>8); \
LCD_SET_DBL(val); \
LCD_CLR_WR(); \
LCD_SET_WR();
LCD_Rect ise şöyle (burda lcd'ye ve avr'ye özgü kodlar var. onları sen uyarlayacaksın.)
void LCD_Rect(unsigned int left, unsigned int top, unsigned int right, unsigned int bottom, unsigned int color)
{
register unsigned int x,y;
LCD_SetArea(left, top, right, bottom);
LCD_OPEN_WRITE(); // portlar çıkış olarak ayarlanıyor.
for(y=top; y<=bottom; y++)
{
for(x=left; x<=right; x++)
{
LCD_FAST_WRITE(color); // buraya senin lcd'ye yazma fonk gelecek
}
}
LCD_CLOSE();
LCD_SetArea(0, 0, GetMaxX(), GetMaxY());
}
avr işlemciler için olan kodların tamamını ve daha fazlasını şurda bulabilirsin:
sayfa: http://www.circuitidea.com/dev-board/BL-TFT240320PLUS-V2.html (http://www.circuitidea.com/dev-board/BL-TFT240320PLUS-V2.html)
direkt link: http://www.circuitidea.com/images/column_1259887831/CID.rar (http://www.circuitidea.com/images/column_1259887831/CID.rar)
ayrıca bir de Font editor written by H. Reddmann (http://www.circuitidea.com/images/column_1259887831/font.rar) programını öneririm.
Hocam hallettim.
Alıntı yapılan: Mucit23 - 19 Mart 2013, 10:07:14
Hocam yaptım birşeyler hem oldu hemde oldu.
Bu iş için şöyle bir fonksiyon yazdım.
void GLCD_Point(unsigned int x, unsigned int y, unsigned int size)
{
int pointx=0, pointy=0;
int angle, temp;
for(temp=1;temp<size+1;temp++)
{
for(angle=0;angle<360;angle++)
{
pointx = x + (temp * cos((pi * angle)/180));
pointy = y + (temp * sin((pi * angle)/180));
GLCD_PutPixel(pointx,pointy);
}
}
}
Mucit23 hocam bu kodun yavaş çalışması normaldir koruma önlemi almamışsınız yani temp=r ,angle=açı olmak üzere temp*cos((pi * angle)/180) sayısı birden çok kere aynı sayıyı gösterir mesela 3.75 ve 3.80 çıktı diyelim bunları direkt 3 e yuvarlar ve aynı bite 2 kez nokta atar hatta bu ara değerler çokça önünüze çıkar dolayısıyla bir önceki değerle karşılaştırma yaparak çizerseniz daha hızlı çalışırdı ama siz zaten çözdüğünüz için affınıza sığınarak bir not olarak buraya düşeyim dedim :)
Arkadaşlar merhaba.
Keilde yani c++ da Round komutunu nasıl kullanırım. Float bir değişkenim var. virgülden sonraki kısmı yok edip integer bir değişkene atmak istiyorum. Yani yuvarlama yapacağım..
resim.h içerisinde bulunan font1, font2, font3 gibi array sabitlerim mevcut. bu bilgileri ben
avl=font1[*s-32]; ile alıp avl nin içerisine atıyorum.
buradaki font1 i nasıl olurda parametreye bağlarım ?
örneklemek istersem
fonksiyon(falan, filan, char fontName)
{
......falan filan....
......kod mod.....
avl=fontName[*s-32];
}
nasıl yaparım ?
Alıntı yapılan: muhittin_kaplan - 28 Mart 2013, 20:15:34
resim.h içerisinde bulunan font1, font2, font3 gibi array sabitlerim mevcut. bu bilgileri ben
avl=font1[*s-32]; ile alıp avl nin içerisine atıyorum.
buradaki font1 i nasıl olurda parametreye bağlarım ?
örneklemek istersem
fonksiyon(falan, filan, char fontName)
{
......falan filan....
......kod mod.....
avl=fontName[*s-32];
}
nasıl yaparım ?
Hocam parametre olarak pointer'ı (işaretçiyi) atın. Zaten fontName[*s-32] gibi bir kullanım için fontName 'in dizi ya da işaretçi olması gerekir.
fonksiyon(falan, filan, char *fontName)
{
......falan filan....
......kod mod.....
avl=fontName[*s-32];
}
şeklinde mi
font1[][32]{{1,2,3,4,5},{10,11,12,13}}
font2[][16]{{A,B,C,D,E},{Z,X,Y,T}}
font3[][8]{{#, $,&,,(,)},{H,K,M,L}}
fonksiyon(falan, filan, char fontName)
{
......falan filan....
......kod mod.....
avl=fontName[*s-32];
}
ne yaptıysam beceremedim. parametre olarak adresi de gönderdim. ama yukardaki fonksiyonla olmayacak gibi.
Alıntı yapılan: M_B - 25 Ekim 2011, 00:07:42
Hocam return() yazmanın bize ne tur bir avantajı olurki. Benim duşuncem hiç bir faydası olmayacağı yonunde.
Program ana donguye (main) girdimi daha cıkmayacaktır. cıksa bile gittiği yerden geri donecektir. Tabi gittiği yerde kısır donguye girmediyse.
Bayağı bir eski mesaj ama cevapsız kalmış galiba.
int main() fonksiyonunun geri dönüşü int tanımlandığı için programın sonunu return(xxx) gibi bir komutla sonlandırmak, main satırından hiç çıkılmayacak olsa bile önemlidir. (En azından derlemede warning mesajı oluşumunu engeller.)
Öte yandan main fonksiyonunu çağıran startup kodun içine bir kaç satır ekleyip eğer main satırından istem dışı çıkıldı ise bunun farkına varıp kontrolu elinizde tutabilirsiniz.
C nispeden düşük seviyeli bir dildir. Stackdan kafanıza göre bir şeyler çekmenizin yolu açıktır. Stack pointer üzerinde yanlış manuplasyon yapıldığında mainden çıkabilirsiniz ve programınız crash olur.
Main rutininden çıkışta hata kodu göndermek özellikle işletim sistemi yada kontrol mekanizmaları üzerinde koşturulan platformlarda kullanılan bir yöntemdir.
Emin değilim ama C de adamlar manin fonksiyonuna int değerle geri dönüşü şart koştularda mainden çıkıldığında koşacak bir standart isimde bir fonksiyon da
isteğe bağlı kullanılıyor olabilir.
Hocalarım swicth case kullanmadan
Alıntı Yapconst unsigned char font1[][12]={ //8x10
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // <Space>
{0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00}, // !
{0x00,0x28,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // "
{0x00,0x00,0x28,0x28,0xFC,0x28,0x50,0xFC,0x50,0x50,0x00,0x00}, // #
.......
.......
const unsigned char font2[][16]={//8x16
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/
{0x00,0x00,0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00},/*"!",1*/
{0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*""",2*/
{0x00,0x00,0x00,0x00,0x36,0x36,0x7F,0x36,0x36,0x36,0x7F,0x36,0x36,0x00,0x00,0x00},/*"#",3*/
........
.........
const unsigned char font3[][32] ={ //16*16 pixel
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // <Space>
{0x00,0x00,0x00,0x00,0x07,0x00,0x0F,0x80,0x0F,0x80,0x0F,0x80,0x0F,0x80,0x0F,0x80,0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x00,0x00}, // !
{0x00,0x00,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x06,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // "
gibi tablolardan "benim seçimime" göre nasıl bilgi alırım ?
Kullandığım fonksiyon aşağıda, string i parametre olarak gönderemedim. (Bilgisayardan alışkanlık ya), adresini göndermeye çalıştım beceremedim
paramatreye bağlı olacak bir yapı kurmam gerek.
Alıntı Yapvoid LCD_write_String(unsigned char startX, unsigned int startY, unsigned char *s,unsigned int color,unsigned int xcolor)
{
unsigned char avl,i,n;
LCD_CS(0);
while (*s)
{
LCD_Set_Window(startX,startY,startX+7,startY+15); // DEĞİŞİCEK
LCD_WR_REG8(0x22);
for(i=0;i<16;i++) //DEĞİŞECEK
{
avl=font2[*s-32]; //DEĞİŞECEK
for(n=0;n<8;n++)
{
if(avl & 0x80) LCD_WR_DATA16(color);
else LCD_WR_DATA16(xcolor);
avl<<=1;
}
}
startX=startX+13;//DEĞİŞECEK
s++;
}
LCD_CS(1);
}
@Kaplan
Aşağıdaki örneğe bakabilirsin.
const unsigned char Data[]={1,2,3};
void SystemInit()
{
}
unsigned char fonk(const unsigned char *d)
{
d++; // Laf olsun diye adımladık
return(*d); // Bu adımdaki değeri okuduk
}
int main()
{
volatile unsigned char a;
a=fonk(Data);
}
Alıntı yapılan: muhittin_kaplan - 29 Mart 2013, 14:58:04
Hocalarım swicth case kullanmadan
gibi tablolardan "benim seçimime" göre nasıl bilgi alırım ?
Kullandığım fonksiyon aşağıda, string i parametre olarak gönderemedim. (Bilgisayardan alışkanlık ya), adresini göndermeye çalıştım beceremedim
paramatreye bağlı olacak bir yapı kurmam gerek.
muhittin hocam;
bu işlemi ne icin kullanacaksınız ?
Aslında ne yapmak istediginizi anlamadığım için soruyorum.
font değişimi için hocam. parametre verecegim.
fonksiyon(x,y,"HelloWrd", Font1) gibi.
swic le uğraşmayayım dedim olay daha başka yerlere gitti.
Dogru tahmin etmişim.
Hocam
stm322xg_eval_lcd.c ve stm322xg_eval_lcd.h kutuphanelerini incelediniz mi ?
Ornek kullanımı aşağıda.
fontu değiştirmek icin
LCD_SetFont(&Font12x12); fonksiyonunu cagıracaksınız.
LCD_SetFont(&Font12x12);
LCD_SetTextColor(LCD_COLOR_GREEN);
LCD_SetBackColor(LCD_COLOR_BLACK);
LCD_DisplayStringLine(LINE(1), (uint8_t *)MESSAGE1);
LCD_SetFont(&Font8x12);
LCD_SetTextColor(LCD_COLOR_BLACK);
LCD_DisplayStringLine(135," Versiyon: v1.0.1 ");
mesaj birleştirme:: 30 Mart 2013, 15:36:07
+ hocam onları incelerken fonts.c ve fonts.h da inceleyin. Orda tanımlanmış yapılar var.
Alıntı Yap
gibi tablolardan "benim seçimime" göre nasıl bilgi alırım ?
Kullandığım fonksiyon aşağıda, string i parametre olarak gönderemedim. (Bilgisayardan alışkanlık ya), adresini göndermeye çalıştım beceremedim
paramatreye bağlı olacak bir yapı kurmam gerek.
Stringin adresini fonksiyona nasıl göndereceğini ve fonksiyonda da bu adresdeki stringin bileşenlerine pointer üzerinden nasıl ulaşacağının yolunu göstermiştik halbuki.
Fonksiyona fontun adresini yollayacaksın.
Niye kiziyon ki.
Pointer i biliyorum. Fonksiyona da parametre olarak gonderiyorum. Ama tablo cift olunca yapamadim.
Hocam inceledim. Font ceviriciler tek sutunlu tablo hazirliyordu ben sonrasinda degistiriyordum. Simdi adresi alip satiri hesaplayip basacagim karakteri. Yani anlayacagin tek sutunlu bir array la yapacagim.
İlginize tesekkur ederim. Z kizdi biraz ama :)
void degerYaz (unsigned char *s,char *fontName)
{
int loop;
char a;
char *startPoint;
a=(*s-32);
startPoint=fontName+(a*12);//font uzunlugu=12byte
char deger;
for (loop = 0; loop < 12; ++loop) {
deger=*startPoint++;
if (deger!=0) {
deger=1;
}
}
}
sanırım yukardaki olur.
Hala kızıyorum. Array'ın başlangıç adresini yolladıktan sonra arrayin kaç boyutlu olduğunun önemi varmı?
yok.
Hocam neden var? Arrayın boyutunu da uzunluğunu da biliyorsun adresini de.
Hocam çift yada tek olsun, hafızada ardışık olarak durmuyormu ?
"
Bu aralar kalın kafalığım üzerimde, yada "iğhtiyarlıyoruz zannımca"
coşkun zaman ayırdı anlattı, ama problem bende az et yiyorum bu aralar herhalde.
aşağıdaki gibi bir yapım var.
(http://img266.imageshack.us/img266/5411/3103.png)
peki neden main.c de
LCD_write_String(10,20,"DENEME YAZISI",MAVI,BEYAZ,font1);
dediğimde font1 bulunamadı diyor.
Olayı Baştan Anlatırsanız daha çok sevinirim
Hocam dikkat edin #include (başlık dosyalarının dahil edilmesi) ağacı gösterdiğiniz şekilde değil.
Main.c, Main.h'yi içeriyor.
Main.h, ili9325.h'yi içeriyor.
-- SON --
ili9325.c, ili9325.h'yi içeriyor.
ili9325.c, englishFont.h'yi içeriyor.
ili9325.h, englishFont.h'yi içermiyor.
Degil derken hatali yani. Bu isin mantigi nedir
(Cepten bagliyim bu arada)
Mantığı basit hocam. Preprocessor yani önişlemci denen mekanizma, #include gibi içermeleri ve #define, #ifndef gibi ifadeleri çözümlüyor. Dahil etme (include) için yaptığı tek şey belirtilen dosyanın içeriğini alıp, #includue "xxx.h" satırının yerine koyuyor.
Bu işlemin sonucunu gcc'de -E parametresi ile görebilirsiniz.
Örnek C dosyası:
#include "kod.h"
int kod(){
myStruct yapi1;
yapi1.a = 10;
yapi1.b = 20;
}
H dosyası:
#ifndef KOD_H
#define KOD_H /* özyinelemeden koru */
typedef struct {
int a;
short b;
} myStruct;
#endif
gcc -E kod.c çıktısı:
# 1 "kod.c"
# 1 "<command-line>"
# 1 "kod.c"
# 1 "kod.h" 1
typedef struct {
int a;
short b;
} myStruct;
# 2 "kod.c" 2
int kod(){
myStruct yapi1;
yapi1.a = 10;
yapi1.b = 20;
}
Gördüğünüz gibi header başlık dosyası önişlendikten sonra doğrudan yerine yerleştirildi. Ve bu olay karşılıklı değil.
Yani kod.h dosyasında tanımladığım bir şeye kod.c den erişebilirim. Ancak kod.c de tanımladığım birşeye kod.h'den erişemem.
Bunun için main.c dosyasından başlayarak kağıt ve kalem eşliğinde :) bir include ağacı oluşturun. Yapmanız gereken tek şey dahil edeni üste, dahil edileni de dallanarak altına yazmak.
Bu şekilde sorunu çözebilirsiniz, kolay gelsin, iyi çalışmalar hocam...
derleme esnasında birkaçtane uyarı alıyorum ?
warning: pointer targets in passing argument 3 of 'LCD_write_String' differ in signedness [-Wpointer-sign]
Alıntı yapılan: muhittin_kaplan - 06 Nisan 2013, 14:32:26
derleme esnasında birkaçtane uyarı alıyorum ?
warning: pointer targets in passing argument 3 of 'LCD_write_String' differ in signedness [-Wpointer-sign]
Hocam parametre olarak belirtilen tip ile gönderilen tip işaret bakımından farklı diyor. Yani örneğin fonksiyonu:
void foo(int *p)
gibi tanımladınız kullanırken:
unsigned int *p1 = 0xDEADC0DE;
foo(p1);
yaptınız. Dolayısıyla işaret farkı oluyor. explicit olarak atayabilirsiniz ya da işaretleri kontrol edin.
Selamlar.C diline hakim değilim.Bir konuda sıkıntı yaşıyorum.Normalde bir fonksiyona parametre girişi yapabiliyoruz.Bunu biliyorum ancak parametreleri öteleme komutuyla nasıl giriyoruz onu anlamadım.
Send(unsigned int8 WriteAddress, unsigned int8 SendByte , unsigned int8 DeviceAddress)
{}
Şeklinde bir fonksiyonum var.Ancak bu fonksiyonu başka bir yerde şöyle çağırmış;
Send( (s_data >> 8) & 0xFF ,s_data & 0xFF , ADDR_WM8731S) );
Benim anlamadığım her parametre için bir sürü işlem yaptırmış bu nasıl oluyor?Mesela s_data için fonk. çağırıldığında sağa sekiz ötelemiş bir de kalkıp 0xff ile andlemiş.Bunu hangi sıralamayla yapıyor?Yani s_data nın ilk değer örneğin dec 1 olsun. (0x01 aynı şey.)
Send((0x01>>8)& 0xff,x,x)
Şimdi 0x01 önce sekiz kez sağa ötelenip bir değer oluşturulacak doğru mu?Bu da 0 olacak.Bunu 0xff ile and yaparsak 0x00 olacak.Yani fonksiyon işlenmeye başladığında s_data nın değeri 0x00 olmuş olacak doğru mu?
Fonksiyonun tamamı;
{
unsigned int i2c_state= I2C_Start();
if(!(i2c_state))
return DISABLE;
I2C_SendByte(DeviceAddress & 0xFF);
if(!I2C_WaitAck()){I2C_Stop(); return DISABLE;}
I2C_SendByte( WriteAddress );
I2C_WaitAck();
I2C_SendByte(SendByte);
I2C_WaitAck();
I2C_Stop();
return ENABLE;
}
Alıntı yapılan: yldzelektronik - 15 Nisan 2013, 15:20:19
Selamlar.C diline hakim değilim.Bir konuda sıkıntı yaşıyorum.Normalde bir fonksiyona parametre girişi yapabiliyoruz.Bunu biliyorum ancak parametreleri öteleme komutuyla nasıl giriyoruz onu anlamadım.
Send(unsigned int8 WriteAddress, unsigned int8 SendByte , unsigned int8 DeviceAddress)
{}
Şeklinde bir fonksiyonum var.Ancak bu fonksiyonu başka bir yerde şöyle çağırmış;
Send( (s_data >> 8) & 0xFF ,s_data & 0xFF , ADDR_WM8731S) );
Benim anlamadığım her parametre için bir sürü işlem yaptırmış bu nasıl oluyor?Mesela s_data için fonk. çağırıldığında sağa sekiz ötelemiş bir de kalkıp 0xff ile andlemiş.Bunu hangi sıralamayla yapıyor?Yani s_data nın ilk değer örneğin dec 1 olsun. (0x01 aynı şey.)
Send((0x01>>8)& 0xff,x,x)
Şimdi 0x01 önce sekiz kez sağa ötelenip bir değer oluşturulacak doğru mu?Bu da 0 olacak.Bunu 0xff ile and yaparsak 0x00 olacak.Yani fonksiyon işlenmeye başladığında s_data nın değeri 0x00 olmuş olacak doğru mu?
Fonksiyonun tamamı;
{
unsigned int i2c_state= I2C_Start();
if(!(i2c_state))
return DISABLE;
I2C_SendByte(DeviceAddress & 0xFF);
if(!I2C_WaitAck()){I2C_Stop(); return DISABLE;}
I2C_SendByte( WriteAddress );
I2C_WaitAck();
I2C_SendByte(SendByte);
I2C_WaitAck();
I2C_Stop();
return ENABLE;
}
Hocam neticede bu dilleri de insanlar oluşturdu. Dolayısıyla derleyiciler de insan mantığı gibi çalışıyor. İfadeler genellikle içten dışa doğru ayrıştırılıyor.
Bir ifadenin parametre verirken çağrılmasının normalden hiçbir farkı yok.
(s_data >> 8) & 0xFF
Bu sık kullanılan bir aritmetik ifadedir. s_data'nın 8.bitinden başlayan bir byte'ı ayıklamak için kullanılır.
Parantezlere bakılırsa önce s_data 8 bit sağa kaydırılır, sonra 0xFF ile 've' işlemi uygulanır. Elde edilen sonuç yığıta basılır. Fonksiyon bu değeri parametre olarak kullanır.
Karmaşıklık açısıdan şu da mümkündür:
((t<<1)^((t<<1)+(t>>7)&t>>12))|t>>(4-(1^7&(t>>19)))|t>>7
Bunu alıp iç içe iki fonksiyona parametre gönderebilirsiniz. Hatta parametre gönderiken cast ile atama bile yapabilirsiniz, size kalmış :)
Aslinda olay parse etmek yani 16 bit verinin yüksek bitlerine ulaşmak. (bu işem için bir diğer yöntemde 2 nin katlarina bölmektir) Bir int. veriyi 8 kez ötelerseniz yüksek baytini küçüğe yüklersiniz. 0xFF ile andlemek ise küçük baytın dışındaki hiçbir biti alma demek anlamına geliyor. Değişkenler ram adresi olunca ve 8, 16, 32 bit belleklere sahipse veride istenilen kısımlarına ulaşmak için bu kaydırmalar kullanılıyor.
Aşağıda ki gibi bir döngüde pow() fonksiyonu düzgün çalışmıyor şöyle ki;
for (index=0;index<6;index++){
y=index*(pow(10,index));
k=k+y;
}
y değişkenine debug ile bakınca mesela index=2 olunca 200 döneceğine 199 dönüyor sebebini çözemedim.
Casting'le ilgili olabilir, pow fonksiyonu double döndürmüyor mu?
float integer dönüşümünden kaynaklanıyor gibi geldi bana da....
O zaman daha ilginç birşey söyleyeyim döngü yapmadan
2*pow(10,2) kullanınca temiz 200 veriyor bende castingde düşünümüştüm en başta ama bu daha da kafamı karıştırdı.
Fonksiyon lazım olduğundan değilde merak uyandırdı böyle olması.
int x=4,y,index,k=0,m=0,sayi=3;
char degisken[]="123";
for (index=0;index<sayi;index++){
k+=(degisken[index]-0x30)*pow(10.00,index);
}
m=1*pow(10,0)+2*pow(10,1)+3*pow(10,2);
printf("\nk=%d m=%d",k,m);
system("pause");
}
Bu kodla k=320 çıkıyor. m=321 çıkıyor :)
Alıntı yapılan: AsHeS35 - 14 Mayıs 2013, 13:15:52
Aşağıda ki gibi bir döngüde pow() fonksiyonu düzgün çalışmıyor şöyle ki;
for (index=0;index<6;index++){
y=index*(pow(10,index));
k=k+y;
}
y değişkenine debug ile bakınca mesela index=2 olunca 200 döneceğine 199 dönüyor sebebini çözemedim.
hocam y'nin ve indexin ne şekilde tanımlandığına bağlı galiba. c++ da pow fonksiyonunu parametrelerini şu linkte açıklamış. http://www.cplusplus.com/reference/cmath/pow/ (http://www.cplusplus.com/reference/cmath/pow/)
buna göre ben ufak bir deneme yaptım. y'yi double tanımladığım zaman doğru çalışıyor ancak integer tanımladığım zaman hatalı sonuç veriyor
C'de 24 bitlik bir değişken tanımlayabiliyormuyuz? Ramda 3 x 8 byte yer kaplayacak. (!!!! 32 bit değil !!!)
Yada 40 bit değişken tanımlayabiliyormuyuz?
unsigned short long int XC8 derleyicisinde 24-bit değişkeni tanımlamada kullanılıyor. 40 bit için structtan başka bir yol düşünemedim (8-bit için).
hem 24 bit hem 40 bit tanımlayabiliriz bir structın içinde mesela struct içinde bir adet unsigned short long int ve 5 adet unsigned char ile __packed anahtar sözcüğü ile yapılabilir gibi z hocam (32 bit için).
24+16 veya 32+8 şeklindede kombine edilebilir 40 bit sayımız.
Örneğin 24 bitlik i değişken tanımlayabileyim ve i++; şeklinde kullanabileyim isterim. (32 Bit tanımla gitsin cevap olmayacak)
microchipin generictypedef.h dosyasında adam şöyle birşey tanımlamış
/* 24-bit type only available on C18 */
#if defined(__18CXX)
typedef union
{
UINT24 Val;
UINT8 v[3] __PACKED;
struct __PACKED
{
UINT8 LB;
UINT8 HB;
UINT8 UB;
} byte;
struct __PACKED
{
__EXTENSION UINT8 b0:1;
__EXTENSION UINT8 b1:1;
__EXTENSION UINT8 b2:1;
__EXTENSION UINT8 b3:1;
__EXTENSION UINT8 b4:1;
__EXTENSION UINT8 b5:1;
__EXTENSION UINT8 b6:1;
__EXTENSION UINT8 b7:1;
__EXTENSION UINT8 b8:1;
__EXTENSION UINT8 b9:1;
__EXTENSION UINT8 b10:1;
__EXTENSION UINT8 b11:1;
__EXTENSION UINT8 b12:1;
__EXTENSION UINT8 b13:1;
__EXTENSION UINT8 b14:1;
__EXTENSION UINT8 b15:1;
__EXTENSION UINT8 b16:1;
__EXTENSION UINT8 b17:1;
__EXTENSION UINT8 b18:1;
__EXTENSION UINT8 b19:1;
__EXTENSION UINT8 b20:1;
__EXTENSION UINT8 b21:1;
__EXTENSION UINT8 b22:1;
__EXTENSION UINT8 b23:1;
} bits;
} UINT24_VAL, UINT24_BITS;
#endif
Alıntı yapılan: jackal183 - 18 Haziran 2013, 10:20:58
microchipin generictypedef.h dosyasında adam şöyle birşey tanımlamış
/* 24-bit type only available on C18 */
#if defined(__18CXX)
typedef union
{
UINT24 Val;
UINT8 v[3] __PACKED;
struct __PACKED
{
UINT8 LB;
UINT8 HB;
UINT8 UB;
} byte;
struct __PACKED
{
__EXTENSION UINT8 b0:1;
__EXTENSION UINT8 b1:1;
__EXTENSION UINT8 b2:1;
__EXTENSION UINT8 b3:1;
__EXTENSION UINT8 b4:1;
__EXTENSION UINT8 b5:1;
__EXTENSION UINT8 b6:1;
__EXTENSION UINT8 b7:1;
__EXTENSION UINT8 b8:1;
__EXTENSION UINT8 b9:1;
__EXTENSION UINT8 b10:1;
__EXTENSION UINT8 b11:1;
__EXTENSION UINT8 b12:1;
__EXTENSION UINT8 b13:1;
__EXTENSION UINT8 b14:1;
__EXTENSION UINT8 b15:1;
__EXTENSION UINT8 b16:1;
__EXTENSION UINT8 b17:1;
__EXTENSION UINT8 b18:1;
__EXTENSION UINT8 b19:1;
__EXTENSION UINT8 b20:1;
__EXTENSION UINT8 b21:1;
__EXTENSION UINT8 b22:1;
__EXTENSION UINT8 b23:1;
} bits;
} UINT24_VAL, UINT24_BITS;
#endif
Hocam adamlar zaten halihazırda UINT24 tipini kullanmışlar. Sadece C18 de mevcut demişler...
Benim sorum basittir.
struct birlik
{
int *a;
int *b;
float *c;
};
typedef struct birlik ADC;
diye bir tanımlama yaptim.Oluşturulan sınıftaki değişkenlere değer nasıl veriliyor ? İlk değer ve fonksyon içerisinde kullanmaya yönelik ?
Teşekkürler..
int x,y;
float z[10];
typedef struct
{
int *a;
int *b;
float *c;
}birlik;
birlik ADC = { &x, &y, z};
Doğrudan Ulaşamıyormuyuz ?
Alıntı yapılan: Fkarizmatik - 18 Haziran 2013, 17:43:44
Benim sorum basittir.
struct birlik
{
int *a;
int *b;
float *c;
};
typedef struct birlik ADC;
diye bir tanımlama yaptim.Oluşturulan sınıftaki değişkenlere değer nasıl veriliyor ? İlk değer ve fonksyon içerisinde kullanmaya yönelik ?
Teşekkürler..
Değişken gruplamaktan bahsediyorsanız c++ da böyle kullanılıyor
struct birinci_grup {
int ilk_sayi;
int ikinci_sayi;
};
int main()
{
struct birinci_grup, hesapla;
hesapla.ilk_sayi=5;
hesapla.ikinci_sayi=10;
}
Alıntı yapılan: muhittin_kaplan - 19 Haziran 2013, 13:08:16
Doğrudan Ulaşamıyormuyuz ?
soruyu tam anlamadım?
sorduğun doğrudan ulaşma şöyle bir şey mi
struct MyStruct
{
int a;
int b;
int c;
} = { 1,2,3}
bu şekilde de tip tanımı yapmadan , doğrudan yapıyı tanımlayıp erişebilirsiniz.
Alıntı yapılan: Klein - 19 Haziran 2013, 18:46:51
soruyu tam anlamadım?
sorduğun doğrudan ulaşma şöyle bir şey mi
struct MyStruct
{
int a;
int b;
int c;
} = { 1,2,3}
bu şekilde de tip tanımı yapmadan , doğrudan yapıyı tanımlayıp erişebilirsiniz.
Klein hocam bazı derleyiciler int* a yaptığımızda bildiğimiz gibi a yı kullanılır halde vermiyorlar yani;
int* a;
(*a)=5;
//Burada hata verir ama bazıları pointerı tanıttığınız anda ona kendine ait adres alanı atayabiliyor.
Adres vermeyip hata veren derleyici(ben standardı bu diye biliyorum) Dev-C++ altında ki gcc derleyicisi, tanımlayıp adres atayan derleyici Keil UV4 altında C51 derleyicisi açıkçası C51 ile yapılan sağlıklı çalışır mı emin değilim.
Yani @muhittin_kaplan ın sorusu şudur bence
struct MyStruct eleman;
*(eleman.a)=5;
yapamayacak mıyız sorusudur.Bence derleyiciye göre değişir.
struct MyStruct
{
int *a;
int *b;
float *c;
};//olarak planlanmıştır.
...
birlik ADC = { &x, &y, z};
dedikten sonra yapabilirsiniz.
Pointer'ı tanıttığımızda otomatik olarak bir adrese işaret etmesini ilk defa duydum, neden böyle bir şey yapsın ki?
Arkadaşın sorusu yapıya ilk değer vermekti. Kullandığı örnekte pointer olduğu için ona göre cevap verdim.
neden gerekebilir?
Herhangi bir değişkene neden ilk tanımladığımızda değer veriyorsak aynı sebepten.
Alıntı yapılan: Klein - 19 Haziran 2013, 21:22:20
Arkadaşın sorusu yapıya ilk değer vermekti. Kullandığı örnekte pointer olduğu için ona göre cevap verdim.
neden gerekebilir?
Herhangi bir değişkene neden ilk tanımladığımızda değer veriyorsak aynı sebepten.
Ben doğrudan ulaşamaz mıyız sorusuna cevaben yazmıştım Klein hocam yoksa size saygımız sonsuz :) .
sanki ortalığı biraz karıştırmışım.
struct tarih {
int gun;
int ay;
int yil;
} dogum = {22,12,1991};
ile hepsine birden ulaşıyorsunuz. Benim sorduğum (c# ve vb den kalma alışkanlıkla) ise aşağıdaki çözümdü
struct tarih {
int gun, yil, ay;
} dogum;
dogum.gun = 22;
dogum.ay = 12;
dogum.yil = 1991;
Şöyle diyeyim;
#include<stdio.h>
int main( void )
{
int i;
// Dogum tarihi tutmak icin
// 'dogum_tarihi' adinda bir yapi
// olusturuyoruz
struct dogum_tarihi {
int gun;
int ay;
int yil;
};
// Kisiye ait bilgileri tutmak
// icin 'sahis_bilgileri' adinda
// bir yapi kuruluyor.
struct sahis_bilgileri {
char isim[40];
int boy;
struct dogum_tarihi tarih;
};
// Dizi elemanlarina ilk deger atamasi yapiyoruz.
struct sahis_bilgileri kisi[3] = { "Ali", 170, { 17, 2, 1976 },
"Veli", 178, { 14, 4, 1980 },
"Cenk", 176, { 4, 11, 1983 } };
Yapı dizisini ekrana nasıl yazdıracağım ?
boy isimli integer değişkenini nasıl yazdırıyorsanız kisi[0].boy'u da aynı şekilde yazdırabilirsiniz. Structure'ın içinde olunca integer'lığından bir şey kaybetmiyor :). (bkz:o kadar strong bir presence var ki (http://eksisozluk.com/o-kadar-strong-bir-presence-var-ki--792439))
Alıntı yapılan: muhittin_kaplan - 20 Haziran 2013, 09:42:57
sanki ortalığı biraz karıştırmışım.
struct tarih {
int gun;
int ay;
int yil;
} dogum = {22,12,1991};
ile hepsine birden ulaşıyorsunuz. Benim sorduğum (c# ve vb den kalma alışkanlıkla) ise aşağıdaki çözümdü
struct tarih {
int gun, yil, ay;
} dogum;
dogum.gun = 22;
dogum.ay = 12;
dogum.yil = 1991;
Hocam son verdiğiniz kod parçasında atamalar nerede yapılıyor? Global section'da yapamazsınız. İllâ ki bir fonksiyon içinde olması lazım.(C için)
Ya da constructor yani yapıcı fonksiyonlardan mı bahsediyorsunuz?
C#'ta
private struct Tarih
{
public int Gun;
public int Ay;
public int Yil;
public Tarih()
{
Gun = 20;
Ay = 6;
Yil = 2013;
}
}
Eğer kastettiğiniz bu ise bu özellik C de yok. Yapıcı/ilklendirici fonksiyonlar aslında C++ ile class/sınıflarda vardır. C++ ile struct'ın sınıftan pek farkı kalmadığından C# ta bundan etkilenmiştir.
Struct belleğe yüklenirken .ctor yani yapıcı fonksiyonu çağrılır. Sizin verdiğiniz ilk değerler debir fonksiyon ile yerine aktarılır.
dogum.gun = 22;
dogum.ay = 12;
dogum.yil = 1991;
Hocam tabiki bir fonksiyonda yazılması gerekir. örnek olması açısından yapıştırmıştım.
değişik bir yapı gördüm yada bana öyle geldi.
zavazing.h içerisinde
typedef struct {
int a;
int b;
int c;
int d;
} DenemeData;
var.
abidikgubidik.c de
DenemeData Bilgiler;
var. Buradan Anlamam Gereken Şu mudur ?
Oluşturulmuş DenemeData Adındaki tipim e Bu dosyanın içerinde Bilgiler Olarak Ulaşacağım. Örneğin Bilgiler.a, Bilgiler.b gibi
Evet aynen öyle. Daha doğrusu şöyle.
Header içinde DenemeData isimli yeni bir tip tanımladın. .C programı içinde de bu tipten bir değişken yarattın.
Ama neden değişik geldi anlamadım. Son zamanlarda STM32'nin kütüphane dosyalarında onlarca kez gördün ve kullandın.
Kütüphanedekiler pointer olarak tanımlandığı için "x.y" şeklinde değil "x->y" şeklinde ulaştın.
Ne bileyim Garip Geldi. (Uzun Zamandır Kod Yazmıyorum Ondandır.)
kafama takılan yeri şimdi daha iyi anladım.
DenemeData Bilgiler
ile nasıl bir tanımlama yapıyor?
int a deken a nın integr olduğunu anlıyourm.buradaki denemeData bir tip olduğu için aslında "kendim oluşturduğum" bir data type ı tanımlamış oluyorum değil mi ?
Evet. Aynen öyle.
benimde bir sorum olsun :)
ilkin c++ ile programlama yapan arkadaslar visual (görsel) kismi naasil hallediyorsunuz ? qt ilemi?
ikincisi asagidaki program parcasi tam ollarak ne yapar ?
g_pHF->SetAndCheckMotorOutputs(DF_MIN_MOT_CURRENT_TEST1, DF_MAX_MOT_CURRENT_TEST1, DF_TOLERANCE_MOT_CURRENT_TO_REAL_TEST1);
DF ile baslayanalr include da tanimlanmis sabit degerler ama benim anlamadiigm nokta bu basdaki g_pHF -> parcasi ne yapar ? sanirim bu OOP ile ilgili olsa gerek (OOP: objekt oriented programing)
Yanlış olabilir uzman hocalarım daha doğru cevabı verecektir ama benim bildiğim kadarını söyleyeyim.
g_pHF isimli (struct)yapının içinde tanımlı SetAndCheckMotorOutputs() fonksiyonuna ulaşmış.
Büyük harfle yazılanlarda bu fonksiyona aktarılan parametreler.
Peki fonksiyon bir struct içindeyse neden
g_pHF.SetAndCheckMotorOutputs(......);
şeklinde yazmadık ta nokta yerine -> işarti kullandık diye soracak olursan bu da bildiğim kadarıyla başka bir dosya da tanımlanmış olan yapılara erişmek için kullanılan bir C ifadesi.
-> işareti struct'ın pointerı değil mi?
Hocam C++ ta sınıf(class) lara ait pointerlar var. Bu sınıfların fonksiyonlarına da pointer'la ulaşabiliyorsunuz. (Tabi struct için de aynısı geçerli)
Alıntı yapılan: z - 17 Haziran 2013, 20:23:33
Örneğin 24 bitlik i değişken tanımlayabileyim ve i++; şeklinde kullanabileyim isterim. (32 Bit tanımla gitsin cevap olmayacak)
Böyle bir kurguyu ancak C++ da veya daha üst versiyon dillerde yapabilirsiniz.
Örneğin C++ da bununla ilgi bir sınıf(class) yazarsınız sonrada bu sınıflara operator overloading fonksiyonlarını yazarsanız istediğiniz olur. Ama bunu sınıf içinde 3 byte veri bile tutsa sınıfın kendi boyutu 3 byte fazla olur.
mesaj birleştirme:: 05 Temmuz 2013, 06:46:09
Alıntı yapılan: teknikelektronikci - 04 Temmuz 2013, 17:29:51
benimde bir sorum olsun :)
ilkin c++ ile programlama yapan arkadaslar visual (görsel) kismi naasil hallediyorsunuz ? qt ilemi?
ikincisi asagidaki program parcasi tam ollarak ne yapar ?
g_pHF->SetAndCheckMotorOutputs(DF_MIN_MOT_CURRENT_TEST1, DF_MAX_MOT_CURRENT_TEST1, DF_TOLERANCE_MOT_CURRENT_TO_REAL_TEST1);
DF ile baslayanalr include da tanimlanmis sabit degerler ama benim anlamadiigm nokta bu basdaki g_pHF -> parcasi ne yapar ? sanirim bu OOP ile ilgili olsa gerek (OOP: objekt oriented programing)
q_pHF isimli değişken bir yapı veya union olan bir pointer(yapının adresini tutan değişken). Nokta operatörü yapının içinde ki bir değişkene erişmek için kullanılır. Ama q_pHF bir yapı değil, sadece yapının adresini tutuyor. Dolaysıyla q_pHF içinde bir yapı yok ki, yapının içindeki elemana ulaşın. yapının içindeki elemana ulaşmak için bir kaç yöntem var.
örneğin * operatörü pointerin içindeki değere ulaşır.
O zaman :
(*g_pHF).SetAndCheckMotorOutputs(DF_MIN_MOT_CURRENT_TEST1, DF_MAX_MOT_CURRENT_TEST1, DF_TOLERANCE_MOT_CURRENT_TO_REAL_TEST1);
yada doğrudan pointer üzerinden işlem yapılacaksa o zaman -> operatörünü kullanılması gerekiyor. O zaman gösterdiği adresin kendisine erişiyoruz. yazılımı daha dolay oluyor. Örneğini yukarıda vermişsiniz.
Bu yapının içinde de parametreli bir fonksiyon adresi var. fonksiyonları çağırma işlemi aslında fonksiyon adresi ve parametresi şeklinde olduğundan. doğrudan fonksiyon adresini alıp sonra bu adresi yazdığımızda fonksiyon çağırmış oluyoruz.
cevaplar icin tesekür ederim, kod cok karmasik bir kod, rtos icinde kosan test programi, bende önce struct union yapilarini düsündüm ve gözüm aradi ama bulamadim.
anlamak istedigim bu yapi baska bir class icinde tanimlandigi icinmi? -> ile ulasiyoruz? sanirim . olursa pointer olmuyor -> olunca pointer oluyor. sonuc ollarak proje icinde ama baska bir class ve cpp dosyasinda SetAndCheckMotorOutputs adli fonksiyonu buldum ama niye bunu union veya struct ile yapioruz onu cözmüs degilim, :/ beni c de de en cok bu union struct yapilari zorlamisdi simdi tekrar burda var=)
Selamlar.
Anlamsız bir şekilde kodda hata alıyorum.
Ecpect ; diyor ancak eksik söz konusu değil.
(http://imageshack.us/a/img13/3177/qzpw.jpg)
2 hata bir uyarı var.İlk hata
i2c_write(adress);
satırında. İkinci de for döngüsünde ve saçma bir şekilde.İlgili kısım aşağıdaki gibi;
for (i=0;i<HYT271_BUFFER_LEN;i++)
{
buffer = i2c_read();
}
Burada da i2c_read(); satırında aynı hatayı veriyor.O warningi zaten hiç anlamadım.Hatanın sebebi ne olabilir?
#DEVICE parametresi varsayılan olarak ANSI değil, bu yüzden büyük-küçük harf ayrımı yapılmıyor. Ya ANSI yapın ya da #define ile yaptığınız tanımlamaları yeniden adlandırın. (Bence ANSI yapsanız da yeniden adlandırın.)
Alıntı yapılan: teknikelektronikci - 05 Temmuz 2013, 11:11:10
cevaplar icin tesekür ederim, kod cok karmasik bir kod, rtos icinde kosan test programi, bende önce struct union yapilarini düsündüm ve gözüm aradi ama bulamadim.
anlamak istedigim bu yapi baska bir class icinde tanimlandigi icinmi? -> ile ulasiyoruz? sanirim . olursa pointer olmuyor -> olunca pointer oluyor. sonuc ollarak proje icinde ama baska bir class ve cpp dosyasinda SetAndCheckMotorOutputs adli fonksiyonu buldum ama niye bunu union veya struct ile yapioruz onu cözmüs değilim, :/ beni c de de en cok bu union struct yapilari zorlamisdi simdi tekrar burda var=)
başka bir class veya struct içinde tanımlandığı için değil. Pointer lduğu için "->" ile ulaşıyoruz.
typedef struct
{
int x;
int y;
}DenemeTipi;
Deneme tipi a;
Deneme tipi *b = a;
Burada DenemeTipi isimli bir tip tanımladık. Bu tipten a isimli değişken ve aynı tipten b isimli işaretçi tanımladık.
eğer a değişkeninin x isimli üyesine ulaşmak istersek a.x = 5 diyebiliriz.
ama a değişkeninin x isimli üyesine b işaretçisi ile ulaşmak istersek b->x = 5 dememiz gerekir.
İki durumda da aynı işi yaptık. birinde doğrudan diğerinde işaretçi üzerinden.
Struct neden kullanılır?
Asıl amaç verilerimizi derli toplu hale getirip organize olabilmek. Bir çeşit veri tabanı gibi.
diyelim ki bir fonksiyonun var bu fonksiyon 5 tane parametre alıyor ve bu parametreler üzerinde çeşitli işlemler yapıp bazı global değişkenlere de bu değerleriyazıyor.
örn:
int a;
int b;
int c;
int d;
int e;
fonk ( int *a, int *b, int *c, int *d, int *e)
{
*a = (*d) * (*e);
*d = *b;
....
...
}
fonksiyon ( &a, &b, &c, &d, &e);
bu tip bir fonksiyonu çağırırken 5 tane parametre geçmen gerek. a,b,c,d,e değişkenlerinin adresini geçtin.
1- Çağırıren 5 tane parametre geçtiğin için yığında 5 adres için yer açıldı.
2- Çağırırken 5 tane parametreyi ayrı ayrı geçmek zorunda kaldın.
bu kod şöyle olsaydı.
typedef struct
{
int a;
int b;
int c;
int d;
int e;
}StructType;
StructType test;
fonksiyon( StructType *x)
{
x->a = x->d * x->e;
x->d = x->b;
....
...
}
fonksiyon( & test)
1-Bu durumda yığında sadece 1 adres için yer açıldı.
2- fonksiyonu çağırırken sadece 1 parametre ile çağırdığın için hem daha kolay hatırladın. hem de kodun daha derli toplu durdu.
Bu verdiğim örnek neden struct kullanırız sorusuna basit bir cevap veriyor. Çok daha kompleks nedenler de var. ama başka bir başlıkta ele alınabilir.
hocam cok tesekürler örnek ile daha güzel oldu, sanirim birincide fonk, fonksiyon olacak :) Saygilar
fonk ( int *a, int *b, int *c, int *d, int *e)
Arkadaşlar merhaba aşağıdaki soruyu daha öncede sordum açıklayıcı bir cevapta aldım sadece bir satır aklıma takıldı.
#define IAP_ADDRESS 0x7FFFFFF1
typedef unsigned int (*IAP)(unsigned int[], unsigned int[]);
static const IAP iap_entry = (IAP) 0x7FFFFFF1;
IAP ile flash memory veri yazdım okudumda lakin aşağıdaki satırda özellikle "(IAP) 0x7FFFFFF1;" kısmını anlamıyorum.
IAP iap_entry = (IAP) 0x7FFFFFF1;
yardımlarınız için şimdiden teşekkür ederim.
Sadece tür dönüşümü amacıyla yapılımış bişey.Yani derleyici 0x7FFFFFF1 adresini IAP türünde bir adrese dönüştürme yapıyo.IAP da geri dönüş değeri unsigned int olan ve parametreleri unsigned int türünden adres olan bir fonksiyon göstericisi.
Arkadaşlar merhaba.Benim sorum şu şekilde.
atıyorum delay_ms fonksyonu yazdık.Ben üst limit olarak 12ms belirledim.Üstünde girildiğinde derleyici hata mesajı versin istiyorum.Kullandığım derleyici MPLAB X sizce nasıl yapabilirim ?
#if derleyici ön bildirimi yaparsın sanırım.
Fonksiyon argümanı çalışma anında belirleniyorsa, yapılabilecek birşey olduğunu sanmıyorum.
xc8 ile ;
if(!WriteI2C(HYT271_ADDR+I2CREAD) == 0 )
şeklindeki kullanımda hata alıyorum.Amacım;
i2c write dan ack dışında bişey gelirse if i işle.Onu;
if(WriteI2C(HYT271_ADDR+I2CREAD) !== 0 )
şeklinde yapmaya kalktığımda da hata alıyorum.Sorun nedir?
Derleyicinin verdiği hata mesajı nedir?
Hocam bi de aşağıdaki gibi dener misin?
if(WriteI2C(HYT271_ADDR+I2CREAD) != 0 )
if(!WriteI2C(HYT271_ADDR+I2CREAD) == 0 ) bu kullanımda da ya baştaki ünlemi silmeniz gerekiyo ya da ==0 kısmını.Çünkü ikisi eğer 0 sa demek
Alıntı yapılan: yamak - 17 Temmuz 2013, 16:49:52
Hocam bi de aşağıdaki gibi dener misin?
if(WriteI2C(HYT271_ADDR+I2CREAD) != 0 )
Syntax hatası verdi.Şeklinde çözdüm.Denemiştim aslında bunu ama silip bi daha yazınca düzeldi :/
Elimde;
Alıntı Yapsigned char getsI2C( unsigned char *rdptr, unsigned char length )
şeklinde bir fonksiyonum var. Ben bu fonksiyona giriş parametresi olarak;
Alıntı YapgetsI2C((char *)buffer,(HYT271_BUFFER_LEN - 1));
verebilir miyim?Bu arada buffer 4 elemanlı bir dizi.
Arkadaşlar,
32 bitlik (4 byte halinde bulunan) bilgiyi hızlı bir şekilde birer bit sola kaldırmak istiyorum.
32 bitlik deger 4 ayrı byte halinde bulunduğu için sorun yaşıyorum.
Bu bahsettigim işlemi 16x32 led ekran üzerinde yapmaya çalışıyorum. Ekranın yapısı 8bitlik değişken halinde olmakla beraber toplamda 16x4 byte ediyor. Her 4byte lık degerin yanyana birlesmesiyle 32bitlik genişlik elde edilyor.16 satır 32 sütun.
Normalde bu ekran üzerinde düzgün ve hızlı çalışan pixel fonksiyonlarım var. Bu işlemi pixel komutuyla yapabiliyorum fakat cok uzun sürüyor.pixel ve getpixel komutu cok fazla kullanılıyor.
Bu sebeble Başka bir yolla yapmam gerekiyor.
Kullandıgım mcu İşlemci 40mhz de çalışıyor. Bu işlemi 40us nin altında bir surede yapabilirmiyim.
int32 DegA;
DegA=0x12345678;
DegA=DegA<<1;
ree istediği o değil
int8 A,B,C,D
int32 Z şeklinde
adam bunları birleştirip sola kaydıracak sanırım.
mucit23 herbir byte nasıl saklanmış değişkeni nedir ? onları birleştirip sola kaydır.
Alıntı yapılan: muhittin_kaplan - 19 Temmuz 2013, 01:47:13
ree istediği o değil
int8 A,B,C,D
int32 Z şeklinde
adam bunları birleştirip sola kaydıracak sanırım.
mucit23 herbir byte nasıl saklanmış değişkeni nedir ? onları birleştirip sola kaydır.
Durum sizin dediğiniz gibiyse
a en düşük byte, d en yüksek byte olmak üzere;
z=a+(((int32)b)<<8)+(((int32)c)<<16)+(((int32)d)<<24);
z<<=1;//1 bit kaydır.
Yukarıda ki gibi işlemi yaptıktan sonra aynı yöntemin tersiyle sayıyı parçalarsanız.
Arkadaşlar merhaba , bir datayı 32 bit olarak taşıyorum , lakin adet olarak artırırken algoritmatik olarak sıkıntı yaşıyorum.
Her butona basıldığında adet birer bire artıyor 3...45....60(long) sprintf ile char array dönüştürüyorum. Veriyi gonderdiğimde 1000....2000....3000. bir iki üç seklinde gidiyor ama okurken sanki 1000 gibi okunuyor.
void send_rf(void){
if (!( FIO1PIN & (0x01<<16))){
while (!(FIO1PIN & (0x01<<16))){}
adet ++;
sprintf(sadet ,"%ld",adet );
TxBuf[9] = sadet [0];
TxBuf[10] = sadet [1];
TxBuf[11] = sadet [2];
TxBuf[12] = sadet [3];
check_array ();
TxBuf[31] = '\n';
rfTxPacket();
}
Aşağıdaki şekilde değiştirdiğimde değer bu sefer 0001 ...(bir)0003....(üç).....0051(15) ama okuduğumda 51 oluyor .
TxBuf[9] = sadet [3];
TxBuf[10] = sadet [2];
TxBuf[11] = sadet [1];
TxBuf[12] = sadet [03];
Alıntı yapılan: muhittin_kaplan - 19 Temmuz 2013, 01:47:13
ree istediği o değil
int8 A,B,C,D
int32 Z şeklinde
adam bunları birleştirip sola kaydıracak sanırım.
mucit23 herbir byte nasıl saklanmış değişkeni nedir ? onları birleştirip sola kaydır.
Hocam Ekran yapım bu şekilde.
(http://s2.postimg.cc/feo6ymis9/Ekran_Al_nt_s.png) (http://postimg.cc/)
free pic (http://postimg.cc/)
Hafızada 16X4 lük iki boyutlu bir dizi tanımladım. Bu dizideki değerleri yukarıdaki resimdeki yapıya göre ekrana yansıtıyorum. Örneğin Ekranın 0,0 noktasındaki ledi yakmak için display_ram[0][0] değerine 10000000 yüklemem gerekir. Arka planda ramdeki bu değişklik hemen ekrana yansıtılıyor. Buralar süper işliyor. Şimdi amacım yukarıdaki şekilde tasarlanmış alanı birer bit sağa ve sola kaydırmak.
Alıntı yapılan: AsHeS35 - 19 Temmuz 2013, 02:01:50
Durum sizin dediğiniz gibiyse
a en düşük byte, d en yüksek byte olmak üzere;
z=a+(((int32)b)<<8)+(((int32)c)<<16)+(((int32)d)<<24);
z<<=1;//1 bit kaydır.
Yukarıda ki gibi işlemi yaptıktan sonra aynı yöntemin tersiyle sayıyı parçalarsanız.
Hocam birleştirme aklıma geldi aslında ama program biraz esnek olsun istiyorum. Örneğin Ekranda bir tane veya iki tane daha yan yana koyduğumda kaydırma işlemi sıkıntılı olacak. Örneğin ekran boyutu 16x64 olsa bende bu 64 sütünü iki adet 32 bitte saklasam bu iki 32 bit arasında yine bir geçiş işlemi olacak.
Hocam aklıma assembly ile yazmak geldi. Hatırladığım kadarıyla asm ile sola kaydırma işlemi yapıldığında en soldaki bit status registerinin elde bitine düşüyordu. CCS de ise en soldaki bit kayboluyor. Gerçi asm deki bu durum 16F de böyleydi 18F de durum nasıl bilmiyorum. Sola kaydırma işleminde Elde bitini alıp önceki registerin 7. bitine yazsam nasıl olur? Daha önce C de Asm kod hiç gömmedim . İsimi görecek kadar asm biliyorum. Sizce ASM ilemi yapmalıyım?
shiftleft veya rotate left
gibi kodlar var idi ama
Yeni bir konu açmak istedim müsade varsa kısa bir soru sormak istiyorum.
static void sda_low(void) {
SDA_PORT_ &= ~(SDA_MASK_); // internen Pull-Up aus
SDA_DDR_ |= SDA_MASK_; // Pin von SDA als Ausgang
}
şeklindeki tanımda sda_mask ne amaçla kullanılmış biraz kafamı karıştırdı doğrusu.
hedar içinde;
#define SDA_PORT_ PORTA
#define SDA_PIN_ PINA
#define SDA_DDR_ DDRA
#define SDA_MASK_ (1<<PORTA3)
source içinde;
#define I2C_SDA_LOW sda_low()
#define I2C_SDA_HIGH sda_high()
şeklinde tanımlarım var.Burada yapılmaya çalışılan genel anlamda ilgili pinleri h l yapmak ancak kafamı karıştıran tris yazmacına da mı müdahale var?Nasıl yapılmış?Biri açıklayabilir mi?Biraz kafam karıştı.
Alıntı yapılan: yldzelektronik - 19 Temmuz 2013, 15:00:55
Yeni bir konu açmak istedim müsade varsa kısa bir soru sormak istiyorum.
static void sda_low(void) {
SDA_PORT_ &= ~(SDA_MASK_); // internen Pull-Up aus
SDA_DDR_ |= SDA_MASK_; // Pin von SDA als Ausgang
}
şeklindeki tanımda sda_mask ne amaçla kullanılmış biraz kafamı karıştırdı doğrusu.
hedar içinde;
#define SDA_PORT_ PORTA
#define SDA_PIN_ PINA
#define SDA_DDR_ DDRA
#define SDA_MASK_ (1<<PORTA3)
source içinde;
#define I2C_SDA_LOW sda_low()
#define I2C_SDA_HIGH sda_high()
şeklinde tanımlarım var.Burada yapılmaya çalışılan genel anlamda ilgili pinleri h l yapmak ancak kafamı karıştıran tris yazmacına da mı müdahale var?Nasıl yapılmış?Biri açıklayabilir mi?Biraz kafam karıştı.
I2C'de iletişim pinleri open-drain. Yani bilgi göndermek için sadece pull-down yapabiliyorlar entegre içinden. 1'e çekme kısmını dışarıdaki pull-up direnci hallediyor.
Eğer pin open-drain değil ise :
0 gönderilmek istenildiğinde pin çıkış yapılıp 0 yapılıyor.
1 gönderilmek istenildiğinde pin giriş yapılıp boşta bırakılıyor.
Gösterdiğin kodlarda da yapılan bu.
I2C açıklamasında da şöyle bir not gördüm , aynı şeyden bahsediyor :
Alıntı YapAt the physical layer, both SCL & SDA lines are of open-drain design, thus, pull-up resistors are needed. Pulling the line to ground is considered a logical zero while letting the line float is a logical one.
1-Wire hattında da aynı bu şekilde MCU tarafı yazılıyor.
Alıntı yapılan: Mucit23 - 19 Temmuz 2013, 00:46:33
Arkadaşlar,
32 bitlik (4 byte halinde bulunan) bilgiyi hızlı bir şekilde birer bit sola kaldırmak istiyorum.
32 bitlik deger 4 ayrı byte halinde bulunduğu için sorun yaşıyorum.
Bu bahsettigim işlemi 16x32 led ekran üzerinde yapmaya çalışıyorum. Ekranın yapısı 8bitlik değişken halinde olmakla beraber toplamda 16x4 byte ediyor. Her 4byte lık degerin yanyana birlesmesiyle 32bitlik genişlik elde edilyor.16 satır 32 sütun.
Normalde bu ekran üzerinde düzgün ve hızlı çalışan pixel fonksiyonlarım var. Bu işlemi pixel komutuyla yapabiliyorum fakat cok uzun sürüyor.pixel ve getpixel komutu cok fazla kullanılıyor.
Bu sebeble Başka bir yolla yapmam gerekiyor.
Kullandıgım mcu İşlemci 40mhz de çalışıyor. Bu işlemi 40us nin altında bir surede yapabilirmiyim.
uint8_t x[8];
uint32_t *p32;
uint64_t *p64;
p32 = (uint32_t *) x;
*p32 <<=1;
p64 = (uint64_t *) x;
*p64 <<=1;
veya
uint8_t x[8];
*(uint32_t *) x <<= 1;
*(uint64_t *) x <<= 1;
eğer byte değişkenleriniz array şeklinde değilse , derleyici bu 4 veya 8 adet değişkeni sıralı yerleştirmeyebilir. bu yüzden yukarıdakimantık çalışmaz. Ancak array olması durumunda çalışır.
kaç mikrosaniyede yapar, ne kadar kod harcar bilmem. çıktısına bakmak gerek.
for(n=7;n>0;n--)
{
if((dram[n]&0b10000000)>0) bitset(dram[n+1],0); else bitclr(dram[n+1],0);
dram[n]<<=1;
}
for döngüsünü, örneğe göre düşünürsek 7 adıma yayman performans arttırır. program hafızasını kısıtlamadığı sürece adımlara bölmeni öneririm.
birde hi-tech c nin önerdiği şekli var bunun:
for(n=7;n>0;n--) dram[n] = (dram[n-1]>>7 | dram[n]<<1);
ancak performansı çok etkileyecek şekilde benim ilk önerime göre kötü.
performans konusunda bir kaç şey daha önerebilirim. mesela 8 bitlik hafıza lar arasında birden fazla kayma yapmak istiyorsak önce 8 er grup halinde kaydırıp sonra kalan kısmı bit bit şeklinde kaydırmak performansa oldukça katkısı oluyor.
i=cnv_data/8;
for(;i>0;i--)dshift_lbl();
i=cnv_data%8;
for(;i>0;i--)dshift_left();
@Klein Hocam Öneriniz için teşekkür ederim. Yalnız CCS kullanıyorum. verdiğiniz Yapı ccs ile çalışacağını sanmıyorum. :-[
@HasanKara Hocam Ben AsHeS35 in dediği mantık ile fonksiyon yazdım.
void ShiftLeft(int var1, int var2, int var3, int var4){
unsigned int32 buffy=0;
buffy=((((int32)var1<<24)+(int32)var2<<16)+(int32)var3<<8)+var4;
buffy=buffy<<1;
var5=((int32)buffy&0xFF000000)>>24;
var6=((int32)buffy&0x00FF0000)>>16;
var7=((int32)buffy&0x0000FF00)>>8;
var8=((int32)buffy&0x000000FF);
}
4 byte ın 32 bitte birleştirme işlemi çalışıyor. Sorun 32biti tekrar eski haline yani 4 adet 8 bite dönüştürme işleminde. Yukarıdaki Kodda Var8 ve Var7 den değer alıyorum. Yani ilk 16 bit bölünüyor fakat sonraki 16 bit bölünmüyor. Bunu çözersem hız sorununu büyük ihtimalle aşmış olacam. Çünkü Yukarıdaki fonksiyonun çalışma süresini ölçtüğümde işlemcinin fonksiyona girip çıkması tam olarak 8uS sürüyor.
32 bit değer 4 adet byte nasıl bölerim hızlı bir şekilde?
bir değişken tanımla örneğin vart olsun
var8=((int32)buffy&0x000000FF);
vart=((int32)buffy)>>8;
var7=((int32)vart&0x000000FF);
vart=((int32)buffy)>>8;
var6=((int32)vart&0x000000FF);
vart=((int32)buffy)>>8;
var5=((int32)vart&0x000000FF);
sadece bir fikir.
%f tanimlayicisini kullanmayi bilmiyorum.
8 digitlik ekranim var. 2 bir ekranim da expont gosterilebiliyor.
A double bir degisken
Ornegin;
Eger A icindeki sayi 1.2 e+7 ise 12000000 olarak ekranda gosterilsin.
Fakat A icindeki sayi 1.234567 e+8 ise ekranda gosterilecek deger 1234567 Exp 2 olsun.
Bunun icin %f nasil kullanilir?
Alıntı yapılan: z - 20 Temmuz 2013, 15:43:24
%f tanimlayicisini kullanmayi bilmiyorum.
8 digitlik ekranim var. 2 bir ekranim da expont gosterilebiliyor.
A double bir degisken
Ornegin;
Eger A icindeki sayi 1.2 e+7 ise 12000000 olarak ekranda gosterilsin.
Fakat A icindeki sayi 1.234567 e+8 ise ekranda gosterilecek deger 1234567 Exp 2 olsun.
Bunun icin %f nasil kullanilir?
Hocam %f format tanımlayıcıyla floating point sayıları doğrudan açarak gösterirsiniz. Üstel kısma bakılmaksızın sayının normal hali basılır. %e tanımlayıcısıyla sayı bilimsel gösterimle basılır. Burada da sayı 0.23 bile olsa 2.3e-1 olarak basılır. Sayının büyüklüğüne bakacak şekilde kendiniz bir printf fonksiyonu yazabilirsiniz. Ya da zor yoldan kendiniz bir fpu emülasyonu yapabilirsiniz. (C için konuşuyorum)
Bir iş ilanında şu ibareyi gördüm, "Ninja skills in C/C++ programming languages" .Sorum şu "- Ninja skills in C/C++" nedir? ne değildir? C de ne yapabilirsek mınçıka sahibi oluruz.
Alıntı yapılan: kantirici - 22 Temmuz 2013, 21:23:26
Bir iş ilanında şu ibareyi gördüm, "Ninja skills in C/C++ programming languages" .Sorum şu "- Ninja skills in C/C++" nedir? ne değildir? C de ne yapabilirsek mınçıka sahibi oluruz.
;D ;D
Selamlar.
Elimde şu şekilde bir fonksyionum var;
float *nem = 0.0;
float *isi = 0.0;
I2C_ERROR hyt271_get_measurements(float* humidity, float *temperature){
unsigned int buffer[BUFFER_LEN];
i2c_start();
if(i2c_write(ADDR + I2CWrite)){
printf("Sensore Erisim Basarisiz\n\r");
i2c_stop();
return I2C_BUS_ERROR;
}
else{
printf("Erisim basarili\n\r");
i2c_write(0x00);
}
i2c_stop();
delay_ms(CONV_DELAY);
i2c_start();
if(i2c_write(ADDR + I2CREAD)){
printf("Sensorden Veri Okunama Basarisiz\n\r");
I2C_Stop();
return I2C_BUS_ERROR;
}
else{
for(unsigned int i = 0;i<(_BUFFER_LEN );i++){
buffer[i] = i2c_read();
}
}
I2C_Stop();
printf("I2C: Veri okunuyor\n\r");
unsigned int16 rawhum = ((buffer[0]<<8 | buffer[1]) & 0x3FFF);
*humidity = (100.0/16383.0*rawhum);
unsigned int16 rawtemp = buffer[2]<<6 | (buffer[3] & 0x3F);
*temperature = (165.0/16383.0*rawtemp) - 40.0;
return I2C_ERROR_NONE;
}
Ben bu fonksiyona giriş parametresi olarak pointer mi girmeliyim?Yani isi ve nem i tanımlarken * koymadan tanımlasam da fonksiyona parametre olarak girsem?Bu iş nasıldır?Bir de derleyici ccs c nin ve orada yazdığı kadarıyla float unsupport. Ben double mı tanımlamalıyım değişkenleri mi?
Hocam ilk parametreye değişkenin adresini girmelisiniz.
Örneğin
float nem,temp;
hyt271_get_measurement(&nem,temp)
{
}
şeklinde.
CCS yi daha önce hiç kullanmadığım için bişey diyemeyecem.
Fonksiyon dışındaki tanımlamaların float nem = 0.0; float isi = 0.0; gibi olması gerekir. Aslında ilk değer vermeye gerek de yok ama yine de vermek daha iyi. Fonksiyon çağrılırken de hyt271_get_measurements(&nem, &isi); şeklinde çağrılmalı. Tercihen dönüş değeri kontrol edilerek bir hata olup olmadığı anlaşılabilir ama "kendimi şanslı hissediyorum" dersen, fonksiyonun hatasız olarak çalıştığını varsayıp dönüş değerine bakmasan da olur. İşler yolunda gittiyse, nem ve isi değişkenleri sensörden gelen verilere göre güncellenmiş olacaktır.
Merhabalar
Bir adet 64 elemanlı sabit bir dizim bir dizim var. Bu diziyi ramde tanımladığım yine 64 elemanlı başka bir diziye nasıl kopyalayabilirim.
Hocam memcpy komutunu kullanabilirsiniz.Bu komutu bi araştırın isterseniz.
Evet memcpy sanırım işimi görür. Teşekkürler
Objective C de;
A ve B double degiskenler.
B=0 iken A/B inf sonucu veriyor.
(long int) A / (long int) B sifir sonucunu veriyor. Sebebi hakkinda ne dusunuyorsunuz?
Sıfıra bölme tanımsızdır. x/y = z ise ve ondalıklı bölmede kalanda w ise x= y.z + w yapar. y=0 ise o zaman sıkıntı.
B sifir oldugu halde neden (long int) A / (long int) B sonucu sifir cikiyor onu merak ediyorum. Aklima derleyicinin hatasi geliyor sadece.
double değişkende fpu devrede iken long-int vs tipi yazılım olmasa bile kapılarla yapılıyor diye biliyorum hocam
bu durumda 0 göstermesi normal aslında, 65535 vs göstermek yerine koruma durumları koymak gerekseydi bende bu tarz durumlar için 0'a çekerdim
infinite durumunun tanımlı olduğu tek alan kayar noktaydı doğru hatırlıyorsam
Merbaha arkadaşlar.STM32f4 teki RTC ile uğraşıyorum.Low level yazıyorum programı.Programı calıstırdım fakat Saat ve Tarih bilgilerini register içinden ayıramıyorum.Mesela RTC->TR registerinin okudum.21. 20. bitler o anki saatin onlar basamagı, 19...16. bitler saatin birler basamagı,14:12. bitler dakikanın onlar basamağı gibi :)
Registeri okuduktan sonra saat,dakika ve saniye bilgilerini nasıl ayrıştırabilirim acaba?
Kolay gelsin...
stm bilmiyorum ama ilgili biti ayrıştırmak için, saat bilgisi için 20 kez sağa kaydır 000000FF ile and le saatin onlar basamağı çıkar, 16 kez sağa kaydırıp 0x0000FFFF ile and le saatin birler basamağı çıkar, benzer şekilde diğerlerini de bulabilirsin.
Ufak bi vergi hesaplama programı yapmaya çalışıyorum ancak çarpma işleminde örneğin;
x=45*12,5 yaptığım zaman ,5'i hesaba katmıyo. neden olabilir ?
x float olarak tanımlanmıştır.
Çıktıyı ne ile alıyosun.Eğer printf kullanıyosan ve %d kullanıyosan %d yi %f yaparak dener misin?
%3f olarak yazdırmaya çalışıyorum :S
printf olmadan da çıktı alabilir miyim ?
virgül mü nokta mı o ?
Farketmiyo virgül veya nokta olması :S
eder.
İkisini de yazıyorum hesap yaparken ancak sonuçta bişey değişmedi :S
Programı yeniden gözden geçircem pc başında olmadan kağıda bi dökeyim
virgül ve nokta ile ben denedim, virgül ile sonuç yanlış çıkıyor, nokta ile doğru çıkıyor
Bir sorum olacak.
6 haneli desimal bir sayım var.
Örneğin 456678 gibi..
Ben bu sayının sadece birer ve onlar basamağını almak istiyorum
Yukarıdaki örnek uzerinde yapacağım işlem sonucu elimde yine devrede desimal 78 sayısı olmalı.
Bu dediğim işlemi nasıl yapabilirim?
sayi%100 olur.
Evet sanırım mod kullanmam gerekli
Sedece birer hanesi için sayi% 10 olması gerekiyor ozaman.
char * ile char [] ın farkı nedir?
#include "stdio.h"
void main()
{
int i;
char *test="deneme123";
for(i=0;i<20;i++){
printf("%c",test[i]);
}}
çıktısı : deneme123
#include "stdio.h"
void main()
{
int i;
char test[]="deneme123";
for(i=0;i<20;i++){
printf("%c",test[i]);
}}
çıktısı : deneme123�͂��
bu iki örnekte de aynı şekilde alanın dışında karakterler göstermesi beklenemez miydi?
Dizi kaç eleman, mesela 9 eleman. 10. elemana 0 değerini verin.
örn:
deneme[]="123456789";
deneme[10]=0;
char *a ile pointer tanımlarısınız. a içerisine değişken uzunlukta veri yükleyebilirsiniz. char a[5] veya char a[]={1,2,3,4,5} şeklinde tanımlarsanız 5 elemanlı bir dizi tanımlarsınız ve daha fazla yükleme yapamazsınız.
Siz deneme123 yüklmeiş fakat 20 adet veri çekmeye çalışmışsınız.Bu durumda bellekte başka bir değişkene karşılık yada boş rastgele değerler çekiyorsunuz. uzunluğa göre işlem yaparsanız sorun hallolur.
İşaretçi (pointer) bir veri alanı değildir. istediğimiz kadar veri yükleyemeyiz.
işaretçiler veri alanlarının adreslerini bulundururlar.
Pointer mantığını kavramaya çalışıyorum fakat burada neden char[] dizisi bittikten sonrada rastgele değerler gelebilirken char* pointerin gösterdiği değeri artımama rağmen herhangi bir değer gelmediği. neticede ikiside pointer (ilk byte in bellektekiş adresi) ? Bunu compiler mı engelliyor? çokta aklıma takılmadı ama merak ediyorum hala. cevap veren arkadaşlara da teşekkürker.
Normalde pointer'de olsa dizi de olsa işaretçiyi artırdığınızda gösterdiği yerde ne varsa gelmesi gerekir. Bu durum bir tesadüf olabilr.
char *p = "xxxxxxx"
char *t = "yyyyyyy"
şeklinde p işaretçisinin hemen ardına başka bir dizi yerleştirin. p işarteçisi taşınca t'nin içeriğinden bir şeyler geliyor mu bir bakın.
İşte taşmasını beklerken taşma olmamasını anlayamadım. Dediğinizi yaptım yani. gcc varsayılan derleme acaba pointer bellek taşmasını engelliyormu?
bir de şöyle yapın. Muhtemelen herhangi bir snırlama olmayacak.
char a[] = "xxxxxxx";
char *p = a;
@Klein hocam bu arada iyileştirmelerin/optimizasyonların açık olmaması da önemli...
Alıntı yapılan: Klein - 03 Eylül 2013, 12:19:43
bir de şöyle yapın. Muhtemelen herhangi bir snırlama olmayacak.
char a[] = "xxxxxxx";
char *p = a;
Evet bu şekilde taşma oluyor. Ama buda zaten o dizi nin kendisi oluyor.
birde şöyle yazayım dedim ve dizi tanımlamasıyla pointerin (galiba) bellekte oldukça farklı yerlerde olduklarını gördüm.pointerden içindeki değerden sonra gelen veriler aslında tanımlanan yerde değilde printf() ile ekrana yazılan alanla aynı yerde.Bu nedemek bilmiyorum ama %p ile gelen bellek adresleri farklı yerdeler.Bu yüzden taşma olsada gösterecek bir değeri olmuyor döngünün. C de yeniyim bu yüzden oldukça kurcalayarak, deneme-yanımayla öğrenmeye çalışıyorum.
#include "stdio.h"
int main()
{
char a[]="test";
char *p="test";
int i=0;
for(i=0;i<100;i++){
printf("Döngü adet:%i AdresPointer:%p DegerPointer:%c AdresDizi:%p DegerDizi:%c\n",i,&(p[i]),p[i],&(a[i]),a[i]);
}
return 0;
}
Ekran çıktısı :
#gcc -o d d.c
Döngü adet:0 AdresPointer:0x80485a0 DegerPointer:t AdresDizi:0xbfee80d7 DegerDizi:t
Döngü adet:1 AdresPointer:0x80485a1 DegerPointer:e AdresDizi:0xbfee80d8 DegerDizi:e
Döngü adet:2 AdresPointer:0x80485a2 DegerPointer:s AdresDizi:0xbfee80d9 DegerDizi:s
Döngü adet:3 AdresPointer:0x80485a3 DegerPointer:t AdresDizi:0xbfee80da DegerDizi:t
Döngü adet:4 AdresPointer:0x80485a4 DegerPointer: AdresDizi:0xbfee80db DegerDizi:
Döngü adet:5 AdresPointer:0x80485a5 DegerPointer: AdresDizi:0xbfee80dc DegerDizi:
Döngü adet:6 AdresPointer:0x80485a6 DegerPointer: AdresDizi:0xbfee80dd DegerDizi:J
Döngü adet:7 AdresPointer:0x80485a7 DegerPointer: AdresDizi:0xbfee80de DegerDizi:
Döngü adet:8 AdresPointer:0x80485a8 DegerPointer:D AdresDizi:0xbfee80df DegerDizi:
Döngü adet:9 AdresPointer:0x80485a9 DegerPointer:� AdresDizi:0xbfee80e0 DegerDizi:5
Döngü adet:10 AdresPointer:0x80485aa DegerPointer:� AdresDizi:0xbfee80e1 DegerDizi:
Döngü adet:11 AdresPointer:0x80485ab DegerPointer:n AdresDizi:0xbfee80e2 DegerDizi:z
Döngü adet:12 AdresPointer:0x80485ac DegerPointer:g AdresDizi:0xbfee80e3 DegerDizi:
Döngü adet:13 AdresPointer:0x80485ad DegerPointer:� AdresDizi:0xbfee80e4 DegerDizi:P
Döngü adet:14 AdresPointer:0x80485ae DegerPointer:� AdresDizi:0xbfee80e5 DegerDizi:J
Döngü adet:15 AdresPointer:0x80485af DegerPointer: AdresDizi:0xbfee80e6 DegerDizi:
Döngü adet:16 AdresPointer:0x80485b0 DegerPointer:a AdresDizi:0xbfee80e7 DegerDizi:
Döngü adet:17 AdresPointer:0x80485b1 DegerPointer:d AdresDizi:0xbfee80e8 DegerDizi:
Döngü adet:18 AdresPointer:0x80485b2 DegerPointer:e AdresDizi:0xbfee80e9 DegerDizi:�
Döngü adet:19 AdresPointer:0x80485b3 DegerPointer:t AdresDizi:0xbfee80ea DegerDizi:�
Döngü adet:20 AdresPointer:0x80485b4 DegerPointer:: AdresDizi:0xbfee80eb DegerDizi:
Döngü adet:21 AdresPointer:0x80485b5 DegerPointer:% AdresDizi:0xbfee80ec DegerDizi:
Döngü adet:22 AdresPointer:0x80485b6 DegerPointer:i AdresDizi:0xbfee80ed DegerDizi:
Döngü adet:23 AdresPointer:0x80485b7 DegerPointer: AdresDizi:0xbfee80ee DegerDizi:
Döngü adet:24 AdresPointer:0x80485b8 DegerPointer:A AdresDizi:0xbfee80ef DegerDizi:
Döngü adet:25 AdresPointer:0x80485b9 DegerPointer:d AdresDizi:0xbfee80f0 DegerDizi:
Döngü adet:26 AdresPointer:0x80485ba DegerPointer:r AdresDizi:0xbfee80f1 DegerDizi:�
Döngü adet:27 AdresPointer:0x80485bb DegerPointer:e AdresDizi:0xbfee80f2 DegerDizi:
Döngü adet:28 AdresPointer:0x80485bc DegerPointer:s AdresDizi:0xbfee80f3 DegerDizi:
Döngü adet:29 AdresPointer:0x80485bd DegerPointer:P AdresDizi:0xbfee80f4 DegerDizi:
Döngü adet:30 AdresPointer:0x80485be DegerPointer:o AdresDizi:0xbfee80f5 DegerDizi:
Döngü adet:31 AdresPointer:0x80485bf DegerPointer:i AdresDizi:0xbfee80f6 DegerDizi:
Döngü adet:32 AdresPointer:0x80485c0 DegerPointer:n AdresDizi:0xbfee80f7 DegerDizi:
Döngü adet:33 AdresPointer:0x80485c1 DegerPointer:t AdresDizi:0xbfee80f8 DegerDizi:x
Döngü adet:34 AdresPointer:0x80485c2 DegerPointer:e AdresDizi:0xbfee80f9 DegerDizi:�
Döngü adet:35 AdresPointer:0x80485c3 DegerPointer:r AdresDizi:0xbfee80fa DegerDizi:
Döngü adet:36 AdresPointer:0x80485c4 DegerPointer:: AdresDizi:0xbfee80fb DegerDizi:�
Döngü adet:37 AdresPointer:0x80485c5 DegerPointer:% AdresDizi:0xbfee80fc DegerDizi:7
Döngü adet:38 AdresPointer:0x80485c6 DegerPointer:p AdresDizi:0xbfee80fd DegerDizi:N
Döngü adet:39 AdresPointer:0x80485c7 DegerPointer: AdresDizi:0xbfee80fe DegerDizi:y
Döngü adet:40 AdresPointer:0x80485c8 DegerPointer: AdresDizi:0xbfee80ff DegerDizi:
Döngü adet:41 AdresPointer:0x80485c9 DegerPointer:D AdresDizi:0xbfee8100 DegerDizi:
Döngü adet:42 AdresPointer:0x80485ca DegerPointer:e AdresDizi:0xbfee8101 DegerDizi:
Döngü adet:43 AdresPointer:0x80485cb DegerPointer:g AdresDizi:0xbfee8102 DegerDizi:
Döngü adet:44 AdresPointer:0x80485cc DegerPointer:e AdresDizi:0xbfee8103 DegerDizi:
Döngü adet:45 AdresPointer:0x80485cd DegerPointer:r AdresDizi:0xbfee8104 DegerDizi:�
Döngü adet:46 AdresPointer:0x80485ce DegerPointer:P AdresDizi:0xbfee8105 DegerDizi:�
Döngü adet:47 AdresPointer:0x80485cf DegerPointer:o AdresDizi:0xbfee8106 DegerDizi:
Döngü adet:48 AdresPointer:0x80485d0 DegerPointer:i AdresDizi:0xbfee8107 DegerDizi:�
Döngü adet:49 AdresPointer:0x80485d1 DegerPointer:n AdresDizi:0xbfee8108 DegerDizi:�
Döngü adet:50 AdresPointer:0x80485d2 DegerPointer:t AdresDizi:0xbfee8109 DegerDizi:�
Döngü adet:51 AdresPointer:0x80485d3 DegerPointer:e AdresDizi:0xbfee810a DegerDizi:
Döngü adet:52 AdresPointer:0x80485d4 DegerPointer:r AdresDizi:0xbfee810b DegerDizi:�
Döngü adet:53 AdresPointer:0x80485d5 DegerPointer:: AdresDizi:0xbfee810c DegerDizi:
Döngü adet:54 AdresPointer:0x80485d6 DegerPointer:% AdresDizi:0xbfee810d DegerDizi:�
Döngü adet:55 AdresPointer:0x80485d7 DegerPointer:c AdresDizi:0xbfee810e DegerDizi:
Döngü adet:56 AdresPointer:0x80485d8 DegerPointer: AdresDizi:0xbfee810f DegerDizi:
Döngü adet:57 AdresPointer:0x80485d9 DegerPointer: AdresDizi:0xbfee8110 DegerDizi:�
Döngü adet:58 AdresPointer:0x80485da DegerPointer: AdresDizi:0xbfee8111 DegerDizi:�
Döngü adet:59 AdresPointer:0x80485db DegerPointer:A AdresDizi:0xbfee8112 DegerDizi:�
Döngü adet:60 AdresPointer:0x80485dc DegerPointer:d AdresDizi:0xbfee8113 DegerDizi:�
Döngü adet:61 AdresPointer:0x80485dd DegerPointer:r AdresDizi:0xbfee8114 DegerDizi:
Döngü adet:62 AdresPointer:0x80485de DegerPointer:e AdresDizi:0xbfee8115 DegerDizi:/
Döngü adet:63 AdresPointer:0x80485df DegerPointer:s AdresDizi:0xbfee8116 DegerDizi:
Döngü adet:64 AdresPointer:0x80485e0 DegerPointer:D AdresDizi:0xbfee8117 DegerDizi:
Döngü adet:65 AdresPointer:0x80485e1 DegerPointer:i AdresDizi:0xbfee8118 DegerDizi:M
Döngü adet:66 AdresPointer:0x80485e2 DegerPointer:z AdresDizi:0xbfee8119 DegerDizi:�
Döngü adet:67 AdresPointer:0x80485e3 DegerPointer:i AdresDizi:0xbfee811a DegerDizi:
Döngü adet:68 AdresPointer:0x80485e4 DegerPointer:: AdresDizi:0xbfee811b DegerDizi:
Döngü adet:69 AdresPointer:0x80485e5 DegerPointer:% AdresDizi:0xbfee811c DegerDizi:
Döngü adet:70 AdresPointer:0x80485e6 DegerPointer:p AdresDizi:0xbfee811d DegerDizi:
Döngü adet:71 AdresPointer:0x80485e7 DegerPointer: AdresDizi:0xbfee811e DegerDizi:
Döngü adet:72 AdresPointer:0x80485e8 DegerPointer: AdresDizi:0xbfee811f DegerDizi:
Döngü adet:73 AdresPointer:0x80485e9 DegerPointer: AdresDizi:0xbfee8120 DegerDizi:`
Döngü adet:74 AdresPointer:0x80485ea DegerPointer:D AdresDizi:0xbfee8121 DegerDizi:�
Döngü adet:75 AdresPointer:0x80485eb DegerPointer:e AdresDizi:0xbfee8122 DegerDizi:
Döngü adet:76 AdresPointer:0x80485ec DegerPointer:g AdresDizi:0xbfee8123 DegerDizi:�
Döngü adet:77 AdresPointer:0x80485ed DegerPointer:e AdresDizi:0xbfee8124 DegerDizi:1
Döngü adet:78 AdresPointer:0x80485ee DegerPointer:r AdresDizi:0xbfee8125 DegerDizi::
Döngü adet:79 AdresPointer:0x80485ef DegerPointer:D AdresDizi:0xbfee8126 DegerDizi:
Döngü adet:80 AdresPointer:0x80485f0 DegerPointer:i AdresDizi:0xbfee8127 DegerDizi:
Döngü adet:81 AdresPointer:0x80485f1 DegerPointer:z AdresDizi:0xbfee8128 DegerDizi:
Döngü adet:82 AdresPointer:0x80485f2 DegerPointer:i AdresDizi:0xbfee8129 DegerDizi::
Döngü adet:83 AdresPointer:0x80485f3 DegerPointer:: AdresDizi:0xbfee812a DegerDizi:
Döngü adet:84 AdresPointer:0x80485f4 DegerPointer:% AdresDizi:0xbfee812b DegerDizi:
Döngü adet:85 AdresPointer:0x80485f5 DegerPointer:c AdresDizi:0xbfee812c DegerDizi:H
Döngü adet:86 AdresPointer:0x80485f6 DegerPointer:
AdresDizi:0xbfee812d DegerDizi:�
Döngü adet:87 AdresPointer:0x80485f7 DegerPointer: AdresDizi:0xbfee812e DegerDizi:�
Döngü adet:88 AdresPointer:0x80485f8 DegerPointer: AdresDizi:0xbfee812f DegerDizi:�
Döngü adet:89 AdresPointer:0x80485f9 DegerPointer: AdresDizi:0xbfee8130 DegerDizi:
Döngü adet:90 AdresPointer:0x80485fa DegerPointer: AdresDizi:0xbfee8131 DegerDizi:
Döngü adet:91 AdresPointer:0x80485fb DegerPointer: AdresDizi:0xbfee8132 DegerDizi:
Döngü adet:92 AdresPointer:0x80485fc DegerPointer: AdresDizi:0xbfee8133 DegerDizi:
Döngü adet:93 AdresPointer:0x80485fd DegerPointer: AdresDizi:0xbfee8134 DegerDizi:
Döngü adet:94 AdresPointer:0x80485fe DegerPointer: AdresDizi:0xbfee8135 DegerDizi:�
Döngü adet:95 AdresPointer:0x80485ff DegerPointer: AdresDizi:0xbfee8136 DegerDizi:�
Döngü adet:96 AdresPointer:0x8048600 DegerPointer: AdresDizi:0xbfee8137 DegerDizi:
Döngü adet:97 AdresPointer:0x8048601 DegerPointer: AdresDizi:0xbfee8138 DegerDizi:
Döngü adet:98 AdresPointer:0x8048602 DegerPointer: AdresDizi:0xbfee8139 DegerDizi:
Döngü adet:99 AdresPointer:0x8048603 DegerPointer: AdresDizi:0xbfee813a DegerDizi:
@everygelem hocam sorununuzun cevabı tam olarak yok aslında. Bu olay derleyiciye ve platforma çok bağlı. Ancak Windows ve Visual C için düşünürsek, basit bir assembly çıktısı olayı çözüyor.
Asıl mesele programın nasıl çalıştırıldığı. Sizin programınız .exe halinde iken farklı kısımlara(section) sahiptir. Bunlardan ilki .text sectionıdır. Bu kısımda sizin çalıştırılabilir kodunuz saklanır.
Bir diğeri .rdata kısmıdır. GCC için .rodata dır. Bu kısmın adı Read Only DATA'dır. Yani yalnızca okunabilir olan veriler buraya kaydedilir. İşletim sistemi bu kısımları RAM'e kopyalayarak çalıştırır.
Sizin programınızdan daha basit olan şu kodu ele alalım:
#include <stdio.h>
void main()
{
char a[] = "bu dizi seklinde";
char * b = "bu ptr seklinde";
printf("%d %d %d %d", a, b);
}
Kod basitçe bir dizi ve bir pointer oluşturup bunların adreslerini ekrana basıyor. Bu programı derlediğinizde iki metin de ("bu dizi seklinde" ve "bu ptr seklinde") .rdata sectionına konulur.
Programın Assembly çıktısına bakarak olayların nasıl geliştiğini görebiliriz:
; Listing generated by Microsoft (R) Optimizing Compiler Version 18.00.20617.1
TITLE C:\Users\Fatih\Desktop\deneme.c
.686P
.XMM
include listing.inc
.model flat
INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES
_DATA SEGMENT
$SG3045 DB 'bu dizi seklinde', 00H
ORG $+3
$SG3047 DB 'bu ptr seklinde', 00H
$SG3048 DB '%d %d %d %d', 00H
_DATA ENDS
PUBLIC _main
EXTRN _printf:PROC
EXTRN @__security_check_cookie@4:PROC
EXTRN ___security_cookie:DWORD
; Function compile flags: /Odtp
_TEXT SEGMENT
_b$ = -28 ; size = 4
_a$ = -24 ; size = 17
__$ArrayPad$ = -4 ; size = 4
_main PROC
; File c:\users\fatih\desktop\deneme.c
; Line 4
push ebp
mov ebp, esp
sub esp, 28 ; 0000001cH
mov eax, DWORD PTR ___security_cookie
xor eax, ebp
mov DWORD PTR __$ArrayPad$[ebp], eax
; Line 5
mov eax, DWORD PTR $SG3045
mov DWORD PTR _a$[ebp], eax
mov ecx, DWORD PTR $SG3045+4
mov DWORD PTR _a$[ebp+4], ecx
mov edx, DWORD PTR $SG3045+8
mov DWORD PTR _a$[ebp+8], edx
mov eax, DWORD PTR $SG3045+12
mov DWORD PTR _a$[ebp+12], eax
mov cl, BYTE PTR $SG3045+16
mov BYTE PTR _a$[ebp+16], cl
; Line 6
mov DWORD PTR _b$[ebp], OFFSET $SG3047
; Line 8
mov edx, 1
imul eax, edx, 0
add eax, DWORD PTR _b$[ebp]
push eax
mov ecx, 1
imul edx, ecx, 0
lea eax, DWORD PTR _a$[ebp+edx]
push eax
mov ecx, DWORD PTR _b$[ebp]
push ecx
lea edx, DWORD PTR _a$[ebp]
push edx
push OFFSET $SG3048
call _printf
add esp, 20 ; 00000014H
; Line 9
xor eax, eax
mov ecx, DWORD PTR __$ArrayPad$[ebp]
xor ecx, ebp
call @__security_check_cookie@4
mov esp, ebp
pop ebp
ret 0
_main ENDP
_TEXT ENDS
END
Parça parça ele alırsak:
_DATA SEGMENT
$SG3045 DB 'bu dizi seklinde', 00H
ORG $+3
$SG3047 DB 'bu ptr seklinde', 00H
$SG3048 DB '%d %d %d %d', 00H
_DATA ENDS
Burası data segmentini oluşturuyor. .rdata'nın en başına ilk mesajımız yazılıyor. 3 byte ileri atlanıp sonraki mesajımız yazılıyor ve pesine printf'deki stringimiz yazılıyor.
Buraya kadar mesajlarımız aynı yerdeymiş gibi görünüyor. Doğru, dosyada peş peşeler ancak sonrasında durum değişiyor.
mov eax, DWORD PTR $SG3045
mov DWORD PTR _a$[ebp], eax
mov ecx, DWORD PTR $SG3045+4
mov DWORD PTR _a$[ebp+4], ecx
mov edx, DWORD PTR $SG3045+8
mov DWORD PTR _a$[ebp+8], edx
mov eax, DWORD PTR $SG3045+12
mov DWORD PTR _a$[ebp+12], eax
mov cl, BYTE PTR $SG3045+16
mov BYTE PTR _a$[ebp+16], cl
Burada a dizimize .rdata section'undaki metin 4'er 4'er kopyalanıyor. Yani _a değişkeni aslında bellekte rastgele bir yerde, biz metnimizi oraya kopyalıyoruz. Örneğin dosyamız diskten alında ve işletim sistemi dosyayı açtı, .rdata kısmını ramin 0x1000 adresine çıkardı. Ancak bizim _a değişkenimiz (ki bu .text içinden alındı) bellekte 0x1234'te oluşturuldu(heap). Kodumuz, .rdata'daki metni 0x1000'den 0x1234'e kopyaladı.
Bu yüzden programı her çalıştırdığınızda a'nın adresi farklı bir değer alır.
İkinci kısma gelelim:
mov DWORD PTR _b$[ebp], OFFSET $SG3047
Buradaki işlem çok basit. Yalnızca ikinci metnin offset adresi alınıyor ve _b nin içine kopyalanıyor. _b burada bir pointer olduğundan sadece verinin adresini saklıyor.
Şimdi, nasıl oluyor da _a ile _b çok farklı yerlere gidiyor? Başka bir deyişle _a her seferinde değişirken _b sabit kalıyor. Bu noktada virtual memory diye bir olay ortaya çıkıyor. İşletim sistemi MMU birimini kullanarak bize hep sahte adresler veriyor. Hiç bir zaman gerçek fiziksel adresleri kullanmıyoruz. Bu adresler sadece bize bildirilen 4GB'lık sanal bellek alanında oluşturulmuş adresler, bu yüzden bizim programımız kendini hep bellekte 100 adresine yüklenmiş sanıyor. Verilerin adresleri de buna göre offsetleniyor. Yani bizim ikinci metnimiz gerçek fiziksel bellekte çok farklı yerlede de olsa, biz onu kendi bellek alanımızda aynı yerde sanıyoruz.
Sonuçta bu iki mesaj ram'de ard arda olsalar bile biz ikincisini yanımızda sanıyoruz.
En başta çok değişken demiştim. Bu durumda bundan kaynaklanıyor. Eğer bu kodu işletim sistemi olmadan bir PIC ile çalıştırırsanız, ard arda adresler görebilirsiniz. Ya da GCC ile farklı, VC++ ile farklı sonuçlar elde edebilirsiniz.
Yanlışım varsa düzeltin.
İyi çalışmalar...
char a[]="test";
char *p="test";
yukarkıda ki,
char a[]="test"; anlamı
içinde "test" yazısı tutan ve const olmayan bir değişkendir.
onu şöylede yazabilirsiniz.
char a[]={'t','e','s','t',0};
oysa char *p="test"; ise aynı anlama gelmiyor. Büyük ihtimalle de yukarıda ki şekilde yazdığımızda hata verir.
"test" = const bir yazı dizisidir. Bu const dizi adresini bir pointere (p ye) yükleyip ona oradan işlem yapıyoruz.
RAM (const olmayan ) ile ROM (const olan) değişkenlerin adresleri farklı yerlerdir. ondan farklı adres vermiştir. Dediğimi ispatlamanın bir yoluda
a[0]='m';
p[0]='m';
yazdğımızda a nın değiştiği ama p nin değişmediğini gördüğümüzde anlarız.
burdan anladığım C çalışmaya devam edicem demek ki hızı artırarak. Zaman ayırıp yanıt veren arkadaşlara tekrar teşekkürler.
@arslan74 hocam sabit olarak kalacak yazıları dizi değişken tanımlamak , değişecek verileride pointerter tanımlamak mı mantık lı?
Hangisini hangi durumda kullanmak mantıklı?
Alıntı yapılan: meftun - 05 Eylül 2013, 17:49:50
@arslan74 hocam sabit olarak kalacak yazıları dizi değişken tanımlamak , değişecek verileride pointerter tanımlamak mı mantık lı?
Hangisini hangi durumda kullanmak mantıklı?
Merhaba,
Sabit kalacak, değişmeyecek yazıları, verileri const tanımlaki ram'den yemesin.
Değişecek veriler için ister pointer kullan istersen array(dizi).
Değişkenlere pointer atanacağı gibi değişmeyenler içinde pointer tanımlayabilirsin, pointer sadece const olur yani point ettiği adresi okursun ama o adrese yazamazsın.
Ben şunu anlamadım:
char a[]="test\0";
char *p="test";
bu iki satır aynı anlama gelmiyor mu?
a[0]='m';
p[0]='m';
yazdığımda neden değişmiyor anlamadım, ikiside ram de tanımlı değil mi, p neden değişmiyor?
char *p="test";
Bu tanımlamada, pointeri sabit mi tanımlamış oluyoruz?
Hayır iki satır aynı anlama gelmiyor.
char *p ="abcde";
p nin gösterdiği adres yani "abcde" katarı Ram'da değil Rom'da tanımlı.
char *p ="abcde";
hayır işaretçiyi sabit tanımlamıyoruz. İşaretçinin gösterdiği adres değişebilir. Rom da içerisinde "abcde" katarı olan bir alan açıp. işaretçiye de buranın adresini veriyoruz.
Alıntı yapılan: Klein - 05 Eylül 2013, 18:53:16
char *p ="abcde";
hayır işaretçiyi sabit tanımlamıyoruz. İşaretçinin gösterdiği adres değişebilir. Rom da içerisinde "abcde" katarı olan bir alan açıp. işaretçiye de buranın adresini veriyoruz.
Hımm teşekkürler, bunu bilmiyordum.
Selamlar.
atof()
ile uarttan gelen virgüllü sayıyı bir değişkene almak istiyorum.Ancak kafamı karıştıran bir nokta var.Terminalden girilecek değeri alacağım ancak eğer kullanıcı rakam ve . yerine karaktere basarsa ne olacak?Bunu nasıl algılayabilirim?Yani;
10.54 yazarken kullanıcı oldu ya;
10.e4 yazdı.Bu durumu nasıl algılayabilirim? atof fonksiyonunu daha önce kullanmadım.
atof() fonksiyonuna verilen giriş geçerli bir float sayıyı göstermiyorsa, 0 döndürür.
Fonksiyon e (ve E)'yi exponent olarak görüyor; bunların dışındaki karakterler en baştaysa sıfır döndürüyor, ortalardaysa o karaktere kadar olan kısmı float olarak alıyor. Rakam dışında girilen hatalı değerleri algılamak için kendi fonksiyonunuzu yazmanız gerekecek. "atof function implementation in c" aramasıyla bazı örnekler çıkıyor.
c18 dilinde
putrsUSART("Merhaba ");
şeklinde veri gönderdiğimde:
Alıntı YapWarning [2066] type qualifier mismatch in assignment
uyarısı veriyor aşağıdaki gibi yazınca sorun yok.
putrsUSART((const rom far char *)"Merhaba ");
Burda anlamadığım, rom demek zaten değişmeyen sabit veriler demek, const demek de sabit demek, far ne anlama geliyor bilmiyorum...
gerçi
putrsUSART((rom far char *)"Merhaba ");
şeklinde de çalışıyor ama, aşağıdaki gibi çalışmıyor
putrsUSART((const far char *)"Merhaba ");
Demekki ikisi aynı şey değil...
Const değişkenler için olan, rom tanımsız katarlar olabilir mi?
const ve rom arasında ne fark var?
far ne demek?
Aydınlatırsanız sevinirim.
Merhaba,
PIC ler Harvard mimarsine shaip işlemciler. Yani bunları üc tane farklı hafıza bölgeleri var. program memory, ram ve EEPROM gibi alanlar dır. Bu alanların erişim kanalları birbirinden farklı dır, ortak erişim kanalı yoktur. Dolaysıyla C de bir alan tanımladığımızda bunun hangi alanda olmasını istediğimizi sadece adres kullanarak ifade edemiyoruz. Hepsinde ortak adresler bulunabiliyor. Bu ayrımı yapabilmek için C18 dilinde standart C dilinin dışında RAM ve ROM kelimeleri eklendi. Bununla ben bu hafıza alanını nerede tanımlamak istiyorum diye belirte biliyorsun. Von Neumann mimarisinde bütün hafıza alanları tek bir adres blokunda gösterilmiştir. RAM ve FLASH gibi alanlar farklı adreslerle tanımlanmıştır. Bu yüzden Von Neumann mimarisinde adres bakarak bu bilgi hangi alanda olduğunu anlayabiliriz, ana harvard mimarisinde bunu yapmak mümkün değil. PIC32 serisinde Von Neumann mimarisi kullanılmıştır, o yüzden RAM ve ROM kelimelerini kullanmak gerekmiyor. Yada bir fonksiyonun RAM ve ROM için iki tane ayrı yazılmış fonksiyonlar yazılması gerekmiyor.
Alıntı Yapfar ne demek?
Bunlarda PIC18 serisine için özel ifadeler. Genel olarak hafıza erişimin iki farklı metodu var. Eğer hafıza alanı 64K üstünde ise far kullanmak gerekiyor. Altında ise near kullanmak işlem hızı artıracak. far kullanmamız sadece hız olarak etkileyecek.
Teşekkür ederim çok güzel bilgiler verdiniz.
aslan hocam görüşemiyorz uzun zamandır. :)
Alıntı yapılan: arslan74 - 09 Eylül 2013, 09:55:26
Merhaba,
PIC ler Harvard mimarsine shaip işlemciler. Yani bunları üc tane farklı hafıza bölgeleri var. program memory, ram ve EEPROM gibi alanlar dır. Bu alanların erişim kanalları birbirinden farklı dır, ortak erişim kanalı yoktur. Dolaysıyla C de bir alan tanımladığımızda bunun hangi alanda olmasını istediğimizi sadece adres kullanarak ifade edemiyoruz. Hepsinde ortak adresler bulunabiliyor. Bu ayrımı yapabilmek için C18 dilinde standart C dilinin dışında RAM ve ROM kelimeleri eklendi. Bununla ben bu hafıza alanını nerede tanımlamak istiyorum diye belirte biliyorsun. Von Neumann mimarisinde bütün hafıza alanları tek bir adres blokunda gösterilmiştir. RAM ve FLASH gibi alanlar farklı adreslerle tanımlanmıştır. Bu yüzden Von Neumann mimarisinde adres bakarak bu bilgi hangi alanda olduğunu anlayabiliriz, ana harvard mimarisinde bunu yapmak mümkün değil. PIC32 serisinde Von Neumann mimarisi kullanılmıştır, o yüzden RAM ve ROM kelimelerini kullanmak gerekmiyor. Yada bir fonksiyonun RAM ve ROM için iki tane ayrı yazılmış fonksiyonlar yazılması gerekmiyor.
Bunlarda PIC18 serisine için özel ifadeler. Genel olarak hafıza erişimin iki farklı metodu var. Eğer hafıza alanı 64K üstünde ise far kullanmak gerekiyor. Altında ise near kullanmak işlem hızı artıracak. far kullanmamız sadece hız olarak etkileyecek.
Hocam normalde zaten const dediğimizde rom da diğer türlü ram de saklanmıyor mu veriler?
Alıntı yapılan: yamak - 10 Eylül 2013, 10:00:43
Hocam normalde zaten const dediğimizde rom da diğer türlü ram de saklanmıyor mu veriler?
C dilinde öyle bir mecburiyet yok. Bu derleyicilerin var sayımı ile ilgili bir şey. const anlamı ben bu değişkene okuma yapacağım yazma yapmayacağım anlamı veriyor. illa yazma yapamıyorum anlamı yükleme. RAM de const değişken tanımlaya bilirsin, O zaman ben sadece bu RAM den okuma yapacağım yazma yapmayacağım diye ifade ediyorsun. kodda yazma yapacağın zaman uyarı veriyor. Bu okunurluğu artırıyor.
Not:
Alıntı Yapaslan hocam görüşemiyorz uzun zamandır. :)
Evet haklısınız uzun süredir. Forumlara pek takılmıyordum, 1.5 senelik yoğun bir işle uğraştım. O zaman zarfında forumlara girecek vakit bile bulamadım diyebilirim. Forumda görüştüğüm bir çok arkadaşlarla da irtibatım kesildi. Hafızam da zayıfladı. Sizinle görüştüğümü hatırlıyorum. Ama ayrıntıları pek fazla hatırlamıyorum. Bunun için kusura bakmayın, anlaşılan yaşlanıyoruz.
Uzunluğu sabit olmayan string veriyi usart ile alırken hangi metodu kullanıyorsunuz?
gets kullandığımda sıkıntı yaşıyorum.Kullandığım terminal programlarıyla bu sıkıntıyı aşamadım.Siz nasıl metodlar kullanıyorsunuz?
Hiç kimse uart/usart kullanmıyor mu?
Alıntı yapılan: yldzelektronik - 10 Eylül 2013, 11:17:29
Uzunluğu sabit olmayan string veriyi usart ile alırken hangi metodu kullanıyorsunuz?
gets kullandığımda sıkıntı yaşıyorum.Kullandığım terminal programlarıyla bu sıkıntıyı aşamadım.Siz nasıl metodlar kullanıyorsunuz?
Burda c18 ile ilgili bir uygulama yapmıştım, terminalde de denedim isiste de denedim çalışıyor. CCS C ' de nasıl olur bilmiyorum.
http://gokhanbeken.com/?p=912 (http://gokhanbeken.com/?p=912)
Aşağıdaki kısım ile enter tuşu kontrolü yapılıyor:
while(1)
{
while(BusyUSART()); // wait for input //while (!DataRdyUSART());
getsUSART(usart_ram, 1); //usart_ram değişkenine 1 karakterlik veri alıyoruz
putsUSART(usart_ram); //adam ne yazdığını bu kod sayesinde görüyor, eğer back spack tuşunuda enter gibi kontrol edersek silmesinide sağlayabiliriz, gerçi isiste backspack tuşu ile silebiliyoruz ama normalde oluyor mu bilmiyorum
if(usart_ram[0]==(char)13)
{
break;
}
*cevap=usart_ram[0];
cevap++;
}
}
Alıntı yapılan: yldzelektronik - 10 Eylül 2013, 11:17:29
Uzunluğu sabit olmayan string veriyi usart ile alırken hangi metodu kullanıyorsunuz?
gets kullandığımda sıkıntı yaşıyorum.Kullandığım terminal programlarıyla bu sıkıntıyı aşamadım.Siz nasıl metodlar kullanıyorsunuz?
karakter karakter alıp bitirme karakterini arıyorum, mesela \n\r gibi.
Alıntı yapılan: berat23 - 11 Eylül 2013, 10:34:20
karakter karakter alıp bitirme karakterini arıyorum, mesela \n\r gibi.
Kod örneği vermeniz mümkün mü?
@meftun senin yaptığının benzerini yaptım ancak nedense bir türlü o 13 karakterini yakalayamıyorum :(
Şöyle birşey yapsak uzunluğu belli olmayan veriyi rs232 ile yollarken:
1) ilk olarak ( ilk byte) gönderilecek datanın uzunluğunu yollayalım ve ardından datayı yollayalım
2) CCS C de verileri alırken getch(); fonk. gönderirken de putc(); fonk. kullanalım.
örnek kod (proteus da denedim)
#include <16f877a.h>
#fuses XT,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD
#use delay (clock=4000000)
#use rs232(baud=9600, xmit=PIN_c6, rcv=PIN_c7, parity=N, stop=1)
int data[16];
int aktar[16]={1,1,2,3,4,5,6,7,13,51};
//aktar ın ilk byte uzunluk verisi gönderilecek veri
int sayac;
#int_rda
void rs232_alim()
{
disable_interrupts(int_rda);
int uzunluk; // alınacak datanın uzunluğunu icerir
uzunluk=getch();// gelen verinin uzunluk bilgisini aktardık
for(sayac=1;sayac<=uzunluk;++sayac) // veriler alınıyor.
data[sayac]=getch();
//gelen verilerden ilki uzunluk olduğundan sayac=1 den başlatıldı
//----------bu if ile gelen verilerden birini sorgulayarak dogru alım oldu mu diye baktım
// tamamen deneme amaclı
if(data[8]==13)
output_toggle(pin_b2);
else
output_toggle(pin_b3);
}
////////////////////////////////RS232_veri_basma////////////////////////////////
void veri_bas(int uzunluk)
{
aktar[0]=uzunluk;
for(sayac=0;sayac<=uzunluk;++sayac)//uzunluk byte ile uzunluk+1 kadar byte gönderilir toplamda
putc(aktar[sayac]);
output_toggle(pin_b4);// sadece veri göndermenin gerçekleştigini görmek icin
}
//*************************ANA FONKSİYON***************************************
main()
{
enable_interrupts(global);
enable_interrupts(int_rda);
output_low(pin_b2);
while(1)
{
enable_interrupts(int_rda);
if(input(pin_b0))
{
while(input(pin_b0));
veri_bas(8); // 8 gönderilecek data uzunluğu 8 byte
}
}
}
Alıntı yapılan: coderun - 11 Eylül 2013, 12:21:25
Şöyle birşey yapsak uzunluğu belli olmayan veriyi rs232 ile yollarken:
1) ilk olarak ( ilk byte) gönderilecek datanın uzunluğunu yollayalım ve ardından datayı yollayalım
2) CCS C de verileri alırken getch(); fonk. gönderirken de putc(); fonk. kullanalım.
örnek kod (proteus da denedim)
#include <16f877a.h>
#fuses XT,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD
#use delay (clock=4000000)
#use rs232(baud=9600, xmit=PIN_c6, rcv=PIN_c7, parity=N, stop=1)
int data[16];
int aktar[16]={1,1,2,3,4,5,6,7,13,51};
//aktar ın ilk byte uzunluk verisi gönderilecek veri
int sayac;
#int_rda
void rs232_alim()
{
disable_interrupts(int_rda);
int uzunluk; // alınacak datanın uzunluğunu icerir
uzunluk=getch();// gelen verinin uzunluk bilgisini aktardık
for(sayac=1;sayac<=uzunluk;++sayac) // veriler alınıyor.
data[sayac]=getch();
//gelen verilerden ilki uzunluk olduğundan sayac=1 den başlatıldı
//----------bu if ile gelen verilerden birini sorgulayarak dogru alım oldu mu diye baktım
// tamamen deneme amaclı
if(data[8]==13)
output_toggle(pin_b2);
else
output_toggle(pin_b3);
}
////////////////////////////////RS232_veri_basma////////////////////////////////
void veri_bas(int uzunluk)
{
aktar[0]=uzunluk;
for(sayac=0;sayac<=uzunluk;++sayac)//uzunluk byte ile uzunluk+1 kadar byte gönderilir toplamda
putc(aktar[sayac]);
output_toggle(pin_b4);// sadece veri göndermenin gerçekleştigini görmek icin
}
//*************************ANA FONKSİYON***************************************
main()
{
enable_interrupts(global);
enable_interrupts(int_rda);
output_low(pin_b2);
while(1)
{
enable_interrupts(int_rda);
if(input(pin_b0))
{
while(input(pin_b0));
veri_bas(8); // 8 gönderilecek data uzunluğu 8 byte
}
}
}
Çok iyi örneklenmiş teşekkürler.Ancak yaşadığım soruna çözüm değil ne yazık ki.Çünkü sorun pc tarafında terminal ile mcu üzerindeki menüye ulaşmak.Menüye giriş için karakterler genelde tek byte ancak bazen 3 4 belki 6 byte olabiliyor.Değer atamaları için.Kullanıcının terminalde kaç karakter göndereceğini eklemesi çok uygun olmaz sanırım?
İşin diğer boyutu her menünün bir de alt menüsü var ki en az bir alt menü.Hal böyle olunca biraz karışıyor.Mcudan mcuya rs232 üzerinden gönderim yapmak istediğimde sorun yok ancak pcden mcuya farklı uzunluklarda string göndermek istediğimde mecburen \r karakterini bekliyorum.Ancak terminal programlarıyla \r karakterini gönderemiyorum. ???
Monitör programıyla seri protu gözlüyorum ve gönderdiğim veriler arasında \r yada \n karakteri yok.
Şöyle ki;
(http://img713.imageshack.us/img713/8967/3n3i.jpg)
Benim terminalde menüye eriştiğimde elde etmem gereken görüntü;
(http://img855.imageshack.us/img855/6162/9brg.jpg)
gets() kullandığımda \r gelmeyince çakılıp kalıyor.getch kullansam tek karakter alabiliyorum.getc ile döngüye girsem iki ihtimal var.
Ya belli uzunlukta string alıcam yada enter bekleyecem ki getsden farkı yok.İlk ihtimali düşünsek sorun da bu zaten.String uzunluğu belli değil.En büyük string uzunluğu kadar döngü kursam kullanıcı her seferinde o kadar karakter göndermek zorunda kalıyor.
Mesela en fazla 6 karakter olsun.Döngüyü 6 karakter için kurduğumda 1 karakterle menüye erişilebilecek yerlerde dahi 6 karakter göndermesi gerekiyor ki bu rahatsız edici ve hiç kullanışlı değil.
Acaba ben mi büyütüyorum olayı?Biri fikir verebilir mi?
Acaba C ile
12345
23451
34512
45124
51234
nasıl yazabiliriz.
Alıntı yapılan: Fkarizmatik - 11 Eylül 2013, 13:11:28
Acaba C ile
12345
23451
34512
45124
51234
nasıl yazabiliriz.
Bu benim soruma cevaben mi yazıldı?
@yldzelektronik kendine bir protokol yapmalısın. Mesela her verinin sonunda \r olursa verisonu geldigini anlamış olursun. Veriyide kesme ile almalısın. Her kesmede gelen veriyi kontrol ederk \r gelmişse bir bayragı setleyerek main içerisinde ilgili işlemi yapıp bayragı sıfırlamalısın, temel yapı bu şekilde.
@Fkarizmatik Bu rakamlar bir dizide olsun. Diziyi ekrana bastıktan sonra dizi uzunlugu kadar bir döngüde
{
temp=dizi;
dizi=dizi[i+1];
dizi[i+1]=temp;
}
böylece dizinin yanyana iki elemanını yer değiştirdik.temel yapı bu şekilde, daha optimum birşeylerde yazılabilir.
Alıntı yapılan: kantirici - 11 Eylül 2013, 13:49:38
@yldzelektronik kendine bir protokol yapmalısın. Mesela her verinin sonunda \r olursa verisonu geldigini anlamış olursun. Veriyide kesme ile almalısın. Her kesmede gelen veriyi kontrol ederk \r gelmişse bir bayragı setleyerek main içerisinde ilgili işlemi yapıp bayragı sıfırlamalısın, temel yapı bu şekilde.
Gelen veriyi kesme ile alıyorum
\r sorgusu yaptığım için programım çakılıyor.
Sorun gelen veriyi yakalamak da değil.Gelen veri içerisinde \r olmamasından kaynaklanıyor.
Mcu to mcu olduğunda sorun yok.
Sadece terminal gibi programlar kullandığımda bu sorunu yaşıyorum.
https://www.picproje.org/index.php/topic,35908.msg364197.html#msg364197 (https://www.picproje.org/index.php/topic,35908.msg364197.html#msg364197)
resimlerle gösterdiğim gibi porta pcnin yazdığı verilerde \r yok.
Zaten bütün mesele de bu. ???
@yldzelektronik
şimdi kod veremem fakat beklerseniz akşam eve gidince birşeyler paylaşabilirim. ben gps mesajlarını parse ederken kullanmıştım, aşşağı yukarı benzer bir mantık. uyduya bağlandığında mesaj daha uzun oluyordu, bağlanamadığı zaman daha kısa oluyordu.
Alıntı yapılan: berat23 - 11 Eylül 2013, 14:43:38
@yldzelektronik
şimdi kod veremem fakat beklerseniz akşam eve gidince birşeyler paylaşabilirim. ben gps mesajlarını parse ederken kullanmıştım, aşşağı yukarı benzer bir mantık. uyduya bağlandığında mesaj daha uzun oluyordu, bağlanamadığı zaman daha kısa oluyordu.
Halen beklemedeyim.
Alıntı yapılan: kantirici - 11 Eylül 2013, 13:49:38
@yldzelektronik kendine bir protokol yapmalısın. Mesela her verinin sonunda \r olursa verisonu geldigini anlamış olursun. Veriyide kesme ile almalısın. Her kesmede gelen veriyi kontrol ederk \r gelmişse bir bayragı setleyerek main içerisinde ilgili işlemi yapıp bayragı sıfırlamalısın, temel yapı bu şekilde.
@Fkarizmatik Bu rakamlar bir dizide olsun. Diziyi ekrana bastıktan sonra dizi uzunlugu kadar bir döngüde
{
temp=dizi[i+1];
dizi=dizi[i+1];
dizi[i+1]=temp;
}
böylece dizinin yanyana iki elemanını yer değiştirdik.temel yapı bu şekilde, daha optimum birşeylerde yazılabilir.
Çift boyutlu bir dizide gösterebilirmisiniz hocam
Çift boyutlu derken biraz daha açarmısınız? Dizinin satır ve sutünları arasındamı değiştirmek istiyorsunuz?
Yukaridaki belirttigim 5x5 matrisin algoritmasini cozemedim Ornekbir program ile yardimci olabilirmisiniz Cift bouytlu dizilerde swap islemini anlamadim.
Tesekkurler iyi forumlar
Selamlar.
Eepromda bir tablo oluşturmak istiyorum.Cihazın açılışta default değerleri tutabilmesi için.
Ancak sol tarafı 4 sağ tarafı 2 haneli bir sayıyı en verimli ve hızlı okuyup yazabilmek şartıyla eeproma nasıl yazdırabilirim?
Alıntı yapılan: yldzelektronik - 13 Eylül 2013, 17:20:25
Selamlar.
Eepromda bir tablo oluşturmak istiyorum.Cihazın açılışta default değerleri tutabilmesi için.
Ancak sol tarafı 4 sağ tarafı 2 haneli bir sayıyı en verimli ve hızlı okuyup yazabilmek şartıyla eeproma nasıl yazdırabilirim?
Hocam haneleri belirtmişsiniz ancak biraz daha detaya inebilir misiniz? 2048'e kadar sayıları 11 bit ile saklayabilirsiniz ancak 9999 için en az 14-bit gerekiyor. İki haneli sayı 99'a kadar olacaksa 7-bit yeterli.
Boyutu küçültmek için bu şekilde bit hesabı yapmalısınız. Hız konusu işlemciye bağlı. Mimari 8-bit ise 16-bit sol ve 8-bit sağ olarak 3 baytlı bir yapı olur. Ancak 16-bit işlemcide verilerin 16-bit olması işlem hızını arttıracaktır.
İyi çalışmalar...
Alıntı yapılan: fatih6761 - 13 Eylül 2013, 18:09:52
Hocam haneleri belirtmişsiniz ancak biraz daha detaya inebilir misiniz? 2048'e kadar sayıları 11 bit ile saklayabilirsiniz ancak 9999 için en az 14-bit gerekiyor. İki haneli sayı 99'a kadar olacaksa 7-bit yeterli.
Boyutu küçültmek için bu şekilde bit hesabı yapmalısınız. Hız konusu işlemciye bağlı. Mimari 8-bit ise 16-bit sol ve 8-bit sağ olarak 3 baytlı bir yapı olur. Ancak 16-bit işlemcide verilerin 16-bit olması işlem hızını arttıracaktır.
İyi çalışmalar...
sayı maksimum 1100.00 olabiliyor.En az 800.00.Küsüratta da evet .99 en fazla.
Ben sprintf ile stringe çevirip 7 byte ile hallederim diye düşündüm ancak sizin dediğiniz yöntemi biraz açar mısınız?Anlamadım.
Hocam sayılar floating point ise iş değişir. Küsürat iki basamaksa floating point sayıları fixed point'e çevirerek kaydedebilirsiniz. Ya da her floating point sayı 32-bit yer tutar. İki tanesi 8-byte eder. String'e çevirip yazma okuma yapmakla doğrudan floating point yazıp okumak arasında dağlar kadar fark var. Stringe çevirmek en kötü olasılık. Yazdığınız yere bakarak C dili kabul ediyorum. Bu konuda derleyicinin dökümanlarını biraz araştırın.Standart 32-bit floating sayı kullanıyorsa bir pointer ile hallolur. Örneğin:
// yazma
float key = 1000.0f; // sondaki f önemli sebebi çok defa anlatıldı.
int * keyptr = &key;
eeproma_yaz(keyptr, 4); // keyptr adresinden itibaren 4-byte yazılacak
// okuma
char keyArray[4];
eepromdan_oku(keyArray, 4); // keyArray dizisine 4-byte eepromdan oku
float key = *((float *)keyArray);
Alıntı yapılan: yldzelektronik - 13 Eylül 2013, 18:32:26
sayı maksimum 1100.00 olabiliyor.En az 800.00.Küsüratta da evet .99 en fazla.
Toplam 3 bayt ile kaydedilebilir.
Sayının tam kısmı en fazla 1100 değil 66536 kadar büyük bile olsa 16 bit yani 2 bayt ile kaydedilebilir, ondalıklı kısmı maksimum 99 değil 255 bile olsa 1 baytta halledilebilir.
1100=0x044C yani 16 bit(2bayt)
99=0x69 yani 8 bit(1bayt)
Ccs helpinde float ile ilgili yer alan bilgiler şöyle:
(http://t1309.hizliresim.com/1f/g/sphv3.jpg)
(http://m1309.hizliresim.com/1f/g/sphvh.jpg)
Ayrıca ex_float.c diye örnek kodu var.O da şöyle:
/////////////////////////////////////////////////////////////////////////
//// EX_FLOAT.C ////
//// ////
//// This program shows input, output and standard operations with ////
//// floating piont numbers. I/O is RS232. ////
//// ////
//// Jumpers: ////
//// PCM,PCH pin C7 to RS232 RX, pin C6 to RS232 TX ////
//// ////
//// This example will work with the PCM and PCH compilers. The ////
//// following conditional compilation lines are used to include a ////
//// valid device for each compiler. Change the device, clock and ////
//// RS232 pins for your hardware if needed. ////
/////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996,2003 Custom Computer Services ////
//// This source code may only be used by licensed users of the CCS ////
//// C compiler. This source code may only be distributed to other ////
//// licensed users of the CCS C compiler. No other use, ////
//// reproduction or distribution is permitted without written ////
//// permission. Derivative programs created using this software ////
//// in object code form are not restricted in any way. ////
/////////////////////////////////////////////////////////////////////////
#if defined(__PCM__)
#include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#elif defined(__PCH__)
#include <18F452.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#endif
#include <stdlib.h>
#include <input.c>
void main() {
long int l;
float a, b;
while(TRUE) {
printf("\r\nEnter first number: ");
a=get_float();
printf("\r\nEnter second number: ");
b=get_float();
printf("\r\n\nA= %E\r\n", a);
printf("B= %E\r\n", b);
printf("\r\na + b = %E", a + b);
printf("\r\na - b = %E", a - b);
printf("\r\na * b = %E", a * b);
printf("\r\na / b = %E\r\n", a / b);
if(a <= b)
printf("a<=b, ");
else
printf("a>b, ");
if(a < b)
printf("a<b, ");
else
printf("a>=b, ");
if(a == b)
printf("a==b\r\n");
else
printf("a!=b\r\n");
l = (long int)a;
printf("\r\n(long)a = %lu ", l);
a = (float)l;
printf("\r\n(float)(long)a = %E\r\n", a);
}
}
Resimlerden birinde benim dikkatimi çeken ifade;
CCS uses the same format Microchip uses in the 14000 calibration constants
Merak ettiğim ccs nin kullandığı float sayılar standartlara uygun olan mı?(ifade ne kadar doğru oldu bilmiyorum ama kastım standart c nin ne tarafında olduğu) Ayrıca double için;
double
Is a reserved word but is not a supported data type.
ifadesine yer vermiş.Ne demektir?Ayrılmış fakat desteklenmiyor ne demektir?
Çözüm için meftunun bahsettiği üzere
void write_eepromfloat(char position_eeprom,float flt){
int16 katsayi = flt;
char kusurat = (flt - katsayi) * 100;
write_eeprom16bit(position_eeprom,katsayi);
write_eeprom(position_eeprom + 2,kusurat);
}
float read_eepromfloat(position_eeprom){
float katsayi = read_eeprom16bit(position_eeprom);
float kusurat = (float)read_eeprom(position_eeprom + 2) / 100;
float flt = katsayi + kusurat;
return flt;
}
şeklinde bir yöntem denedim ve çalışıyor.Ancak bir sıkıntı var.Bazı sayılarda 0.01 eksik değer dönüyor..Sebebini anlayamadım.Öyle lineer de değişmiyor.
Yani 12.12 de aynı değer dönüyor.Ancak 123.12 den dönen değer 123.11 65535.25 den dönen değer 65535.25 .Garipsedim biraz.Sebebi ne ola ki?
Hocam bu kadar sıkıştırmaya ihtiyacınız var mı gerçekten? 3-bayt yerine 4-bayt olması çok önemli değilse bir önceki mesajımda verdiğim yöntemi uygulayın. Hatta CCS C içinse doğrudan kodu vereyim:
void write_eepromfloat(int8 addr, float val){
int8 * ptr = &val;
write_eeprom(addr, *(ptr));
write_eeprom(addr+1, *(ptr+1));
write_eeprom(addr+2, *(ptr+2));
write_eeprom(addr+3, *(ptr+3));
}
float read_eepromfloat(int8 addr){
int8 data[4];
data[0] = read_eeprom(addr);
data[1] = read_eeprom(addr + 1);
data[2] = read_eeprom(addr + 2);
data[3] = read_eeprom(addr + 3);
return *((float *)data);
}
Bu yöntemle float veri tipinin tüm hassasiyetini kullanabilirsiniz. Hem de hiç bir hatalı değer olmadan.
Eğer sayın float ise: göstergede tam değeri göremezsin. Kaç hane ggösteriyorsan ona göre yuvarlanmış halini görürsün.
Örneğin:
Sayı 123.1156 bu sayıyı noktadan sonra 2 hane görmek istersen 123.12 görürsün.
kaydederken noktadan sonraki haneleri 100 ile çarptın. 0.1156 * 100 = 11,56 olur. Bunu tamsayıya çevirip yazdığında 11 olarak kaydedersin ve 11 olarak okursun.
Sayılarla bu şekilde oynayarak eeprom'a kaydetmek benim önereceğim bir yöntem değil. Float sayı 4 byte. o zaman 4 bytaolarak kaydedeceksiniz. Hızlı olsun demişsiniz ama bölme çarpma işlemleri için bir sürü zaman harcamışsınız. Bence verimsiz bir yöntem.
Bence doğru olan @fatih6761 arkadaşın söylediği gibi pointer ile tüm 4 bayt kaydedip geri 4 byte olarak okumak.
önereceğim yöntem bu.
void ee_write_float(unsigned int addr , float *floatptr){
unsigned char edata;
unsigned int I;
for(I=0;I<4;I++){
edata = *((unsigned char *)floatptr+I);
ee_write_byte(addr+I,edata);
}
}
void ee_read_float(unsigned int addr , float *floatptr){
unsigned char edata;
unsigned int I;
for(I=0;I<4;I++){
edata=ee_read_byte(I+addr);
*((unsigned char *)floatptr+I) = edata;
}
}
float sayi = 123.567
ee_write_float(adres , &sayi);
ee_read_float(adres , & sayi);
başka bir yol ise
typedef union
{
float f;
char c[4];
}FtoC;
void ee_write_float ( int adres, float sayi)
{
FtoC x;
x.f = sayi;
for( char i =0 i< 4; i++)
{
eeprom_write_byte(i+adres, x.c[i];
}
}
float ee_read_float(int adres)
{
FtoC x;
for(char i =0; i< 4; i++)
{
x.c[i] = ee_read_byte(adres);
}
return(x.f);
}
Alıntı yapılan: fatih6761 - 14 Eylül 2013, 14:50:13
Hocam bu kadar sıkıştırmaya ihtiyacınız var mı gerçekten? 3-bayt yerine 4-bayt olması çok önemli değilse bir önceki mesajımda verdiğim yöntemi uygulayın. Hatta CCS C içinse doğrudan kodu vereyim:
void write_eepromfloat(int8 addr, float val){
int8 * ptr = &val;
write_eeprom(addr, *(ptr));
write_eeprom(addr+1, *(ptr+1));
write_eeprom(addr+2, *(ptr+2));
write_eeprom(addr+3, *(ptr+3));
}
float read_eepromfloat(int8 addr){
int8 data[4];
data[0] = read_eeprom(addr);
data[1] = read_eeprom(addr + 1);
data[2] = read_eeprom(addr + 2);
data[3] = read_eeprom(addr + 3);
return *((float *)data);
}
Bu yöntemle float veri tipinin tüm hassasiyetini kullanabilirsiniz. Hem de hiç bir hatalı değer olmadan.
Hocam teşekkür ederim 6 haneye kadar denedim ve tık fark yok.Girdiğim değer aynı şekilde çalışıyor.
Yalnız kodu biraz açıklar mısın?
write_eeprom(addr, *(ptr));
satırıyla eeproma ptrnin adres değerini mi yazdırıyoruz?
int8 * ptr = &val;
satırıyla val değişkeninin adresini almıyor muyuz?
Ben her yeni değer girdiğimde farklı adreslere mi atanıyor bu değişken?Anlayamadım?
@Klein
Alıntı yapılan: Klein - 14 Eylül 2013, 14:54:45
...
önereceğim yöntem bu.
...
başka bir yol ise
typedef union
{
float f;
char c[4];
}FtoC;
void ee_write_float ( int adres, float sayi)
{
FtoC x;
x.f = sayi;
for( char i =0 i< 4; i++)
{
eeprom_write_byte(i+adres, x.c[i];
}
}
float ee_read_float(int adres)
{
FtoC x;
for(char i =0; i< 4; i++)
{
x.c[i] = ee_read_byte(adres);
}
return(x.f);
}
Anlamadığım kısımlar var.
ee_write içinde sadece x.cyi yazdırmışsın.Ancak float sayı x.f içinde doğru mu?Peki x.c ye hiçbir müdahele yapmadan neden onu yazdırdın?Ekleme: Union olduğunu farkettim.Ki bu da aynı bellek alanına farklı isimlerle erişme imkanı sağlıyor.
@yldzelektronik hocam siz fonksiyonu çağırdığınızda sayının stack'de bir kopyası oluşturulur ve fonksiyon bu kopyaya ulaşır.
int8 * ptr = &val;
kısmında dediğiniz gibi bir int8 pointer oluşturuyoruz ve bu pointer'da float değişkenimizin adresini veriyoruz. Yani ptr, val'in adresini taşıyor. float 4 bayt ama biz bu ptr ile her baytı birer int8'miş gibi adresleyebiliyoruz.
Eeproma yazarken *ptr (bu*(ptr) ile aynıdır) ptr'nin işaret ettiği adresteki bir baytı ifade eder. Eeproma bellekten sırayla 4-baytı yazıyoruz.
İyi çalışmalar, kolay gelsin...
Alıntı yapılan: fatih6761 - 14 Eylül 2013, 15:38:12
@yldzelektronik hocam siz fonksiyonu çağırdığınızda sayının stack'de bir kopyası oluşturulur ve fonksiyon bu kopyaya ulaşır.
int8 * ptr = &val;
kısmında dediğiniz gibi bir int8 pointer oluşturuyoruz ve bu pointer'da float değişkenimizin adresini veriyoruz. Yani ptr, val'in adresini taşıyor. float 4 bayt ama biz bu ptr ile her baytı birer int8'miş gibi adresleyebiliyoruz.
Eeproma yazarken *ptr (bu*(ptr) ile aynıdır) ptr'nin işaret ettiği adresteki bir baytı ifade eder. Eeproma bellekten sırayla 4-baytı yazıyoruz.
İyi çalışmalar, kolay gelsin...
Hocam kusura bakma biraz zor anlıyorum.
Şimdi *ptr ile oluşturduk.
*ptr = &value ile float value nin bellekteki adresini yazdık.Yani daha valuenin değeriyle ilgilenmedik.Doğru mu?
Eğer böyle ise şöyle bir şey oluyor.Benim elimde ptr içinde duran bir adres var ve bu adres sıralı 4 byte ile float bir sayı taşıyor.Peki ben o adresteki değeri ptr ile nasıl görücem?
write_eeprom(adres,*prt); ile ben parametre olarak valuenin adresinin ilk bytenı geçtim?
Şöyle;
float value = 123.123; // Bellekte 0x00 adresinde.
int *ptr = &value; //ptrnin içinde 0x00 oldu.
Ben herhangi bir yere *ptr olarak geçersem 0x00 adresinin ilk byte olarak taşıdığı değere erişiyorum.Yani 123.123 4 bytelık sayısının ilk bytena eriştim.Doğru mu?
Yani o zaman şu oluyor;
*ptr ile
ptr kullanımı fark ediyor. Doğru mu?
Bir yere *ptr olarak geçersem adresin taşıdığı değere, ptr olarak geçersem o adrese yani buradaki 0x00 a erişirim.Doğru mu?
Teşekkürler.
Hocam pointer in adresine ulaşmak icin ne yapmaliyiz? Yine bir pointer mi tanimlamaliyiz? Baska bir soru da, pointer kullaniminda herhangi bir sinirlama var mi?
Alıntı yapılan: mir_as82 - 14 Eylül 2013, 16:16:01
Hocam pointer in adresine ulaşmak icin ne yapmaliyiz? Yine bir pointer mi tanimlamaliyiz? Baska bir soru da, pointer kullaniminda herhangi bir sinirlama var mi?
Pointer türünden bir pointer tanımlamak için iki tane ** operatörü kullanılır.
int **ipp;
int i = 5;
int *ip1 = &i;
ipp = &ip1;
Sınırlama olayı hafıza kapasitesi ile ilgili bir durum.
Alıntı yapılan: mir_as82 - 14 Eylül 2013, 16:16:01
Baska bir soru da, pointer kullaniminda herhangi bir sinirlama var mi?
visual c++ ta sınırlama var, bellekteki bütün verileri okuyayım derseniz; güvenlik sebebiyle, compile etmenize izin vermiyor. Sadece programınızdaki belli başlı adresleri okuyabiliyorsunuz. Ancak standart c++ ta böyle değil.
İşletim sistemi varsa bellek koruma ünitesi engeller. @Meftun hocamın da dediği gibi derleyici de bunu engelleyebilir ancak koda birkaç satır ekleyerek derleyicinin bu özelliği kapatılabilir.
https://www.picproje.org/index.php/topic,35908.msg364869.html#msg364869 (https://www.picproje.org/index.php/topic,35908.msg364869.html#msg364869)
Ne oldu şimdi?Doğru mu yanlış mı?
Bu konu altında oldukça faydalı tartışmalar oluyor ancak tek bir konu başlığı altında olması takibi zorlaştırıyor.
Bu mesajın altına açılan yeni konular farklı adlarla C programlama bölümü adı altında açılsa daha faydalı olacağını düşünüyorum.
Alıntı yapılan: yldzelektronik - 14 Eylül 2013, 15:47:39
......
float value = 123.123; // Bellekte 0x00 adresinde.
int *ptr = &value; //ptrnin içinde 0x00 oldu.
Ben herhangi bir yere *ptr olarak geçersem 0x00 adresinin ilk byte olarak taşıdığı değere erişiyorum.Yani 123.123 4 bytelık sayısının ilk bytena eriştim.Doğru mu?
Yani o zaman şu oluyor;
*ptr ile
ptr kullanımı fark ediyor. Doğru mu?
Bir yere *ptr olarak geçersem adresin taşıdığı değere, ptr olarak geçersem o adrese yani buradaki 0x00 a erişirim.Doğru mu?
Teşekkürler.
float value = 123.123; // Bellekte 0x00 adresinde.
int *ptr = &value; //ptrnin içinde 0x00 oldu.
Yanlis.
Dogrusu;
float value = 123.123; // Bellekte 0x00 adresinde.
float *ptr = &value; //ptrnin içinde 0x00 oldu.
*ptr ile
ptr kullanımı fark ediyor. Doğru mu?
Elbette farkli. *ptr ile pointerin gosterdigi hedefe erisiyorsun. Yildiz olmadan tek basina ptr oldumu pointere erisiyorsun.
Bir yere *ptr olarak geçersem adresin taşıdığı değere, ptr olarak geçersem o adrese yani buradaki 0x00 a erişirim.Doğru mu?
Yanlis. Dogrusunu bir ust satirda acikladim. *ptr ile pointerin gosterdigi hedefe (adrese ulasirsin) bu tamam. ptr ile pointere ulasirsin.
Alıntı yapılan: yldzelektronik - 16 Eylül 2013, 09:00:28
https://www.picproje.org/index.php/topic,35908.msg364869.html#msg364869 (https://www.picproje.org/index.php/topic,35908.msg364869.html#msg364869)
Ne oldu şimdi?Doğru mu yanlış mı?
Hocam mikrodenetleyicide herhangi bir işletim sistemi kullanmadığınızdan bu tür kontroller yok, dolayısıyla verdiğim kod doğru. Ayrıca, kontrol olsaydı da hata vermezdi, çünkü zaten float için ayrılan 4-byte bize ait. İster char ptr ile, ister int ptr ile erişebiliriz.
while((SSP1CON2 & 0x1F) | STAT_RW));
Satırı tam olarak ne anlam taşıyor? Biraz kafam karıştı. İlk parantez ile ikinci şart or lanıyor mu?İlk parantez veya ikinci yazan olduğu sürece anlamına mı geliyor?
Hocam hata vermesi lazım , parentezlerde problem var.
Alıntı yapılan: armsistem - 02 Ekim 2013, 16:51:45
Hocam hata vermesi lazım , parentezlerde problem var.
Bir parantez fazla fark ettim şimdi ancak henüz derlemedim.Sondaki parantezin biri olmayacak.Ancak halen ne olduğu çözülmüş değil?
Alıntı yapılan: yldzelektronik - 02 Ekim 2013, 16:42:10
while((SSP1CON2 & 0x1F) | STAT_RW));
Satırı tam olarak ne anlam taşıyor? Biraz kafam karıştı. İlk parantez ile ikinci şart or lanıyor mu?İlk parantez veya ikinci yazan olduğu sürece anlamına mı geliyor?
Parantez hatasından ayrı olarak bu satırla iki sayı aralarında lojik OR işlemine tabii tutuluyor ve sonuç sıfırdan farklı ise döngünün içerisine giriyor. Burada ki OR işlemi şunu ifade etmiyor SSP1CON2&0x1f işlemi veya STAT_RW sayısı 0 dan farklıysa dallan yerine bu sayıları aralarında OR işlemine tabi tutarak en sonunda karar veriyor. Misal
0b001
0b101 bitsel or işlemine tabii tutulursa sonuç 0b101 olacak ve while döngüsüne girilecektir.
Teşekkürler.Peki orada SSP1CON2 bir struct ve ben şimdi derlediğimde hata alıyorum.Yapıya bu şekilde erişmem mümkün değil mi?
Yapı şöyle tanımlı;
struct {
int1 BF; //Bufferın doluluk durumu hakkında bilgi tutar.
//Veri Alma Modunda Veri Gönderme Modunda
//1==>Veri alımı tamamlandı ve SSPBUF dolu. 1==>Gönderme yapılıyor ve SSPBUF dolu.
//0==>Veri alımı tamamlanmadı ve SSPBUF boş. 0==>Gönderme tamamlanmadı ve SSPBUF boş.
int1 UA; //10bitlik I2C modunda adres güncelleme bitidir.
int1 R_W; //I2C modunda okuma/yazma yapıldığının bilgisini tutar.
// Master Modda Slave Modda
// 1==> Veri iletimi yapılıyor. 1==>Oku
// 0==> Veri iletimi durdu. 0==>Yaz
int1 S; //Start biti.
int1 P; //Stop biti.
int1 D_A; //Data veya Adres biti.
int1 CKE; //SmBus aktif etme biti.
int1 SMP; //Standart hız modu için çevrim hızı kontrolü pasif/aktif (1/0)
}SSP1STAT;
#byte SSP1STAT = 0x214 //0x214
Not : derleyici ccs c 5
mesaj birleştirme:: 02 Ekim 2013, 17:25:54
Soruyu şöyle düzelteyim.
Mcunun registerlerine direkt olarak erişmek istiyorum.Ccs kullandığımdan donanım destekli i2c fonksiyonu yazmak sıkıntı yaşatıyor.
Bu yüzden xc8 in mcu headerlerinde yaptığı gibi yapmak istedim.Gayet kullanışlı geldi.
Her register için yapı tanımlamış ve o yapı türünde bir değişken tanımlamış ve o değişkene direkt olarak registerin adresini vermiş.Bunu nasıl yapabilirim?
@yldzelektronik madem reg. düzeyinde çalışmak istiyorsunuz bence ccs c ile vakit harcamadan direk xc8e yönelin. Bildigim kadarıyla ccs c de her portun, her reg. adresini tanımlayıp öyle kullanmak gerekiyor.
Alıntı yapılan: kantirici - 02 Ekim 2013, 18:21:26
@yldzelektronik madem reg. düzeyinde çalışmak istiyorsunuz bence ccs c ile vakit harcamadan direk xc8e yönelin.
Ben de istiyorum ama hazırda kütüphanelerim yok.Bir de orada kütüphane oluşturmak için vakit harcarsam işler iyice yavaşlar.
CCS bilmediğim için Standart C'deki TypeCasting örneği vereyim. Siz CCS' uyarlayın.
struct
{
....
}x;
*((int *) x) = 1234;
veya
int *a;
a = (int *)x;
*a = 1234;
Sorunu şimdilik şöyle çözdüm;
while((*1234 & 0x1F) | SSP1STAT.R_W);
* koyduğumda ona adres muamelesi yaptı demek ki.Yanılıyor muyum?
*((int *) x) = 1234
Bu kod icin konusalim:
(int*)x Demek, x olarak verilen degeri adres olarak donusum yapti.
Daha sonra,
*((int*)x) kodu ile o adresin icine 1234 degerini yazdi.
Yani İlk* casting icin.
İkincisi ise adresin icine veri yazmak icin
Alıntı yapılan: mir_as82 - 03 Ekim 2013, 07:17:21
*((int *) x) = 1234
Bu kod icin konusalim:
(int*)x Demek, x olarak verilen degeri adres olarak donusum yapti.
Daha sonra,
*((int*)x) kodu ile o adresin icine 1234 degerini yazdi.
Yani İlk* casting icin.
İkincisi ise adresin icine veri yazmak icin
Süper.
O halde ben dizi oluşturup o diziye yapının başlangıç adresini verip for döngüsü içinde yapının istediğim elemanına erişebilirim..Yanlız merak ettiğim bir şey var.Sizeof işleci yapılarda işe yarıyor mu?
Şöyle bir örnek ekleyeyim.
char x[4] = {1,2,3,4};
unsigned long y;
y= *((unsigned long *)&x[0]);
İşleminin sonucunda y de 04030201 yani 01020304 değeri atanır. Böylece bir dizi (bu bir struct olabilir) elemanlarına bir bütünmüş (unsigned long) gibi
işlem yapabiliriz.
Alıntı yapılan: yldzelektronik - 03 Ekim 2013, 09:15:10
Yanlız merak ettiğim bir şey var.Sizeof işleci yapılarda işe yarıyor mu?
while (*katar != '\0')
{
katar++;
katar_uzunluğu++;
}
printf("bu pointer %d karakterdir...",katar_uzunluğu);
sizeof() veri tipinin byte cinsinden uzunluğunu verir. Yani bir pointer kullandığınız platforma göre 4 byte da olabilir 2 byte da. Eğer struct içinde pointerlar varsa sizeof bunların gösterdiği yerdeki veriyi hesaba katmaz.
Alıntı YapŞöyle bir örnek ekleyeyim.
Kod: [Seç]
char x[4] = {1,2,3,4};
unsigned long y;
y= *((unsigned long *)&x[0]);
İşleminin sonucunda y de 04030201 yani 01020304 değeri atanır. Böylece bir dizi (bu bir struct olabilir) elemanlarına bir bütünmüş (unsigned long) gibi
işlem yapabiliriz.
hocam bu bilgi için teşekkürler. Bir eksik daha gitti :)
Derleyici için "C" ile 'C' arasında ne fark var?Neden tek karakter olduğunda ' ' aralığında olmak zorunda?
Alıntı yapılan: yldzelektronik - 08 Ekim 2013, 10:43:41
Derleyici için "C" ile 'C' arasında ne fark var?Neden tek karakter olduğunda ' ' aralığında olmak zorunda?
Hocam "C" string tir 'C' ise karakterdir.Bir string bellekte en az iki byte lık yer ayrılır çünkü derleyici otomatik olarak string in sonuna '\0' karakterini koyar fakat karater için en az 1 byte gerekir.Ayrıca stringler aslında adrestir.Yani bi string in adı onun ilk karakterinin adresidir.
Alıntı yapılan: yamak - 08 Ekim 2013, 11:24:10
Hocam "C" string tir 'C' ise karakterdir.Bir string bellekte en az iki byte lık yer ayrılır çünkü derleyici otomatik olarak string in sonuna '\0' karakterini koyar fakat karater için en az 1 byte gerekir.Ayrıca stringler aslında adrestir.Yani bi string in adı onun ilk karakterinin adresidir.
Anladım.
Teşekkürler.
Şimdi bir konuda canım sıkıldı.;
rom float Birim[4] = {100,0.1f,1,1};
Şeklinde bir dizim var.Görüldüğü üzere burada sadece 0.1 yüzünden bu diziyi float tanımlıyorum ve çok yer kaplıyor.Alanım daralıyor ve optimizasyona gitmem gerek.
O eleman 0.1 olarak kalmak durumunda çünkü dizinin ilgili elemanını direk formülde kullanıyorum.Aklıma şu geldi;
Ben o diziyi char tanımlasam ve 0.1f şeklinde ilk değeri kalsa ve formülde ilgili yerde formülün başına (float) şeklinde tanımlama koysam uygun değer çıkar mı?
Veya daha uygun ne yapılabilir?
#mufitsozen abiydi sanırım.Fixed point sayılardan bahsetti.Biraz bakındım ancak çok bir şey bulamadım.
Ne yapılabilir?
Teşekkürler.
Ekleme:
//Bu değişkenlerin hangi bellek bölgesinde tutulduğunu söyleyebilir misiniz?
char degisken;
char degisken = 12;
static char degisken;
static char degisken = 23;
const char degisken = 43;
static const char degisken = 56;
rom char degisken;
Teşekkürler.
Merhaba,
Benim ilk akılma gelen şey,
Tüm sayıların 10 katını kullan. Dolaysıyla float sayıdan kurtulmuş olursun. ilgili formülde sayısı float'a cevirip sonra 10'a bölüp öyle fonksiyonuna verirsen hiçbir problem kalmaz.
Selamlar
Hocam struct kullabilirsiniz.
typedef struct
{
char dizi[3];
float flt;
}birim;
Tabi bu şekilde yaparsanız struct ın boyutu 7 byte dan büyük çıkabilir tam 7 byte olmasını istiyosanız aşağıdki gibi tanımlayabilirsiniz.
#pragma pack(push,1)
typedef struct
{
char dizi[3];
float flt;
}birim;
#pragma pack(pop)
Düzeltme: printf protatip için
int printf ( const char * format, ... );
verilmiş.Bu üç nokta ne demek?Bir fonksiyona parametre olarak böyle bir şey girilebilir mi?
Alıntı yapılan: yldzelektronik - 12 Ekim 2013, 10:21:58
Düzeltme: printf protatip için
int printf ( const char * format, ... );
verilmiş.Bu üç nokta ne demek?Bir fonksiyona parametre olarak böyle bir şey girilebilir mi?
Yanıt : Evet verilebilir. Bunun anlamı, değişken parametre oluyor. Printf değişken bir sürü parametresi olduğu için C'de ancak bu şekilde kullanılır.
Alıntı yapılan: arslan74 - 12 Ekim 2013, 16:44:16
Yanıt : Evet verilebilir. Bunun anlamı, değişken parametre oluyor. Printf değişken bir sürü parametresi olduğu için C'de ancak bu şekilde kullanılır.
Teşekkürler.Ancak,
Açıklaması yok mu?Bu kadar mı?
Nasıl tanımlayabilirim,nasıl kullanılır?
Örnek verebilir misiniz?
Merhaba,
Değişken parametreli fonksiyonu nerede kullanmak istiyorsunuz? Onu belirtirseniz doğrudan onun nasıl yapabiliriz diye örnek bir kod yazalım.
Eğer sadece öğrenmek için soruyorsanız, İnternet te değişken parametreli fonksiyon veya arguman listesi ("Variable-length Argument Lists") diye aratırsanız karşınıza bir sürü örnek kod çıkar. Bulduğum en basit örnek kodu yayımlıyorum.
Fonksiyonun açıklaması: Bu fonksiyon değişken uzunluktaki sayıların ortalamasını alır. fonksiyonun ilk parametresi kaç tane sayının girileceği bilgisini belirtiyor. ondan sonra gelenlerde ortalaması alınacak sayılardır.
Değişken parametrei kullana bilmek için "#include <stdarg.h>" bildirimin yapılması şart. Fonksiyon içinde bu işi gören "va_list" yapısı bildirilmesi gerekiyor. sonra uç fonksiyon kullanılıyor.
"va_start ( arguments, num );" ile girdiğimiz değer ile ilişkilendiriyor uz.
"va_arg ( arguments, double ); " türünü önceden bildiğimiz parametreleri çekiyoruz. Her çağırmadan sırayla bir sonraki parametreyi getirir.
"va_end ( arguments );" ile bu yapının içi boşaltılır.
#include <stdarg.h>
#include <stdio.h>
/* this function will take the number of values to average
followed by all of the numbers to average */
double average ( int num, ... )
{
va_list arguments;
double sum = 0;
/* Initializing arguments to store all values after num */
va_start ( arguments, num );
/* Sum all the inputs; we still rely on the function caller to tell us how
* many there are */
for ( int x = 0; x < num; x++ )
{
sum += va_arg ( arguments, double );
}
va_end ( arguments ); // Cleans up the list
return sum / num;
}
int main()
{
/* this computes the average of 13.2, 22.3 and 4.5 (3 indicates the number of values to average) */
printf( "%f\n", average ( 3, 12.2, 22.3, 4.5 ) );
/* here it computes the average of the 5 values 3.3, 2.2, 1.1, 5.5 and 3.3
printf( "%f\n", average ( 5, 3.3, 2.2, 1.1, 5.5, 3.3 ) );
}
@arslan Teşekkürler.
inline
separate
register
tam olarak nedir?Compiler help de izah etmiş ama tam anlayamadım.Anladığım kısım separate de romdan tasarruf sağlarken stack şişiriyormuş.
Açıklaması var mı bu direktiflerin?
Ekleme:Ram de istediğim adres alanlarını kendime ayırabilir miyim?
Şöyle bir sorun ile karşı karşıyayım;
50 elemanlı bir katar oluşturuyorum ve katarı ramde sıralı olarak yerleştirmiyor.İlk 5 kadar eleman sıralı,sonraki elemanları farklı adreslere yerleştiriyor.Normalde dizi değişkenler sıralı yerleştirilmez mi?
"inline" : fonksiyonun başına yazdığın zaman fonksiyon üretmek doğrudan olduğu yere kodunu yazar. Dolaysıyla fonksiyon çağırma işlemleri olmayacağını için daha hızlı çalışacaktır. Ancak C89'de yok C99 standartlarına var.
"seperate" bunu bilmiyorum. Örnek kod gösterbilirmisin.
Alıntı yapılan: arslan74 - 23 Ekim 2013, 11:38:52
Örnek kod gösterbilirmisin.
#pragma id version
#reserve 0x20:0x2f
int CYCLES; // Global cycles (note upper case)
#inline
void pulse_B0() {
#pragma use fast_io(B)
output_low(PIN_B0);
delay_ms(100);
output_high(PIN_B0);
delay_ms(100);
#pragma use standard_io(B)
}
#separate
void send_pulses() {
int cycles; // Local cycles (note lower case)
for(cycles=CYCLES; cycles!=0; --cycles) {
pulse_B0();
}
}
#pragma zero_ram
Burada reserve kullanılmış.Acaba benim sorduğum soruya cevap olabilir mi?
Alıntı yapılan: yldzelektronik - 23 Ekim 2013, 11:20:20
50 elemanlı bir katar oluşturuyorum ve katarı ramde sıralı olarak yerleştirmiyor.İlk 5 kadar eleman sıralı,sonraki elemanları farklı adreslere yerleştiriyor.Normalde dizi değişkenler sıralı yerleştirilmez mi?
Böyle bir şey olamaz. Eğer dizi oluşturulmuş ise bu sıralı olur. Aksı takdirde dizi olmaz.
Alıntı yapılan: arslan74 - 23 Ekim 2013, 11:43:38
Böyle bir şey olamaz. Eğer dizi oluşturulmuş ise bu sıralı olur. Aksı takdirde dizi olmaz.
Abi olmaz derken suçlanan ben miyim yoksa bana bunu gösteren program mı?Debug mu?Anlayamadım.
Şuan yaşadığım sorun tamamen bununla alakalı.Dizinin içinde karakter arıyorum ancak dizi sıralı olmadığından farklı adresler çıkıyor.
Alıntı yapılan: yldzelektronik - 23 Ekim 2013, 11:46:29
Abi olmaz derken suçlanan ben miyim yoksa bana bunu gösteren program mı?Debug mu?Anlayamadım.
Şuan yaşadığım sorun tamamen bununla alakalı.Dizinin içinde karakter arıyorum ancak dizi sıralı olmadığından farklı adresler çıkıyor.
Anlatığın şeyin örnekleri verirsen daha açıklayıcı olur. Bir de verdiğin örnek hangi derleyici ye ait?
Alıntı yapılan: arslan74 - 23 Ekim 2013, 11:55:08
Anlatığın şeyin örnekleri verirsen daha açıklayıcı olur. Bir de verdiğin örnek hangi derleyici ye ait?
Derleyici ccs.
Alıntı yapılan: yldzelektronik - 23 Ekim 2013, 12:05:29
Derleyici ccs.
CCS Ansi-C standartlarında uyumlu değil, yanlış biliyorsam düzeltin. Derleyicilerin bir standartları olmalı, C89 veya C99 gibi standardı olan bir derleyici ye göre konuşuyorum.
Alıntı yapılan: arslan74 - 23 Ekim 2013, 12:11:53
CCS Ansi-C standartlarında uyumlu değil, yanlış biliyorsam düzeltin. Derleyicilerin bir standartları olmalı, C89 veya C99 gibi standardı olan bir derleyici ye göre konuşuyorum.
Anladım.
Diğer sorular kaynadı ama...
Sorunun kaynağının
if (Parameters.Temp_Unit == 1){
#undef Temp_UstLimit
#define Temp_UstLimit 257f
}
else{
#undef Temp_UstLimit
#define Temp_UstLimit 125f
}
Satırları olduğunu gördüm.Bu şekilde bir kullanım hatalı mıdır?
Eklem:Sanırım meseleyi anladım.
#define tarzı tanımlamalar derleyiciye söylenen şeyler.Dolayısıyla compile time da etkisi olur.Run time da bu arkadaşlar etkisiz oluyor.Doğru mudur?
Alıntı yapılan: yldzelektronik - 23 Ekim 2013, 13:43:59
Anladım.
Diğer sorular kaynadı ama...
Sorunun kaynağının
if (Parameters.Temp_Unit == 1){
#undef Temp_UstLimit
#define Temp_UstLimit 257f
}
else{
#undef Temp_UstLimit
#define Temp_UstLimit 125f
}
Satırları olduğunu gördüm.Bu şekilde bir kullanım hatalı mıdır?
Eklem:Sanırım meseleyi anladım.
#define tarzı tanımlamalar derleyiciye söylenen şeyler.Dolayısıyla compile time da etkisi olur.Run time da bu arkadaşlar etkisiz oluyor.Doğru mudur?
Evet doğrudur. "#define" compile olmadan önce precompile ile sadece yer değiştirme olur, sonra compile olur. yani derlemeye bir etkisi olmaz. derleme öncesine ait bir olay.
Alıntı yapılan: arslan74 - 14 Ekim 2013, 03:26:00
Merhaba,
Değişken parametreli fonksiyonu nerede kullanmak istiyorsunuz? Onu belirtirseniz doğrudan onun nasıl yapabiliriz diye örnek bir kod yazalım.
Eğer sadece öğrenmek için soruyorsanız, İnternet te değişken parametreli fonksiyon veya arguman listesi ("Variable-length Argument Lists") diye aratırsanız karşınıza bir sürü örnek kod çıkar. Bulduğum en basit örnek kodu yayımlıyorum.
Fonksiyonun açıklaması: Bu fonksiyon değişken uzunluktaki sayıların ortalamasını alır. fonksiyonun ilk parametresi kaç tane sayının girileceği bilgisini belirtiyor. ondan sonra gelenlerde ortalaması alınacak sayılardır.
Değişken parametrei kullana bilmek için "#include <stdarg.h>" bildirimin yapılması şart. Fonksiyon içinde bu işi gören "va_list" yapısı bildirilmesi gerekiyor. sonra uç fonksiyon kullanılıyor.
"va_start ( arguments, num );" ile girdiğimiz değer ile ilişkilendiriyor uz.
"va_arg ( arguments, double ); " türünü önceden bildiğimiz parametreleri çekiyoruz. Her çağırmadan sırayla bir sonraki parametreyi getirir.
"va_end ( arguments );" ile bu yapının içi boşaltılır.
#include <stdarg.h>
#include <stdio.h>
/* this function will take the number of values to average
followed by all of the numbers to average */
double average ( int num, ... )
{
va_list arguments;
double sum = 0;
/* Initializing arguments to store all values after num */
va_start ( arguments, num );
/* Sum all the inputs; we still rely on the function caller to tell us how
* many there are */
for ( int x = 0; x < num; x++ )
{
sum += va_arg ( arguments, double );
}
va_end ( arguments ); // Cleans up the list
return sum / num;
}
int main()
{
/* this computes the average of 13.2, 22.3 and 4.5 (3 indicates the number of values to average) */
printf( "%f\n", average ( 3, 12.2, 22.3, 4.5 ) );
/* here it computes the average of the 5 values 3.3, 2.2, 1.1, 5.5 and 3.3
printf( "%f\n", average ( 5, 3.3, 2.2, 1.1, 5.5, 3.3 ) );
}
@arslan74 hocam burada veriler double türünden gönderilmiş.peki printf deki gibi char, int gibi farklı veri türleri gönderebiliyormuyuz bu fonksiyon yapısı ile.
Merhaba,
printf de const char dizisinden sonra ne geldiğini veriye bakararak anlayamayız. Onu girilen string'in içinde parse ederecek elde etmeliyiz.
Örneğin:
"%d %f %c"
içini analiz ettiğimizde, bütün bilgileri yazının içinde var. 2. parametre = int , 3. parametre = float , 4. parametre = yazı.
şeklinde tespit edilir. Dikkat ederseniz değişken parametre mutlaka sabit bir veya daha fazla parametre ile birlikte kullanılır. tek başına içinde değişken parametre kullanılmaz. Sebebi bu yüzden.
Merhaba,
CMSIS dosyalarını incelerken önişlemci komutları (#if, #ifdef, #ifndef) ile ilgili anlamadığım bir şey oldu..
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F4xx_IT_H
#define __STM32F4xx_IT_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
void NMI_Handler(void);
void HardFault_Handler(void);
void MemManage_Handler(void);
void BusFault_Handler(void);
void UsageFault_Handler(void);
void SVC_Handler(void);
void DebugMon_Handler(void);
void PendSV_Handler(void);
void SysTick_Handler(void);
#ifdef __cplusplus
}
#endif
#endif /* __STM32F4xx_IT_H */
Yukarda tamamını gördüğünüz dosyanın başta bulunan kısmı:
#ifndef __STM32F4xx_IT_H // __STM32F4xx_IT_H ifadesi tanımlanmamışsa
#define __STM32F4xx_IT_H // bu ifadeyi tanımla.
//__STM32F4xx_IT_H ne olarak tanımlanıyor?
"define" önişlemci komutunu kullanırken kullandığımız anahtar kelimenin hangi değerin yerine geçtiğini de belirtmek gerekir diye biliyorum. Örneğin:
#define PI 3.14
Yukardaki
#define __STM32F4xx_IT_H
satırında __STM32F4xx_IT_H ifadesinin karşılığı ne olmaktadır? Yani bu satır derleyiciye ne söylemektedir? Verdiğim örneği herhangi bir başlık dosyasından aldım. Bu tip tanımlamalar diğer başlık dosyalarında da bulunuyor.
Saygılar.
Alıntı yapılan: gerbay - 14 Kasım 2013, 19:01:36
aynı proje içerisinde farklı farklı kod dosyalarından aynı header file include edilebilir hatta başka header lar başka header lar içerisinden de include edilebilir ki bu normal bir durum, bu tür durumlarda preprocessor bir kez işlediği header file ı tekrar işlemeye çalışmasın diye öyle bir icat var.
preprocessor ilk kez o olay ile karşılaşınca kendi definition uzayında define ederek aradakileri işleyip geçer, sonra devam ederken yoluna aynı header tekrar çıkarsa daha önce define edildiğinden o ifdef in içine girmez, bu şekilde bir kez işlenmiş ve tanımlanmış olur o dosyadakiler..
buna "multiple inclusion protection" diyo gavurlar..
@gerbay hocam,
Cevap için teşekkür ederim. Peki bu durumda sorumda bahsettiğim "__STM32F4xx_IT_H" ifadesi tanım uzayının bir yerinde mutlaka bir değer ile tanımlanmış mı demektir?
Veya verdiğim örnekten yola çıkarsak. Diyelim ki "__STM32F4xx_IT_H" ifadesi hiçbir yerde tanımlanmamış ve önişlemci ilk kez aşağıdaki kodda bu ifadeyi rastladı ve ifndef 'in içine girdi. Bu durumda "__STM32F4xx_IT_H" alacağı değer ya da karşılığı ne olacaktır?
#ifndef __STM32F4xx_IT_H
#define __STM32F4xx_IT_H
Merhaba,
Bu kodu amacı, bir koduna farklı işlemcilere göre yazılıp ortak kütüphane yapması için kullanılıyor. Örneği tek bir fonksiyonunuz var ama onu çok farklı işlemcilerde yazmamız gerekir. Her seferinde hangi işlemciyi kullanıyorsanız ona göre yazılmış kodu eklemeniz gerekir. Ama tek bir fonksiyonda hangi işlemci kullanılacaksa ayrılan yerleri belirtip ona göre otomatik seçmesini sağlamak için bu yapı kullanılır.
Aşağıda örnek bir kod veriyorum. Hangi işlemci kullanılmış ise ona göre otomatik seçer.
Bu bildirimler dosyada kod içinde yazılabileceği gibi ayrıca proje içinde yazılabilir. Projeyi içinden menü ile işlemci seçilebilinir. Bu illa işlemci olmak zorunda herhangi bir özellikte olabilir.
#define islemci_a
int fonksiyon_foo(int val)
{
#ifdef islemci_a
return val*10;
#endif
#ifdef islemci_b
return val*20;
#endif
}
#define ile tanımlanan değişkene bir değer verilmesi gerekmiyor. Bu durumda o değişken sadece "tanımlı" oluyor, yani herhangi bir değeri olmuyor. gerbay hocamın bahsettiği şey bazen "header guard" olarak da adlandırılır. Tüm header dosyası ancak o baştaki ifade daha önce tanımlanmamışsa işleme sokuluyor ve ifade tanımlanıyor. Dosya ile tekrar karşılaşıldığında giriş ifadesi artık tanımlı olduğundan ön-işleyici header dosyasını tamamen gözardı eder.
Alıntı yapılan: Tagli - 14 Kasım 2013, 22:20:26
#define ile tanımlanan değişkene bir değer verilmesi gerekmiyor. Bu durumda o değişken sadece "tanımlı" oluyor, yani herhangi bir değeri olmuyor. gerbay hocamın bahsettiği şey bazen "header guard" olarak da adlandırılır. Tüm header dosyası ancak o baştaki ifade tanımlanmamışsa işleme sokuluyor ve ifade tanımlanıyor. Dosya ile tekrar karşılaşıldığında giriş ifadesi tanımlı olduğundan ön-işleyici header dosyasını tamamen gözardı eder.
@Tagli hocam, "tanımlı" olmak deyince aklıma "ne ile tanımlı olmak?" sorusu geliyor. Daha önceki örnekte bahsettiğim gibi
#define PI 3.14
dediğimde PI için 3.14 ile tanımlıyorum. Ama
#define PI
dediğim zaman bunu boş bir değer "NULL" ya da sıfır ile mi tanımlamış olacaktım?
@arslan74 hocam, örnekten ve anlattıklarınızdan sonra kafamda şöyle bir şey oluştu:
"islemci_a" seni yoktan var ettim ama şimdilik hiçbir şey değilsin. Ne olacağını, hayatın (burada tabi ki kodun :) ) akışı belirleyecek.
Olayı bu şekilde özetlesem doğru olur mu?
Alıntı yapılan: iruraz - 15 Kasım 2013, 01:22:56
#define PI
dediğim zaman bunu boş bir değer "NULL" ya da sıfır ile mi tanımlamış olacaktım?
Hayır. Sadece "PI diye birşey var" demiş olacaktın. Programın başka bir yerinde de "PI diye birşey var mı?" sorusunu sormak mümkün olacaktı böylelikle. Ama mesela "alan = PI * r * r" yazmak mümkün olmayacaktı.
Bu tür ifadeler genellikle derleme ayarlarını belirlemek için kullanılır. Örneğin yazılan kodda LCD fonksiyonları var ama bazı durumlarda cihazda LCD takılı olmuyor diyelim. Bu durumda LCD ile ilgili kodları "#ifdef LCD_KULLANILIYOR" gibi bir şeyle sarmalayabilirsin. Eğer programın başında #define LCD_KULLANILIYOR tanımlaması yoksa, o bölüm hiç derlenmez. Böylece yerden kazanırsın veya kodda onun yerine başka birşey derlenir, mesela 7 bölmeli gösterge kodu gibi. Bazen de debug kodlarını ayırmak için bu tanımlamalar yapılır.
Ayrıca, önceden tanımlanmış birşeyi tanımsız hale de getirebilirsin. Bunun için de #undef kullanılır.
Bu preprocessor komutları if-else yapısına da sahip:
#if X == 1
...
#elif X == 2
...
#else
...
#endif
yeri gelmişken sorayım PreProcess komutları (derleme öncesi komutlar) kullanılmasının amacı,
tekbir programla çeşitli ayarlarda programı aynı çatı altına almakmıdır ? Başka Amacı varmıdır
(yukarda tagli örnek vermiş)
Muhittin hocam makrolarda preprocess komutlarıdır. Gerekirse fonksiyon yerine de kullanılır.
#define DEBUG veya #define __GCC__ gibi tanımlar birer ayardır.
#define PI 3 dediğinizde PI değişkenine 3 aktarma yapılmaz. Preprocessten geçince PI yazan her yere 3 konur. Hatta utf stringlere eklenen L makrosuda bunun gibidir.
#define GET_BIT(a,b) a & (1 << b)
Burada GET_BIT fonskiyonu oluşmaz. Preprocess esnasında GET_BIT() kullanılan her yere parametre isimleri değiştirilerek makroya yazdığınız tanım yerleştirilir.
Genelde koşullu derleme için kullanılıyor. Bazen makro oluşturmak için de kullanılıyor ama bu tartışmalı bir konu. Genel kanı makroların tehlikeli olduğu yönünde.
Wikipedia'da kullanım alanları örneklerle birlikte gösterilmiş: http://en.wikipedia.org/wiki/C_preprocessor (http://en.wikipedia.org/wiki/C_preprocessor)
@Tagli, @fatih6761 açıklamalar için teşekkürler..
Alıntı yapılan: iruraz - 15 Kasım 2013, 19:31:30
@arslan74 hocam, örnekten ve anlattıklarınızdan sonra kafamda şöyle bir şey oluştu:
"islemci_a" seni yoktan var ettim ama şimdilik hiçbir şey değilsin. Ne olacağını, hayatın (burada tabi ki kodun :) ) akışı belirleyecek.
Olayı bu şekilde özetlesem doğru olur mu?
Olmayan bir şeyi tanımlamanın bir anlamı ve amacı olmaz. Kodu biz olan bir şeye göre yazarız. Kodumuzda iki veya daha fazla farklı işlemcileri veya özellikleri belirtmek ve ayırt etmek için kullanılır.
Alıntı yapılan: arslan74 - 15 Kasım 2013, 23:17:42
Olmayan bir şeyi tanımlamanın bir anlamı ve amacı olmaz. Kodu biz olan bir şeye göre yazarız. Kodumuzda iki veya daha fazla farklı işlemcileri veya özellikleri belirtmek ve ayırt etmek için kullanılır.
@arslan74 hocam,
Benzetmemde "yoktan var ettim" derken "amaçsız yarattım" demek istemedim. Seni bir amaç için yarattım ama ne için kullanılacağın ve ne olacağın kodun akışında belli olacak demek istemiştim.
Konu benim açımdan açıklığa kavuştu. Yardımcı olanlara tekrar teşekkür ederim..
ilginç bir benzetme olmuş. ama sevdim.
Merhaba,
Bir kütüphane olarak kullandığım .c ve .h dosyalarında .c içerisinde tanımladığım global bir değişken var. Bu değişkene main ve diğer .c dosyalarında nasıl erişim sağlarım?
Alıntı yapılan: kantirici - 07 Aralık 2013, 23:43:58
Merhaba,
Bir kütüphane olarak kullandığım .c ve .h dosyalarında .c içerisinde tanımladığım global bir değişken var. Bu değişkene main ve diğer .c dosyalarında nasıl erişim sağlarım?
Header dosyası içerisinde veya kullanacağın yerde
extern <degiskentipi> <degiskenismi>
extern int variable;
yazarsan kullanabilirsin.
@AsHeS teşekkürler.
Merhaba şu şekilde tanımlamaları daha önceden kullanmadım, bir stack yapısı ile çalıştığım için (C sadece) belki de yeni karşılaşıyorumdur.
#ifndef x_API
#define x_API
#endif
Ben şu şekilde beklerdim, eğer x_API bir şekilde tanımlanmış ise (preprocessor de mesela, IAR orneği verirsem)
#define x_API birşeyler
derdim. Ama bu şekilde hiçbir tanımlama bulunmuyor. Daha sonradan şu şekilde fn-lar felan tanımlanmış:
x_API void xyz(void)
{
/* başka şeyler*/
birfn();
ikifn();
}
Bunu ya bir yerlerde typedef ile tanımlamışlar yada benim bilmediğim C dilinin bir özelliği. (Yazdıkları .lib'den çekiyor olabilir)
Ne acaba?
atioky_216, ilk sorunun cevabı yine bu başlıkta bir sayfa önce (48) verilmişti.
İkinci kullanımı ben de ilk defa görüyorum, maalesef hiçbir fikrim yok. Önce "makro mu acaba?" dedim ama ona da benzemiyor pek.
Alıntı yapılan: atioky_216 - 12 Aralık 2013, 15:10:43
x_API void xyz(void)
{
/* başka şeyler*/
birfn();
ikifn();
}
bunda birşey yok ki normal #define gibi.
#define x_API public static
x_API void xyz(void)
{
/* başka şeyler*/
birfn();
ikifn();
}
ha böyle yazmışsınız
ha böyle:
public static void xyz(void)
{
/* başka şeyler*/
birfn();
ikifn();
}
Alıntı yapılan: Tagli - 12 Aralık 2013, 16:08:46
atioky_216, ilk sorunun cevabı yine bu başlıkta bir sayfa önce (48) verilmişti.
İkinci kullanımı ben de ilk defa görüyorum, maalesef hiçbir fikrim yok. Önce "makro mu acaba?" dedim ama ona da benzemiyor pek.
Topluca yazmadığım için farklı anlaşıldı ilk yapı
#ifndef x_API
#define x_API birseyler
#endif
şeklinde tanımlamada anlaşılmayacak bir şey yok zaten. Benim merak ettiğim herhangi şekilde (eğer düşündüğüm şekilde varsa tabi)
#define x_API herhangibirtur
şeklinde tanımlama goremedim.Sadece şu şekilde tanımlayıp:
#ifndef x_API
#define x_API
#endif
daha sonrasında (sanki bir tur gibi) fn- ile beraber kullanılması ilk defa karşılaştığım bir şey. Dediğim gibi herhangi bir yerde x_API tanımlaması ve ne olduğunu da bulamadım.
@gerbay galiba sizin bahsettiğiniz durum oluyor bu. Ben iyice bakayım.
Ama gerçekten merak etmiştim:
#ifndef x_API
#define x_API
#endif
şekilde yazılmasındaki amaç nedir? Tanımlama felanda yok, insanı şaşırtıyor.
Alıntı yapılan: gerbay - 12 Aralık 2013, 17:13:00
o da eğer derleyiciye x_API nin ne olduğu define edilmezse derlemede hataolmasın diye alınan bir güvenlik önlemi.. eğer x_API nin ne olduğu bildirilmezse fonsiyonların başındaki x_API ler derleme sırasında kaldırılıyormuş gibi düşünün..
O zaman yazdığım eğer define edilmemiş ise define edilmesi için bu. Bu proproc. kısmında pek bilgim yoktu bu zmana kadar sadece #define a b
vs... Detay gördüğüm şeyleri yeniden karıştırmam gerekiyor.
NOT: Evet @gerbay özellikle derleme sırasında header kullanırken tam da dediğiniz gibi işe yarıyor imiş yeni öğrendim.
Alıntı yapılan: atioky_216 - 12 Aralık 2013, 17:22:00
O zaman yazdığım eğer define edilmemiş ise define edilmesi için bu. Bu proproc. kısmında pek bilgim yoktu bu zmana kadar sadece #define a b
vs... Detay gördüğüm şeyleri yeniden karıştırmam gerekiyor.
Donanım bağımlı/bağımsız bir kod yazdığınızı düşünün PIC18, PIC24, dsPIC30/33, PIC32, LPC17xx, STM32xx gibi tüm MCU lar ve bunlar için kod geliştirilen tüm derleyicilerle sorunsuzca derlenebilsin. Ne güzel olurdu değil mi ? :) İşte C deki "preprocessor/predefined macro" dediğimiz yapılar bu gibi sorunların çözümüne hizmet ediyor.
@ByteMaster
Bunların o işe yaradığını biliyorum. Benim sorum bunu açıkçası yukarıdaki verdiğim örnek ile nasıl gerçekleştirdiği....
Örneğin herhangi bir şekilde
#define x_API herhangibirdataturu
tür dönüşümü yapılmadan
x_API void birfonksiyon(int a, char* b vs); deklerasyonundan ne anlamamiz gerekiyor? Bu idi benim sorumun temeli.
Şimdilik @gerbay 'ın yorumunu araştırıyorum.
Aslında @gerbay gayet açık anlatmış ama ben biraz daha eklemeye çalışayım. Bir projeniz var bu projede iki uygulama var bu uygulamaların biri DLL(API) diğeri ise API için Test GUI programı.
GUI' niz kodladığınız DLL' den bir fonksiyonu import ediyor. Fakat DLL bu fonksiyonu barındırıyor. Bu projelerin kodları ortak. Derleme esnasında derleyiciye "Bak kardeşim bu kodlar sadece DLL' in içinde olsun ama aynı zamanda GUI uygulaması da bu DLL in bu fonksiyonlarını import ederek kullanıyor." diye bir bildirim yapabilmemiz için @gerbay' in bahsettiği yöntem kullanılıyor.
GUI projesinin ayarlarında ADD_EXPORTS bildirimini yapmıyorsunuz. Ama DLL proje ayarlarında yapıyorsunuz. Derleyici her iki projede de aynı kodu derlerken biri için sadece oluşacak EXE dosyanın IAT(Import Address Table) kısmına şu DLL in içindeki(aslındaki içinde değilde sistem tarafından RAM' de haritalanmış bir bölge.) şu adresdeki fonksiyon olduğuna dair bir pointer yazıyor.(Windows Internals ile alakalı bir konu) Ancak DLL için aynı kodu derliyorken gidip tüm fonksiyonu oluşacak DLL dosyasına gömüyor. Yani kodun aslı DLL in içine gömülmüş oluyor. GUI programına ise sadece bu DLL' i çağırması gerektiğine dair referans veriliyor.
Oradaki x_API void birfonksiyon(int a, char* b vs); makrosu derleyiciye x_API gördüğü yere __declspec(dllexport) veya __declspec(dllimport) koyacağını bildirmekten başka bir görev üstlenmiyor. Bu kullanım şekilleri (__declspec(dllexport) ve __declspec(dllimport) ) zaten windows programlama ve DLL kodlama ile alakalı şeyler. Yani başka yerde pek karşınıza çıkmaz.
Ayrıca şunu gözardı etmemek gerekli bir fonksiyonun tanımlanması demek derleyiciye fonksiyonu derlerken oluşturulacak stack hakkında ve fonksiyonun nasıl çağrılacağı hakkında fikir verir. Siz derleyiciyi bu konuda aldatabilme lüksüne sahipsiniz.
gerbay'ın yazdığı bir noktaya da ben dikkat çekeyim.
eğer
#define x_API
gibi bir tanımlamayı kodların içinde bulamadıysanız bir de komut satırı parametrelerine bakınız. yani (kullandığınız IDE'ye göre değişmekle birlikte) 'project properties'te bir yerlerde x_API tanımı derleyiciye komut satırında bir parametre olarak geçiliyor olabilir. belki de makefile dosyasında bu tanım yapılıyordur.
STM32F4 Discovery kitteki 4 ledi biliyorsunuz.
Led adinda fonksiyon yazmak istiyorum.
Led(Y0) dersem yesil led sonecek, Led(K1) dersem kirmizi led yanacak vs
Led(Y1,K1,M0) dersem Yesil ve kirmizi led yanacak, Mavi led sonecek.
yada Led(M0,Y0,K1,S1) dersem mavi ve yesil ledler sonecek, kirmizi ve sari(kavunici) ledler yanacak.
Bu fonksiyon nasil yazilir?
illa böylesi şartmı yoksa
led(off,off,on,on) yapsak olmazmı
Onu ebem de yazar.
Alıntı yapılan: z - 25 Aralık 2013, 16:16:37
STM32F4 Discovery kitteki 4 ledi biliyorsunuz.
Led adinda fonksiyon yazmak istiyorum.
Led(Y0) dersem yesil led sonecek, Led(K1) dersem kirmizi led yanacak vs
Led(Y1,K1,M0) dersem Yesil ve kirmizi led yanacak, Mavi led sonecek.
yada Led(M0,Y0,K1,S1) dersem mavi ve yesil ledler sonecek, kirmizi ve sari(kavunici) ledler yanacak.
Bu fonksiyon nasil yazilir?
c'de "variable arguments" ile yapilabilir. (variadic functions diyede gecer)
Sometimes, you may come across a situation, when you want to have a function, which can take variable number of arguments, i.e., parameters, instead of predefined number of parameters. The C programming language provides a solution for this situation and you are allowed to define a function which can accept variable number of parameters based on your requirement. The following example shows the definition of such a function.
int func(int, ... )
{
.
.
.
}
int main()
{
func(1, 2, 3);
func(1, 2, 3, 4);
}
It should be noted that function func() has last argument as ellipses i.e. three dotes (...) and the one just before the ellipses is always an int which will represent total number variable arguments passed. To use such functionality you need to make use of stdarg.h header file which provides functions and macros to implement the functionality of variable arguments and follow the following steps:
Define a function with last parameter as ellipses and the one just before the ellipses is always an int which will represent number of arguments.
Create a va_list type variable in the function definition. This type is defined in stdarg.h header file.
Use int parameter and va_start macro to initialize the va_list variable to an argument list. The macro va_start is defined in stdarg.h header file.
Use va_arg macro and va_list variable to access each item in argument list.
Use a macro va_end to clean up the memory assigned to va_list variable.
Now let us follow the above steps and write down a simple function which can take variable number of parameters and returns their average:
#include <stdio.h>
#include <stdarg.h>
double average(int num,...)
{
va_list valist;
double sum = 0.0;
int i;
/* initialize valist for num number of arguments */
va_start(valist, num);
/* access all the arguments assigned to valist */
for (i = 0; i < num; i++)
{
sum += va_arg(valist, int);
}
/* clean memory reserved for valist */
va_end(valist);
return sum/num;
}
int main()
{
printf("Average of 2, 3, 4, 5 = %f\n", average(4, 2,3,4,5));
printf("Average of 5, 10, 15 = %f\n", average(3, 5,10,15));
}
When the above code is compiled and executed, it produces the following result. It should be noted that the function average() has been called twice and each time first argument represents the total number of variable arguments being passed. Only ellipses will be used to pass variable number of arguments.
Average of 2, 3, 4, 5 = 3.500000
Average of 5, 10, 15 = 10.000000
merbaba,
iki şekilde yazılabilir,
1. c de kullanılan:
void Led(const char * fmt, ...)
{char TmpData[100]
va_list val;
va_start(val, fmt);
vsnprintf (TmpData,sizeof(TmpData), fmt, val);
*****
va_end(val);
}
** yerde fscanf ile text icindeki değerler alınarak değişkenlere atılarak denenir.
2. her fonskiyon için overload fonksiyonları yazılır icerisindeki parametreler typedef enum ile tanımlanarak alınabilir
led(enum bir );
led(enum bir, enum iki);
led(enum bir, enum iki,enum üc);
....
Mufitsozen hocam tesekkurler.
Aklima takilan tek sey kaldi. yazdigim fonksiyon kendisine kac tara parametre geldigini nereden bilecek?
Edit: pardon cevabi varmis zaten.
mesaj birleştirme:: 25 Aralık 2013, 17:01:00
Bu isleyisle ilgili biraz detay verebilirmisiniz?
C de Led(Y1,K0) yazacagim ama Led fonksiyonunu tamamen ASM yazacagim.
ASM tarafina kac tane parametre gidecek?
Mantiken
parametrelerin yazildigi ram alaninin adresi
parametre sayisi
parametrelerin size'i gibi 3 parametre sart.
Deneme yaparak da bir seyler bulabilirim belki ama hazir bilgi varsa sevinirim.
Istedigim olmuyor galiba. Ilk parametre olarak veri sayisini benim vermem gerekiyor diye anladim.
Led(1,K1) 1 lede erisilecek bu da kirmizi
Led(3,K1,Y0,S1) 3 lede erisilecek.
Yanlis mi anladim?
@z hocam bir kaç sayfa geride bu konu hakkında konuşulmuştu bende aynı şeyi sormuştum. Fonksiyona kaç tane parametre gidicekse bunun sayısınıda beraber göndermemiz gerekiyor.
https://www.picproje.org/index.php/topic,35908.msg370896.html#msg370896 (https://www.picproje.org/index.php/topic,35908.msg370896.html#msg370896)
Alıntı yapılan: z - 25 Aralık 2013, 16:42:27
Onu ebem de yazar.
Acı Çekmekten mi Hoşlanıyorsunuz neden zorluyorsunuz :D
birden fazla parametre kullanılarak yazılan fonksiyonlarda ilk başta kaç argüman gittiğini yazmanız gerekmiyor.
o kullanım sabit 1 adet giriş istiyor sadece, ister argüman sayısını gönderin ister başka birşey
argüman sayısı öğrenilemediğinden başta sayıyı göndermek tercih edilebilir ama bu tehlikeli bir durum malesef
düzenlerken yada yazım sırasında sorun çıkabilir.
en son argümanın bilinen bir değer gönderirseniz listenin sonuna geldiğinizi öğrenebilirsiniz ve yazarken, düzenlerken daha kolay olur
Aslinda derleme asamasinda derleyici parametreleri saysa kod uretirken de R0'a arguman sayisini yerlestirse, ardindan R1'e de argumanlarin int mi char mi vs tipini de belirtse, argumanlari da staga atsa ...
Illa ben mi ogretecem bu adamlara bu isi?
Peki derleyiciye bunu yaptirmamim bir yolu varmi?
Yani derlenirken ben de kendimden bir seyler katabilirmiyim?
Geri kalan parametreler ayni tipte ise, dizin kullanin. ilk eleman'in pointer'ini verirsiniz olur.
Baska yöntem flag kullanmak, burada da bir sinir verirsiniz (max 32 bit örnegin)
Led(YAK_1|KAPAT_5|SONDUR_6| ... );
google a "vprintf source code" deyip içerik nasıl kullanılmış bakılabilir aslında
Delphi'de fonsiyonun sonuna overload yazdığınızda aynı isimde çok sayıda fonksiyon tanımlanıyor.
function Led(s1:string); boolean; overload;
begin
//...
end;
function Led(s1, s2:string); boolean; overload;
begin
//...
end;
function Led(s1, s2, s3:string); boolean; overload;
begin
//...
end;
function Led(s1, s2, s3, s4:string); boolean; overload;
begin
//...
end;
Böylece her fonksiyonun kodlamasına uygun kod eklenebilir. C'de benzer yöntem mutlaka vardır.
Alıntı yapılan: z - 25 Aralık 2013, 18:16:50
Istedigim olmuyor galiba. Ilk parametre olarak veri sayisini benim vermem gerekiyor diye anladim.
Led(1,K1) 1 lede erisilecek bu da kirmizi
Led(3,K1,Y0,S1) 3 lede erisilecek.
Yanlis mi anladim?
Eğer tek fonksiyon ile çözülebiliyor ise kaç lede erişileceğini belirtmeye gerek yok.
Diyelim
Led(s1,s2,s3); s'lere y0, k1 gibi değerler girildi. Eğer s4 uzunluğu 0 ise (veya 2'den farklı ise) s4 tanımlanmamış demektir. s1, s2 ve s3'e tanımlama yapıldığı için 2 karakter uzunluğa sahipler.
@z hocam virgülleri | yapın. Alın size flag. Bu flagı kaydırıp kaydırıp ledleri yakar söndürürsünüz :)
O sekilde ledleri yakarim da nasil sondururum?
değişken değikenli fonksiyon zaten derleme aşamasında kaç parametre girildiyse her fonksiyon ona göre yeniden düzenlenir.
ama dizi,struct,string gibi girişle kolaya gidilebilinir.
led("s1k0")
string incelenir ilgili karakter ve sonra gelen değer bulunur 1 se ya 0 sa söndür.
while case ifelse
Hocam 4 led var. K0 K1 Y0Y1 ifadeleri 8-bit olur. İlk dört bit led numarasını belirtir. İkinci dört bit ise aynı konuma gelen led durumunu.
Yani;
#define K0 (0x00010000)
#define K1 (0x00010001)
#define M0 (0x00100000)
#define M1 (0x00100010)
...
gibi. Kullandığınız işlemcide bit manipülasyon komutları varsa kolay olabilir.
bende olsam speak ın dediği gibi string manipulation la yaparım
eğer fantazi yapacaksam tabi, yoksa ne gerek var.
Alıntı yapılan: z - 26 Aralık 2013, 02:01:24
O sekilde ledleri yakarim da nasil sondururum?
İki tane fonksiyon yazsan bir yakan diğer ide söndüren. O şekilde olmaz mı?
Sorun ledleri yakip sondurecek fonksiyon yazma sorunu değil.
Sorun, merakin tetiklenmis olmasi.
MufitSozen hocamizin verdigi bilgiler isiginda C programin asm ciktisindan olayi kavradim fakat asm yazacak olsam bile stdarg.h'i include etmek gerekiyor.
Bu hosuma gitmedi.
Hocam stdarg ile işim şöyle var;
Eger bunu include etmezsem parametre icinde ... goren keil parametreleri stacka atmiyor.
Ne zaman stdarg yi include edersem o zaman stacka atiyor.
Ha dersen ki include et. Ok.
Tekrar bakayim hocam.
Gerbay burada 4 tane parametre gonderdigini zaten ilk parametre ile soylemissin. Bu sart mi? Eger sart ise istegimi gerceklemiyor.
Led.h isimli bir dosyada böye bir tanım yapmış
#define R1_0 LED |= 1UL<<2
#define R1_1 LED &= ~(1UL<<2)
#define G1_0 LED |= 1UL<<3
#define G1_1 LED &= ~(1UL<<3)
#define B1_0 LED |= 1UL<<4
#define B1_1 LED &= ~(1UL<<4)
ve bu şekilde kullanmıştım.
if(320 =< Count){
Count=0;ms10++;
if(_R1){ R1_1;R3_1;FR1=1;} else{ R1_0;R3_0;}
if(_G1){ G1_1;G3_1;FG1=1;} else{ G1_0;G3_0;}
if(_B1){ B1_1;B3_1;FB1=1;} else{ B1_0;B3_0;}
}
hc595_yaz(LED);
int gerbay(int i, ...)
{
int k, result = 0;
int *pI = &i;
pI++;
for (k = 0; k < i; k++)
{
result += *pI++;
}
return result;
}
En son parametrenin adresi k degiskeninden bir önceki adres olma ihtimali varmidir ? öyleyse döngüyü degistirip yapilabilir.
while (pI < &k)
{
result += *pI++;
}
Output() adında C fonksiyonu yazacağım.
Parametrelerini de örneğin aşağıdaki gibi göndereceğim.
Output(A0_0, A2_1, C4_0);
Bir başka yerde ise Output(D10_1);
Nekaddar yakışıklı bir şey bu. İlk komut GPIOA da A0 pinini 0, A2 pinini 1 yaparken GPIOC de C4 pini 0 olmaktadır.
Alttaki satırda ise GPIOD de D10 pini 1 yapılmaktadır.
Şimdi ne gerek var buna diye bana alternatif fikirler sunuyorsunuz. Bana alternatif sunmayın. Yukarıdaki yakışıklı çözümü istiyorum.
Çözümüm varmı var. Bunu B planı olarak saklıyorum. Çünkü derleme işlemine müdahil olmak istemiyorum.
Alıntı yapılan: z - 27 Aralık 2013, 13:54:04
Output() adında C fonksiyonu yazacağım.
Parametrelerini de örneğin aşağıdaki gibi göndereceğim.
Output(A0_0, A2_1, C4_0);
Bir başka yerde ise Output(D10_1);
Nekaddar yakışıklı bir şey bu.
Function Overloading (Fonksiyon Aşırı Yüklemesi)
C++,birbirinden farklı parametreleri olduğu sürece aynı isimli birden fazla fonksiyonun tanımlamasına izin verir.
Bu yetenek fonksiyon aşırı yüklemesi olarak adlandırılır.
Bu aralar düşündüğüm bir konu var, yardımcı olursanız sevinirim.
8 bitlik mikrodenetleyicilerde dinamik bellek yönetimi olmuyor bildiğim kadarıyla.
a) 8 bitliklerde malloc calloc gibi komutlar kullanmak mümkün müdür? Değilse neden böyle bir destek yok.
b) 16 bit ve daha yüksek mcu'larda mümkün mü?
c) Hangi diller desteliyor, hangi diller desteklemiyor?
d) Kendi fonksiyonlarımız ile bunu yapmak ne kadar mümkün, ne kadar sağlıklı?
8051 de malloc kullanabiliyorsun. İşlemcinin yeterince ramı varsa malloc komutu olmaması için neden yok gibi görünüyor.
http://www.nongnu.org/avr-libc/user-manual/malloc.html (http://www.nongnu.org/avr-libc/user-manual/malloc.html)
---------------------------------------------------------------------------------
C de aşağıdaki isteğim gerçeklenebilirmi?
f1(a,b,c);
f2(x);
gibi f1 ve f2 fonksiyonlarım var.
f1 de kaç parametre var, f2 de kaç parametre var diye sorgulayabileceğim herhangi bir komut varmı?
Bakınca f1 de 3, f2 de 1 komut olduğunu görüyoruz. Bunu sorgulamak suretiyle öğrenmek istiyorum.
Benim verdigim kod çalismiyor, ama stack ve heap pointer'e bakarak bir çözüm olabilir diye dusundum.
Heap ve stack pointer'i su asagidaki kodda kullaniyorum (AVR) :
Alıntı Yap
int freeRam ()
{
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
B Plani ise makro kullanmak ve son parametreye hiç gelmeyecek bir deger vermek FFFF (-1)
#define Led LedInt(__VA_ARGS__,-1)
...
Led(YA_0,SONDUR,1,....)
...
LedInt()
while (*pI != - 1)
{
result += *pI++;
}
Alıntı yapılan: picusta - 27 Aralık 2013, 19:36:45
Benim verdigim kod çalismiyor, ama stack ve heap pointer'e bakarak bir çözüm olabilir diye dusundum.
Heap ve stack pointer'i su asagidaki kodda kullaniyorum (AVR) :
B Plani ise makro kullanmak ve son parametreye hiç gelmeyecek bir deger vermek FFFF (-1)
#define Led LedInt(__VA_ARGS__,-1)
...
Led(YA_0,SONDUR,1,....)
...
LedInt()
while (*pI != - 1)
{
result += *pI++;
}
Hocam optimizasyon aşamasında alt üst olur... O noktada derleyiciye müdahale etmek gerekir ki bu istenmeyen durum.
void f2()
{
.....;
}
void f1()
{
f2();
}
void main()
{
f1();
f2();
}
f2 fonksiyonu kendisini cagiran fonksiyonun adresini bilmek istiyor?
Dikkat!!! Hangi adresden cagrildigi sorulmuyor, hangi fonksiyondan cagrildigini dolayisi ile bu fonksiyonun baslangic adresi isteniyor?
1. Seçenek
backtrace_symbols() = Stack trace yapar, kimler çağırmış adı ne ?
2. Seçenek
__builtin_return_address + addr2line aracı = Size çağıran fonskiyonun adı, dosyası ve satırını verir. Map File'dan bakarsınız çağıranın adresi neymiş.
3. Seçenek
Kendiniz Map file'i parse edersiniz.
Alıntı yapılan: z - 27 Aralık 2013, 17:40:24
8051 de malloc kullanabiliyorsun. İşlemcinin yeterince ramı varsa malloc komutu olmaması için neden yok gibi görünüyor.
hi-tech c, c18 ve xc8 derleyicileri için araştırdım desteklemiyor, ancak desteklenemeyen şey ne? Anlamadım ki.
Alanın az veya çok olması o kadar önemli değil diye düşünüyorum.
Ben bellekten alan ayıracağım, eğer bellekte yer kalmamışsa zaten malloc, 0(sıfır) dönderir. Bunu yazılımla kontrol etmekteyiz zaten.
Bir kutuphane'yi projeye dahil edip, kutuphaneden sadece bir dosyayi cagiran kucuk bir program yazip derledigimizde, elde edilen hex dosyada sadece cagrilan fonksiyon mu olur yoksa tum kutuphane mi?
Eger tum kutuphane projeye dahil oluyorsa nerede hata yapiyor olabilirim?
mesaj birleştirme:: 03 Ocak 2014, 21:15:32
Alıntı yapılan: meftun - 31 Aralık 2013, 16:06:03
hi-tech c, c18 ve xc8 derleyicileri için araştırdım desteklemiyor, ancak desteklenemeyen şey ne? Anlamadım ki.
Alanın az veya çok olması o kadar önemli değil diye düşünüyorum.
Ben bellekten alan ayıracağım, eğer bellekte yer kalmamışsa zaten malloc, 0(sıfır) dönderir. Bunu yazılımla kontrol etmekteyiz zaten.
Sonucu 0 (basarisiz) donecegi kesin olan fonksiyon neden yazilsin ki?
Adi ustunde memory allocate, ram dan yer ayirmak anlamina geliyor. Ram alani az islemcilerde ram ancak degiskenlere ve stack'a yetecegi varsayiliyorsa malloc komutu hazirlamak anlamsiz olur.
Atiyorum 256 byte dan daha az rami olan islemciler icin malloc cok da sart değil.
Eger ramda bir miktar yer kalmissa o kisma bir char array yerlestirip pointerler sayesinde o kismi genel amacli kullanabilirsin.
Linker ayarlarına bakabilirsiniz.
merhaba;
aşağıdaki kodda Done şartında döngüden nasıl çıkarım? while- break işe yaramıyor :)
goto-label ve ekstra değişken kullanmadan
while(1)
{
switch(mesaj-Stat)
{
case Status:
//..
//..
break;
case Done:
//..
//..
break
}
/...
/..
}
Çıkamazsın. Ben olsam bayrak kullanırdım.
Burada (http://stackoverflow.com/questions/10587196/break-c-which-loop-is-it-actually-breaking) yazdığına göre C++11'de başka bir yol daha varmış.
@ercan_t
While döngüsü bir fonksiyonun içinde ise return ile çıkabilirsin.
merhaba
@leblebitozu,
fonksiyondan çıkmadan sadece döngüden çıkmak istiyorum.
Alıntı yapılan: ercan_t - 07 Ocak 2014, 13:38:50
merhaba
@leblebitozu,
fonksiyondan çıkmadan sadece döngüden çıkmak istiyorum.
iki degisik yol ile yapabilirsiniz, ikisinide tavsiye etmem. sadece niye diye sormadan sorunuza cevap olsun diye oneriyorum.
1 - switch(mesaj-Stat) blogundan ciktigi yere asagidaki satiri ekleyiniz
if (Done ==(mesaj-Stat)) break;
2- switch case blogunu if-elseif-else'e ceviriniz,
==Done elseif blogunun sonuna break; ekleyiniz
__IO ne için kullanılıyor?
__IO uint16_t falancadegisken;
neyi ifade eder?
Burada (http://stackoverflow.com/questions/14359775/what-is-the-io-directive-in-gcc) bir miktar açıklama var. Dediğine göre makro imiş ve derleyiciye göre açılımı farklı olabilirmiş. volatile ile aynı anlama gelme ihtimali yüksek.
uint16_t ise platformdan bağımsız işaretsiz 16 bitlik tamsayıyı ifade ediyor. Bunun yerine unsigned int de yazabilirsin ama bu dsPIC için olan bir derleyici tarafından 16 bitlik bir değişken olarak düşünülürken belki 32 bitlik bir ARM mimarisinde 32 bitlik bir değişken olarak derlenebilir. uint16_t yazınca, bu o platformda 16 bitlik işaretsiz değişken için ne olması gerekiyorsa ona açılıyor, mesela belki de ARM'da unsigned short oluyordur.
Alıntı yapılan: mistek - 04 Şubat 2014, 21:11:14
__IO ne için kullanılıyor?
__IO uint16_t falancadegisken;
neyi ifade eder?
ARM Derleyicilerinde, "__IO" volatile manasına geliyor... O şekilde tanımlanmış... Birde bunun "__I", "__O" versiyonları bulunmaktadır...
#ifdef __cplusplus
#define __I volatile /*!< Defines 'read only' permissions */
#else
#define __I volatile const /*!< Defines 'read only' permissions */
#endif
#define __O volatile /*!< Defines 'write only' permissions */
#define __IO volatile /*!< Defines 'read / write' permissions */
Cevaplar için teşekkürler. Düşündüğüm şey değilmiş.
extern'le aynı işi yapacak benzer bişey varmı.
Şöyle bi durum oluştu.
main.c içerisinde değişken tanımlıyorum ve diğer kütüphane dosyalarında bunu extern ile belirtip ulaşmaya çalışıyorum. Nasıl ifade edeceğim tam bilmiyorum. Normalde derlerken sorun yok hatasız derleniyor ancak program gerçek zamanlı çalışırken aslında bu değişkene hiç ulaşamıyor ve değerini değiştirmiyor.
Daha somut olması açısından; ADC-DMA okuma yapıyorum DMA nın buffer olacak kullanacağı diziyi main.c içerisinde tanımlayıp ADC.c içerisinde extern ile belirtiyorum. Derleme anında sorun yok normal derleniyor ama kodu çalıştırdığımda DMA bu diziye ulaşamıyor.
Eğer değişkeni ADC.c içerisinde tanımlayıp main.c içerisinde extern ile belirtirsem DMA buna ulaşabiliyor sorunsuz derliyor ve çalışıyor.
Böylede kullanıyorum ama değişkenler gözümün önünde olsun istiyorum, birde sebebini öğrenmek istiyorum
Adc dosyasina extern tanimlayip ayni degiskeni main icerisine normal tanimlayip denermisin?
Alıntı yapılan: mistek - 04 Şubat 2014, 22:28:27
Daha somut olması açısından; ADC-DMA okuma yapıyorum DMA nın buffer olacak kullanacağı diziyi main.c içerisinde tanımlayıp ADC.c içerisinde extern ile belirtiyorum. Derleme anında sorun yok normal derleniyor ama kodu çalıştırdığımda DMA bu diziye ulaşamıyor.
Ben bu sekilde dizi tanimladim ve usb den gelen verileri sorunsuz okuyabiliyorum, baska bir problem olabilir mi?
Tek tek herşeyi denedim en son ADC dizisini tanımladığım yeri değiştirdim problem olmadı ama neden böyle olduğuna anlam veremiyorum. Keil 4.70'de derliyorum
eksik bir library olabilir.
Stm32 std lib. kullanıyorum. Kendi oluşturduğum ADC.c ve ADC.h projeye dahil. Eğer siz normal olarak kullanabiliyorsanız mutlaka benim kodlarımda sorun vardır, göz atayım tekrardan.
mistek ben stnin kendi sample larini kullaniyorum , onlar uzerinde degisiklik yaparak proje olusturdum hatta extern ile degiskeni tanimlayip baska bir tanimlama yapmadan static extern gibi degiskenin icindeki veriyi okudum,buna bile birsey demedi .
Hocam tanımlamada sorun yok normalde bende extern ile diğer kütüphane dosyalarında değişiklik yapıyorum ama DMA uygulamasında garip davrandı.Daha doğrusu önceden böyle kullanıyordum. Derleyici bişey demiyor kod normal olarak çalışıyor ancak adc verilerinin yazılacağı diziyi okuduğumda hep içeriği 0 okuyorum.
Adc dizisini kendi dosyasında tanımlarsam ve main.c'de okursam dma verileri bu diziye yazmış oluyor ve 0 dan farklı değer okuyorum. Sanki Keil kod tamamlama yaparken benim dizimi başka bir yere bağlıyor. DMA da yolu şaşırıyor. Eski bilgisayarımda derlediğimde(Keil 4.72) her iki durumda da sorunsuz çalışıyordu çünkü. Bi ara 4.72 yükleyeceğim tekrar denerim.
Merabalar,
typedef struct _direntry
{
char sName[8];
char [spam][3];
char bAttr;
char bReserved[8];
int16 hClusterH;
int16 hTime;
int16 hDate;
int16 hCluster;
int32 wSize;
} DIR;
Şeklinde bir tanımlama var.Ancak bu yapı içinde
char [spam][3] şeklinde bir ifade var.Bu yapıyı kullanırken -char [spam][3] kısmında- ;
DIR beDir;
beDir->[spam][i];
şeklinde kullanmış.Yani ısrarla [spam][3] yapısına sağdık kalmış.Bu nasıl bir tanımlamadır?Özelliği nedir?
Ben bunu derlerken hata alıyorum.Çünkü dikkat edilirse char ifadesinden sonra hiçbir değişken adı yer almamış.
Bu hatayı nasıl giderebilirim?
spam'ın etrafında köşeli parantez olmamalı. Kod neden öyle yazılmış anlamadım.
#define [spam] baska_bir_ad gibi birşey yapılabilir mi bilmiyorum ama #define içinde hiç köşeli parantez gördüğümü hatırlamıyorum.
Alıntı yapılan: Tagli - 14 Şubat 2014, 11:58:50
spam'ın etrafında köşeli parantez olmamalı. Kod neden öyle yazılmış anlamadım.
#define [spam] baska_bir_ad gibi birşey yapılabilir mi bilmiyorum ama #define içinde hiç köşeli parantez gördüğümü hatırlamıyorum.
Herhangi bir yerde define tanımlaması da yok.Acaba pointer olma ihtimali var mı?Yani
char *[spam][3]] tarzı bir şey?Böyle bir tanımlama legal mıdır?
int a=0x0000000F;
int b=0x00000000;
int c=0x00000000;
for (b=0;b<32;b++){
c=a<<1;
}
yukardaki gibi çok basit olan kodda bir hata var mı ?
merhaba,
[spam][3] tarzı hiç tanımlamaya rastlamadım kodda tuaflık var
ama aşağıdaki gibi çok tanımlamalarda bulunmuştum bit düzeyinde limitleyerek tanımlama aşağıdaki struct tam 5 bayt(bitleri toplayın...) :)
örneğin ready 4 bit yer kaplıyor üstünü gecemez yani değeri 0-15 arası....
typedef struct __attribute__((__packed__)){
unsigned ready:4;
unsigned error_occured:1;
unsigned disk_spinning:1;
unsigned write_protect:1;
unsigned head_loaded:1;
unsigned error_code:8;
unsigned track:9;
unsigned sector:5;
unsigned command:5;
}DISK_REGISTER;
Öyle sanıyorum ki o tanımlamada iki boyutlu bir dizi tanımlanmaya çalışılmış.Çünkü yapıyı çağırırken de aynı şekilde çağırıyor.Ancak oradaki ifade pointer mi diye düşünüyorum.
muhittin_kaplan, muhtemelen var. c hep aynı değeri alır, çünkü a<<1 işlemi a güncellenmediği için hep aynı değeri üretir. Bu durumda döngünün de bir anlamı kalmaz.
Döngünün içinin şu şekilde yazılması uygun olur: c = a << b;
Tabi Ya. 0x0000000F i hep birkez sola kaydırıyorum. (Yaşlanıyorum Galiba :D)
Çalışma zamanlı olarak diziye string atanamıyor mu?
Örneğin
char dizi[10] = {0};
tanımlıyorum.
program içerisinde dizi[] = {"aliveli "}; yazamıyorum derleyici hata veriyor. Kitaba hızlı bir göz gezdirdim ancak buladım.
Alıntı yapılan: mistek - 16 Şubat 2014, 23:09:53
Çalışma zamanlı olarak diziye string atanamıyor mu?
Örneğin
char dizi[10] = {0};
tanımlıyorum.
program içerisinde dizi[] = {"aliveli "}; yazamıyorum derleyici hata veriyor. Kitaba hızlı bir göz gezdirdim ancak buladım.
strcpy yada strncpy
Hocam hafızayı çok meşgul etmeyen komutlara ihtiyacım var. Bunların durumu nasıldır?
şuan bu şekilde yapıyorum
dizi[0] = 'A';
dizi[1] = 'l';
dizi[2] = 'i';
dizi[3] = 'V';
...
Malesef!
strcpy veya strncpy kullanabilirsiniz.
eğer stringleriniz sabit ise:
const char str1[] = {"String 1"};
const char str2[] = {"String 2"};
char *ptr;
void xxx(void)
{
ptr = str1;
ptr = str2;
}
şeklinde kullanabilirsiniz.
veya
const char StrTable[][] = {"String 1", "String 2", "String 3"};
char *ptr;
ptr = &StringTable[0][0];
ptr = &StringTable[1][0];
şeklinde kullanabilirsiniz.
Alıntı yapılan: mistek - 16 Şubat 2014, 23:17:03
şuan bu şekilde yapıyorum
dizi[0] = 'A';
dizi[0] = 'l';
dizi[0] = 'i';
dizi[0] = 'V';
...
Ve bütün dizi elemanlarına ulaşabiliyor musun?Bunu gerçekten yapabiliyor musun?
Çünkü her yerde
dizi[0] var.
strcpy veya strncpy istemiyorsan for veya do while dene veya while(){i++;}?
2x16 lcdye yazı yazacağım normalde sprintf ile yazdırılacakları biçimlendirip LCD dizisine atıyordum sprintf bana 5kb alana mal oluyor.
lcd dizisi sabit içerisine yazılacaklar program içerisinde değişiyor.
Strcpy kullanıp kullandığı alana bakacağım.
Teşekkürler.
mesaj birleştirme:: 16 Şubat 2014, 23:28:41
Alıntı yapılan: yldzelektronik - 16 Şubat 2014, 23:22:00
Ve bütün dizi elemanlarına ulaşabiliyor musun?Bunu gerçekten yapabiliyor musun?
Çünkü her yerde dizi[0] var.
strcpy veya strncpy istemiyorsan for veya do while dene veya while(){i++;}?
Hocam buraya yanlış yazmışım dizi elemanları 1 artan sırada gidiyor.
mesaj birleştirme:: 16 Şubat 2014, 23:41:11
Aynı ifadeyi ekrana yazmak için strcpy ile daha fazla alan harcadım.
Alıntı yapılan: mistek - 16 Şubat 2014, 23:27:46
2x16 lcdye yazı yazacağım normalde sprintf ile yazdırılacakları biçimlendirip LCD dizisine atıyordum sprintf bana 5kb alana mal oluyor.
lcd dizisi sabit içerisine yazılacaklar program içerisinde değişiyor.
Strcpy kullanıp kullandığı alana bakacağım.
Teşekkürler.
mesaj birleştirme:: 16 Şubat 2014, 23:28:41
Hocam buraya yanlış yazmışım dizi elemanları 1 artan sırada gidiyor.
mesaj birleştirme:: 16 Şubat 2014, 23:41:11
Aynı ifadeyi ekrana yazmak için strcpy ile daha fazla alan harcadım.
strcpy nasil cok alan harcar? gercek bir strcpy subroutine asagida!
char *strcpy(char *s1, const char *s2)
{
char *s = s1;
while ((*s++ = *s2++) != 0)
;
return (s1);
}
Alıntı yapılan: mufitsozen - 17 Şubat 2014, 09:07:12
strcpy nasil cok alan harcar? gercek bir strcpy subroutine asagida!
char *strcpy(char *s1, const char *s2)
{
char *s = s1;
while ((*s++ = *s2++) != 0)
;
return (s1);
}
Hocam Keil derledikten sonra en altta verdiği bilgilere bakarak söylüyorum.
strcpy ile yaptığımda Code Size:27256strcpy(arguman,"ABCDEFGH12345678");
Lcd_Cursor(1,1);
lcd_Puts(arguman);
strcpy(arguman,"ABCDEFGH12345678");
lcd_Cursor(2,1);
lcd_Puts(arguman);
sprintf ile yazdığımda Code Size: 27184sprintf(arguman,"ABCDEFGH12345678");
lcd_Cursor(1,1);
lcd_Puts(arguman);
sprintf(arguman,"ABCDEFGH12345678");
lcd_Cursor(2,1);
lcd_Puts(arguman);
Optimizasyon Level 0
Merhabalar
C de dizi tanımlamalarında 3 ve üstü tanımlamalarla ilgili derin dokumana ve anlatıma rastlamadım. (Genelde hep yüzeysel anlatım mevcut )
Örnegin şu şekilde Dizi [2][3][4]
3 boyutlu bir dizi tanımladım diyelim 2 / 3 / 4 anlamları nedir.
Veya alt resimdeki tabloda 3 boyutlu tanımlanmış dizinin acıklaması nasıldır ? ( anlayamadım )
(http://www.yazilimmutfagi.com/Makale/Dersler/CSharp/Ders4/resim1.jpg)
indeks[2][0][1] de 56 yi göstermiş.
Burda 2 ye 2.satır desek
0 ?
1 ?
Alıntı yapılan: M_B - 19 Şubat 2014, 10:38:36
Merhabalar
C de dizi tanımlamalarında 3 ve üstü tanımlamalarla ilgili derin dokumana ve anlatıma rastlamadım. (Genelde hep yüzeysel anlatım mevcut )
Belki de 3'den fazla boyuta ihtiyaç olmadığındandır. Aynı şeyi daha basit bir yaklaşımla çözmek daha uygun olabilir. Böyle çok karışık olmaz mı?
Dizi elemanlarını struct yapın.
Keil programında derleme sonrasında kodun içinden derlenilen kodun boyutunu çağırmanın bir yolu varmı?
Romun adresi belli.
Yazacagın fonksiyon romun başından itibaren romun sonuna doğru verileri tarasın. 0xFF... ler ard arda gelmeye başladığında boş alana geldin demektir.
Burdan işlemci kod uzunluğunu bulmuş olur.
zaten o şekilde yapıyorum hocam teşekkürler.
Aslında bir yöntem daha var.
Ne kadar işe yarar bilmiyorum. Programın en sonuna bir fonksiyon ekle. Romdaki program boyu bilgisine ihtiyacın olduğunda bu fonksiyonun adresini öğren. Bu değerden rom başlangıç adresini çıkartırsan tüm programın boyunu çok az hata ile öğrenmiş olursun. Buna 3...5 daha ekleyip gerçek sonucu da hesaplayabilirsin.
merhaba
keildeki proje ismine sağ tıklayıp map dosyasını açtığımızda en alt satırda yazan kısın kod boyutunu vermiyor mu? bunu mu demek istediniz..
örnek olarak : RO size 12Kb gibi yazıyor
Total RO Size (Code + RO Data) 12920 ( 12.62kB)
Total RW Size (RW Data + ZI Data) 568 ( 0.55kB)
Total ROM Size (Code + RO Data + RW Data) 12960 ( 12.66kB)
Hocam kodun boyutunu tam olarak bilip crc almam gerekiyor. Her derlemede kendim yazmak istemiyorum. Bu 32 lik crc yi versiyon eşiti olarak kullanmak istiyorum.
O zaman bos ver program uzunlugunu, "CRC"yi tum rom boyu icin hesapla. Bos olan rom alanlari 0xFFFF datasi olarak isleme alinsin.
Onu denedim olmadı diye hatırlıyorum yarın tekrar denerim. C# ile aynı kodu .bin kaynak kodundan crc oluşturuyorum adreslerde atlamalar olursa veya hepsini alırsam standart bir kod çıkartamıyorum.
winrar-winzip gibi programların oluşturduğu crc ile aynı polinomu işledim. Sonucu aynı yakalamam için bitiş adresi gerekli.
M_B
3 boyutlu dizi dendiğinde aklıma hep küp gelir. Yöntemde öyledir.
http://barisvelioglu.net/2010/02/14/cda-diziarray-yapisi-ve-cok-boyutlu-diziler/ (http://barisvelioglu.net/2010/02/14/cda-diziarray-yapisi-ve-cok-boyutlu-diziler/)
Soft I2C'de bit tanımlaması için şöyle bir macro kullanayım dedim
#define SDA(x) ((x) ? (GPIOB->BSRR = SDA_Pin) : (GPIOB->BRR = SDA_Pin))
derlemede sıkıntı yok ama kullanıma geçince keil aşağıdaki hatayı veriyor
Hardware\I2C\I2C.c(33): error: #136: struct "<unnamed>" has no field "BSRR"
Sebebi nedir? Yanlış kullanımmı söz konusu?
printf() scanf() deki "f" fonksiyon mu demek ? Öyleyse parantez de fonksiyonun içi mi oluyor ?
http://answers.yahoo.com/question/index?qid=20071220030343AApQcDk (http://answers.yahoo.com/question/index?qid=20071220030343AApQcDk)
Fonksiyonun biçimlendirilmiş (formatlanmış) çıktı verdiğini gösteriyor. Sadece bir isimlendirme yöntemi, çalışması ile ilgisi yok. Bu sınıftaki fonksiyonların tırnak içindeki bölümleri format olarak adlandırılıyor.
Alıntı yapılan: Tagli - 03 Mart 2014, 14:31:24
http://answers.yahoo.com/question/index?qid=20071220030343AApQcDk (http://answers.yahoo.com/question/index?qid=20071220030343AApQcDk)
Fonksiyonun biçimlendirilmiş (formatlanmış) çıktı verdiğini gösteriyor. Sadece bir isimlendirme yöntemi, çalışması ile ilgisi yok. Bu sınıftaki fonksiyonların tırnak içindeki bölümleri format olarak adlandırılıyor.
Anladım teşekkür ederim :)
selamlar.Şöyle bir soru takıldı aklıma
int dizi[3]={5,3,7};
int i,j,k;
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
if(dizi>dizi[j])
{
k=dizi[j];
dizi[j]=dizi[j];
dizi=k;
}
}
}
program dizi elemanlarını yerini değiştirmeden önce dizi 5 değeri bulunmakta.if içindeki şart sağlandığında dizi elemanları yer değiştirdiğinde bu diziye direk yansıyormu yoksa döngünün sonlanması mı lazım
yansıyor ama j lerden 2 si i olacak
Merhaba, C de baştaki Main() fonksiyonunun içine void Main(void) şeklinde konmasının amacı nedir ? Hangi durumlarda konur ? Ne farkı vardır ?
Boş olması void ile aynı anlama gelmektedir, derleyiciye kesin olarak bildirmek için void olarak da yazılır. Artık günümüz derleyicilerinde özellikle void şeklinde belirtmeye pek gerek yok sanıyorum. Eski bir gelenek diyelim.
Alıntı yapılan: SpeedyX - 23 Mart 2014, 11:51:54
Boş olması void ile aynı anlama gelmektedir, derleyiciye kesin olarak bildirmek için void olarak da yazılır. Artık günümüz derleyicilerinde özellikle void şeklinde belirtmeye pek gerek yok sanıyorum. Eski bir gelenek diyelim.
İlla void olarak belirtmek gerekiyor diyelim, o zaman void'in anlamı nedir ya da eskiden ne maksatla yazılıyordu ?
C programa parametre yollamak istersen bu void yerine parametrenin degisken tipini belirliyorsun. Ancak bu durum isletim sistemi ustunde calistirilan programlar icin gecerli.
Bizim ciplak islemci ustunde kosan programlarda bunu main(void) yaz gitsin.
Alıntı yapılan: unknownperson - 23 Mart 2014, 15:50:54
İlla void olarak belirtmek gerekiyor diyelim, o zaman void'in anlamı nedir ya da eskiden ne maksatla yazılıyordu ?
Merhaba, aslında konuya bakış açısı burada önemli.
PICC, CCS, C18, C for ARM vb gibi derleyicilerde main(); yada main(void); olmasının farkı yok, çünkü onların üzerinde çalışan bir işletim sistemi yok ve biz customexecutable -param -param2 şeklinde onu çağırmıyoruz. Direkt main in anlamı program başıdır yada belli internal işlemler (low_level_init) yapıldıktan sonra gidilen etikettir. Burada main(void) yazmış olmanız yada boş bırakmış olmanız birşey ifade etmeyecek, hatta main(int i) bile deseniz o i parametresini veren olmayacağı için anlamsız olacaktır.
Eğer bir işletim sistemi üzerinde C/C++ ile kod geliştiriyor olsaydık burada ufak bir fark oluşuyor. Orada da neden eski bir gelenek dediğim anlaşılacaktır.
main(void) yazarak, yaptığımız executable ın bir parametre almadığını kesin olarak ifade ederiz. Boş bıraktığımızda ise belirsiz bir durum oluşur, belirlenmemiş sayıda belirlenmemiş tipte parametreler alır hale gelir.
In C:
void foo() means "a function foo taking an unspecified number of arguments of unspecified type"
void foo(void) means "a function foo taking no arguments"
In C++:
void foo() means "a function foo taking no arguments"
void foo(void) means "a function foo taking no arguments"
pure C ciler main(void) şeklinde yazmaya alıştıklarından dolayı low level da da bu geleneği sürdürmüşler. Fakat görüyorsunuz ki sonradan çıkan C++ da bu fark yokedilip, her iki şekilde de aynı davranış tanımlanmış.
Kusura bakmayın sadece C'yi ayrıntılı olarak öğrenmek istediğimden bu tür sorular sorup biraz uğraştırıyorum sizi , şimdi anladım cevapladığınız için teşekkür ederim
Herkese merhaba, şöyle bir sorum olacak yazdığım programı herhangi bir tuşa basarak kapatmak istiyorum ya da do while komutuyla işlem sonunda while parantezi içine koşul koyucam bu koşulda mesela 1 e basarsa program tekrar edicek 2 ye basarsa program sonlanıcak bunu nasıl yaparım ? İnternette araştırdım kimisinde getchar kimisinde getch kullanıyor kimisi her ikisinide kullanmıyor ben getchar kullanmak istiyorum yardımcı olursanız sevinirim.
do
{
...
...
}
while(degisken != 0);
komutu, degisken 'in sıfırdan farklı olduğu durumlarda do-while döngüsüne devam edecektir.
Eğer illa soru sorup, cevaba göre işlem yapılacaksa, mesela
while(1)
{
printf("tamam mı devam mı? :) ");
scanf("%d", &baskaDegisken);
if (baskadegisken == 1)
devam et;
else if (baskaDegisken == 2)
break;
else
printf("Yanlış seçim...");
}
İlk soru, Windows üzerinde "system("pause");" iş görür. Tabi stdlib.h 'ın include edilmesi gerekir. Bir tuşa basılmasını bekler.
getchar() mı getch() mi, bunlardan birisi standart C içerisinde yoktu ama hangisiydi hatırlayamıyorum şu anda. Sanırım getch() fonksiyonunun standart olması gerek.
Yani standartsa, her ortamda kullanılabilir. Standart değilse, kullanılan derleyicinin klavuzlarına bakmak gerekir bu fonksiyon var mı yok mu diye.
(Yorgun olduğumdan biraz dağınık oldu cevap kusura bakmayın. İnşallah anlatabilmişimdir.)
Alıntı yapılan: Tesla.25 - 05 Nisan 2014, 00:01:17
do
{
...
...
}
while(degisken != 0);
komutu, degisken 'in sıfırdan farklı olduğu durumlarda do-while döngüsüne devam edecektir.
Eğer illa soru sorup, cevaba göre işlem yapılacaksa, mesela
while(1)
{
printf("tamam mı devam mı? :) ");
scanf("%d", &baskaDegisken);
if (baskadegisken == 1)
devam et;
else if (baskaDegisken == 2)
break;
else
printf("Yanlış seçim...");
}
İlk soru, Windows üzerinde "system("pause");" iş görür. Tabi stdlib.h 'ın include edilmesi gerekir. Bir tuşa basılmasını bekler.
getchar() mı getch() mi, bunlardan birisi standart C içerisinde yoktu ama hangisiydi hatırlayamıyorum şu anda. Sanırım getch() fonksiyonunun standart olması gerek.
Yani standartsa, her ortamda kullanılabilir. Standart değilse, kullanılan derleyicinin klavuzlarına bakmak gerekir bu fonksiyon var mı yok mu diye.
(Yorgun olduğumdan biraz dağınık oldu cevap kusura bakmayın. İnşallah anlatabilmişimdir.)
If li olarak değilde daha çok şöyle yapmak istiyorum.
do
{
...
printf("If you want to continue click to 1");
scanf("%d",&repeat);
}
while(repeat == 1);
Bu çalışıyor sorun yok ama bunun devamında diyelim çıkmak istedi 0'a bassın istiyorum ama onu bu düzeneğe koyamadım.Yani bunun için kesinlikle if mi kullanmalıyım ?
#include <stdio.h>
int main(int argc, char **argv)
{
int degisken;
do
{
printf("For exit, press 1\n");
scanf("%d", °isken);
printf("merhaba\n\n");
}while(degisken == 1 || degisken != 0);
}
Mesela bu kodda, while satırına bakarsanız, program 0 girince kapanıyor. 1 girince devam ediyor.
Alıntı yapılan: Tesla.25 - 06 Nisan 2014, 11:07:51
#include <stdio.h>
int main(int argc, char **argv)
{
int degisken;
do
{
printf("For exit, press 1\n");
scanf("%d", °isken);
printf("merhaba\n\n");
}while(degisken == 1 || degisken != 0);
}
Mesela bu kodda, while satırına bakarsanız, program 0 girince kapanıyor. 1 girince devam ediyor.
Tamam şimdi oldu çok teşekkür ederim :)
C dilinde parametre olarak port ismini nasıl alabiliriz ? Örnek ile anlatmak gerekirse;
unsigned char xxxx(&PORTB,1); şeklinde.
aşağıaki yöntemin olması lazım
unsigned char xxxx(volatile unsigned char * port, unsigned char x){
return ((*port)&x);
}
Merhaba arkadaşlar ben ccs ıle pıc ogrenıyorum kendımı c de gelıstırmek ıcın visual studıo da c kodları yazmaya basladım fakat her seferinde aynı hatayı alıyorum bi başlayabilsem süper olcakda bu hata nedir ?
#include<stdio.h>
main()
{
int r;
float pi,alan;
pi=3.14;
printf("dairenin yari çapini gir=");
scanf("%d",&r);
alan=pi*(r*r);
printf("alan=%f\n",alan);
}
hata
Error 1 error C4430: missing type specifier - int assumed. Note: C++ does not support default-int c:\users\ekrem\documents\visual studio 2012\projects\project1\project1\main.cpp 3 1 Project1
Dev-C++ indirirsen başlangıçta seni daha az üzer.
aşağıda ki gibi bir dene
#include<stdio.h>
int main()
{
int r;
float pi,alan;
pi=3.14;
printf("dairenin yari çapini gir=");
scanf("%d",&r);
alan=pi*(r*r);
printf("alan=%f\n",alan);
return 1;
}
dev c++ kurdum tesekkurler cok ısıme yaradı kolay gelsın :)
Arkadaşlar void olarak fonksiyon tanımlıyorum fakat aşağıda çağırma kısmının 2. printf de bir hata veriyor sanırım %d olmayacak fakat void'e ne karşılık geliyor bilmiyorum, yardımcı olursanız sevinirim.
void menu1(int height);
void menu1(int height){
int i,j;
for(i=1;i<=height;i++){
for(j=1;j<=i;j++){
printf("*");
}
printf("\n");
}
//Yukarıdaki gibi bir fonksiyon tanımladım.
int main()
{
int height;
printf("Please enter the height");
scanf("%d",&height);
printf("%d",menu1(height));
}
//Burada 2. printfde hata veriyor sanırım %d olmayacak peki ne olacak void'e karşılık gelen nedir ?
void'e karşılık gelen bir şey yok. Adı üstünde zaten void = hiçlik. Dönüşü void olan fonksiyonu bir değer gibi kullanamazsın. Bu durumda printf("%d",menu1(height)); hatalı. menu1 fonksiyonu zaten yazdırma işi yapıyor, onu tekrar printf içinde kullanmaya çalışmak mantıksız. Doğrudan menu1(height); şeklinde kullanmalısın.
Alıntı yapılan: unknownperson - 11 Nisan 2014, 20:20:44
Arkadaşlar void olarak fonksiyon tanımlıyorum fakat aşağıda çağırma kısmının 2. printf de bir hata veriyor sanırım %d olmayacak fakat void'e ne karşılık geliyor bilmiyorum, yardımcı olursanız sevinirim.
sayin @unknownperson:
- void' turkce karsiligi sifat olarak gecersiz, bos hukumsuz demek. menu1 fonksiyonundan printf icinde %d ile kullanilabilecek ne gibi bir deger donmesini bekliyordunuz?
- menu1 fonksiyonundan cikarken geriye bir deger dondurmuyorsunuz! printfde ne degeri basacak diye dusundunuz? (1, 2, 5, 102, 11234, 32176, -345 ....?)
- program yazmadan once C programlama dili ile ilgili bir kitap okumayi hic dusundunuzmu?
Alıntı yapılan: unknownperson - 11 Nisan 2014, 20:20:44
Arkadaşlar void olarak fonksiyon tanımlıyorum fakat aşağıda çağırma kısmının 2. printf de bir hata veriyor sanırım %d olmayacak fakat void'e ne karşılık geliyor bilmiyorum, yardımcı olursanız sevinirim.
void menu1(int height);
void menu1(int height){
int i,j;
for(i=1;i&amp;amp;lt;=height;i++){
for(j=1;j&amp;amp;lt;=i;j++){
printf("*");
}
printf("\n");
}
//Yukarıdaki gibi bir fonksiyon tanımladım.
int main()
{
int height;
printf("Please enter the height");
scanf("%d",&amp;amp;amp;height);
printf("%d",menu1(height));
}
//Burada 2. printfde hata veriyor sanırım %d olmayacak peki ne olacak void'e karşılık gelen nedir ?
İlacının adı Deitel;Deitel C ve C++
Alıntı yapılan: Tagli - 11 Nisan 2014, 20:59:54
void'e karşılık gelen bir şey yok. Adı üstünde zaten void = hiçlik. Dönüşü void olan fonksiyonu bir değer gibi kullanamazsın. Bu durumda printf("%d",menu1(height)); hatalı. menu1 fonksiyonu zaten yazdırma işi yapıyor, onu tekrar printf içinde kullanmaya çalışmak mantıksız. Doğrudan menu1(height); şeklinde kullanmalısın.
Fonksiyonun içinde saten printf ile bastırıyorum , bu yüzden sadece fonksiyonu çalıştırmam yeterli çok teşekkür ederim net bir şekilde anlattığınız için.Emeğinize sağlık.
Alıntı yapılan: mufitsozen - 11 Nisan 2014, 21:04:50
sayin @unknownperson:
- void' turkce karsiligi sifat olarak gecersiz, bos hukumsuz demek. menu1 fonksiyonundan printf icinde %d ile kullanilabilecek ne gibi bir deger donmesini bekliyordunuz?
- menu1 fonksiyonundan cikarken geriye bir deger dondurmuyorsunuz! printfde ne degeri basacak diye dusundunuz? (1, 2, 5, 102, 11234, 32176, -345 ....?)
- program yazmadan once C programlama dili ile ilgili bir kitap okumayi hic dusundunuzmu?
1. Void'i şuana kadar ilk defa kullanıyorum ki hiçbir programda ya da başka bir yerde görmedim , okulda anlatılandan daha ilerde gidiyorum daha fonksiyonlar konusunu dahi görmedik kendi başıma bu programı yazmaya çalışıyorum hocamın sadece bana dediği void kullanmam bende o yüzden bu şekilde kullandım.
2.Aynı şekilde return satırını da ilk defa kullanıyorum, o yazdığım kodlar programın bitmiş hali değildi ben size sadece printf deki hatayı sordum.
3.Daha önce 2 kitap bitirdim şimdi Deitel'e başladım okul ile beraber okuyarak ilerliyorum, ama C programlamada olay okumakla olmuyor deneme yanılma yöntemiyle hata yapa yapa öğreniliyor.
İyi Akşamlar.
Alıntı yapılan: AsHeS - 11 Nisan 2014, 21:29:32
İlacının adı Deitel;Deitel C ve C++
Evet haklısınız Deitelde 5. ünite fonksiyonları okuyup tamamıyla anlayıp bu işe girişmem daha doğru olacak ;D
%d yanlış sanırım int değişken tanımlamışsın printf ile desimal deger basmasını istiyorsun %lu'yu dene istersen. Kolay gelsin
Alıntı yapılan: Huzame - 12 Nisan 2014, 02:51:08
%d yanlış sanırım int değişken tanımlamışsın printf ile desimal deger basmasını istiyorsun %lu'yu dene istersen. Kolay gelsin
Yok Tagli'nin dediği gibi olacak sizin dediğinizi de alternatif olarak deneyim dedim hata verdi.
Alıntı yapılan: z - 25 Ekim 2011, 01:46:12
Kaydirma operatorleri
a=1<<4 a ya 0x10 yukle demek. 1 degerini 4 kere sola kaydirdi.
a=3<<4 a ya 0x30 yukle demek. 3 degerini 4 kere sola kaydirdi.
a=0x80>>1 a ya 0x40 yukle demek. 0x80 degerini 1 kere saga kaydirdi.
a=0x80>>7 a ya 0x01 yukle demek. 0x80 degerini 7 kere saga kaydirdi.
Ornegin neden a ya 0x10 yuklemek icin a=0x10 değil de a=1<<4 yazariz?
Bir registerin adi REG olsun ve buna ait aciklamalarinin bulundugu dokumanda PortClkOn adindaki bitin sira numarasi 4 olsun.
Yani; 0. değil, 1. hic değil, 2. de değil, 3. de değil 4. bit
Reg=1<<4 yazinca bir bakista regin 4. bitini 1 yaptigimiz anlasilir. reg=0x10 yazarsak da anlasilir.
Fakat Reg=3<<4 yapinca Reg'in 5 ve 4 nolu bitlerinin 1 oldugu daha sempatik anlasilir. Siz isterseniz Reg=0x30 da yazabilirsiniz.
Fakat kaydirma operatorlerinde kayma miktarini hep sabit deger vermek zorunda değilsiniz. Reg=a<<b; de yazarak parametrik deger verebilirsiniz.
Hocam reg = 0<<5 dersek 5. biti 0 mı yapmış oluruz?
Alıntı yapılan: Huzame - 13 Nisan 2014, 01:38:55
reg = 0<<5 dersek 5. biti 0 mı yapmış oluruz?
reg=0<<5 demek reg=0 ile ayni anlama gelir.
Eger 5 nolu biti 0 yapmak istiyorsan reg'in diger bitlerine dokunmak istemiyor sadece 5. biti 0 yapmak istiyorsun demektir.
reg degiskenini 8 bit varsayalim;
Bu durumda reg = reg & 0xDF yapilir.
Ya da reg &=0xDF
Yada reg & = ~0x20
Yada reg &=~(1<<5) yapabilirsin.
Bunlarin hepsi de reg degiskenini 0xDF ile and yapmakla esdegerdir.
Hocam gecenin bu saatinde bu kadar kısa bir sürede cevap için soğolun. Bu inanılmaz bir şey ben gelecekten çok ümitvarım. Emeğinize sağlık
Ne zaman OR ne zaman AND?
A adında degişkenimiz olsun. Bunun en düşük 2 bitine 10 verisi yükleyelim. Fakat A nın diğer bitleri değişmesin. -> Burdaki yeni A sayımız 0xFFFFFF10 mi?
A= A & 0xFFFFFFFC; yada A&= 0xFFFFFFFC; En düşük bitleri sil -Burda en düşük 2 biti sileceğiz değil mi? Yani 0xFFFFFF10 olacak?- (Diğer bitleri 1 ile AND'lediğimiz için değişmez) -Diğer bitleri nasıl 1 ile end'liyoruz? Bir de and'lemek demek çarpma oluyor değil mi?-
A= A | 0x00000002; yada A|= 0x00000002; Silinmiş bitler 00, bunu 10 ile OR'la ve yerine yaz. -Silinmiş bitler 00 kısmında neyi kastettiğinizi tam olarak anlayamadım hocam. :( Burada benim anladığım şekli A sayısı 0x00000010 olacak en başta dediğimiz üzere sonra bunu or'larsak yani yeni A sayımız ile 0x00000002'i çarparsak mı sonuca ulaşırız? Doğru mudur hocam-
Böylece diğer bitler aynen kaldı fakat en düşük bitler 10 yapılmış oldu.
Eğer A registerine doğrudan A=0x00000002 yazsaydık en düşük 2 bit 10 olacaktı fakat diğerleri de 0 olacaktı. (Bunu istemeyiz) -Bu kısımda da aklıma takılan yer A'ya doğruda 0x00000002 yazsaydık aynı sayı ile and'leseydik yani çarpsaydık nasıl en düşük iki biti 10 olacaktı?-
----------------------------------- Hocam çok eksiğim var valla yardımcı olursanız çok sevinirim.
Şimdiye kadar görmediğimiz NOT operatörü ile de aynı işlemi yapabiliriz.
A&= ~0x00000003; En düşük 2 biti (A1 A0) sil (Diğer bitleri 1 ile AND'lediğimiz için değişmez)
A|= 0x00000002; Silinmiş bitler 00, bunu 10 (Decimal 2) ile OR'la ve yerine yaz.
GPIOD->MODER=0x55000000; // GPIOD nin 15, 14, 13, 12 pinleri cikis tanimlandi (Ledler bu pinlerde)
0x55000000 sayısını nasıl elde ettik?
Moder registerinin anlatildigi sayfada 0x55000000 32 bit sayisinin 1 ve 0 olan olan bitlerinin registerde hangi bitlere karsilik geldigine bak ve buraya yaz.
Bu zahmete girmezsen bu isi ogrenemezsin. Buraya yaz kontrol edelim.
0x55000000 sayisinda 1 degerini alan bitlerin MODER registerindeki adlari nelerdir?
Bir ara binary hesap makinesi daha dogrusu verilen hex sayiyi bitler halinde gosteren bir uygulama programi vermistim. Bu programi bulup indir. isleri cok kolaylastirir.
Şimdi olayı anladım. Rehberi kullanmayı yeni öğrendim de diyebilirim. Bendeki Rehberin 278. sayfasına göre;
00: Input (reset state)
01: General purpose output mode
10: Alternate function mode
11: Analog mode
Böyle bir olay varmış. Yani sizin dediğiniz 15,14,13,12'yi OUTPUT yaptık derken. Moder 15, Moder 14, Moder 13, Moder 12'nin rw'lerini 1 0 olarak ayarlardım. Sonucunda da 01010101000000000000000000000000 böyle bir sayı elde ettim. Bu tabi binary bunu da Hex'e çevirince. 0x55000000 elde etmiş oldum.
0x55000000 sayisinda 1 degerini alan bitlerin MODER registerindeki adlari nelerdir? //Bu soruyu tam olarak anlayamadım?
Tamam iste olay bundan ibaret.
Anlayamadim dedigin kisim;
Atiyorum hex sayinin 1 olan bitlerinden birisi MODER registerinde 30 nolu bitine isabet ediyorsa katalogda MODER registerinde 30 nolu bite atiyorum M2 diye isim vermistir sen bu M2 yi cevap verecektin ama gerek kalmadi olayi cozmussun.
selamlar
bir karakter dizisine ASCII tablosundaki karakterleri random olarak yüklüyorum fakat dizinin ilk karakterine '\0'(NULL) atanabiliyor(dizi[0]='\0',dizi[1]='\0',dizi[2]='a'...)
bu diziyi ekrana string olarak basmak için ne gibi işlemler yapmalıyım
String üzerinde işlem yapan kütüphane fonksiyonlarını kullanamazsın çünkü bunlar \0 karakterini görünce dururlar. Kendin bir döngü yazmalı diziyi karakter karakter bastırmalısın. printf("%c", karakter_adi) şeklinde yazarsan \0 için çalışır mı emin değilim ama çalışmaz ise, bir if bloğu içinde karakteri kontrol edip ekrana kendin elle "\0" yazdırabilirsin. Zaten unutma, ASCII tablosundaki bazı karakterlerin görsel karşılığı yoktur. Bunları hex kodu olarak bastırman gerekli.
İlk karakteri kontrol edip '\0' olup olmamasına göre aşağıdaki gibi bi işlem yapsan olmaz mı?
if(dizi[0]==0)
printf("%s",dizi+1);
else
printf("%s",dizi);
karakter karakter basmada sorun yok (görsel karşılığı olmayanlara dikket ediyorum).tabi dediğiniz gibi string işlemleri yapan fonksiyonlar ilk karakterde işlemi sonlandırıyor.elle yapmak gerekecek.
Teşekkürler
mesaj birleştirme:: 23 Mayıs 2014, 14:22:06
Alıntı yapılan: yamak - 23 Mayıs 2014, 14:14:14
İlk karakteri kontrol edip '\0' olup olmamasına göre aşağıdaki gibi bi işlem yapsan olmaz mı?
if(dizi[0]==0)
printf("%s",dizi+1);
else
printf("%s",dizi);
tüm karakterler önemli NULL dahil kesip atamıyorum diziden
merhaba arkadaşlar
stm ve keil ile çalışmaya başladım hafiften program yazıyorum.birkac takıldığım nokta var;
1-keilde int değişkeni tanımlarken uint32_C ifadesi nedir.
2-#define adr (byte *) "clnt2" burda adr ye clnt2 string ifadesinin adresini mi atıyoruz?
3-
int main()
{
char data[8];
while(*data)
{
data++; //burda left value hatası veriyor.neden verdiğini anlayamadım
}
}
fakat bunu fonksiyon olarak tanımlayınca sıkıntı olmuyor.örneğin
void fonk(char *data)
{
while(*data)
{
data++; //NORMAL
}
}
4-
int str[1];
sprintf(str,"%d",500);
printf("str:%s",str); //burda str için ayırdığım alana nasıl oluyor 500 atayabiliyorum ??
bu konularda yardımcı olurmusunuz
Ilkinde data++ satiri söyle anlasiliyor :
data tablosu(8 uzunlugunda) = data tablosu + 1
bir tablo ile 1 degeri toplanamiyor.
Ikinci kodda data pointer'i 1 artiliyor, bir sonraki adrese geçiliyor.
Bunu main içinde tanımlayınca neden öyle anlaşıldı normal fonksiyonda neden istenilen şekilde anlaşılıyor?
hocam burrda tablo dediğiniz adres mi oluyor.(adress + değişken) gibi mi oluyor
Main de data isimli bir array var. Dikkat et bu bir işaretçi değil array. Adresi belli.
data++ ile işaretçinin gösterdiği adresi artırırsın. Ama senin bir işaretçin yok.
fonksiyona geilen parametre ise işaretçi. bu yüzden fonksiyonda sorun olmuyor.
char data[8]
ptr *= data;
while( *ptr)
{
ptr++;
}
şeklinde yazsaydınız sorun olmazdı.
diğer soruda ise , durum şu.
sprintf(..) fonksiyonunun ilk parametresi bir işaretçi. printf bu parametreye geçilen adresi bilir sadece. Kaç byte uzunluğunda olduğunu bilmez. yazar gidrer.
İşaretilerle çalışmak güzeldir. Ama tüm sorumlulık programcıdadır. Siz bileceksiniz onun 1 byte olduğunu ve "500" stringinin oraya sığmayacağını.
mesaj birleştirme:: 26 Mayıs 2014, 17:51:51
uint32_c 32 bit constant.
32 bit işlemci için aşağıdaki satıra eşit
const unsigned int
2-#define adr (byte *) "clnt2" burda adr ye clnt2 string ifadesinin adresini mi atıyoruz?
Tam olarak öyle değil.
adr tek başına kullanılabilir bir şey değil. derleyici adr gördüğü yere karşısındaki ifadeyi yerleştiriyor.
byte *ptr;
ptr = adr;
şeklinde bir satır derlenirken, derleyici bu ifadeyi ptr = (byte *) "clnt2" şekline çeviriyor.
Teşekkürler hocam cevaplarınız için çok faydalı oldu.
iyi akşamlar
void send(uint8_t byt)
{
.....
}
void send_data(uint16_t adres)
{
send((uint8_t)(adres>>7));
}
arkadaşlar 16 bitlik adres bilgisi 7 bit kaydırılıp sonra 8 bit olarak mı ayarlanıyor yoksa 8 bite dönüştürülüp sonra mı 7 bit kaydırılıyor
adress ve kaydırma komutu aynı parantezde olduğu için, önce kaydırma yapılıyor.
assert_failed fonksiyonunu kullanan vardır diye umut ediyorum. Hatalı Dosyayı, Fonksiyonu ve geçirilmeye çalışılan parametreyi veriyor diye biliyorum.
Bunu Nasıl Yapıyor ?
Merhaba, C de Sudoku yapmayı planlıyorum fakat bunu kendim internetten herhangi bir kod bakmayarak yapmak istiyorum. Kafamda şekillendi diziden 3x3 tablo oluşturup rand() ile sayı atıcam herşeyi planladım fakat tek sıkıntım şu bu sudokunun çözülmesi için belli sayıların yeri boşluk olmalı ki kullanıcı tamamlasın fakat hangi yerlerin boşluk olacağını nasıl ayarlıcam ? yardımcı olursanız sevinirim.
Alıntı yapılan: muhittin_kaplan - 13 Haziran 2014, 14:38:47
assert_failed fonksiyonunu kullanan vardır diye umut ediyorum. Hatalı Dosyayı, Fonksiyonu ve geçirilmeye çalışılan parametreyi veriyor diye biliyorum.
Bunu Nasıl Yapıyor ?
Muhittin hoca hala cevabı bulamadıysan söyleyeyim __FILE__ ve __LINE__ makrosu ile.
printf("File: %s Line = %d",__FILE__, __LINE__);// Dosya ismi ve satır numarasını alırsın direkt.
Edit: Ahanda doküman
http://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html (http://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html)
c de int *dizi[6]; tanımlaması nasıl kullanılıyor?
Alıntı yapılan: musaak - 11 Temmuz 2014, 01:06:38
c de int *dizi[6]; tanımlaması nasıl kullanılıyor?
int *dizi; deserseniz int türünde bir adet pointer tanımlamış olursunuz.
int *dizi[6]; deserseniz int türünde 6 farklı adres tutabilen bir pointer tanımlamış olursunuz.
Can Bus ile uğraşırken bir sorunla karşılaştım önerilerinizi almak isterim.
Şöyle bir Struct yapı var
typedef struct
{
uint32_t StdId; /*!< Specifies the standard identifier.
This parameter can be a value between 0 to 0x7FF. */
uint32_t ExtId; /*!< Specifies the extended identifier.
This parameter can be a value between 0 to 0x1FFFFFFF. */
uint8_t IDE; /*!< Specifies the type of identifier for the message that will be transmitted.
This parameter can be a value of @ref CAN_identifier_type */
uint8_t RTR; /*!< Specifies the type of frame for the message that will be transmitted.
This parameter can be a value of @ref CAN_remote_transmission_request */
uint8_t DLC; /*!< Specifies the length of the frame that will be transmitted.
This parameter can be a value between 0 to 8 */
uint8_t Data[8]; /*!< Contains the data to be transmitted. It ranges from 0 to 0xFF. */
} CanTxMsg;
/**
* @brief CAN Rx message structure definition
*/
typedef struct
{
uint32_t StdId; /*!< Specifies the standard identifier.
This parameter can be a value between 0 to 0x7FF. */
uint32_t ExtId; /*!< Specifies the extended identifier.
This parameter can be a value between 0 to 0x1FFFFFFF. */
uint8_t IDE; /*!< Specifies the type of identifier for the message that will be received.
This parameter can be a value of @ref CAN_identifier_type */
uint8_t RTR; /*!< Specifies the type of frame for the received message.
This parameter can be a value of @ref CAN_remote_transmission_request */
uint8_t DLC; /*!< Specifies the length of the frame that will be received.
This parameter can be a value between 0 to 8 */
uint8_t Data[8]; /*!< Contains the data to be received. It ranges from 0 to 0xFF. */
uint8_t FMI; /*!< Specifies the index of the filter the message stored in the mailbox passes through.
This parameter can be a value between 0 to 0xFF */
} CanRxMsg;
Ben CanBus kütüphanemde Yukarıdaki gibi CanRxMsg türünde değişken tanımlar gibi bir yapı tanımlıyorum.
CanRxMsg RxMessage;
CanBus kütüphanesi içerisinde yukarıdaki şekilde tanımlanmış yapının elemanlarındaki değerleri görebiliyorum. Örneğin RxMessage.StdId nin içerisindeki değerleri doğru bir şekilde görebiliyorum. Şimdi Ben aynı yapıyı yani RxMessage yapısını main.c içerisindede kullanayım diyorum. Gerektiğinde RxMessage.StdId içeriğini main'dede görebileyim.
main.c'nin başına aşağıdaki gibi bir tanımlama yapıyorum.
extern CanRxMsg RxMessage;
Bu şekilde bir kullanımda keil hata vermiyor ama CanBus kütüphanesi içerisinde RxMessage.StdId içerisindeki değeri görebilirken aynı değere main içerisinde baktığımda içinin 0 olduğunu görüyorum. RxMessage nin bütün elemanları için geçerli bu durum.
Örneğin CanBus kütüphanes içerisinde RxMessage.StdId değişkenine 0x3042 yüklüyorum ve mainde aynı elemanı okuyorum içeriği sıfır.
Ama aynı şekilde CanBus kütüphanesinde yine Global olarak tanımladığım uint8_t türündeki değişkenimi aynı şekilde main programının başında tanımlayıp kullanabiliyorum. Tek bir değişkende sıkıntı çıkmıyor.
Anlam veremedim. Normalde bir fonksiyon içerisinde global olarak tanımlanmış Struct bir yapıyı başka bir fonksiyonda kullanmak için ne yapmamız gerekiyor. Yanlış birşeymi yapıyorum?
Hocam sadece sonunun son cümlesi için,
Fonksiyon içinde global tanımlama nasıl oluyor? Benim bildiğim fonksiyon içinde tanımlanan sadece o fonksiyonun yerel değişkenleri olmaz mı? Global yapmak için "file scope" olması gerekmez mi?Yani fonksiyon alanı dışında tanımlanması gerekmiyor mu?
1 - Global değişkenleri mümkün mertebe kullanmamaya özen gösterin.
2 - Eğer illa kullanacaksanız volatile olduğundan emin olun.
3 - Global değişken kullanmak yerine bu türde değişken aktarımlarını weak callback fonksiyonlar ile yapabilirsiniz.
Alıntı yapılan: mir_as82 - 15 Ağustos 2014, 09:47:22
Hocam sadece sonunun son cümlesi için,
Fonksiyon içinde global tanımlama nasıl oluyor? Benim bildiğim fonksiyon içinde tanımlanan sadece o fonksiyonun yerel değişkenleri olmaz mı? Global yapmak için "file scope" olması gerekmez mi?Yani fonksiyon alanı dışında tanımlanması gerekmiyor mu?
Hocam pardon, Aslında orada cümleyi yanlış kurmuşum. Dediğiniz gibi tezatlık var. Global derken RxMessage Yapısını CanBus kütüphanemin başında tanımlıyorum. CanBus kütüphanesi için Global oluyor sanırım.
Normalde bu işlemi tek değişken ile sıklıkla kullanırım. Global değişken neden kullanmamaya özen gösteriyoruz?
Dediğiniz gibi veri aktarımı için bir fonksiyon yazabilirim ama doğrudan bahsettiğim yöntemle değişken aktarımı daha çok işime gelir.
Benim anlamadığım, tek bir değişkende sürekli kullandığım yöntem neden bir struct için işe yaramıyor?
Alıntı YapGlobal değişken neden kullanmamaya özen gösteriyoruz?
1 - Global değişkenler hatalara en çok sebebiyet verenlerdir.
2 - Her fonksiyon tarafından erişilebilir olmaları yazılım büyüdükçe takip edilmelerini çok zorlaştırır.
3 - Doğru tanımlanmamışsalar derleme esnasında derleyici tarafından optimize edilebilirler.
Ayrıca değişkenleri kullanılacakları yere yakın tutmak iyi bir tasarım pratiğidir. Ayrıca mümkünse derleyiciniz destekliyorsa C99 ve üstü standartlara uygun kod yazmaya çalışın. Keil v4 için "--c99" parametresini C/C++ sekmesinde tanımlamanız bu işi görür. Keil v5 de zaten seçebiliyorsunuz.
@ByteMaster Dediklerinizi anladım. Ama hala asıl sorun hakkında cevap alamadım. Fikri olan varmı?
Hocam benim anladığım global bir structure oluşturmak istiyorsunuz.
define.C dosya içerisinde struck tanımlayıp isimlendirin.
struct CanTx CanTxMsg;
define.H dosya içerisinide aşağıdaki şekilde oluşturun.
struct CanTxMsg
{
...
} ;
extern struct CanTx CanTxMsg;
Bu şekilde define.H dosyasını çağırdığınız her C dosyasında struct dizilerinize erişebilirsiniz. Bunun başka türlü bir yolu yok.
Başınıza multiple inclusion sorunu gelirse bunu egale etmeyi de unutmayin. Belki olabilir diye uyarayim dedim : )
Merhaba,
Elimde ki uint16-8 tipi değişkenlerin yüksek değerli 2 basamağını bir diziye kaydetmek için sprintf ile çalışıyorum.
sprintf(array,"a:%02 b:%1d",a,b); gibi kullanıyorum. Fakat a değişkeni içinde 3 basamaklı olduğunda 3, 2 olduğunda ise 2 basamaklı yazıyor yani 0 eklemiyor. Aynı şekilde b değişkeninide tek hane yazmıyor.Çıktı şu şekilde oluyot;
a:251 b: 123
a:25 b:563 gibi.
Daha önce yazıyordu program üzerinde biraz ekle çıkar dan sonra düzgün çalışmamaya başladı. Sorun neden kaynaklı olabilir acaba?
Bu iş için bir fonksiyon yazabilirm ama çok sayıda ve değişken uzunlukta sayılarla uğraşacagım için sprintf daha esnek olur diye düşünüyorum.
printf(%5d\n",3);
çıktı: "00003"
%5d ifadesi ile 5 karakterlik yer ayrılıyor fakat 0 konmuyor.
Ben olmayan basamaklarda da sıfır olsun istiyorum. Mesela sayı sıfırsa 00, sayı 2 ise 02 gibi. Dolaysıyla %02d ifadesini kullanıyorum ama işlev görmüyor.
Ayrıca yazmayı unutmuşum derleyici xc8.
Arkadaşın sorusunu umarım baltalamam.Ancak benim de sormak istediğim bir şey var.
Keil ile mi ilgili bilmiyorum ama bir sorun yaşıyorum.Şöyleki;
void GPIOConfig(GPIOConfigEnum_Typedef* CurrentGPIOConfigEnum)
şeklinde bir fonksiyonum var.Fonksiyonda aldığım değişkeni;
switch(*CurrentGPIOConfigEnum){
case ConfigEnum_FSMC:
şeklinde kontrol ediyorum.Parametreyi gönderdiğim fonksiyonda parametreyi yalnızca karşılaştırma amaçlı kullanıyorum.
Ancak gönderiğim parametrelerin değerlerine göre hareket etmiyor.Keil ile debug da watcha veya memorye eklesem not in scope diyor veya adresini 0 olarak değerini de 0 olarak gösteriyor.
Aynı durum oluşturduğum struct değişkenler için de geçerli oluyor.Ancak başka bir şey daha dikkatimi çekti.
Stnin standart lib de yer alan fonksiyonlarında da aynı şey oluyor.Mesela gpioinit fonksiyonunda da pointer olarak struct gönderiliyor.Orada da aynı şeyler oluyor.Ama nedenini anlamadım.
Bir de global bir struct tanımlayıp main içinde fonksiyona çağrı yaparken structı gönderiyorum.Şöyle;
BoardConfig_Typedef BoardConfigStructure;
int main(void){
BoardConfigStructure.LCDConfig.ConnectionMode = ConnectionMode_8080;
BoardConfigStructure.LCDConfig.Resulation = P800x480;
BoardConfigStructure.LCDConfig.LCDFlag = 1;
BoardConfig(&BoardConfigStructure);
...
}
void BoardConfig(BoardConfig_Typedef* BoardConfigStructure){
//InitStatusFlags_Typedef InitStatasFlagStructure;
delay_init(100);
if (BoardConfigStructure->LCDConfig.LCDFlag == 1){
...
}
}
Ancak boardconfig fonksiyonu içinde yapıya debug ile baktığımda başta init ettiğim gibi değerler almadığını görüyorum.Ancak ben maindeki değişkenin adresini göndermiştim.Mainde global olarak tanımladığım değişkenin adresiyle gitmesi gerekmez miydi?Haliyle ilk verdiğim değerleri çağrı yaptığım fonksiyonda da koruyo olması gerekmez mi?
Son olarak enum bir değişkeni pointer olarak parametre geçebilir miyiz?
typedef enum{
P320x240,
P480x272,
P640x480,
P800x480
}Resulation_Typedef;
void LCD_Init(Resulation_Typedef* Resulation){
switch(*Resulation){
şeklindeki kullanım doğru mudur?
Kimsenin söyleceği bir kelimesi yok sanırım?
Bildiğim kadarıyla switch epey nazlı bir komut. Özellikle C'de, C++'ta olduğundan daha da nazlı. İçine sadece sabit tamsayı ifade veya enum gibi şeyler kabul eder. Pointer ile kullanımında ben derleyicinin hata vermesini beklerdim, ama hata vermiyorsa da garip çalışmasına şaşırmam. enum'lar struct gibi bileşenler değil, o yüzden pointer ile aktarmana gerek yok. Aslında hiç öyle yapıldığını da görmedim, bana yanlış gibi geldi. Doğrudan aktar fonksiyona.
Bu arada, Resulation değil, Resolution olacak.
burda temel mantık hatası var. enum dediğin zaten pointer kadar yer tutar. neden fonksiyona pointer parametre geçiyorsun ki? ayrıca switch yerine if ile dallanabilirsin. switch, sıralı dallanan kodlarda mantıklı, mesela 0,1,2,3... diye gidiyorsa. zaten asm çıktısına bakarsanız ofset + o değişken tipinde jmp gibi komutlak olarak derlenir. ayrıca nazlı olan enum ve struct'tır bence. packed olması vs. compiler'a bağımlı birçok şey var dikkat etmezsen.
struct pointer konusunda hata yok gibi anlattığın kadarıyla. kodun tamamını görmek lazım.
Birşey sorayım. Bilgisayarda konsol uygulaması için soruyorum...
getchar fonksiyonuna zaman aşımı koyabiliyor muyuz?
Kullanıcı 5 saniye boyunca bir tuşa basmaz ise daha fazla beklemesin devam etsin gibi...
Sırf merak ettim, lazım değil aslında.
Merhaba,
Sorum "const" niteleyicisi ile ilgili.
#include <stdio.h>
int main(void)
{
const char *dizi[4] = {"bir", "iki", "uc", "dort"};
dizi[0] = "on";
dizi[1] = "yirmi";
dizi[2] = "otuz";
dizi[3] = "kirk";
return 0;
}
Yukardaki kodda görülen "array pointer" ın içeriği "const" olarak tanımlanmış. Yani içeriği değiştirememem gerekiyor. Ama her dizi elemanı için (dizi[0], dizi[1], dizi[2], dizi[3]) yeni string girdiğimde hata vermeden derliyor. Bu durumda "const" niteleyicisinin kullanım amacı ne oluyor?
Bir başka kod örneği, daha basit, bu da hatasız derleniyor.
#include <stdio.h>
int main(void)
{
const char *dizi = "atmak";
dizi = "tutmak";
return 0;
}
İyi akşamlar.
@gerbay hocam, teşekkür ederim.
İki boyutlu pointer nasıl oluyor? Pek anlayamadım, "pointer to pointer" mı oluyor? Örnek verdiğim kodda dizide değişiklik yapabilmemin sebebi pointer 'ın sadece dizi adresini sabit (const) yapması mı? Böylece içeriği değiştirebiliyorum.
Hocam onu değiştirmek run time hatasi olabilir. Yani derleme zamanında hata almayabilirsin.
Alıntı yapılan: mir_as82 - 04 Kasım 2014, 20:07:15
Hocam onu değiştirmek run time hatasi olabilir. Yani derleme zamanında hata almayabilirsin.
hocam nasıl bir "run time" hatası olabilir?
Her dizi elemani diyor ki. Ben gosterdigim adresi sadece okuma yapmak için gosteririm. O adreslerin içeriğini benim vasitamla değiştiremezsiniz, der. Yani senin yaptigin. Verdiğin sozu tutmamaktir:).
mesaj birleştirme:: 05 Kasım 2014, 20:36:22
Sen gerbay hocanin dediğini yap.
Ömrü boyunca ayni adresi ve o adresi de sadece okuma yapmak için göstersin. Kendisi const gosterdigi yer const olan gösterici demek. Const char * const dizi[ ]. Bu su demek. Hep ayni adresi gosteririm ve o adresin olduğu yerdeki nesneyi benim vasitamla degisemezsin.
Hocam @gerbay hocam da anlatmış ama.
#include <stdio.h>
int main(void)
{
const char *dizi[4] = {"bir", "iki", "uc", "dort"};
dizi[0] = "on";
dizi[1] = "yirmi";
dizi[2] = "otuz";
dizi[3] = "kirk";
return 0;
}
Sizin yukarıdaki kodda tanımladığınız dizinin her bir elemanı const char* türünden ve bu da demek oluyo ki bu dizinin her bir elemanı bir adres ve bu adresteki veri değiştirilemez.Siz dizi[0]="on" dediğinizde bu adresteki veriyi değil de adresin kendisini değiştirmiş oluyosunuz.Fakat *dizi[0]=5 gibi bir işlemi yapamazsınız.Bunu yapabilmeniz için const belirtecini kaldırmanız gerekir.Tabi sadece const u kaldırarak denerseniz derleme hatası almazsınız ama çalışma esnasında segmentation fault oluşabilir.Tabi bu ayrı bi konu.
Chat *const dizi [ ] deseydiniz. O zaman kendi dizinizi sadece ilk değer verilen adresleri tutmasi ile sinirlamis olacaktiniz. C de string literaller adres olarak ele alinir. "Ali" bir string literaldir.
Alıntı yapılan: kantirici - 29 Ağustos 2014, 22:35:41
%5d ifadesi ile 5 karakterlik yer ayrılıyor fakat 0 konmuyor.
Ben olmayan basamaklarda da sıfır olsun istiyorum. Mesela sayı sıfırsa 00, sayı 2 ise 02 gibi. Dolaysıyla %02d ifadesini kullanıyorum ama işlev görmüyor.
Ayrıca yazmayı unutmuşum derleyici xc8.
%5d yerine %05d yaz istediğin olur.
Aşağıdaki makaleyi okursanız "const" konusunda detaylı bilgilere erişebilirsiniz.
http://www.dansaks.com/articles/1998-08%20What%20const%20Really%20Means.pdf (http://www.dansaks.com/articles/1998-08%20What%20const%20Really%20Means.pdf)
Alıntı yapılan: arslan74 - 05 Kasım 2014, 08:46:57
%5d yerine %05d yaz istediğin olur.
Merhaba,
XC8 de deniyorum sorunsuz çalışıyor. Sende başka sorun olabilir.
Alıntı yapılan: yamak - 04 Kasım 2014, 23:32:18
Siz dizi[0]="on" dediğinizde bu adresteki veriyi değil de adresin kendisini değiştirmiş oluyosunuz.Fakat *dizi[0]=5 gibi bir işlemi yapamazsınız.Bunu yapabilmeniz için const belirtecini kaldırmanız gerekir.Tabi sadece const u kaldırarak denerseniz derleme hatası almazsınız ama çalışma esnasında segmentation fault oluşabilir.Tabi bu ayrı bi konu.
@yamak hocam, eğer
dizi[0] = "on"; dediğimde değişen adresin kendisi oluyorsa aşağıdaki kodu derleyip çalıştığımda neden aynı adres değerleri dönüyor? Diziyi değiştirdiğimde adres değerinin de değişmesi gerekmez mi?
#include <stdio.h>
int main(void)
{
int i;
const char *dizi[4] = {"bir", "iki", "uc", "dort"};
for(i = 0; i < 4; i++)
{
printf("&dizi[%d]: %p\n", i + 1, &dizi[i]);
}
dizi[0] = "on";
dizi[1] = "yirmi";
dizi[2] = "otuz";
dizi[3] = "kirk";
printf("\n****************************\n\n");
for(i = 0; i < 4; i++)
{
printf("&dizi[%d]: %p\n", i + 1, &dizi[i]);
}
return 0;
}
(http://i.hizliresim.com/ozRGgX.jpg) (http://hizliresim.com/ozRGgX)
Alıntı yapılan: mir_as82 - 04 Kasım 2014, 20:26:47
Her dizi elemani diyor ki. Ben gosterdigim adresi sadece okuma yapmak için gosteririm. O adreslerin içeriğini benim vasitamla değiştiremezsiniz, der. Yani senin yaptigin. Verdiğin sozu tutmamaktir:).
mesaj birleştirme:: 05 Kasım 2014, 20:36:22
Sen gerbay hocanin dediğini yap.
Ömrü boyunca ayni adresi ve o adresi de sadece okuma yapmak için göstersin. Kendisi const gosterdigi yer const olan gösterici demek. Const char * const dizi[ ]. Bu su demek. Hep ayni adresi gosteririm ve o adresin olduğu yerdeki nesneyi benim vasitamla degisemezsin.
Hocam amacım söz verip de tutmamak değil :) Anlamadığım şey, "array pointer"
const char *dizi[] şeklinde tanımlandıktan sonra
*dizi[] nin taşıdığı bilgi string 'in başlangıç adresleri mi oluyor. Yukarda yazdığım kod parçasını değiştirip derlediğimde:
#include <stdio.h>
int main(void)
{
int i;
const char *dizi[4] = {"bir", "iki", "uc", "dort"};
for(i = 0; i < 4; i++)
{
printf("*dizi[%d]: %p\n", i + 1, *dizi[i]);
}
dizi[0] = "on";
dizi[1] = "yirmi";
dizi[2] = "otuz";
dizi[3] = "kirk";
printf("\n****************************\n\n");
for(i = 0; i < 4; i++)
{
printf("*dizi[%d]: %p\n", i + 1, *dizi[i]);
}
return 0;
}
(http://i.hizliresim.com/ynrY59.jpg) (http://hizliresim.com/ynrY59)
sonucu ortaya çıkıyor. Burada çıkan değerler girilen string 'lerin başlangıç adresleri mi oluyor?
Burak hocam makale için teşekkür ederim.
Hocam &dizi[1] şeklinde yazdırdığınızda dizi[1] değişkeninin bellekte tutulduğu adresi öğrenmiş olursunuz.Halbuki öğrenmeniz gereken bu adreste saklanan adres.
Mesela aşağıdaki gibi bi pointerım olsun
int* ptr;
Ben bu tanımlamayı yaptığımda ptr değişkenini derleyici bellekte bir yere yerleştirir.
ptr="on";
dediğimde ise ptr değişkeninin bellekte tututlduğu adrese "on" string inin adresi yerleştirilir.
Benim yukarıdaki bahsettiğim şey ptr'nin bellekte tutulduğu adres içindeki adreste tutulan değerin değiştirilemeyeceği fakat ptr'nin tutulduğu adresteki adresin ise değiştrilebileceği.Siz yukarda her seferinde ptr'nin bellekteki adreseni yazdırmış oluyosunuz,o adresteki adresi değil.
Hocam kafamı karıştıran Deitel 'den Struct konusunu çalışırken aşağıdaki örnek oldu:
/* Fig. 10.3: fig10_03.c
The card shuffling and dealing program using structures */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/* card structure definition */
struct card {
const char *face; /* define pointer face */
const char *suit; /* define pointer suit */
}; /* end structure card */
typedef struct card Card; /* new type name for struct card */
/* prototypes */
void fillDeck( Card * const wDeck, const char * wFace[],
const char * wSuit[] );
void shuffle( Card * const wDeck );
void deal( const Card * const wDeck );
int main( void )
{
Card deck[ 52 ]; /* define array of Cards */
/* initialize array of pointers */
const char *face[] = { "Ace", "Deuce", "Three", "Four", "Five",
"Six", "Seven", "Eight", "Nine", "Ten",
"Jack", "Queen", "King"};
/* initialize array of pointers */
const char *suit[] = { "Hearts", "Diamonds", "Clubs", "Spades"};
srand( time( NULL ) ); /* randomize */
fillDeck( deck, face, suit ); /* load the deck with Cards */
shuffle( deck ); /* put Cards in random order */
deal( deck ); /* deal all 52 Cards */
return 0; /* indicates successful termination */
} /* end main */
/* place strings into Card structures */
void fillDeck( Card * const wDeck, const char * wFace[],
const char * wSuit[] )
{
int i; /* counter */
/* loop through wDeck */
for ( i = 0; i <= 51; i++ ) {
wDeck[ i ].face = wFace[ i % 13 ];
wDeck[ i ].suit = wSuit[ i / 13 ];
} /* end for */
} /* end function fillDeck */
/* shuffle cards */
void shuffle( Card * const wDeck )
{
int i; /* counter */
int j; /* variable to hold random value between 0 - 51 */
Card temp; /* define temporary structure for swapping Cards */
/* loop through wDeck randomly swapping Cards */
for ( i = 0; i <= 51; i++ ) {
j = rand() % 52;
temp = wDeck[ i ];
wDeck[ i ] = wDeck[ j ];
wDeck[ j ] = temp;
} /* end for */
} /* end function shuffle */
/* deal cards */
void deal( const Card * const wDeck )
{
int i; /* counter */
/* loop through wDeck */
for ( i = 0; i <= 51; i++ ) {
printf( "%5s of %-8s%s", wDeck[ i ].face, wDeck[ i ].suit,
( i + 1 ) % 4 ? " " : "\n" );
} /* end for */
} /* end function deal */
/**************************************************************************
* (C) Copyright 1992-2010 by Deitel & Associates, Inc. and *
* Pearson Education, Inc. All Rights Reserved. *
* *
* DISCLAIMER: The authors and publisher of this book have used their *
* best efforts in preparing the book. These efforts include the *
* development, research, and testing of the theories and programs *
* to determine their effectiveness. The authors and publisher make *
* no warranty of any kind, expressed or implied, with regard to these *
* programs or to the documentation contained in these books. The authors *
* and publisher shall not be liable in any event for incidental or *
* consequential damages in connection with, or arising out of, the *
* furnishing, performance, or use of these programs. *
*************************************************************************/
Buradaki const kullanımlarını pek anlayamadım. Mesela neden struct içindeki ifadeleri const olarak tanımlamış?
struct card {
const char *face; /* define pointer face */
const char *suit; /* define pointer suit */
};
Onun gösterdiği yerdeki verileri değiştirmemesi için olabilir. Yani sen o değişkene başka bir yerin adresini yukleyip pointer degiskenin baska adresi gostermeaini saglayabilirsin ama o yukledigin adresin içindeki veriyi pointer değişkeni dereference ederek degisemezsin.
mesaj birleştirme:: 05 Kasım 2014, 20:16:26
Adam yazilari değiştirmek istemiyor ki. Kartların adi belli. Ama elindeki kartin ne olacagina adreslerini değişerek set ediyor. Yani switch gibi düşün. Anahtarı 1 konumuna aliyor 1 konumunun altindaki devreleri değiştirmek istemiyor. 1 konumunu yesil ledi yaksin, 2 nolu konum kirmizi ledi yaksin. Adamin yesil veya kirmizi ledi değişmek gibi bir niyeti yok. Adam anahtarin konumunu degiserek ya kirmiziyi yakacak ya yesili.
Alıntı yapılan: mir_as82 - 05 Kasım 2014, 19:59:44
Onun gösterdiği yerdeki verileri değiştirmemesi için olabilir. Yani sen o değişkene başka bir yerin adresini yukleyip pointer degiskenin baska adresi gostermeaini saglayabilirsin ama o yukledigin adresin içindeki veriyi pointer değişkeni dereference ederek degisemezsin.
mesaj birleştirme:: 06 Kasım 2014, 20:16:26
Adam yazilari değiştirmek istemiyor ki. Kartların adi belli. Ama elindeki kartin ne olacagina adreslerini değişerek set ediyor. Yani switch gibi düşün. Anahtarı 1 konumuna aliyor 1 konumunun altindaki devreleri değiştirmek istemiyor. 1 konumunu yesil ledi yaksin, 2 nolu konum kirmizi ledi yaksin. Adamin yesil veya kirmizi ledi değişmek gibi bir niyeti yok. Adam anahtarin konumunu degiserek ya kirmiziyi yakacak ya yesili.
Teşekkürler @mir_as82 hocam verdiğiniz örnekle kafamda netleşti.
@yamak hocam açıklama için teşekkürler.
İyi akşamlar.
#define LCD_RAM *(vu16*)((u32)0x60020000)
LCD_RAM = 0x2c; Keil bu işlem için hata veriyor . Problem nedir ?
Alıntı yapılan: GreeN - 18 Kasım 2014, 12:49:14
#define LCD_RAM *(vu16*)((u32)0x60020000)
LCD_RAM = 0x2c; Keil bu işlem için hata veriyor . Problem nedir ?
birde
*LCD_RAM = 0x2c;
böyle dene.
..\..\tft\src\glcd.c(210): error: #18: expected a ")"
..\..\tft\src\glcd.c(210): error: #20: identifier "u32" is undefined
hala şeklinde bir hata veriyor. Keil ile daha önce derlemişti. Farklı PC de çalışıyorum şu an bu hatayı veriyor.
Sanki bu kodda değilde, bunun öncesinde bir hata var gibi duruyor.
uint16_t GLCD_ReadRAM(void)
{
uint16_t dumry;
LCD_REG = 0x2C;
dumry=LCD_RAM;
return LCD_RAM;
}
mesaj birleştirme:: 18 Kasım 2014, 13:17:39
Keil'in c/c++ ayarlarıyla ilgili olabilir mi?
#define LCD_RAM *(vu16*)((u32)0x60020000)
bu değeri şuna cevirip denermisin
#define LCD_RAM *(unsigned short*)((unsigned int)0x60020000)
#20: identifier "u32" is undefined
ile u32 tanımlı değil demiş.
#define u32 unsigned int
kodunu ekleyerek denermisin.
#define LCD_RAM *(volatile uint16_t*)((uint32_t)0x60020000)
şeklinde oldu.
#define LCD_RAM *(vu16*)((u32)0x60020000)
vu16 ve u32 yeni oluşturduğum projede tanımsız , ama eski bir proje açtığımda bunlar tanımlı. Teşekkürler.
Merhaba,
Aşağıdaki kodu hata almadan derleyip çalıştırabiliyorum:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct liste
{
char *isim;
};
typedef struct liste Liste;
int main(void)
{
Liste n1;
scanf("%s", n1.isim);
printf("%s\n", n1.isim);
return 0;
}
struct yapısı için char *soyisim şeklinde ikinci bir pointer tanımlıyorum. Derlediğimde hata vermiyor fakat çalışırken "dosya_adi.exe çalışmayı durdurdu" hatası alıyorum. Sebebi nedir acaba?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct liste
{
char *isim;
char *soyisim;
};
typedef struct liste Liste;
int main(void)
{
Liste n1;
scanf("%s", n1.isim);
printf("%s\n", n1.isim);
return 0;
}
İyi akşamlar.
adi bir program oldugundan olmasin? :P
sayin @iruraz normalde ismini kullanmayan uyelerin isteklerine cevap vermem ama siz o kadar naif o kadar hos bir hata yapmissinizki diger tecrubesiz arkadaslarda birseyler ogrenir diye cevap yaziyorum.
kullandiginiz char pointerlari initialize etmemisiniz, bunlar nereyi "point" ediyorlarki scanf fonksiyonu oraya bir bilgi yazsin!
uygun buyuklukte(scanf'in tasirmiyacagi kadar buyuk) bir char alan tanimlayip parametre olarak verdiginiz n1.isim pointer'ini initialize ediniz. (tabii n1.soyisim'ide)
Hocamizin dediği gibi çöp değer ile değer alan bir pointer değişkenin, tuttuğu adrese yazi kaydetmeye calisiyorsun.
Alıntı yapılan: mufitsozen - 18 Kasım 2014, 20:24:40
adi bir program oldugundan olmasin? :P
sayin @iruraz normalde ismini kullanmayan uyelerin isteklerine cevap vermem ama siz o kadar naif o kadar hos bir hata yapmissinizki diger tecrubesiz arkadaslarda birseyler ogrenir diye cevap yaziyorum.
kullandiginiz char pointerlari initialize etmemisiniz, bunlar nereyi "point" ediyorlarki scanf fonksiyonu oraya bir bilgi yazsin!
uygun buyuklukte(scanf'in tasirmiyacagi kadar buyuk) bir char alan tanimlayip parametre olarak verdiginiz n1.isim pointer'ini initialize ediniz. (tabii n1.soyisim'ide)
sayın ve pek değerli @mufitsozen hocam, teşekkürler..
initialize etmek dediğinizde olayı anladım. İşaret ettiği yeri göstermek gerekiyor dediğiniz gibi.
Bilgisizliğimden dolayı
adi programlar yazıyorum ama bazı şeyleri aşmak için bu süreçleri yaşamak gerekiyor sanırım. Adım Murat, gerçek isimlere neden önem verdiğinizi anlamadım. Sonuçta burası bilgi, fikir, tecrübe vs. paylaşılan bir yer. İsimler bunu değiştirir mi?
Alıntı yapılan: mir_as82 - 18 Kasım 2014, 23:04:26
Hocamizin dediği gibi çöp değer ile değer alan bir pointer değişkenin, tuttuğu adrese yazi kaydetmeye calisiyorsun.
@mir_as82 hocam teşekkürler.
Kafama takılan şey dün gönderdiğim ilk adi kodun çalışıyor olması:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct liste
{
char *isim;
};
typedef struct liste Liste;
int main(void)
{
Liste n1;
scanf("%s", n1.isim);
printf("%s\n", n1.isim);
return 0;
}
Burada işaretçiye bir adres gösterilmemesine rağmen
scanf diziyi kaydediyor. Code::Block 13.12 'de çalışıyor. Bunun düzgün çalışma sebebi nedir?
Hocam runtime hatasının en kötü tarafı bu zaten. Runtime hatası her zaman gözlemlenebilen bir durum değildir. Yani tamamen "ne olacağını Allah bilir" durumudur.
Senin kodunun doğru çalışması, o kodun doğru kod olduğu manasına gelmez.
Alıntı yapılan: mir_as82 - 19 Kasım 2014, 13:52:51
Hocam runtime hatasının en kötü tarafı bu zaten. Runtime hatası her zaman gözlemlenebilen bir durum değildir. Yani tamamen "ne olacağını Allah bilir" durumudur.
Senin kodunun doğru çalışması, o kodun doğru kod olduğu manasına gelmez.
Tamamdır hocam. Pek kodun çalışması tam olarak şans eseri olmasa da derleyici arka planda bir şeyler (iyileştirme gibi) yapıyor olabilir mi?
Kodu yazarken seni uyarabilirdi kullandığın IDE.
C nin güçlü olmasının sebebi zaten küçük ve minimalist olması. Derleyici programcıyı işini biliyor olarak bakar. C yazıyorsan yazdığın kodu denetleyici sen olursun. Derleyici kullanıcıya fazla müdahale etme taraftarı olmaz.
Yani şöyle düşün: Sen küçük bir atölyede iyi bir ustasın. Elinin altında matkap, testere, sac makası, tornavida pense vb herşey var. Sen o atölyede bu malzemeleri iyi kullanamazsan kendine zarar verirsin. O iş yerinin patronu seni iyi bir usta kabul edip işe alır, tutup okuldan yeni çıkmış adamı alıp ince hassas ve tecrübe gerektiren işlerini emanet etmez. Veya örneğin ağır bir malzeme taşıyan masa yapacaksın o masanın o ağır malzemeyi tartıp tartmayacağını kendin ustalığınla veya hesap kitapla kestireceksin ve bileceksin, senin elinde solidworks gibi veya buna benzer bir simulasyon aracı olmaz.
Alıntı yapılan: iruraz - 19 Kasım 2014, 13:45:01
Bilgisizliğimden dolayı adi programlar yazıyorum ama bazı şeyleri aşmak için bu süreçleri yaşamak gerekiyor sanırım.
Evet bu surecten geciliyor. Dahada coook uzun bir sure gecilecek.
firinlarla ekmek yenecek, uzun geceler uykusuz calisilacak, okunacak, ogrenilecek.
Ben
adi bir program yazdiginizdan olabilir derken, sizin mesajinizda çalışırken "dosya_adi.exe çalışmayı durdurdu" hatası alıyorum. yazdiginiz icindi. Gordugunuz gibi burada programinizin adini
adi dosya koymussunuz! ;)
Alıntı yapılan: iruraz - 19 Kasım 2014, 13:45:01
Adım Murat, gerçek isimlere neden önem verdiğinizi anlamadım. Sonuçta burası bilgi, fikir, tecrübe vs. paylaşılan bir yer. İsimler bunu değiştirir mi?
isim ve
SOYADI cok onemlidir. ustada cirakda olsa butun zanaatkarlar adinin bilinmesini ister. Cunki kimliklerini yaptiklarina yansitir, yaptigi ise
onem verirler. Ornegin van gogh bes parasiz oldu, yasarken yaptigi tablolar bes para etmedigi halde hepsine adini koymustur filan falan. Ama bunlar benim kendime has fikirlerim, seni baglamaz. Istersen banane banane ben adimi yazmam dersin, bende senin yazdiklarina cevap yazmam. Nede olsa bu sitede yazmak icin izin almak istenmiyecegi gibi cevaplamak icinde bir zorunluluk yok.
@mir_as82 hocam açıklama için teşekkür ederim.
sayın @mufitsozen hocam, haklısınız adi dosya espirisini anlayamamışım :)
İsim konusundaki fikrinize saygı duyuyorum. Ama benim için genel olarak insanların ismi onların tavrı, bilgisi ve yeteneğinin gölgesinde kalan bir şeydir.
İyi akşamlar.
Selamlar,
Arkadaşlar Şu çarpışan balonlar algoritmasını bilgisayar ortamında denemek istiyorum. Dev-C de graphics kütüphanesini ekledim. Ekrana çember dikdörtgen felan çizdirdim. Çalışma ortamım hazır.
Çarpışan balon algoritmasının tam olarak adı nedir? Bir iki baloncuk ile deneme yapmak istiyorum.
Dün derste Rescursive (Tekrarlı)fonksiyonlardan bahsedildi. Mantığını birazda olsa anladım ama kullanım açısından yada işleyiş açısından bana pek mantıklı gelmedi. Merak ettim. Bu tip kendi kendini tekrar eden fonksiyonlar hangi durumlarda kullanılır? Bize faydaları ne olur?
Mikroişlemcilerde bildiğim kadarıyla belirli bir sayıdan fazla iç içe fonksiyon çağıramıyorduk. Stack taşması gibi durumlar söz konusuydu. C'de her bir fonksiyonun alt program olduğunu düşürsek, Fonksiyonun kendi içinde tekrar etme sayısı mikroişlemcinin stack boyutunu aşarsa ne olur?
Program çakılır tabi. Bilgisayarda şansın varsa bir hata mesajı alabilirsin.
Recursion genel olarak program yazmayı kolaylaştırır, karmaşık problemlerin daha sade ve anlaşılır bir şekilde koda dökülmesine olanak verir.
Ama resursion bilgisayarın işini kolaylaştırmaz. Teorik olarak, resursion ile yazılabilen her algoritma, recursion kullanmadan da yazılabilir. Recursion kullanıldığında bilgisayarın performansı düşer.
Ancak çoğu durumda, kodun anlaşılabilirliği ve bakım yapılabilirliği performanstan daha önemlidir. Bu sebeple recursion sıklıkla kullanılır. Ancak genel olarak, belleği düşük olan mikrodenetleyici sistemleri için uygun olmadığını düşünüyorum.
aşarsa kim bilir ne olur program rastgele bir yerlere gider. pic için STVREN sigortası kullanılırsa pic resetlenir
recursive sudoku çözdürürken kullanılabilir
Dev C de konsol uygulamaları üzerinde çalışıyorum. Debug yapmak çok zor. Kolayca debug yapabileceğim kod tamamlaması vs olan kullanışlı bir editör olarak ne önerirsiniz.
Borland c builder
Hocam indirmeye başladım ama program ücretli.30 günlük deneme sürümünü indiriyorum. Bunun küreklisi varmı.
Visual Studioyu kursam daha iyi olacak sanırım.
Builder 6 ise kurek kolay, zaten eski derleyici, her tarafta kuregi vardir;bulamazsan kurekleriz.
Hocam neden Qt kullanmaıyosunuz.Zaten ücretsiz.
merhaba arkadaşlar
1)#define x (myStruct *)0x100000000
2)#define x ((myStruct *)0x100000000)
1.sinde oluşturduğum yöntemle mySruct yapısının elemanlarına erişemiyorum ama 2. ifadede parantez koyarak istediğim şekilde yapı elemanlaraına erişiyorum
Parantez bu işi nasıl etkiliyor anlayamadım?
Oncelik problemi olusuyordur. Operator öncelik tablosundan kaynaklanabilir.
Define ile siz sadece akilli yer değiştirme yapıyorsunuz. Olaya o gözle bakin. Yazdiginiz kodda gidin x yerine define ile tanımlanan ifadeyi yazin sonra bakin ne oluyor.
mesaj birleştirme:: 16 Ocak 2015, 00:43:20
Yani hani "oku baban gibi, eşek olma" ile
"Oku, baban gibi eşek olma" daki virgül kaymasini programa uyarla, senin hatan da öyle birşey.
Kütüphanedeki isdigit, isxdigit vs. kodlarını etkin kullanabilmek için denemeler yapıyordum, kullanıcıdan bir giriş(harf,numara vs.) alıp bunun digit olup olmadığını yazan bir program yazayım dedim. Programdaki sorun şu if kısmına girmiyor daha doğrusu elseden çıkıp gidiyor, büyük ihtimal if'in koşulunda hata var ama benim kullandığım gibi kullananlar olmuş internette sorunu anlayamadım :o
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
main(){
int x,y;
printf("Please press any button from keyboard");
scanf("%d",&x);
y=isdigit(x);
if(y) // y==1'i de denedim
{
printf("%d is a digit.",x);
}
else{
printf("%d is a not digit.",x);
}
return 0;
}
Hocam scanf("%c", &x); ile dener misin?
Alıntı yapılan: mir_as82 - 11 Şubat 2015, 11:48:18
Hocam scanf("%c", &x); ile dener misin?
Evet hocam dediğiniz gibi yapınca düzeldi, şimdi bu kodların içine int koyulucak denmiş o nedenle ben x'i hep int diye düşündüm, %c ile kullanmak gerekiyorsa başta ben x'i char mı tanımlamalıyım yoksa integer mı ? (denedim iki türlü de doğru çalışıyor sebebi nedendir ? )
hocam olay karakter kodunda bitiyor. Sen int değişken tanımla, sıkıntı yok. Ama onun içine dışardan klavye ile alacağın şeyi eğer %c olarak almazsan, fonksiyona ascii kodunu göndermemiş olursun.
Meselan sen y=isdigit(48) gönderirsen sana nonezero döndürmesi lazım.
Çünkü 48 sıfırın ascii kodu.
mesaj birleştirme:: 11 Şubat 2015, 12:08:12
Ama sen dışardan 9 e basıp adama 9 verirsen, adam ascii tablosunda 9 a bakar, hee der 9 un ascii kodu TAB tuşu. O zaman sana zero döndürür.
Alıntı yapılan: mir_as82 - 11 Şubat 2015, 12:05:26
hocam olay karakter kodunda bitiyor. Sen int değişken tanımla, sıkıntı yok. Ama onun içine dışardan klavye ile alacağın şeyi eğer %c olarak almazsan, fonksiyona ascii kodunu göndermemiş olursun.
Meselan sen y=isdigit(48) gönderirsen sana nonezero döndürmesi lazım.
Çünkü 48 sıfırın ascii kodu.
mesaj birleştirme:: 11 Şubat 2015, 12:08:12
Ama sen dışardan 9 e basıp adama 9 verirsen, adam ascii tablosunda 9 a bakar, hee der 9 un ascii kodu TAB tuşu. O zaman sana zero döndürür.
Anladım, teşekkür ederim.
Önemli değil hocam.
strcpy ile strncpy arasındaki fark strncpy'nin string'in sonuna null karakterini koymaması diye biliyorum. Bunu C de uygulayarak göreyim dedim, aşağıdaki gibi bir kod yazdım. Normalde null karakter olmadığından dolayı for döngüsünün içinde sonsuz döngü olması gerekirken, derleyince fordan çıkıp sonraki "End" yazısını yazıyor. Bunun nedeni nedir ?
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
main(){
int i=0;
char s1[20];
char s2[]="David Guetta Concert";
printf("%s",strncpy(s1,s2,20));
for(i=0;s1[i]!='\0';i++){
printf("%c",s1[i]);
}
printf("\nEnd");
return 0;
}
Burada dizi taşması oluşturuyorsun.
Aşağıdaki kod ile for dan doğru şekilde çıkıp çıkmadığını anlayabilirsin.
Bu şekilde end yazmıyor ekrana.
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
main(){
int i=0;
char s1[20];
char s2[]="David Guetta Concert";
printf("%s",strncpy(s1,s2,20));
for(i=0;s1[i]!='\0';i++){
printf("%c",s1[i]);
}
if( i == 20 )
printf("\nEnd"); // Boyle yaparak for dan doğru bir şekilde çıkıp çıkmadığını anlarsın.
return 0;
}
Dizi taşması derken ? Dediğin şekilde de çalıştırdım gene End yazdı hatta sadece i=20 de iken end yazıyor. Dizinin 20. karakterine NULL karakterini koyuyor. s1 dizisinin kapasitesi 15 olsa bile s2 deki tüm karakterleri s1'e yazıp ardına Null koyuyor. O zaman strncpy komutu null karakterini yazıyor ya da bunu otomatik olarak dizi yapıyor :o
Dev C kullanıyorum program çıktımda bir tablo olacak bu nedenle dos ekranı büyük olmalı en az 800x600 , bunu nasıl yapabilirim ?
Alıntı yapılan: unknownperson - 18 Şubat 2015, 15:55:07
strcpy ile strncpy arasındaki fark strncpy'nin string'in sonuna null karakterini koymaması diye biliyorum. Bunu C de uygulayarak göreyim dedim, aşağıdaki gibi bir kod yazdım. Normalde null karakter olmadığından dolayı for döngüsünün içinde sonsuz döngü olması gerekirken, derleyince fordan çıkıp sonraki "End" yazısını yazıyor. Bunun nedeni nedir ?
S değişkeni için ayrılan alanda null"u bulamasa bile ramda illaki bir null bulacaktır.
Sonucta S ram içinde bir yer kaplıyor ama S'in bitiminde diğer değişkenlerin yada boş kullanılmayan alanlar var. Bunlardan biri illaki sıfırdır ve bunu buluyor.
Alıntı yapılan: unknownperson - 15 Mart 2015, 00:19:34
Dev C kullanıyorum program çıktımda bir tablo olacak bu nedenle dos ekranı büyük olmalı en az 800x600 , bunu nasıl yapabilirim ?
Çıktı dos ekranındayken, pencere üzerinde sağ click yap ve özelliklere gir
yerleşim tab'ından istediğin pencere büyüklüğüne getirebilirsin, hatta yazı renklerini vs değiştirebilirsin
Alıntı yapılan: CLR - 15 Mart 2015, 00:51:12
Çıktı dos ekranındayken, pencere üzerinde sağ click yap ve özelliklere gir
yerleşim tab'ından istediğin pencere büyüklüğüne getirebilirsin, hatta yazı renklerini vs değiştirebilirsin
Çok teşekkür ederim :)
mesaj birleştirme:: 15 Mart 2015, 01:15:49
Bir sıkıntım daha var :
//Programın amacı 1 den 1000 e rastgele sayı üretip bunu diziye koymak sonra da dizideki elemanları sırasıyla bir sayıyı bastırıp bir de yanında sayıların hane sayılarının toplamını bastırmak fakat hane sayısını alırken sorun yaşıyorum her yolu denedim bulamadım. (%n kullanma zorunluluğum var)
#include<stdlib.h>
#include<stdio.h>
#include<time.h>
main(){
int array[10],total=0,i=0,y;
srand ( time ( NULL ) );
for(i=0;i<10;i++){
array[i] = rand( ) % 1000 +1;
printf("%d%n",array[i],&y);
total=total+y;
printf("%10d\n",total);
}
return 0;
}
http://www.geeksforgeeks.org/g-fact-31/ (http://www.geeksforgeeks.org/g-fact-31/)
Bu sitede de aynı problemle karşılaşılmış fakat çözüm bulunamamış :(
O parametreyi ben hiç kullanmadım ama kısaca baktığımda devcpp'de sanırım printf'in o özelliği pass geçilmiş(belkide vardır) ama microsoft VC++ ile test edersen çalışıyormuş
default olarak o özellik kapalıymış, açmak için aşağıdaki gibi kullanman gerekiyor
int A=100;
A=_set_printf_count_output(1); // %n printf özelliğini açıyor, kapatmak için 0
printf("A : %n \r\n", &A);
Alıntı yapılan: CLR - 15 Mart 2015, 02:16:07
O parametreyi ben hiç kullanmadım ama kısaca baktığımda devcpp'de sanırım printf'in o özelliği pass geçilmiş(belkide vardır) ama microsoft VC++ ile test edersen çalışıyormuş
default olarak o özellik kapalıymış, açmak için aşağıdaki gibi kullanman gerekiyor
int A=100;
A=_set_printf_count_output(1); // %n printf özelliğini açıyor, kapatmak için 0
printf("A : %n \r\n", &A);
Şu hatayı aldım:
C:\Users\Berkay\AppData\Local\Temp\ccGbZGbt.o İsimsiz1.cpp:(.text+0x1c): undefined reference to `__imp__set_printf_count_output'
https://msdn.microsoft.com/en-us/library/ms175782.aspx (https://msdn.microsoft.com/en-us/library/ms175782.aspx)
// crt_set_printf_count_output.c
#include <stdio.h>
int main()
{
int e;
int i;
e = _set_printf_count_output( 1 );
printf( "%%n support was %sabled.\n",
e ? "en" : "dis" );
printf( "%%n support is now %sabled.\n",
_get_printf_count_output() ? "en" : "dis" );
printf( "12345%n6789\n", &i ); // %n format should set i to 5
printf( "i = %d\n", i );
}
aşağıdaki online vc++ compilerda test ettim çalışıyor
http://webcompiler.cloudapp.net/ (http://webcompiler.cloudapp.net/)
Aşağıdaki kodda bulunan iki struct yapısında ilkinde 6 bayt , ikincisinde 12 bayt bellek kullanımı olması gerekirken sizeof komutuyla ekrana bastırdığımda ilkinde 8 ikincisinde 16 bayt gösteriyor. Bunun nedeni nedir struct başına 2 byte fazla neden gösterir ?
#include <stdlib.h>
#include <stdio.h>
struct memory1{
int lenght;
char name_type[2];
};
struct memory2{
char id[2];
struct memory1 number;
int counter;
};
main(){
int size;
size=sizeof(memory1);
printf("Size of struct is %d\n",size);
size=sizeof(memory2);
printf("Size of struct is %d",size);
return 0;
}
platformun 32 bitlik ise, char tanımlamalarını size olarak yukarı yuvarlar. şöyle ki, 4 adet char tanımlarsın 4 byte kaplar, 3 adet char tanımlayıp üstüne 1 adet int tanımlarsan arada kalan 1 char lık kısmı göz ardı eder ve 8 byte yer kaplamış olur. bunu, kitap bilgisinden değil tecrübeden söylüyorum, bu sebeple çürütülmeye açık bir bilgi olduğunu belirteyim.
Alıntı yapılan: hasankara - 19 Mart 2015, 21:47:04
platformun 32 bitlik ise, char tanımlamalarını size olarak yukarı yuvarlar. şöyle ki, 4 adet char tanımlarsın 4 byte kaplar, 3 adet char tanımlayıp üstüne 1 adet int tanımlarsan arada kalan 1 char lık kısmı göz ardı eder ve 8 byte yer kaplamış olur. bunu, kitap bilgisinden değil tecrübeden söylüyorum, bu sebeple çürütülmeye açık bir bilgi olduğunu belirteyim.
platformdan kasıt ne demek istediğinizi anlayamadım ama programda şunları denedim dediğiniz sanırım doğru:
memory1 in içinde 1 boyutu olan dizi ekledim gene 8 gösterdi yani 7 göstermedi demekki 8'e tamamladı,
sonra 3 boyutu olan dizi ekledim 9 yerine 12 yazdı demekki 12'ye tamamladı,
3 boyutlu diziyi ekleyince memory2 18 yerine 20 gösterdi,
sonra alttaki memory2 deki integer sildim 14 yerine 16 gösterdi
Sonuç: Sanırım 4'erli şekilde 8,12,16,20 şekilden yuvarlanıyor.
Bu arada teşekkür ederim ben de internet ve kitapta böyle bir açıklama göremedim yardımınız için teşekkür ederim.
packed struct diye araştırırsan daha iyi bilgiler elde edebilirsin, forumda araştırırsan var, ben bir kaç arkadaş anlatmıştık, bu konu C'nin püf noktalarındandır
Araştırırken struct padding diye bir şey bulmuştum ama o pointerlarla ilgiliymiş, burada: https://medium.com/@cngzhnp/c-programlama-dilinde-struct-yap%C4%B1s%C4%B1-1bfea688e112
Packed struct öğrenmem iyi oldu daha net bilgilere ulaştım teşekkür ederim :D
platformdan kastım kodları yürüttüğün ortam. bilgisayar olabilir ya da mikrodenetleyici olabilir yada ... . platformun kaç bitlik olduğu konusunda ise, platformun üzerinde ki işlemcinin data genişliğini kast ettim. C nin eli çok yere uzanıyor. 8 bitlik bir mikrodenetleyici için kullanılan bir c derleyicisi bu şekilde yukarı yuvarlamaya gerek duymaz zaten ram in her datası 8 bitlik hücrelerden oluşmuştur.
Konu derleyici ve işlemcinin hafıza erişimi ile alakalı C de bu durumu düzelten bir komut yok bildiğim kadarıyla derleyici detaylarına bakmak lazım.
Alıntı yapılan: hasankara - 19 Mart 2015, 22:19:03
platformdan kastım kodları yürüttüğün ortam. bilgisayar olabilir ya da mikrodenetleyici olabilir yada ... . platformun kaç bitlik olduğu konusunda ise, platformun üzerinde ki işlemcinin data genişliğini kast ettim. C nin eli çok yere uzanıyor. 8 bitlik bir mikrodenetleyici için kullanılan bir c derleyicisi bu şekilde yukarı yuvarlamaya gerek duymaz zaten ram in her datası 8 bitlik hücrelerden oluşmuştur.
Tamam doğru anlamışım acaba dedim platform derken Dev C ya da Visual anlamında mı yoksa pc anlamında mı sorduğunuz diye ikileme düşmüştüm.
C'nin püf noktası derken sanırım yanlış anlaşılmış, compiler'ın C struct yapıları için direktifleri var onları kullanmak gerekiyor,
mesela keil için __packed, #pragma pack(push,x) , pack(pop) gibi
islemlerde su sekilde donusum yapiyoruz ya : a=(float) b*1
Peki bunu floattan integera gecirirken yapabilir miyim su sekilde
b=(integer) a*1
?
olur ama sayının tam kısmını alırsın
Alıntı yapılan: unknownperson - 23 Mart 2015, 15:01:40
islemlerde su sekilde donusum yapiyoruz ya : a=(float) b*1
Peki bunu floattan integera gecirirken yapabilir miyim su sekilde
b=(integer) a*1
?
yapilabilir ama sizin yazdiginiz gibi degil:
b=(int)a;
seklinde sadece float sayinin tamsayi kismini b ye yuklersiniz.
Bitler konusunda sıkıntılarım var aslında konuyu biliyorum fakat bu programı yazarken aldığım hatayı bir türlü çözemedim :
//Bu programda diyelim kullanıcı CD girdi C ve D yi diziye koyup sonra bu harfleri fonksiyona gönderip fonksiyonda unsigned bir sayının ilk 16 bitine ilk //sayıyı diğer 16 bitine ikinci sayıyı koyup yeni bir sayı oluşturmak. Ben iki harfi fonksiyona yolladım baktım number ve number2 diye iki sayıyada //aktarabildim fakat bu iki sayıyı decimal yazdırınca tamam diyorum harf karşılığı doğru ama binary yazdırınca sıkıntı var.
#include<stdlib.h>
#include<stdio.h>
void packCharacters(char,char);
void packCharacters(char x,char y){
int i;
unsigned number=0,number2=0;
number=x;
number2=y;
printf("Number 1 is %u\n",number);
printf("Number 2 is %u\n",number2);
number=number<<16;
printf("After packing Characters: \n");
for(i=1;i<=32;i++){
putchar(number | number2 ?'1':'0');
number=number<<1;
number2=number2<<1;
if(i%8==0){
printf(" ");
}
}
}
main(){
char array[2];
printf("Please enter 2 characters : ");
scanf("%s",&array);
packCharacters(array[0],array[1]);
return 0;
}
putchar(number | number2 ?'1':'0');
yerine
putchar(number | (number2 ?'1':'0'));
yada bunu demek istemiyorsan
putchar((number | number2) ? '1' : '0' );
yazmalısın.
@Burak BAYRAK yok onunla ilgili bir hata yok her ihtimale karşı gene dediğin gibi denedim çözülmedi sorun hala yanlış çalışıyor.
Hocam aşağıdaki kodları
putchar(number | number2 ?'1':'0');
number=number<<1;
number2=number2<<1;
Aşağıdaki gibi değitirip deneyebilir misiniz?
putchar((((number | number2)>>i)&0x01) ?'1':'0');
Eğer ekranda doğru sıralamada görünmesini istiyorsanız for döngüsü de aşağıdaki gibi olmalı
for(i=31;i>=0;i--){
putchar((((number | number2)>>i)&0x01) ?'1':'0');
if(i%8==0)
printf(" ");
}
unsigned number=0,number2=0;
demişsin unsigned int diye tanımla.
Hocam standart C de 'unsigned' 'unsigned int' demek zaten
Bunu bilmiyordum, bir kaç kaynağa baktım şimdi göremedim.
http://en.wikipedia.org/wiki/C_data_types (http://en.wikipedia.org/wiki/C_data_types)
(http://s30.postimg.cc/gccli7iv1/image.jpg) (http://postimg.cc/image/gccli7iv1/)
Öncelikle emeğiniz için hepinize tek tek teşekkür ederim, sorunu dün halledemeyince programı internette biraz araştırarak %100 kendi kodlarımla yazdığımdan vazgeçip başka kodlar ekleyerek tamamladım, programı herkese yararlı olması için bu ileti sonuna ekleyeceğim.
Şuan şöyle merak ettiğim bir konu var deitel kitabındaki enum örneğini aynı şekilde yazdım çalıştırdım fakat hata verdi :
for(month=JAN;month<=DEC;month++) bu döngüdeki month'u ++ operatörüyle kullanamazsın diyor ve bu sorun internette araştırdım month önüne int yazarak çözülebiliyor fakat bu şekilde de enum kullanmanın bir mantığı kalmıyor buradaki hatayı başka nasıl çözebiliriz ve sizce deitelin bile kitabında bu şekilde tanımladığı bir program nasıl olur da hata verir yani nedeni nedir ?
#include<stdlib.h>
#include<stdio.h>
void packCharacters(char,char);
void packCharacters(char x,char y){
int i;
unsigned number=0<<31; //bits was been zero.
unsigned mask=1<<31; //creates mask variable.
unsigned a=x,b=y; //assigning for printing type of binary
printf("%7u = ",x); // x displays type of binary
for (i = 0; i < 32; i++)
{
if (a&mask){
printf("1");
}
else{
printf("0");
}
if ((i+1)%8==0){
printf(" ");
}
a=a<<1;
}
printf("\n%7u = ",y); // y displays type of binary
for (i = 0; i < 32; i++)
{
if (b&mask){
printf("1");
}
else{
printf("0");
}
if ((i+1)%8==0){
printf(" ");
}
b=b<<1;
}
number=number |x; //x assigning to number
number=number<<16; //x values shift to left by 16 at number
number=number |y; //y assinging to number
printf("\nAfter packing Characters: \n%u = ",number);
for (i = 0; i < 32; i++) //print number type of binary
{
if (number&mask){
printf("1");
}
else{
printf("0");
}
if ((i+1)%8==0){
printf(" ");
}
number=number<<1;
}
}
main(){
char array[2];
printf("Please enter 2 characters : "); //takes two letter
scanf("%s",&array); //assinging to array
packCharacters(array[0],array[1]);
return 0;
}
eger kullandiginiz enum degerleri atlamadan sirali ise:
int ndx;
enum {jan, feb,mar,apr,may,jun,jul,agu,sep,oct,nov,dec} aylar;
for(ndx=jan;ndx<= dec; ndx++)printf("\nndx=%d",ndx);
eger sirali gitmiyorsa .....(devam edecek..)
Aşağıdaki kodlar, temsilidir, normalde programımda farklı ama mantık olarak benzer bir şekilde kullanıyorum.
free yi iptal edersem düzgün, ama etmezsem bellek hatası yazıyor.
Ben de freeyi iptal ettim programım sorunsuz çalıştı. Bu hata beni 3-4 saat uğraştırdı, yani hiç beklemezdim böyle bir hatayı, hatayı başka yerlerde aramıştım.
Bu yüzden merak ettim neden bu sorun oluyor.
unsigned int *tampon;
unsigned int len=1024;
while(1){
tampon=realloc(tampon,len*sizeof(int));
if(tampon== NULL ) printf("Bellek hatasi\r\n");
else printf("ok \r\n");
free(tampon);
}
Önce calloc ile bir alan ayırıp, sonra realloc ile düzenleme yapmak mı gerekiyor yoksa?
calloc yada malloc ile sahiplendiğin ram alanında yeniden tanımlama yapacaksan realloc kullanmalısın.
realloc yerine malloc yada calloc yazsan olurdu.
Dediğiniz gibi hocam, calloc kullanamam,
sürekli gelen bir veri var, eğer buffer'daki alan, yetersiz geliyorsa realloc ile dizinin kapasitesini artırıyorum. Gelen verilerin tamamını aldığımda(dosyanın okunması bittiğinde) , yeni bir dosyaya geçebilmem için o diziyi sıfırlayıp yeniden başlamam gerekiyor. Free kısmınu bu yüzden kullanmıştım ama gerek yokmuş sanırım.
Önce calloc ile yer ayır sonra realloc ile boyunu değiştir.
Sonra free kullanabilirsin.
free kullanmazsan ayırdığın ram hala sana zimmetli kalır.
Tam da öyle yaptım hocam, teşekkürler.
Şöyle bir sorunum var belli txt dosyalarında ad, soyad, telefon, mail adresi ve bütçe tutuluyor alt alta. Benim bu dosyadan ekrana ad soyad ve bütçeyi yazdırmam gerekiyor yani telefon ve mail adresini atlamak zorundayım. Satır atlamanın fseek ile yapıldığını biliyorum fakat benim mesela telefon numarasının belli bir uzunluğu var ama mail adresinin belli bir ölçüsü yok kişiden kişiye değişiyor uzunluğu o nedenle fseek kullanamıyorum nasıl o satırları atlayabilirim ?
satirlari fgets ile oku
Alıntı yapılan: mufitsozen - 14 Nisan 2015, 19:13:31
satirlari fgets ile oku
Yani her satırı fgets ile okuyup gerekli satırları bastırayım, o şekilde mi demek istediğiniz ?
Her sorunu çözdüm tek bir sorunum kaldı. Benim dosyadan bir bilgiyi güncellemem için "r+" kullanmam gerekiyor diye biliyorum. Son satırdan bir önceki satırı güncellemem gerekiyor fgets ile o satıra gelip fprintf ile yazdırmaya çalışıyorum yazmıyor :o İnternette r+ kullanımı ile ilgili de hiçbir örnek yok :-[
fgetpos(yada ftell) ve fseek
#include<stdlib.h>
#include<stdio.h>
struct node{
char data;
struct node *nextPtr;
};
typedef struct node Node;
typedef Node *NodePtr;
void insert(NodePtr *sPtr,int value);
void delete(NodePtr *sPtr,int value);
void printlist(NodePtr currentPtr);
main(){
NodePtr *startPtr=NULL;
int item=1;
while(item!=0){
printf("Please enter number to node(0 to exit): ");
scanf("%d",&item);
if(item==0){
break;
}
insert(&startPtr,item);
printlist(startPtr);
}
printf("If you delete please enter 1:");
scanf("%d",&item);
while(item!=0){
printf("Please enter number to delete node(0 to exit): ");
scanf("%d",&item);
if(item==0){
break;
}
delete(&startPtr,item);
}
return 0;
}
void insert(NodePtr *sPtr,int value){
NodePtr newPtr,currentPtr,previousPtr;
newPtr=malloc(sizeof(node));
if(newPtr!=NULL){
newPtr->data=value;
newPtr->nextPtr=NULL;
previousPtr=NULL;
currentPtr=*sPtr;
while(currentPtr!=NULL&& value>(node) (currentPtr->nextPtr)){
previousPtr=currentPtr;
currentPtr=currentPtr->nextPtr;
}
if(previousPtr==NULL){
newPtr->nextPtr=*sPtr;
*sPtr=newPtr;
}
else{
previousPtr->nextPtr=newPtr;
newPtr->nextPtr=currentPtr;
}
}
else{
printf("ERROR!!! Memory didn't open.");
}
}
void delete(NodePtr *sPtr,int value){
NodePtr currentPtr,previousPtr,tempPtr;
if(value==(*sPtr)->data){
tempPtr=*sPtr;
*sPtr=(*sPtr)->nextPtr;
free(tempPtr);
}
else{
previousPtr=*sPtr;
currentPtr=previousPtr->nextPtr;
while(currentPtr!=NULL&¤tPtr->data!=value){
previousPtr=currentPtr;
currentPtr=currentPtr->nextPtr;
}
if(currentPtr!=NULL){
tempPtr=currentPtr;
previousPtr->nextPtr=currentPtr->nextPtr;
free(tempPtr);
}
}
}
void printlist(NodePtr currentPtr){
if(currentPtr!=NULL){
while(currentPtr!=NULL){
printf("%d --> ",currentPtr->data);
currentPtr=currentPtr->nextPtr;
}
}
else{
printf("Memory is empty.");
}
}
Böyle bir kod var birçok hata veriyor ben başlıca sorularımı sormak istiyorum:
1.Programın başındaki şu iki satırı neden kullanıyoruz sebebi nedir?
typedef struct node Node;
typedef Node *NodePtr;
2. Sürekli bu hatayı veriyor sebebi bir şeyin bir şeye çevirlemeyeceğini söylüyor ama normalde çevrilmesi gerekiyor kitapta da bu şekilde yapmış ?
cannot convert 'Node*** {aka node***}' to 'Node** {aka node**}' for argument '1' to 'void insert(Node**, int)'
3. Bir de şu alttaki hatanın sebebini anlayamadım ?
expected unqualified-id before 'delete'
typedef struct node Node;
Bunun manasi şu, derleyici struct node adında bir yapimin adini Node olarak belleyeceksin demek. Bir nevi ikinci bir isim veriyorsun.
typedef Node *NodePtr;
burada bir sikinti var. Bu kodu neden yaziyorsun anlamadim.
typedef Node* NodePtr; //olarak değişse ne
Alıntı yapılan: mir_as82 - 25 Nisan 2015, 20:11:01
typedef struct node Node;
Bunun manasi şu, derleyici struct node adında bir yapimin adini Node olarak belleyeceksin demek. Bir nevi ikinci bir isim veriyorsun.
typedef Node *NodePtr;
burada bir sikinti var. Bu kodu neden yaziyorsun anlamadim.
typedef Node* NodePtr; //olarak değişse ne
Deitel kitabından yazıyorum çalışıp anlamak için.
Dediğiniz gibi değiştirdim bir şey değişmedi.
void insert(NodePtr sPtr,int value);//bu şekilde yaz
Delete yi de bu şekilde yaz.
Fonksiyon tanimlamalarini da bu şekilde degistirsene.
insert((NodePtr *)&startPtr,item);
struct node {
char data;
struct node *nextPtr;
};
Derleyici struct node yapısını görünce "bu adam burda böyle bir şey bildirmiş diyerek" gardını alıyor.
Bu kısım sadece bildirim.
typedef struct node, Burada bildirimini yaptığı yapıyı typedef ile türlüyor ve o türe isim veriyor,artık node yapısında yeni bir türümüz var,türün adı node.
node Node; Buradaki Node ise node türünden bir değişken.
typedef Node *NodePtr; Buradada Node değişkenini türleyip yine o türde bir gösterici yaratmış.
*NodePtr artık bir tür oldu Node türünden adres tutabilen bir tür.
Bildiğim bu.
Selamlar,
Elimde bir bytelık alan var.Bu baytın yüksek 4bitini farklı amaç için düşük 4 bitini farklı amaç için düzenleyebilmek istiyorum.İzahı için şöyle örnekliycem;
1 bytelık bir alanda 7-4 bitlerini delay miktarı 3-0 bitlerini count için tutacak olayım.Ben tek bir struct ile bu bir byte erişip struct elemanlarıyla hem 7-4 arasını hem de 0-3 arasını değiştirebilmek istiyorum.
Aklıma 7-4 aralığı için enum yapıp 0-3 için uint8_t yapmak geldi.Ama böyle olunca 1bytedan büyük olacak.Ama eğer struct ı paketleyebilirsem olabilir.
//Enum için şu tanımı yaptım;
//Ancak bu 7-4 nolu bitlere etki etmeli.
typedef enum{
W_250us = 0x00, //0000
W_500us = 0x01, //0001
W_750us = 0x02, //0010
W_1000us = 0x03, //0011
W_1250us = 0x04, //0100
W_1500us = 0x05, //0101
W_1750us = 0x06, //0110
W_2000us = 0x07, //0111
W_2250us = 0x08, //1000
W_2500us = 0x09, //1001
W_2750us = 0x0A, //1010
W_3000us = 0x0B, //1011
W_3250us = 0x0C, //1100
W_3500us = 0x0D, //1101
W_3750us = 0x0E, //1110
W_4000us = 0x0F, //1111
}ReTransDelay_t;
struct{
ReTransDelay_t Delay;
uint8_t Count;
}AutoRT_Typedef;
//Böyle yaptığımda bir byte dan fazla olacak.
AutoRT_Typedef AutoRT;
AutoRT.Delay = 500us;
AutoRT.Count = 15;
//Dediğimde değerin 0b0001 1111 olmasını istiyorum.
Nasıl yapabilirim?
Sana anahtar kelime vereyim. Şimdi firmadayım ondan ayrıntılı yazamıyorum.
Struct ile bit fields oluşturacaksın. Yazmayı ve okumayı ayrı ayrı iki makro yazıp yapacaksın.
typedef struct{
uint8_t count:4;
uint8_t delay:4;
}xtype;
xtype x;
x.count = 5;
x.delay = 12;
a = x. count;
b = x. delay;
Alıntı yapılan: Klein - 06 Mayıs 2015, 12:07:30
typedef struct{
uint8_t count:4;
uint8_t delay:4;
}xtype;
xtype x;
x.count = 5;
x.delay = 12;
a = x. count;
b = x. delay;
Abi bu şekilde denedim.Ancak veriler karıştı birbirine.Normalde ben de o şekilde sınırlar kullanırım diye düşündüm.Ama olmadı.
@mir_as82 bakıyorum.
Alıntı yapılan: yldzelektronik - 06 Mayıs 2015, 16:06:22
Abi bu şekilde denedim.Ancak veriler karıştı birbirine.Normalde ben de o şekilde sınırlar kullanırım diye düşündüm.Ama olmadı.
@mir_as82 bakıyorum.
veriler karisti yerine verilen ornegi kodladiginizda sonuc ne oldu soylerseniz baska bir hata yapip yapmadiginizida anlayabiliriz.
şunu dener misin?
a = x. count&&0x00;
b = (x. delay >> 4)&&0x00;
pardon: doğrusu bu
a = x. count&&0x0f;
b = (x. delay >> 4)&&0x0f;
Alıntı yapılan: mufitsozen - 06 Mayıs 2015, 17:28:48
veriler karisti yerine verilen ornegi kodladiginizda sonuc ne oldu soylerseniz baska bir hata yapip yapmadiginizida anlayabiliriz.
Haklısınız.Afedersiniz.Debug ortamını dağıtmıştım.net ifade edebilecek kadar hatırlamadığımdan öyle yazdım.
O yapı içinde farklı değişkenler de vardı.Normalde debug ile bakarken ilgili değişkenleri gözlediğimde alması gereken değerleri alıyor.Ancak veriyi yazdıktan sonra tekrar okuduğumda farklı değerler okuyordum.O sebeple karıştı demiştim.
Ama zaten
fit fields ile : kullanımı aynıymış.Bilmiyordum.
Edit: bit olacaktı o.
Alıntı yapılan: mir_as82 - 06 Mayıs 2015, 17:31:05
şunu dener misin?
a = x. count&&0x00;
b = (x. delay >> 4)&&0x00;
Neden iki && var?Anlamadım.
typedef struct _str {
unsigned char delay : 4;
unsigned char count : 4;
}x_t;
int main (int argc , char **argv){
x_t x = {0x04,0x0c};
unsigned char a = (x.delay << 4) | x.count;
printf("a = %x", a);
return 0 ;
}
şeklinde debug da sorun olmuyor da yazdığım yerden okuduğumda farklı değer okuyorum. Sanırım yazma veya okuma rutinleriyle ilgili problem var
Hocam aceleden hata üstüne hata yapmışım :)
Haklısın. Tek & olacak.
&& olan mantıksal VE operatörü.
pardon: doğrusu bu
a = x. count&0x0f;
b = (x. delay >> 4)&0x0f;
mir_82'nin orneginde iki tane problem goruyorum.
1- &&, || 'logical operator'lerdir sonuclari 0 yada non-zero olur. sizin & yada | kullanmaniz lazim
2- Sizin bit fields 4 bit oldugu icin (unsigned) alabilecekleri degerler 0 ile 15 arasinda degisir!
dolayisi ile >>4 yada <<4 (delay yada count degeri ne olursa olsun) sonucu sifirdir!
tam olarak ne yapmak istiyorsunuz?
mesaj birleştirme:: 06 Mayıs 2015, 18:14:19
ucuncu bir problemde 0x00 ile & (and) operasyonu herzaman 0 sonucu verir!
hocam zaten bir alt satıra bakarsan düzelttim hata mı : )
Klein'in yazdığı kısımda sorun olmaması lazım ve böyle shift vs işlemlerde de hata yapmamak için aşağıdaki şekilde kullanabilirsin
typedef struct
{
uint8_t count:4;
uint8_t delay:4;
}xtype;
typedef union
{
uint8_t Reg8;
xtype Nibbles;
}Regs_Typedef;
Regs_Typedef Myregs;
uint8_t LowByte,Hibyte,Allbyte;
Myregs.Reg8 = 0x5A;
Allbyte = Myregs.Reg8; // Allbyte = 0x5A
LowByte = Myregs.Nibbles.count; // Lowbyte = 0xA
HiByte = Myregs.Nibbles.delay; // Hibyte = 0x5
Düzeltme :Program değişmeyecek ama küçük bir adlandırma değişikliği olursa daha iyi olur
LowByte,Hibyte ---> LowNibble,HiNibble
typedef struct
{
uint8_t count:4;
uint8_t delay:4;
}xtype;
Bu kodda, count değişkeninin hafiza bölgesinde düşük değerlikli nipple ya yerlesecegini nasil biliyorsunuz?
Çünkü compiler little endiansa yerleşir
Sağol hocam.
Alıntı yapılan: CLR - 06 Mayıs 2015, 21:05:53
Çünkü compiler little endiansa yerleşir
nibblein hangisinin nereye konacagina C standard'da belirlenmemistir ve compiler'a bagimlidir. O yuzden bir computer/compiler icin calisan bit structlar baskasinda calismayabilir. Yani bit-field'lar 'portable' degildir!
Unspecified behavior
The alignment of the addressable storage unit allocated to hold a bit-field (6.7.2.1).
Implementation-defined behavior
Whether a bit-field can straddle a storage-unit boundary (6.7.2.1).
The order of allocation of bit-fields within a unit (6.7.2.1).
little/big endian tabiiki compiler/computer bagimlidir!
bu yuzden ornegin linux kerneldeki iphdr struct asagidaki gibi yapilmistir:
Alıntı Yap
struct iphdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 ihl:4,
version:4;
#elif defined (__BIG_ENDIAN_BITFIELD)
__u8 version:4,
ihl:4;
#else
#error "Please fix <asm/byteorder.h>"
#endif
@mufitsozen,
Bu forumda konu embedded programlama olduğundan sadece bizim tanımladığımız değişkenler değil asıl işlemcinin hardware registerlerinin little/big endian olması önem arz etmekte. Yoksa sizinde örnek verdiğinizi gibi oluşturulan struct içindeki little/big endian formatı compiler direktifleri ile alt/üst edilerek kolayca seçilebilir ama hardware registerleri seçilemez (çünkü compiler'ların çoğu kolaylık olsun diye bit tanımlamalarını kendisi yapıyor, aslında özel bir struct yapılıp point edilerek yapılabilir fakat her işlemci için yeniden, işlemcinin bit hafıza haritası çıkarılması gerekir).
8-16-32bit programlamada KEIL, IAR, Microchip XCx tipi compiler kullananların bit tanımlamaları %95'i little endian 'dır. Bu compilerlar arasında bitfield struct'lar taşınabilir ve hepsi aynı çalışır. Ama big endian formatta çalışan bir işlemci veya computer'de ters çalışır.
Mesela STM8 ile program yazarken, o işlemcinin hardware register'leri formatı big endian'dır. Dolayısıyla stm8 compiler ya big endian olması gerekir veya little/big endian seçilebilir özellikte olmalı. Ben STM8 için IAR kullandığım için o default olarak big endian formatta bit yerleştirir.
@CLR
Alıntı YapSome architectures (including ARM versions 3 and above, PowerPC, Alpha, SPARC V9, MIPS, PA-RISC, SuperH SH-4 and IA-64) feature a setting which allows for switchable endianness in data segments, code segments or both. This feature can improve performance or simplify the logic of networking devices and software. The word bi-endian, when said of hardware, denotes the capability of the machine to compute or pass data in either endian format.
Many of these architectures can be switched via software to default to a specific endian format (usually done when the computer starts up);
Compiler bunu compile ederken bilemiyecegi icin onermeniz dogru degil problem cikarabilir. Ayni ureticinin ayni ARM MCU bile uygulamada degisik endian olabilir.
Temkinli olmak iyidir.
mesaj birleştirme:: 06 Mayıs 2015, 23:02:50
infocenter.arm.com'dan bir alinti:
Read the AIRCR.ENDIANNESS field to find the implemented endianness, see Application Interrupt and Reset Control Register.
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/I1835.html (http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/I1835.html)
Mufit hocam senin ornegini inceliyorum simdi.struct iphdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 ihl:4,
version:4;
#elif defined (__BIG_ENDIAN_BITFIELD)
__u8 version:4,
ihl:4;
#else
#error "Please fix <asm/byteorder.h>"
#endif
Az once IP header yapisina baktim. Burada version en dusuk degerlikli bit tarafinda. CLR arkadasin dedigi gibi olmuyor o zaman hakli miyim? Eger little endian sistemde ilk yazilan bit degiskeni en dusuk degerlikli alana geliyorsa. IHL en dusuk degerlikli alana gelir ki bu da IP header yapisina ters olmaz mi?
Alıntı yapılan: mir_as82 - 06 Mayıs 2015, 23:59:30
Mufit hocam senin ornegini inceliyorum simdi.struct iphdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 ihl:4,
version:4;
#elif defined (__BIG_ENDIAN_BITFIELD)
__u8 version:4,
ihl:4;
#else
#error "Please fix <asm/byteorder.h>"
#endif
Az once IP header yapisina baktim. Burada version en dusuk degerlikli bit tarafinda. CLR arkadasin dedigi gibi olmuyor o zaman hakli miyim? Eger little endian sistemde ilk yazilan bit degiskeni en dusuk degerlikli alana geliyorsa. IHL en dusuk degerlikli alana gelir ki bu da IP header yapisina ters olmaz mi?
ornek benim degil linux kernel deki ip.h header dosyasi.
@CLR soyledikleri hakkinda ben bir yorum yapamam, acik bir forumda ne yazdigini dusunuyordur herhalde, dolayisi ile ona sormanda fayda var.
IP header yapisindan konusmak icin bu baslik dogru degil. Hem bu hafta cevap kotami doldurdum ;)
@mir_as82
O kodda hiç birşey yok, kernelde compiler direktifleriyle little/big endian tanımlaması yapılmış. O tanımlamaya göre format big endian tanımlıysa compile edilirken register isimleri yer değişiyor. Bu durumda bit yerleride yer değişmiş olur.
@mufitsozen
Little/big endian bit select olması aslında çok çok önemli değil çünkü kullanıcıların en kötü tahminle %95'i default modda kullanır. Tabii siz ben %5'de önemserim diyorsanız ona eyvallah. Benim tarafımda açıkçası iş yükü oluşturduğu için tercih etmiyorum. Mesela şuana kadar hiç cortex m3'te endian formatı değiştirilebildiği halde big endian program yazan görmedim. Mesela isteseler aşağıdaki gibi big endian formata geçebilirler, hatta siz söyledikten sonra merak ettim hiç stm32'ye big endian yazan kardeş varmı diye, bulamadım. (Register taraması yaptım). Olsada fark etmez, sen öyle yazarsın bende böyle. Terch meselesi.
SCB->AIRCR |= 0x05FA8000; // big endian
Tabii sizin yukarıda örnek verdiğiniz linux gibi hardware seviyesinde değilde daha üst seviyede program yazarken, programı yazan vatandaşa göre değişir. İster big endian yazar, isterse little endian veya mix yapar çünkü user değişkenleri kendi oluşturuyor.
Pc veya mini pc'ye göre çok küçük kalan 8-16-32 bit embedded uygulamalarda gereksiz görüyorum. Ama sizin tercihiniz böyle olabilir.
Bu programdaki sorunu bir türlü çözemedim dos ekranı geliyor ama hata veriyor program
//AMAÇ=Palindrome dediğimiz terstende okunuşu aynı olan kelimeleri kontrol eden program
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<ctype.h>
struct stack{
char data;
struct stack *nextPtr;
};
typedef struct stack Stack;
typedef Stack *StackPtr;
void compare(char a[],char b[]);
void push(StackPtr *topPtr,char value);
char pop(StackPtr *topPtr);
main(){
StackPtr startPtr=NULL;
char string1[50],string2[50];
int i;
printf("Please enter a text: ");
scanf("%s",string1);
for(i=0;string1[i]!=NULL;i++){
push(&startPtr,string1[i]);
}
for(i=0;i<=strlen(string1);i++){
string2[i]=pop(&startPtr);
}
compare(string1,string2);
return 0;
}
void push(StackPtr *topPtr,char value){
StackPtr newPtr;
newPtr=(Stack*)malloc(sizeof(Stack));
if(newPtr==NULL){
printf("Memory is not created.");
}
else{
newPtr->data=value;
newPtr->nextPtr=*topPtr;
*topPtr=newPtr;
}
}
char pop(StackPtr *topPtr){
StackPtr tempPtr;
char ch;
if(*topPtr=NULL){
return NULL;
}
else{
tempPtr=*topPtr;
ch=(*topPtr)->data;
*topPtr=(*topPtr)->nextPtr;
free(tempPtr);
return ch;
}
}
void compare(char a[],char b[]){
int i,exit=1;
for(i=0;i<=strlen(a);i++){
if(a[i]!=b[i]){
printf("They are not palindrome.");
exit=0;
}
}
if(exit!=0){
printf("They are palindrome.");
}
}
Alıntı yapılan: unknownperson - 09 Mayıs 2015, 22:45:42
Bu programdaki sorunu bir türlü çözemedim dos ekranı geliyor ama hata veriyor program
Amaç sadece palindrom olup olmadığını anlamaksa stack veri yapısına girmeden tek diziyle halledilebilirdi. Gereksiz uzun yola başvurulmuş burada.
#include <stdio.h>
char kelime[100] = {0};
int uzunluk, indis=0;
int orta_indis;
int palindrom = 1;
int main()
{
printf("Kelimeyi girin: ");
scanf("%s", kelime); // kelimeyi al
while(kelime[indis] != 0)
indis++;
uzunluk = indis;
orta_indis = uzunluk/2;
for (indis = 0; indis < orta_indis; indis++)
{
if (kelime[indis] != kelime[uzunluk - indis - 1])
palindrom = 0;
}
if (palindrom == 1)
printf("Kelime bir palindrom.");
else
printf("Kelime palindrom değil.");
}
Alıntı yapılan: fatih6761 - 09 Mayıs 2015, 22:59:46
Amaç sadece palindrom olup olmadığını anlamaksa stack veri yapısına girmeden tek diziyle halledilebilirdi. Gereksiz uzun yola başvurulmuş burada.
#include <stdio.h>
char kelime[100] = {0};
int uzunluk, indis=0;
int orta_indis;
int palindrom = 1;
int main()
{
printf("Kelimeyi girin: ");
scanf("%s", kelime); // kelimeyi al
while(kelime[indis] != 0)
indis++;
uzunluk = indis;
orta_indis = uzunluk/2;
for (indis = 0; indis < orta_indis; indis++)
{
if (kelime[indis] != kelime[uzunluk - indis - 1])
palindrom = 0;
}
if (palindrom == 1)
printf("Kelime bir palindrom.");
else
printf("Kelime palindrom değil.");
}
Stack kullanmak zorundayım o yüzden girdim, bir de compare fonksiyonu kullanmadan direk harfleri karşılaştırıp da yapmak daha kısa olabilirdi onu düzenleyebilirim ama stackle yapılcak.
Alıntı yapılan: unknownperson - 09 Mayıs 2015, 23:04:42
Stack kullanmak zorundayım o yüzden girdim, bir de compare fonksiyonu kullanmadan direk harfleri karşılaştırıp da yapmak daha kısa olabilirdi onu düzenleyebilirim ama stackle yapılcak.
O halde şöyle yapalım:
EDIT: aman free'yi unutmayalım memory leak olmasın :)
#include <stdio.h>
#include <stdlib.h>
#define STCK_ELEM char
struct T_StackElem {
STCK_ELEM val;
struct T_StackElem * next;
struct T_StackElem * prev;
};
struct T_Stack {
struct T_StackElem *head;
struct T_StackElem *last;
int empty;
} myStack;
void stack_init(struct T_Stack *p)
{
p->head = (struct T_StackElem*)malloc(sizeof(struct T_StackElem));
p->head->val = 0;
p->head->next = 0;
p->head->prev = 0;
p->last = p->head;
p->empty = 1;
}
void stack_push(struct T_Stack *p, STCK_ELEM val)
{
struct T_StackElem *newElem = (struct T_StackElem*)malloc(sizeof(struct T_StackElem));
newElem->val = val;
newElem->next = 0;
newElem->prev = p->last;
p->last->next = newElem;
p->last = newElem;
p->empty = 0;
}
STCK_ELEM stack_pop(struct T_Stack *p)
{
if (p->last == p->head)
{
p->empty = 1;
return 0;
}
struct T_StackElem e = *(p->last);
free(p->last);
e.next = 0;
p->last = e.prev;
return e.val;
}
void stack_free(struct T_Stack *p)
{
while (!(p->empty))
{
stack_pop(p);
}
}
int main()
{
char word[50] = {0};
int i, j, palindrome = 1;
struct T_Stack * p = &myStack;
stack_init(p);
scanf("%s", word);
for (i = 0; word[i] != 0; i++)
stack_push(p, word[i]);
j = i;
i = 0;
while (j > i)
{
char c = stack_pop(p);
if (c != word[i])
palindrome = 0;
j--;
i++;
}
stack_free(p);
printf("Palindrome : %d", palindrome);
}
Alıntı yapılan: fatih6761 - 10 Mayıs 2015, 15:58:23
O halde şöyle yapalım:
EDIT: aman free'yi unutmayalım memory leak olmasın :)
#include <stdio.h>
#include <stdlib.h>
#define STCK_ELEM char
struct T_StackElem {
STCK_ELEM val;
struct T_StackElem * next;
struct T_StackElem * prev;
};
struct T_Stack {
struct T_StackElem *head;
struct T_StackElem *last;
int empty;
} myStack;
void stack_init(struct T_Stack *p)
{
p->head = (struct T_StackElem*)malloc(sizeof(struct T_StackElem));
p->head->val = 0;
p->head->next = 0;
p->head->prev = 0;
p->last = p->head;
p->empty = 1;
}
void stack_push(struct T_Stack *p, STCK_ELEM val)
{
struct T_StackElem *newElem = (struct T_StackElem*)malloc(sizeof(struct T_StackElem));
newElem->val = val;
newElem->next = 0;
newElem->prev = p->last;
p->last->next = newElem;
p->last = newElem;
p->empty = 0;
}
STCK_ELEM stack_pop(struct T_Stack *p)
{
if (p->last == p->head)
{
p->empty = 1;
return 0;
}
struct T_StackElem e = *(p->last);
free(p->last);
e.next = 0;
p->last = e.prev;
return e.val;
}
void stack_free(struct T_Stack *p)
{
while (!(p->empty))
{
stack_pop(p);
}
}
int main()
{
char word[50] = {0};
int i, j, palindrome = 1;
struct T_Stack * p = &myStack;
stack_init(p);
scanf("%s", word);
for (i = 0; word[i] != 0; i++)
stack_push(p, word[i]);
j = i;
i = 0;
while (j > i)
{
char c = stack_pop(p);
if (c != word[i])
palindrome = 0;
j--;
i++;
}
stack_free(p);
printf("Palindrome : %d", palindrome);
}
Çok teşekkür ederim de program saten internette var ben daha çok kendi programımın hatası ne onu çözmeye çalışıyorum
mesaj birleştirme:: 10 Mayıs 2015, 16:50:39
Bu arada sorunu da çözdüm pop içinde if şartında == yerine = yazmışım syntax olarak hata vermeyince de göremedim şimdi adım adım programı test ederken buldum.
Alıntı yapılan: unknownperson - 10 Mayıs 2015, 16:44:08
Çok teşekkür ederim de program saten internette var ben daha çok kendi programımın hatası ne onu çözmeye çalışıyorum
mesaj birleştirme:: 10 Mayıs 2015, 16:50:39
Bu arada sorunu da çözdüm pop içinde if şartında == yerine = yazmışım syntax olarak hata vermeyince de göremedim şimdi adım adım programı test ederken buldum.
Bir de onun yanında sizin program tüm karakterleri birebir eşlemeye çalışıyor onun yerine mesela kelimenin ilk yarısındaki harfleri son yarısındaki harflerle zıt sırada kontrol ederseniz daha az karşılaştırma yaparak sonuca ulaşırsınız. 3-5 kelime için bir şey farketmez ama 1M kelime olursa bariz hız farkı olur. Ayrıca sizin Stack yapısında tüm push edilen elemanlar pop edilmeden stack işi biterse pop edilmeyen elemanlar bellek sızıntısına yol açabilir. Stack_free şeklinde bir fonksiyon ile tüm elemanların free edildiğinden emin olun.
İyi çalışmalar.
Alıntı yapılan: fatih6761 - 10 Mayıs 2015, 17:13:39
Bir de onun yanında sizin program tüm karakterleri birebir eşlemeye çalışıyor onun yerine mesela kelimenin ilk yarısındaki harfleri son yarısındaki harflerle zıt sırada kontrol ederseniz daha az karşılaştırma yaparak sonuca ulaşırsınız. 3-5 kelime için bir şey farketmez ama 1M kelime olursa bariz hız farkı olur. Ayrıca sizin Stack yapısında tüm push edilen elemanlar pop edilmeden stack işi biterse pop edilmeyen elemanlar bellek sızıntısına yol açabilir. Stack_free şeklinde bir fonksiyon ile tüm elemanların free edildiğinden emin olun.
İyi çalışmalar.
Evet bazı dezavantajlar var aslında bellek yönetimi ve program hızı konusunda C programlamada çok bilgim yok, bunları tam olarak nereden öğrenebilirim mesela programı daha az yormayı ve hızlandırmayı , az bellek kullanarak program yazmak gibi.
Merhaba,
Cpp header dosyası içinde class tanımlandı, sonra xxx.cpp dosyasında classın ismiyle fonksiyonlar tanımladık.Dosya sonunda anlamsız iki adet "}" mi olmalı?
bisey.h:
class bisey:{
//bir seyler tanımlanmış olsun.
}
bisey.cpp:
uint8_t bisey::funck(){
}
//vs vs
..
..
..
void bisey::funck2(){
}
//buradan sonra iki adet "}" eklenmeli mi?Şöyle ki:
}
}
//Bu iki "}" olmalı mı?
Çünkü bunları eklemediğimde keil projeye eklediğim cpp dosyasını derlerken expected a } hatası veriyor.Hemde iki tane.Projede 3 adet cpp dosyası var.
Cpp1.cpp--->Cpp2.cpp--->Cpp3.cpp şeklinde birbirlerini soldan sağa include ediyorlar.Bu hatayı yalnızca Cpp3.cpp da alıyorum.
Nedir bu işin kerameti?
class bisey{
//bir seyler tanımlanmış olsun.
};
class tanımının sonundaki parantezden sonra noktalı virgül koymalısın..
O durum header için halledilmiş durumda.Ancak c++ dosyasında dediğim durum halen geçerli.Sebebini anlamış değilim.
Ayrıca şimdi bir toola ihtiyacım oldu. C ,c++,h dosyalarını belli bir formatta düzenleyen bir program veya web sayfası biliyor musunuz?Programı dağınık yazayım ama o tool ile otomatik belli bir formatta düzenleyeyim.
Biliyor musunuz?
https://www.picproje.org/index.php/topic,52774.0.html (https://www.picproje.org/index.php/topic,52774.0.html)
Alıntı yapılan: JKramer - 03 Temmuz 2015, 15:36:27
https://www.picproje.org/index.php/topic,52774.0.html (https://www.picproje.org/index.php/topic,52774.0.html)
Teşekkürler.Harika oldu.Bir de kullanıma hakim olursam :)
Merhaba,
Elimde aşağıdaki gibi struct yapıları var.
typedef struct Button_t {
char Order;
TScreen* OwnerScreen;
char Left;
char Top;
char Width;
char Height;
char Visible;
char Active;
const char *Caption;
char InversText;
TTextAlign TextAlign;
char PressColEnabled;
void (*OnClickPtr)();
} TButton;
struct Screen_t {
unsigned char ObjectsCount;
unsigned int ButtonsCount;
TButton * const * Buttons;
};
Mesela 5 tane buton değişkeni tanımlayıp bunları bir diziye atarak struct Screen_t da bulunan "TButton * const * Buttons; " değişkenine bu dizinin adresini atamak istiyorum. Tanımlamaları aşağıdaki gibi yapıyorum.
TScreen ScreenKeyboard;
TButton buton1, buton2;
const TButton * KeyboardButtons[27] = {
&buton1,
&buton2};
Son olarak dizi adresini "TButton * const * Buttons" a atamak işlemi aşağıdaki gibi yapıyorum.
ScreenKeyboard.Buttons = KeyboardButtons;
Bu atama işlemine derleyici kızıyor ama derliyor. Başka bir fonksiyonda ilgili butonlara ulaşmak istedigimde sıkıntı yaşıyorum. Bazen çalışıyor bazen sıkıntı çıkarıyor. Yapmak istedigim ScreenKeyboard.Buttons[indis] ile dizide tanımladıgım butonlara erişmek.
Burada ne yapmak istediğini anlayamadım, başkalarının yazdığı hazır struct yerine kendi struct'ını yazarsan daha verimli olur. Yinede kullanımı şöyle
// öncelikle 27'lik dizi oluşturmuşsun ama 2 tane değişken tanımlamışsın buna compiler uyarı verir, 2'den büyük buton değişkeni değeri girdiğinde büyük ihtimalle programın kilitlenir çünkü programda kaybolmuşsun demektir. Aşağıdaki gibi yapmanı tavsiye ederim.
// kaç button varsa diziye ekle
const TButton * KeyboardButtons[] = { &buton1, &buton2, .......};
// Kullanırken,
char ButtonNo=1; // kullanacağın buton no olsun
const TButton *Bptr = KeyboardButtons[ButtonNo-1]; // ButtonNo=1 olduğu için button1 struct'ı veya registerleri kullanılır
GlcdPrint( Bptr->Left, Bptr->Width.....); // Burada kullanımı
......
Programdan bir parça aldığım için orası 27 kalmış, normalde içeriği dolu.
Hocam bu mikroC nin bir kütüphanesi kütüphaneyi xc8 de kullanmak için port etmeye çalışıyorum. Her ekran için bir ekran oluşturulup bu ekran da bulunacak yazı,resim, buton v.b şeyler ekran struct ına yükleniyor. Daha sonra ekran lcd ye yansıtılıyor. Ekran geçisinde DrawScreen(Tscreen A) gibi ir fonksiyona ekran struct ı geçirilip o ekranda tanımlanan butonlar, yazılar, resimler ekrana basılıyor. Burada ki espiri bir ekranda 10 buton diğerinde 5 buton bir diğerinde sadece resim veya yazı olabilir. Bunlar için static bir fonksiyon yazmak yerine dinamik çalışan bir yapı sağlanmış . Yani A struct ında tanımlanmış ne varsa onu ekrana basıyor.
ScreenKeyboard adında tanımladıgım ekranda 27 tane buton var. Bu butonları "const TButton * KeyboardButtons[27] " isimli diziye adreslerini alıyorum. Daha sonra Screen struct ında " TButton * const * Buttons;" ile tanımlı yapı elemanına "ScreenKeyboard.Buttons = KeyboardButtons" atamasıyla butonların adreslerinin oldugu diziyi atmaya çalışıyorum. Daha sonra bu butonların ekrana yazıldığı fonksiyon da
......
void DrawScreen(TScreen *aScreen){
TButton *local_button;
......
local_button = (aScreen->Buttons[button_idx]);
if (order == local_button->Order) {
button_idx++;
order++;
DrawButton(local_button);
}
......
}
.......
yukarıda ki gibi "local_button = (aScreen->Buttons[button_idx]);" satırı ile her butona erişip ekrana yazdırıyorum.
Sorun ise şu; xc8 ScreenKeyboard.Buttons = KeyboardButtons;
bu atamaya pointer to pointer to const struct Button_t -> pointer to const pointer to struct Button_t
uyarısını veriyor. Program bazen saçmalıyor. Pointerler ile çalışıldığı için bişeyler yanlış belli. MikroC deki doğru karşılığı tanımlamayı çözemedim. Pointerler konusunda zayıfım.
O uyarıda const hatası yaptığını söylüyor, anladığım kadarıyla, pointer olanı const pointer kullanmışsın, const struct olanıda sadece struct olarak kullanmışsın.
bu durumda pointer yerine, const pointer kullandıysan yeni adresleri point edemezsin, yani birkez atadıktan sonra değiştiremezsin.
sonuç olarak değişken tanımlama hatası var görünüyor,
tüm uyarıları yok etmeden kullanmak programda açık var anlamına gelir
Alıntı yapılan: CLR - 13 Temmuz 2015, 02:29:09
sonuç olarak değişken tanımlama hatası var görünüyor,
Evet hocam sorun orada da nedeni ve çözüm arayışım sürüyor.
Compiler'ın uyarıyı verdiği satırda kullandığın değişkenler ile atağın veya yarattığın değişkenlerin tamamen aynı type mı ona bakacaksın sadece. Cast işlemsel olarak kurtarıyorsa cast yaparsın veya type'lerini değiştirirsin.
merhaba,
Bir konuyu öğrenmek istiyorum.
__attribute__((packed))
konusu.
Genel olarak bellekte verilerin hizalanmasıyla ilgili konu.Ancak biraz daha detaya girmek istiyorum..
Bana struct içindeki düzensiz tanımlamalarım için gerekti.Bu konuyu biraz açıklar mısınız?
Bir de uart spi gibi yerlerden veri gönderirken struct kullanmak üzerine konu vardı.Bu konudan bahsedebilir misiniz?Kullanan arkadaşlar nasıl yapıyorlar.Neler yapıyorlar.
@z tartışacak güzel bir konu arıyordun.Bu konudan biraz bahseder misin?
Aşağıdaki gibi bir tablom var
float concrete_factor [4][4]={0.5800, 0.5825, 0.5850, 0.5900,
0.5500, 0.5600, 0.5700, 0.5800,
0.5200, 0.5400, 0.5600, 0.5800,
0.5100, 0.5150, 0.5200, 0.5250};
Bu tabloyu sprintf fonksiyonunda kullanıyorum aşağıdaki gibi.
sprintf(LCD_String,"%f ",concrete_factor[0][0]);
Fakat "Printf format type is invalid" hatası alıyorum.
Const tanımlamasam hata vermiyor. Acaba Sprintf fonksiyonu const tipi veriler kabul etmiyormu?
(Derleyici CCS C)
LCD_String'i nasıl tanımladın? Char dizisi olmak zorunda benim bildiğim.
eğer char değilse şöyle yap
sprintf((char*)LCD_String,"%f ",concrete_factor[0][0]);
LCD string char dizisi. Normalde sıkıntı yok. Const veriyi yazdırmak istersem sıkıntı oluşuyor.
Birde Dizinin ilgili elemanı 0.5800 ise ekrana yazdırdığımda 0.5799 yazıyor.
CCS C kullanmadım ama derleyiciler const değişkenleri ROM'a yani flash belleğe kaydedebiliyorlar. Sorun burdan kaynaklanıyor muhtemelen.
https://www.ccsinfo.com/content.php?page=compiler-features (https://www.ccsinfo.com/content.php?page=compiler-features)
Note: The const qualifier in CCS always means that the data will be placed in program memory, and that the data is 'read-only'. It does not follow the ANSI definition which simply states that const is 'read-only'.
Alıntı yapılan: Mucit23 - 20 Ağustos 2015, 14:25:31
LCD string char dizisi. Normalde sıkıntı yok. Const veriyi yazdırmak istersem sıkıntı oluşuyor.
Birde Dizinin ilgili elemanı 0.5800 ise ekrana yazdırdığımda 0.5799 yazıyor.
Hocam, işlemciler matematik yapmayı bilmedikleri için herşeyi basit nümerik yöntemle hesaplayıp bir süre sonra bulduğunu iddia ediyorlar. 25in kare kökü de bilgisayar için 4.999999 a eşit, genellikle 5 diyorlar ama 4.9999 bolca gördüm. Düzeltmek için genel bir yol bilmiyorum. Kendi kodunuza göre işlemler yapabilirsiniz. Küsüratın ulaşmadığı bir basamağınız varsa onu kontrol edebilirsiniz eğer o basamak 9 sa yuvarlama yaptırırsınız yada önce bütün sayıları 10000 ile çarpıp int e çevirdikten sonra string e çevirip daha sonra onu noktalı hale getirebilirsiniz.
pic18f4620
unsigned char LowByte=200; (Bunlar unsigned char olmak zorunda eeprom kullanımından dolayı)
unsigned char HighByte=5;
unsigned int FinalByte=0;
FinalByte=(HighByte*256+LowByte);
Ram belleği en az yorarak işlemi en kısa sürede tamamlayan kod örneği verebilirmisiniz?
HighByte*256
kısmını (HighByte<<8)&0xFF00
olarak değiştirmeniz yerinde olur.
Hocam burada HighByte char yani 8 tabanında;
FinalByte=((HighByte<<8)&0xFF00)+LowByte;
şimdi bu şekilde sizin dediğiniz gibi doğru sonucu elde edebilirmiyim ?
0xFF00 ile and'lemeniz şart değil, el alışkanlığı. Doğru sonucu elde edip edemeyeceğinizi anlamak kolay, bilgisayarınıza devc++ IDE'yi kurun yeni bir proje oluşturun ve sonucu ekrana basın, bu yöntem ilerde çok işinize yarar.
Teşekkürler, aşağıdaki sorumada bakabilirmisiniz?
unsigned char A1=2;
unsigned char Z=0;
switch (Z)
{
CASE 0:
..
BREAK;
CASE 1:
....
BREAK;
CASE A1:
...
BREAK;
}
2 'yi A1 yerine kullanabilirmiyim, başka uygulamalarda buna ihtiyacım olcak.
Bu soruların xc8 ile direkt alakası olmadığı için "C Programlama diliyle şamatalar" adlı başlığın altına sormanızı rica ederim.
https://www.picproje.org/index.php?topic=35908.210 (https://www.picproje.org/index.php?topic=35908.210)
soruya gelecek olursak,
unsigned char A1=2;
unsigned char Z=0;
switch (Z)
{
CASE 0:
..
BREAK;
CASE 1:
....
BREAK;
CASE 2: //A1 (istediğinizi yazabilirsiniz)
...
BREAK;
}
dediğiniz bu ise olur, ancak madem kullanmayacaktınız A1'i neden tanımladınız ki?
MB.c:1752: error: (188) constant expression required
MB.c:2518: error: (195) expression syntax
2 yerine A1 yazarsam aldığım hata.
A1i kullanıcam A1 değişerek devam edicek
CASE (DEĞİŞKEN) bu şekilde kullanmam gerekiyor
Olmaz demiş zaten derleyici,
(Case karşısında bir sabit olması gerekiyor demiş hata mesajında)
switch case ile ilgili derleyicilerin çıktılarını gösteren
bir konu vardı yakın zamanda, onu bulsan faydası olur.
Case de değişken olması neden lazım?
Asıl yapılmak istenen ne?
Başka yolları bulunabilir.
mesaj birleştirme:: 10 Eylül 2015, 17:47:23
İlgili konu: (bu konunun tamamında güzel bilgiler var, incelenmeli)
https://www.picproje.org/index.php/topic,60842.msg470809.html#msg470809 (https://www.picproje.org/index.php/topic,60842.msg470809.html#msg470809)
https://en.m.wikibooks.org/wiki/GCC_Debugging/g%2B%2B/Errors/variable_cannot_appear_in_a_constant-expression
switch(A1_Reg)
{
case 1:
SettingFactoryArray[A1_Reg]=RCREG;
DataLength_SettingsA1=SettingFactoryArray[A1_Reg];
A1_CheckSum_Low=A1_CheckSum_Low+SettingFactoryArray[A1_Reg];
break;
default:
SettingFactoryArray[A1_Reg]=RCREG;
A1_CheckSum_Low=A1_CheckSum_Low+SettingFactoryArray[A1_Reg];
break;
case 96:
A1_CheckSum_High=A1_CheckSum_Low/256;
A1_CheckSum_Low=A1_CheckSum_Low%256;
SettingFactoryArray[A1_Reg]=RCREG;
if(SettingFactoryArray[A1_Reg]!=A1_CheckSum_Low){SerialRestBit=1;}
break;
case 97:
SettingFactoryArray[A1_Reg]=RCREG;
if(SettingFactoryArray[A1_Reg]!=A1_CheckSum_High){SerialRestBit=1;}
break;
case 98:
SettingFactoryArray[A1_Reg]=RCREG;
if(SettingFactoryArray[A1_Reg]!=0xFD){SerialRestBit=1;}
break;
}
FactorySettingsCheck();
A1_Reg++;
if(A1_Reg==DataLength_SettingsA1){SerSelect=4;A1_Reg=0;}
Settings_A1_Fin:
__delay_us(1);
Burada uart haberleşmenin alınan kısımları var.
Burada 96 yerine DataLength_SettingsA1-3
97 yerine DataLength_SettingsA1-2
98 yerine DataLength_SettingsA1-1
kullanmam gerekiyor cunku datalength değişken umarım anlatabilmişimdir.
if-else if -else komutuyla bu yapılabiliyor fakat ben switch - case yapısı tercih ediyorum.
Şöyle bir fonksiyon tanımladım
void fonk1(void) {
deger1 = 12;
}
Şöyle çağırdım
fonk1; // yol 1 //deger1 = 0;
fonk1(); //yol 2 //deger1 = 12;
Her iki yolda da hata vermiyor ancak parantezli şekilde çağırdığımda sorun yok.
Boş parantezin olması veya olmaması ne anlama gelir? Standart ne diyor? Uygulamada durum nedir?
Alıntı yapılan: engerex - 27 Ekim 2015, 23:36:17
Şöyle bir fonksiyon tanımladım
void fonk1(void) {
deger1 = 12;
}
Şöyle çağırdım
fonk1; // yol 1 //deger1 = 0;
fonk1(); //yol 2 //deger1 = 12;
Her iki yolda da hata vermiyor ancak parantezli şekilde çağırdığımda sorun yok.
Boş parantezin olması veya olmaması ne anlama gelir? Standart ne diyor? Uygulamada durum nedir?
fonksiyonu cagirmak icin parantez ler sart. Aksi takdirde sadece fonksiyon adresini bir satira yazmis gibi oluyorsunuz. Bu herhangi bir expression yazmak ama kullanamak gibi
ornegin:
int i;
57+24;
ı=75;
57+24; satiri hesaplanir sonrada hicbir islem vermediginiz icin gormezden gelinir(ignored) ve program akisi devam eder.
Sizin orneginizde de fonk1; satirinda fonk1 fonksiyonun adresini deger olarak giriyor ve hicbir islem yapmiyorsunuz.
Bu tip standard disi denemeleri niye yaptiginizida acikcasi ben cok merak ettim? Ne bulmayi umuyorsunuz?
Burda da soranlar olmuş:
http://stackoverflow.com/questions/13881693/call-function-without-parameter-and-parenthesis (http://stackoverflow.com/questions/13881693/call-function-without-parameter-and-parenthesis)
http://stackoverflow.com/questions/1529201/access-a-function-pointer-without-parenthesis (http://stackoverflow.com/questions/1529201/access-a-function-pointer-without-parenthesis)
Alıntı yapılan: mufitsozen - 27 Ekim 2015, 23:46:50
fonksiyonu cagirmak icin parantez ler sart. Aksi takdirde sadece fonksiyon adresini bir satira yazmis gibi oluyorsunuz. Bu herhangi bir expression yazmak ama kullanamak gibi
ornegin:
int i;
57+24;
ı=75;
57+24; satiri hesaplanir sonrada hicbir islem vermediginiz icin gormezden gelinir(ignored) ve bir program akisi devam eder.
Sizin orneginizde de fonk1; satirinda fonk1 fonksiyonun adresini deger olarak giriyor ve hicbir islem yapmiyorsunuz.
Bu tip standard disi denemeleri niye yaptiginizida acikcasi ben cok merak ettim? Ne bulmayi umuyorsunuz?
C'yi yeni yeni öğreniyorum. Yazdığım kodu parantez koymadan çalıştırdım. Haliye problem oldu. Bir müddet takıldım ve parantezden olduğunu farkettim. Bug mu derken başka derleyici ile teyit ettim aynı ve sormak istedim. Ayrıca az önceki denemelerimde belirttiğiniz örneklerdeki gibi tek başına i; kodlayınca da bir hata yok.
Cevap bilgilendiriciydi. Teşekkürler. Yalnız şunu da sormak istiyorum. Şu haliyle bu kodlamalar bir anlam ifade etmiyor gibi görünüyor. Peki neden bu satırlarda hata veya uyarı yok? Yoksa bir incelik mi var?
Alıntı yapılan: engerex - 28 Ekim 2015, 00:18:37
C'yi yeni yeni öğreniyorum. Yazdığım kodu parantez koymadan çalıştırdım. Haliye problem oldu. Bir müddet takıldım ve parantezden olduğunu farkettim. Bug mu derken başka derleyici ile teyit ettim aynı ve sormak istedim. Ayrıca az önceki denemelerimde belirttiğiniz örneklerdeki gibi tek başına i; kodlayınca da bir hata yok.
Cevap bilgilendiriciydi. Teşekkürler. Yalnız şunu da sormak istiyorum. Şu haliyle bu kodlamalar bir anlam ifade etmiyor gibi görünüyor. Peki neden bu satırlarda hata veya uyarı yok? Yoksa bir incelik mi var?
cunku bir hata yok. bir "expression" yaziyorsunuz ve sonra onu kullanmiyorsunuz.
Haliyle c compiler sizin hur iradenizle karar alan, zeki , bilgili ve yetiskin bir insan oldugunuzu dusunuyor ve sizi uyarmiyor (gerci derleyici ayarlari ile oynayarak bir warning almak mumkundur herhalde ama artik onuda siz arastirin)
Derleyiciye göre değişiyor olabilir,
ccsc tam bir c derleyicisi değil ama
kodun bir etkisi yok diye uyarı veriyor:
(https://lh4.googleusercontent.com/-ZjxDX69MZJY/Vi_tQBlyvFI/AAAAAAAACCo/9DCJzp6Wy_U/w556-h615-no/codehasnoeffect.PNG)
Eğer yazdığınız fonksiyonları, main'den önce yazdıysanız derleyici size duruma göre uyarı yada hata mesajı gönderecektir. Eğer fonksiyonu başka bir kaynak dosyasında yada main fonksiyonundan sonra yazıp fonksiyon prototipini belirtmediyseniz, bu tür hatalarla karşılaşabilirsiniz çünkü derleyicinin bu fonksiyonun paremetreleri hakkında bir bilgisi yok. Bu nedenle main'den sonra kullanılan fonksiyonlar için fonksiyon prototipi kullanılmalı.
Alıntı yapılan: engerex - 28 Ekim 2015, 00:18:37
C'yi yeni yeni öğreniyorum. Yazdığım kodu parantez koymadan çalıştırdım. Haliye problem oldu. Bir müddet takıldım ve parantezden olduğunu farkettim. Bug mu derken başka derleyici ile teyit ettim aynı ve sormak istedim. Ayrıca az önceki denemelerimde belirttiğiniz örneklerdeki gibi tek başına i; kodlayınca da bir hata yok.
Cevap bilgilendiriciydi. Teşekkürler. Yalnız şunu da sormak istiyorum. Şu haliyle bu kodlamalar bir anlam ifade etmiyor gibi görünüyor. Peki neden bu satırlarda hata veya uyarı yok? Yoksa bir incelik mi var?
mesaj birleştirme:: 28 Ekim 2015, 13:47:33
Alıntı yapılan: OxfordBlue - 10 Eylül 2015, 16:17:56
Teşekkürler, aşağıdaki sorumada bakabilirmisiniz?
unsigned char A1=2;
unsigned char Z=0;
switch (Z)
{
CASE 0:
..
BREAK;
CASE 1:
....
BREAK;
CASE A1:
...
BREAK;
}
2 'yi A1 yerine kullanabilirmiyim, başka uygulamalarda buna ihtiyacım olcak.
Alıntı yapılan: OxfordBlue - 10 Eylül 2015, 16:17:56
Teşekkürler, aşağıdaki sorumada bakabilirmisiniz?
unsigned char A1=2;
unsigned char Z=0;
switch (Z)
{
CASE 0:
..
BREAK;
CASE 1:
....
BREAK;
CASE A1:
...
BREAK;
}
2 'yi A1 yerine kullanabilirmiyim, başka uygulamalarda buna ihtiyacım olcak.
c dilinde switch-case ile degişken, ondalıklı sayı kullanamazsınız. A2 içinde sabit bir değerde olsa A2 bir degişkendir. Eğer case ile bir integer değişken tanımlamak isterseniz. bunu 'const' ile tanımlayarak kullanabilirsiniz yada #define a2 2 gibi bir ifade kullanabilirsiniz. Bu durumda derleyiciye göre degişebilir.
Merhabalar,
Herhangi bir interrupt(spi, uart ) fonksiyonunu main.c dosyasında tanımlamak zorundamıyız. Eğer değilsek başka bir dosyada nasıl yapabilirim bu işi.
saygılar.
hayır değilsin istediğin .c uzanlıtı bir dosyada kesme fonksiyonunun kullanabilirsin
örneğin usart.c dosyası içinde
void USART1_IRQHandler(void)
{
............
}
gibi kullanabilirsin
Evet dediğiniz şekilde yapıyorum fakat kesme fonksiyonuna girmediğini gördüm. Kesme fonksiyonu main dosyasında olunca sorun yok.
Acaba eksik yaptığım bir şeyler mi var ?
O konu kullandığınız derleyiciye bağlı. ISR vektör tablosunun oluşturulması için preprocessor komutları istiyor çoğu derleyici.
Renesas HEW için örnek:
#pragma INTERRUPT timer_int()
// 1/1000 saniyelik interrupt
void timer_int(void) {}
sect30.inc isimli tanımlama dosyasında da
;---------------------------------------------------------------
; variable vector section
;---------------------------------------------------------------
.section vector,ROMDATA ; variable vector table
.org VECTOR_ADR
.lword dummy_int ; vector 21
.lword dummy_int ; vector 22
;.lword dummy_int ; vector 23
.glb _timer_int
.lword _timer_int
gibi bir ek yapılıyor.
Yani compiler'ın help bölümünü okuyun.
selamlar,
global static bir değişkenimin ilk değeri 0 her interrupt geldiğinde 1 arttırıyorum. Fakat nasıl oluyorsa ilk interrupta girdiğimde 1 den başlıyor.
Bunun nasıl olduğunu anlayamadım?
static volatile rxCounter = 0;
void interrupt()
{
// burda rxCounter değişkeninin değeri = 1 ve interrupt a ilk kez giriyor
.....
.....
rxCounter++;
}
Merhaba,
sprintf ile int bir değişkeni hex olarak bir diziye kaydetmek istiyorum. Fakat ascii değil. Örneğin 32 bit bir değişken için;
a = 0x87654321; ise;
b[3] = 87, b[2] = 65, b[1] = 43, b[0] = 21 şeklinde olmasını istiyorum. sprintf ile mümkün mü ?
Alıntı yapılan: kantirici - 14 Mayıs 2016, 10:40:07
Merhaba,
sprintf ile int bir değişkeni hex olarak bir diziye kaydetmek istiyorum. Fakat ascii değil. Örneğin 32 bit bir değişken için;
a = 0x87654321; ise;
b[3] = 87, b[2] = 65, b[1] = 43, b[0] = 21 şeklinde olmasını istiyorum. sprintf ile mümkün mü ?
Burada sprintf değilde union ve struct ile yeni bir tip tanımlayıp 32 bit değişkenin byte larına erişebilirsin.
typedef union
{
struct BYTES
{
uint8_t byte1;
uint8_t byte2;
uint8_t byte3;
uint8_t byte4;
}bytes;
uint32_t all;
}my_type;
"my_type" türünden "a" diye bir değişken tanımlayıp;
a.bytes.byte1, a.bytes.byte2, a.bytes.byte3, a.bytes.byte4 şeklinde tüm byte lara erişip sprintf le dizine atabilirsin. Tamamına erişmek içinde "a.all" şeklinde kullanabilirsin.
sprintf(buf,"%08X",degisken);
@quarko hocam maalesef union yapısı işimi görmüyor.
@Klein hocam iar da denedim fakat yine tek tek attı diziye ascii olarak.
Union yapısı neden işini görmüyor ki. Byte lara erişebildiysen sprintf ile istediğini yapabilirsin.
Alıntı yapılan: quarko - 14 Mayıs 2016, 16:41:49
Union yapısı neden işini görmüyor ki. Byte lara erişebildiysen sprintf ile istediğini yapabilirsin.
Selam,
@quarko dogru cevabı vermiş.
başka bir yöntem,
a = 0x87654321; ise;
// (a = 0x87654321)
ilkByte = a & 0x000000FF;
// (a>>8) sonrasi (a = 0x00876543)
ikinciByte = (a>>8) & 0x000000FF;
// (a>>16) sonrasi (a = 0x00008765)
UcuncuByte = (a>>16) & 0x000000FF;
(a>>24) sonrasi (a = 0x00000087)
DorduncuByte = (a>>24) & 0x000000FF;
b[0] = ilkByte ;
b[1] = ikinciByte ;
b[2] = UcuncuByte ;
b[3] = DorduncuByte ;
Esen kalın.
uint8_t *byteptr =&a
byte1= *byteptr;byteptr++
byte2= *byteptr;byteptr++
byte3= *byteptr;byteptr++
byte4= *byteptr;
ASCII istemediğini farketmemişim.
Eğer yanlış anlamıyorsam union veya struct iş görmez.
sanırım beklenti şu
0x87654321 sayısını
0x87 , 0x65, 0x43, 0x21 şeklinde bölmek istemiyor. Decimal 87, 65, 43, 21 şeklinde bölmek istiyor. Sonuç dizisini okuduğunda hex 0x57, 0x41, 0x2B, 0x15 görecek.
Yine yanlış anlamışsam , dikkate almayın.
Merhaba arkadaşlar.
Header dosyaları ilgili bir sorum var. Bir lib. oluşturduk ve projemizde farklı .c dosyalarına header dosyalarını include ederek kullanmak isteyelim.
Bu durumda her include durumunda daha önceden lib. zaten include edilmişse tekrar derlenmemesi için;
#ifndef LIB_H
#define LIB_H
uint8_t a,b,c;
void fgh();
...........
#endif
gibi bir koruma içerisine alırız.
Buradaki #ifndef LIB_H yazımını ;#ifndef LIB_H_, #ifndef _LIB_H, #ifndef __LIB_H_ gibi çeşitli biçimlerde görüyorum. Bunlar tam olarak neyi ifade ediyorlar ?
@kantiriciEğer yanlış bilmiyorsam, onlar sadece tanımlama,
İstediğin gibi tanımlarsın. İster __ ile başla ister direk kelime ile başla.Sonuçta aynı tanımı #define ile bir alt satırda yapıyorsun.
Yani
#ifndef __LIB
#define __LIB
ile
#ifndef LIB
#define LIB
Arasında bir fark yok.Kritik nokta. Yeterki
#ifndef ile sorguladığın tanımı bir alt satırında
define ile yeniden tanımla.
Teşekkürler.
Sanırım özel bir anlamı yok.
Selam,
#ifndef _DIGITAL_INPUTS_H_ demek; if not defination demek yani eğer tanımlanmadıysa demektir.
#define _DIGITAL_INPUTS_H_ eğer üst satırdaki sorguda _DIGITAL_INPUTS_H_ daha önce tanımlanmadıysa compiler bir alt satırı işler ve tanımlamayı yapar.
#endif
Burada mesele şu aynı isimle yani aynı sayfada ard arda bu file'ı include ederseniz bu ifadelerden dolayı file tekrar dahil edilmez. Yani duplicate olmaz. Hatayı önlemek amaçlı.
Birde her header file de "_DIGITAL_INPUTS_H_ " kısmı farklı yazmanız lazım yoksa aynı file da dosyaları aynı sanıp dahil etmez.
Esen kalın.
Selamlar,
var değişkenini 1 kere oluşturup döngü içinde kullanmak mı , yoksa döngü içinde koşul sağlandığında her seferinde oluşturmak mı daha iyi performans açısından.
int main()
{
int var;
while (1)
{
if (flag)
{
int var;
.
.
.
}
}
}
}
}
Hocam loop dışı daha mantıklı.
Bu tip şeylerin performansı etkileyeceğini düşünmüyorum.
Adı geçen değişkene ya stackta yer açılacak ya da registerlerden birinde. Çok uyduruk işlemcilerde ise global ramın bir köşesinde.
Registerde yer alacaksa zaten süper. Stackta yer alacaksa aptal bir derleyici olması lazım ki her defasında değişken adresini hesaplasın. Global ramın bir köşesinde yer alacaksa gene sorun yok.
Her durumda adresi bilinen bir değişken.
Alıntı yapılan: z - 06 Ekim 2016, 19:33:13
Bu tip şeylerin performansı etkileyeceğini düşünmüyorum.
Adı geçen değişkene ya stackta yer açılacak ya da registerlerden birinde. Çok uyduruk işlemcilerde ise global ramın bir köşesinde.
Registerde yer alacaksa zaten süper. Stackta yer alacaksa aptal bir derleyici olması lazım ki her defasında değişken adresini hesaplasın. Global ramın bir köşesinde yer alacaksa gene sorun yok.
Her durumda adresi bilinen bir değişken.
İşte ASM bilirsen bu şekilde konuya hakim oluyorsun.
Alıntı yapılan: z - 06 Ekim 2016, 19:33:13
Bu tip şeylerin performansı etkileyeceğini düşünmüyorum.
Adı geçen değişkene ya stackta yer açılacak ya da registerlerden birinde. Çok uyduruk işlemcilerde ise global ramın bir köşesinde.
Registerde yer alacaksa zaten süper. Stackta yer alacaksa aptal bir derleyici olması lazım ki her defasında değişken adresini hesaplasın. Global ramın bir köşesinde yer alacaksa gene sorun yok.
Her durumda adresi bilinen bir değişken.
Peki hocam 200 300 bayt yer kaplıyacak değişkenler için de aynı şeyi diyebilir miyiz?
Basit değişken değil de array ya da structure olsaydı da çok şey değişmeyecekti.
Sonuçta değeri okunacak yada değiştirilecek değişkenin öncelikle fiziksel adresi bir iki adımda hesaplanacak ve bu hesaplama değişkenin nerede tanımlandığından bağımsız.
Belki aklımıza gelmeyen başka trikler vardır.
Soru eksik aslında.
İşlemci ve derleyiciye göre sonuç değişebilir.
Belkide döngü içinde tanımlanınca
asm çıktıda akümülatör kullanacak derleyici.
Birkaç byte için akümülatör kullanmayı yeğlerse derleyici
300 byte değişkende durum farklı olacaktır.
Birde daha çok mikrodenetleyici mantığıyla düşünüyoruz,
bu bir PC programıysa nasıl bir değişiklik olabilir.
Aşağıdaki alıntıda talihsiz bir hata yapmışım. Daha doğrusu anlaşılırlık açısından hata yok da uygulamada başınıza iş açacak bir örnek vermişim.
void hesapla(int a, int b)
{
int x,y,z,w;
x=a+b;
y=a-b;
z=a*b;
w=a/b;
}
hesaplamalarında çağıran fonksiyona x,y,z,w adreslerini geri bildirebiliriz (x,y,z,w yı structure içinde tanımlayıp structure adresini geri döndürebiliriz) fakat bu değişkenler stackta yer aldıklarından fonksiyondan çıktıktan sonra başlarına her şey gelebilir. Bir int gelir ve bu değişkenler artık stağın boş alanında kaldıklarından int girişindeki register saklama işlemleri bunları ezer.
Bu yüzden bu örneği pratikte uygulamayın.
Alıntı yapılan: z - 25 Ekim 2011, 14:27:55
pointer kavramina bakalim.
pointere neden ihtiyac varla baslayalim.
Asagidaki gibi bir fonksiyon dusunelim.
void hesapla(int a, int b)
{
int x,y,z,w;
x=a+b;
y=a-b;
z=a*b;
w=a/b;
}
peki hesaplanan x,y,z,w degerlerini cagiran fonksiyona nasil iletebiliriz? (malesef int int int int hesapla(int a, int b) yazamiyoruz)
Cozum 1. Global degisken kullanmak
int x,y,z,w;
void Hesapla(int a,b)
{
x=a+b;
y=a-b;
z=a*b;
w=a/b;
}
Cozum 2
void Hesapla(int a, int b, int* x, int* y, int* z, int* w)
{
*x=a+b;
*y=a-b;
*z=a*b;
*w=a/b;
}
Burada int *x, gelen veri, x degiskeninin degeri değil adresidir demek.
*X = a+b; demek a+b islemini yap ve sonucu adresi verilen alana yaz demek.
Peki bu fonksiyonu cagirirken nasil adres verecegiz?
main void() // burada parantez icine void yazacaksak yazmayabilme serbestligimiz var
{
int a,b,c,d;
Hesapla (4, 5, &a, &b, &c, &d)(http://picproje.org/Smileys/default/wink.gif) // Buradaki &a, a degiskeninin adresinin sayisal degeri demektir.
}
-------------------------------------------------------------------------------
pointeri anlamak icin bir baska ornek
void main()
{
int a,b; // a ve b integer iki degisken
int* p // p, integer degiskenlerin adresini saklayabilen bir degisken, yani bir pointer
p=&a // a degiskeninin adresini p ye yukledik
a=1; // a=1 yaptik
b=*p; // p degiskenindeki adresdeki veriyi b ye yazdik. (b=a oldu)
}
Pointer denen sey de bundan ibaret.
O halde bir fonksiyondan istedigimiz kadar sonuc geri dondurebiliriz. Daha dogrusu, bir fonksiyondan, istedigimiz kadar degiskenin icine deger yazmasini isteyebiliriz.
Selamlar,
C de özellikle de ST HAL Lib içinde weak tanımları görüyorum.
Anladığım kadarıyla C'de fonksiyonlara overload yapabilmek için kullanılabiliyor.Yani farklı iki dosyada aynı isimde iki fonksiyon olabiliyor.
Bu konu nedir?Neye yarar weak tanımı?
Kendim hiç kullanmadığım için ayrıntılarını bilmiyorum ama overloading gibi çalışmıyor. Normalde yazılması gereken bir fonksiyon eğer kullanıcı tarafından yazılmamışsa geçici olarak kütüphanede başka bir fonksiyon çalışıyor. Daha çok nesne yönelimli programlamada geçen overriding kavramına benziyor. Kullanıcı aynı imzaya sahip kendi fonksiyonunu yazdığında daha önceden sağlanan dandik fonksiyon aradan çekiliyor. Yani bir başka deyişle, "place holder" olarak adlandırabileceğimiz bir fonksiyon yazmaya olanak veriyor.
Startup dosyasında da weak tanımı var ve oradaki amacı biliyorum. Muhtemelen aynı amaca hizmet ediyordur.
Weak tanımlı fonksiyon yerine aynı isimde yeni bir fonksiyon yazarsanız weak tanımlı olan değil yeni tanımlanan fonksiyon geçerli oluyor. Böylece aynı isimde iki fonksiyon oluyor fakat weak tanımlı olan dikkate alınmıyor.
Böylece kullanılmasa da vektör tablosunda adı geçtiği için tanımlanması şart olan int fonksiyonları gibi diğer fonksiyonları weak tanımlamakla derleme hatalarının önüne geçmiş oluyorsunuz.
Teşekkürler
@Tagli Peki blocking ve nonblocking programlama nedir?Bir yazıda, senkron kelimesiyle arama yapın gibi birşeyler gördüm.Yani senkron programlama diye bir kavram da mı var?
Soruları toparlayıp tekrar sorayım.
Alıntı Yap
Peki blocking ve nonblocking programlama nedir?Bir yazıda, senkron kelimesiyle arama yapın gibi birşeyler gördüm.Yani senkron programlama diye bir kavram da mı var?
Hımm.Bir yazıda bu özelliğin, C11 ile geldiğini okudum.Ne kadar doğru?C89 da yok mu?
Hazır konusu açılmışken, Keil ile C89 ve C99 mu kullanabiliyoruz, C11 kullanabiliyor muyuz?
Sorularım güncel.
Ekleme: Ayrıca Keil de C/C++ sekmesinde alt tarafta Include Path altında Misc Control kısmı var. Orası nedir?
Hal lib ile yapılmış bazı projelerde -C99 yazıldığını gördüm o kısma.Halbuki az yukarıda C99 için check box konmuş.Oraya check koysa?Farklı bir trick mi var?
Bir yerde tutulan string var ve ben yeni gelen string ile bu stringin karşılaştırılmasını istiyorum .
Örneğin referans olan string A olsun. A->1234. Yeni gelen string ise 1 olursa negatif dönelim, 12 ise negatif dönelim, 123 ise negatif dönelim, 1234 ise yine negatif dönelim, 12345 ise yine negatif dönelim.
Ama eğer gelen string 1235 ise pozitif dönelim, 12346 ise pozitif dönelim. Veya ilk karakteri 1234 in ilk karakteri ile uyuşmazsa yani 1 den farklı ise[2-9] yine direkt pozitif dönelim.
Bu algoritmanın adını bilen veya implemente edilmiş halini verebilecek olan varmı?
Tamamını karşılamasa da şu ayarda bir şey
int my_strcmp(const char *s1, const char *s2){
int i = 0;
int result = 1;
while(s1[i] != '\n' && s2[i] != '\0'){
// s1 = "1234" s2 = "12345"
//
if(s1[i] == s2[i]){
result = -1;
}
else{
result = 1;
break;
}
if(s2[i] == '\n')
break;
i++;
}
return result;
}
https://www.programiz.com/c-programming/string-handling-functions
Alıntı yapılan: mir_as82 - 28 Aralık 2016, 10:02:27
Bir yerde tutulan string var ve ben yeni gelen string ile bu stringin karşılaştırılmasını istiyorum .
Örneğin referans olan string A olsun. A->1234. Yeni gelen string ise 1 olursa negatif dönelim, 12 ise negatif dönelim, 123 ise negatif dönelim, 1234 ise yine negatif dönelim, 12345 ise yine negatif dönelim.
Ama eğer gelen string 1235 ise pozitif dönelim, 12346 ise pozitif dönelim. Veya ilk karakteri 1234 in ilk karakteri ile uyuşmazsa yani 1 den farklı ise[2-9] yine direkt pozitif dönelim.
Bu algoritmanın adını bilen veya implemente edilmiş halini verebilecek olan varmı?
Bir şeyler yapılır ama sorgulama mantığını anlamadım. 12345 ise negatif dönüp 12346 ise neden pozitif dönülüyor?
O bölümü hatalı yazmışım hocam. 12345 ise yine pozitif dönmek lazım.
Alıntı yapılan: mir_as82 - 28 Aralık 2016, 13:56:57
O bölümü hatalı yazmışım hocam. 12345 ise yine pozitif dönmek lazım.
Verdiğim kodu test ettiniz mi?Kaldı ki
@Zoroaster 'ın dediği gibi standart kütüphanede string fonksiyonları var.Kullanabilirsiniz.
Aşağıdaki kod işinizi görmeli. Her ihtimali test ettim, gözümden bir şey kaçmadıysa sorun yok.
Ufak bir performans arttırıcı if var fonksiyonun içinde o da şartınızdan geliyor. Eğer test ettiğiniz string referans string'inden uzunsa zaten karakterler farklı olacaktır ve bu durumda cevabın pozitif olmasını istiyorsunuz. İlk başta önce buna bakıp boşu boşuna döngüye girmekten kurtulunabilir.
Eğer test ettiğiniz string daha kısa ise fonksiyon bu string'in karakterleri üzerinden kıyas yapıp fark bulduğu an positif değer döndürüyor.
#include <stdio.h>
#include <string.h>
typedef enum { myfalse = 0, mytrue = !myfalse } mybool;
mybool compareStrings(char base[], char test[])
{
if (strlen(test) > strlen(base))
{
return mytrue;
}
else
{
int i =0;
for (i; i<strlen(test); i++)
{
if (base[i] != test[i])
{
return mytrue;
}
}
return myfalse;
}
}
int main()
{
char base[] = "1234";
char myString[] = "1235";
if (compareStrings(base, myString))
{
printf("Positive\n");
}
else
{
printf("Negative\n");
}
return 0;
}
Merhaba
Keil'da User sekmesinde "After Build/Rebuild" kısmında komut textboxuna $K\ARM\ARMCC\bin\fromelf.exe --bin --output=$l@L.bin !L
şeklinde bir tanımlama girilmiş ve "Run#1" check box check konumda.
Bu ifade nedir?Derleme esnasında bir sürü şeyi değiştiriyor.Başka .c ve .h dosyaları içindeki ve extern edilmiş aynı isimdeki fonksiyonları bile derleyebiliyorum bu tanım olunca.
Ekleme: Bu tanım derleme sırasında .bin dosyası üretebilmek içinmiş.
http://www.keil.com/support/docs/3213.htm
Merhaba,
Yine ilginç bir durumla karşı karşıyayım.Nedense beni buluyor hep.Konu C'de fonksiyonların aşırı yüklenmesine benzer bir durum.
Bir BSP var.Yine ST'nin. Kütüphanede herşey struct içinde yapılmış.Bir motor sürücü entegrenin (powerstep01) kontrolünü sağlayan bütün fonksiyonlar struct içinde fonksiyon pointer şeklinde.Sözde vatandaş nesne oluşturmuş.Sıkıntılı kısmı ve structın kendisi şöyle:
Bahsettiğim structın tür tanımı;
typedef struct
{
/// Function pointer to Init
void (*Init)(void*);
/// Function pointer to ReadID
uint16_t (*ReadID)(void);
/// Function pointer to AttachErrorHandler
void(*AttachErrorHandler)(void (*callback)(uint16_t));
/// Function pointer to AttachFlagInterrupt
void (*AttachFlagInterrupt)(void (*callback)(void));
/// Function pointer to AttachBusyInterrupt
void (*AttachBusyInterrupt)(void (*callback)(void));
/// Function pointer to FlagInterruptHandler
void (*FlagInterruptHandler)(void);
/// Function pointer to GetAcceleration
uint16_t (*GetAcceleration)(uint8_t);
/// Function pointer to GetCurrentSpeed
uint16_t (*GetCurrentSpeed)(uint8_t);
/// Function pointer to GetDeceleration
uint16_t (*GetDeceleration)(uint8_t);
/// Function pointer to GetDeviceState
motorState_t(*GetDeviceState)(uint8_t);
/// Function pointer to GetFwVersion
uint32_t (*GetFwVersion)(void);
/// Function pointer to GetMark
int32_t (*GetMark)(uint8_t);
/// Function pointer to GetMaxSpeed
uint16_t (*GetMaxSpeed)(uint8_t);
/// Function pointer to GetMinSpeed
uint16_t (*GetMinSpeed)(uint8_t);
/// Function pointer to GetPosition
int32_t (*GetPosition)(uint8_t);
/// Function pointer to GoHome
void (*GoHome)(uint8_t);
/// Function pointer to GoMark
void (*GoMark)(uint8_t);
/// Function pointer to GoTo
void (*GoTo)(uint8_t, int32_t);
/// Function pointer to HardStop
void (*HardStop)(uint8_t);
/// Function pointer to Move
void (*Move)(uint8_t, motorDir_t, uint32_t );
/// Function pointer to ResetAllDevices
void (*ResetAllDevices)(void);
/// Function pointer to Run
void (*Run)(uint8_t, motorDir_t);
/// Function pointer to SetAcceleration
bool(*SetAcceleration)(uint8_t ,uint16_t );
/// Function pointer to SetDeceleration
bool(*SetDeceleration)(uint8_t , uint16_t );
/// Function pointer to SetHome
void (*SetHome)(uint8_t);
/// Function pointer to SetMark
void (*SetMark)(uint8_t);
/// Function pointer to SetMaxSpeed
bool (*SetMaxSpeed)(uint8_t, uint16_t );
/// Function pointer to SetMinSpeed
bool (*SetMinSpeed)(uint8_t, uint16_t );
/// Function pointer to SoftStop
bool (*SoftStop)(uint8_t);
/// Function pointer to StepClockHandler
void (*StepClockHandler)(uint8_t deviceId);
/// Function pointer to WaitWhileActive
void (*WaitWhileActive)(uint8_t);
/// Function pointer to CmdDisable
void (*CmdDisable)(uint8_t);
/// Function pointer to CmdEnable
void (*CmdEnable)(uint8_t);
/// Function pointer to CmdGetParam
uint32_t (*CmdGetParam)(uint8_t, uint32_t);
/// Function pointer to CmdGetStatus
uint16_t (*CmdGetStatus)(uint8_t);
/// Function pointer to CmdNop
void (*CmdNop)(uint8_t);
/// Function pointer to CmdSetParam
void (*CmdSetParam)(uint8_t, uint32_t, uint32_t);
/// Function pointer to ReadStatusRegister
uint16_t (*ReadStatusRegister)(uint8_t);
/// Function pointer to ReleaseReset
[font=courier][color=red][b][i][u] void (*ReleaseReset)(uint8_t);[/u][/i][/b][/color][/font]
/// Function pointer to Reset
[font=courier][color=red][b][i][u] void (*Reset)(uint8_t);[/u][/i][/b][/color][/font]
/// Function pointer to SelectStepMode
bool (*SelectStepMode)(uint8_t deviceId, motorStepMode_t);
/// Function pointer to SetDirection
void (*SetDirection)(uint8_t, motorDir_t);
/// Function pointer to CmdGoToDir
void (*CmdGoToDir)(uint8_t, motorDir_t, int32_t);
/// Function pointer to CheckBusyHw
uint8_t (*CheckBusyHw)(void);
/// Function pointer to CheckStatusHw
uint8_t (*CheckStatusHw)(void);
/// Function pointer to CmdGoUntil
void (*CmdGoUntil)(uint8_t, motorAction_t, motorDir_t, uint32_t);
/// Function pointer to CmdHardHiZ
void (*CmdHardHiZ)(uint8_t);
/// Function pointer to CmdReleaseSw
void (*CmdReleaseSw)(uint8_t, motorAction_t, motorDir_t);
/// Function pointer to CmdResetDevice
void (*CmdResetDevice)(uint8_t);
/// Function pointer to CmdResetPos
void (*CmdResetPos)(uint8_t);
/// Function pointer to CmdRun
void (*CmdRun)(uint8_t, motorDir_t, uint32_t);
/// Function pointer to CmdSoftHiZ
void (*CmdSoftHiZ)(uint8_t);
/// Function pointer to CmdStepClock
void (*CmdStepClock)(uint8_t, motorDir_t);
/// Function pointer to FetchAndClearAllStatus
void (*FetchAndClearAllStatus)(void);
/// Function pointer to GetFetchedStatus
uint16_t (*GetFetchedStatus)(uint8_t);
/// Function pointer to GetNbDevices
uint8_t (*GetNbDevices)(void);
/// Function pointer to IsDeviceBusy
bool (*IsDeviceBusy)(uint8_t);
/// Function pointer to SendQueuedCommands
void (*SendQueuedCommands)(void);
/// Function pointer to QueueCommands
void (*QueueCommands)(uint8_t, uint8_t, int32_t);
/// Function pointer to WaitForAllDevicesNotBusy
void (*WaitForAllDevicesNotBusy)(void);
/// Function pointer to ErrorHandler
void (*ErrorHandler)(uint16_t);
/// Function pointer to BusyInterruptHandler
void (*BusyInterruptHandler)(void);
/// Function pointer to CmdSoftStop
void (*CmdSoftStop)(uint8_t);
/// Function pointer to StartStepClock
void (*StartStepClock)(uint16_t);
/// Function pointer to StopStepClock
void (*StopStepClock)(void);
/// Function pointer to SetDualFullBridgeConfig
void (*SetDualFullBridgeConfig)(uint8_t);
/// Function pointer to GetBridgeInputPwmFreq
uint32_t (*GetBridgeInputPwmFreq)(uint8_t);
/// Function pointer to SetBridgeInputPwmFreq
void (*SetBridgeInputPwmFreq)(uint8_t, uint32_t);
/// Function pointer to SetStopMode
void (*SetStopMode)(uint8_t, motorStopMode_t);
/// Function pointer to GetStopMode
motorStopMode_t (*GetStopMode)(uint8_t);
/// Function pointer to SetDecayMode
void (*SetDecayMode)(uint8_t, motorDecayMode_t);
/// Function pointer to GetDecayMode
motorDecayMode_t (*GetDecayMode)(uint8_t);
/// Function pointer to GetStepMode
motorStepMode_t (*GetStepMode)(uint8_t);
/// Function pointer to GetDirection
motorDir_t (*GetDirection)(uint8_t);
/// Function pointer to ExitDeviceFromReset
void (*ExitDeviceFromReset)(uint8_t);
/// Function pointer to SetTorque
void (*SetTorque)(uint8_t, motorTorqueMode_t, uint8_t);
/// Function pointer to GetTorque
uint8_t (*GetTorque)(uint8_t, motorTorqueMode_t);
/// Function pointer to SetVRefFreq
void (*SetRefFreq)(uint8_t, uint32_t);
/// Function pointer to GetVRefFreq
uint32_t (*GetRefFreq)(uint8_t);
/// Function pointer to SetVRefDc
void (*SetRefDc)(uint8_t, uint8_t);
/// Function pointer to GetVRefDc
uint8_t (*GetRefDc)(uint8_t);
/// Function pointer to SetNbDevices
bool (*SetNbDevices)(uint8_t);
/// Function pointer to SetAnalogValue
bool (*SetAnalogValue)(uint8_t, uint32_t, float);
/// Function pointer to GetAnalogValue
float (*GetAnalogValue)(uint8_t, uint32_t);
/// Function pointer to SetTorqueBoostEnable
void (*SetTorqueBoostEnable) (uint8_t, bool);
/// Function pointer to GetTorqueBoostEnable
bool (*GetTorqueBoostEnable) (uint8_t);
/// Function pointer to SetTorqueBoostThreshold
void (*SetTorqueBoostThreshold) (uint8_t, uint16_t);
/// Function pointer to GetTorqueBoostThreshold
uint16_t (*GetTorqueBoostThreshold) (uint8_t);
/// Function pointer to GetDualFullBridgeConfig
uint8_t (*GetDualFullBridgeConfig) (void);
}motorDrv_t;
Aşağıda bahsi geçen elemanı kırmızıyla işaretledim, eğik, altı çizik, kalın diye işaretledim.Ama code tagi içinde belli olur mu bilmem. Yukarıdaki yapıda isimler "ReleaseReset" ve "Reset", aşağıda ise "Powerstep01_Board_ReleaseReset" ve "Powerstep01_Board_Reset" fonksiyonları.
Bu da bu türden oluşturulan değişken:
motorDrv_t powerstep01Drv=
{
Powerstep01_Init, //void (*Init)(void*);
Powerstep01_ReadId, //uint16_t (*ReadID)(void);
Powerstep01_AttachErrorHandler, //void (*AttachErrorHandler)(void (*callback)(uint16_t));
Powerstep01_AttachFlagInterrupt, //void (*AttachFlagInterrupt)(void (*callback)(void));
Powerstep01_AttachBusyInterrupt, //void (*AttachBusyInterrupt)(void (*callback)(void));
Powerstep01_FlagInterruptHandler, //void (*FlagInterruptHandler)(void);
0, //uint16_t (*GetAcceleration)(uint8_t);
0, //uint16_t (*GetCurrentSpeed)(uint8_t);
0, //uint16_t (*GetDeceleration)(uint8_t);
0, //motorState_t(*GetDeviceState)(uint8_t);
Powerstep01_GetFwVersion, //uint32_t (*GetFwVersion)(void);
Powerstep01_GetMark, //int32_t (*GetMark)(uint8_t);
0, //uint16_t (*GetMaxSpeed)(uint8_t);
0, //uint16_t (*GetMinSpeed)(uint8_t);
Powerstep01_GetPosition, //int32_t (*GetPosition)(uint8_t);
Powerstep01_CmdGoHome, //void (*GoHome)(uint8_t);
Powerstep01_CmdGoMark, //void (*GoMark)(uint8_t);
Powerstep01_CmdGoTo, //void (*GoTo)(uint8_t, int32_t);
Powerstep01_CmdHardStop, //void (*HardStop)(uint8_t);
Powerstep01_CmdMove, //void (*Move)(uint8_t, motorDir_t, uint32_t );
0, //void (*ResetAllDevices)(void);
0, //void (*Run)(uint8_t, motorDir_t);
0, //bool(*SetAcceleration)(uint8_t ,uint16_t );
0, //bool(*SetDeceleration)(uint8_t , uint16_t );
Powerstep01_SetHome, //void (*SetHome)(uint8_t);
Powerstep01_SetMark, //void (*SetMark)(uint8_t);
0, //bool (*SetMaxSpeed)(uint8_t, uint16_t );
0, //bool (*SetMinSpeed)(uint8_t, uint16_t );
0, //bool (*SoftStop)(uint8_t);
0, //void (*StepClockHandler)(uint8_t deviceId);
Powerstep01_WaitWhileActive, //void (*WaitWhileActive)(uint8_t);
0, //void (*CmdDisable)(uint8_t);
0, //void (*CmdEnable)(uint8_t);
Powerstep01_CmdGetParam, //uint32_t (*CmdGetParam)(uint8_t, uint32_t);
Powerstep01_CmdGetStatus, //uint16_t (*CmdGetStatus)(uint8_t);
Powerstep01_CmdNop, //void (*CmdNop)(uint8_t);
Powerstep01_CmdSetParam, //void (*CmdSetParam)(uint8_t, uint32_t, uint32_t);
Powerstep01_ReadStatusRegister, //uint16_t (*ReadStatusRegister)(uint8_t);
Powerstep01_ReleaseReset, //void (*ReleaseReset)(uint8_t);
Powerstep01_Reset, //void (*Reset)(uint8_t);
Powerstep01_SelectStepMode, //bool (*SelectStepMode)(uint8_t deviceId, motorStepMode_t);
0, //void (*SetDirection)(uint8_t, motorDir_t);
Powerstep01_CmdGoToDir, //void (*CmdGoToDir)(uint8_t, motorDir_t, int32_t);
Powerstep01_CheckBusyHw, //uint8_t (*CheckBusyHw)(void);
Powerstep01_CheckStatusHw, //uint8_t (*CheckStatusHw)(void);
Powerstep01_CmdGoUntil, //void (*CmdGoUntil)(uint8_t, motorAction_t, motorDir_t, uint32_t);
Powerstep01_CmdHardHiZ, //void (*CmdHardHiZ)(uint8_t);
Powerstep01_CmdReleaseSw, //void (*CmdReleaseSw)(uint8_t, motorAction_t, motorDir_t);
Powerstep01_CmdResetDevice, //void (*CmdResetDevice)(uint8_t);
Powerstep01_CmdResetPos, //void (*CmdResetPos)(uint8_t);
Powerstep01_CmdRun, //void (*CmdRun)(uint8_t, motorDir_t, uint32_t);
Powerstep01_CmdSoftHiZ, //void (*CmdSoftHiZ)(uint8_t);
Powerstep01_CmdStepClock, //void (*CmdStepClock)(uint8_t, motorDir_t);
Powerstep01_FetchAndClearAllStatus, //void (*FetchAndClearAllStatus)(void);
Powerstep01_GetFetchedStatus, //uint16_t (*GetFetchedStatus)(uint8_t);
Powerstep01_GetNbDevices, //uint8_t (*GetNbDevices)(void);
Powerstep01_IsDeviceBusy, //bool (*IsDeviceBusy)(uint8_t);
Powerstep01_SendQueuedCommands, //void (*SendQueuedCommands)(void);
Powerstep01_QueueCommands, //void (*QueueCommands)(uint8_t, uint8_t, int32_t);
Powerstep01_WaitForAllDevicesNotBusy,//void (*WaitForAllDevicesNotBusy)(void);
Powerstep01_ErrorHandler, //void (*ErrorHandler)(uint16_t);
Powerstep01_BusyInterruptHandler, //void (*BusyInterruptHandler)(void);
Powerstep01_CmdSoftStop, //void (*CmdSoftStop)(uint8_t);
Powerstep01_StartStepClock, //void (*StartStepClock)(uint16_t);
Powerstep01_StopStepClock, //void (*StopStepClock)(void);
0, //void (*SetDualFullBridgeConfig)(uint8_t);
0, //uint32_t (*GetBridgeInputPwmFreq)(uint8_t);
0, //void (*SetBridgeInputPwmFreq)(uint8_t, uint32_t);
0, //void (*SetStopMode)(uint8_t, motorStopMode_t);
0, //motorStopMode_t (*GetStopMode)(uint8_t);
0, //void (*SetDecayMode)(uint8_t, motorDecayMode_t);
0, //motorDecayMode_t (*GetDecayMode)(uint8_t);
0, //motorStepMode_t (*GetStepMode)(uint8_t);
0, //motorDir_t (*GetDirection)(uint8_t);
0, //void (*ExitDeviceFromReset)(uint8_t);
0, //void (*SetTorque)(uint8_t, motorTorqueMode_t, uint8_t);
0, //uint8_t (*GetTorque)(uint8_t, motorTorqueMode_t);
0, //void (*SetRefFreq)(uint8_t, uint32_t);
0, //uint32_t (*GetRefFreq)(uint8_t);
0, //void (*SetRefDc)(uint8_t, uint8_t);
0, //uint8_t (*GetRefDc)(uint8_t);
Powerstep01_SetNbDevices, //bool (*SetNbDevices)(uint8_t);
Powerstep01_SetAnalogValue, //bool (*SetAnalogValue)(uint8_t, uint32_t, float);
Powerstep01_GetAnalogValue //float (*GetAnalogValue)(uint8_t, uint32_t);
};
Bu da yapı içinde adresi gösterilen fonksiyonların kendisi:
/******************************************************//**
* @brief Releases the powerSTEP01 reset (pin set to High) of all devices
* @retval None
**********************************************************/
void Powerstep01_Board_ReleaseReset(void)
{
HAL_GPIO_WritePin(BSP_MOTOR_CONTROL_BOARD_STBY_RESET_PORT, BSP_MOTOR_CONTROL_BOARD_STBY_RESET_PIN, GPIO_PIN_SET);
}
/******************************************************//**
* @brief Resets the powerSTEP01 (reset pin set to low) of all devices
* @retval None
**********************************************************/
void Powerstep01_Board_Reset(void)
{
HAL_GPIO_WritePin(BSP_MOTOR_CONTROL_BOARD_STBY_RESET_PORT, BSP_MOTOR_CONTROL_BOARD_STBY_RESET_PIN, GPIO_PIN_RESET);
}
Bu fonksiyonların bulunduğu .c dosyasındaki fonksiyon tanımlamaları şöyle:
void Powerstep01_Board_ReleaseReset(void); //Reset the powerSTEP01 reset pin
void Powerstep01_Board_Reset(void); //Set the powerSTEP01 reset pin
Bu da başka bir isimdeki .h dosyası içinde aynı fonksiyonlara ait tanımlama:
extern void Powerstep01_Board_ReleaseReset(uint8_t deviceId); //Reset the powerSTEP01 reset pin
extern void Powerstep01_Board_Reset(uint8_t deviceId); //Set the powerSTEP01 reset pin
Dikkat ettiyseniz iki farklı tanımlama mevcut.Tanımların birinde fonksiyonlar void iken diğerinde parametre alıyor. Oysa struct tür tanımı içinde de .h dosyasında tanımlandığı gibi parametre alıyor. Ancak fonksiyonun kendisinden bir tane var ve o da parametre almıyor. Void.
Peki nasıl oluyor da bu adam bu proje dosyasını derlediğinde hiçbir hata almıyor da ben derlediğimde bana kızıp bu fonksiyondan falan dosyada da var ve tanımlar birbiriyle uyuşmuyor deyip hata veriyor.Şöyleki:
..\BSP\STM32L0xx_Nucleo\stm32f103_stepper.c(93): error: #147-D: declaration is incompatible with "void Powerstep01_Board_ReleaseReset(uint8_t)" (declared at line 988 of "..\BSP\Components\powerstep01\powerstep01.h")
void Powerstep01_Board_ReleaseReset(void); //Reset the powerSTEP01 reset pin
..\BSP\STM32L0xx_Nucleo\stm32f103_stepper.c(94): error: #147-D: declaration is incompatible with "void Powerstep01_Board_Reset(uint8_t)" (declared at line 989 of "..\BSP\Components\powerstep01\powerstep01.h")
void Powerstep01_Board_Reset(void); //Set the powerSTEP01 reset pin
Konu gücenlliğini koruyor. Halen bir cevap bulabilmiş değilim.Konuyla ilgili dikkatimi çeken bir durum var.
Keil IDE üzerinden "Options For Target altında, C/C++ sekmesinde "Misc Controls" kısmında "--C99" tanımı var.Bu da keil yardım dosyasından anladığım kadarıyla derleyiciye C99 moduyla derleme yapmasını söylüyor. Bir de "Linker" sekmesinde yine "Misc Controls" kısmındaki "--diag_suppress=L6329" tanımı var.Bu ise linkere bazı warningleri bastırmasını söylüyor. Aslında tam anlamadım ama söylediği Compiler 5 için:
L6329W: Pattern <module>(<section>) only matches removed unused sections.
All sections matching this pattern have been removed from the image because they were unused. For more information, use --info unused.
See the following in the armlink User Guide:
Elimination of unused sections.
--info=topic[,topic,...].
Compiler 6 için ise:
L6329W: Pattern <module>(<section>) only matches removed unused sections.
All sections matching this pattern have been removed from the image because they were unused. For more information, use --info unused.
See the following in the armlink User Guide:
Elimination of unused sections.
--info=topic[,topic,...].
Bir de benim bahsettiğim projedeki kod L6329 ancak burada bulduğum ise L6329W. Bütün bunlardan sonra, nasıl oluyor da bu hatayı örnek aldığım proje dosyasında derleme yaptığımda almıyorum da ben farklı bir mcu ile stdlib kullanarak ve bütün bu mesajda bahsettiklerimi de eklememe rağmen ben alıyorum.
Hocam linkteki örneği http://www.wolinlabs.com/blog/stm32f4.adc.dsp.dac.html
Embitz 1.1 ile derlendiğinde hatasız uyarı vermeden derliyor.
Keil ile derlendiğinde ;
1- C mode 99 seçili değil diğer c dosyaları ekli ise 9 Error, 3 Warning veriyor.
(https://s29.postimg.cc/gdkzrlz2r/image.gif) (https://postimg.cc/image/gdkzrlz2r/)
2- C mode 99 seçili değil diğer c dosyaları ekli değil ise 1 Error ,1 Waring veriyor.
(https://s23.postimg.cc/jj84a4ydz/image.gif) (https://postimg.cc/image/jj84a4ydz/)
3-C mode 99 seçili diğer c dosyaları ekli değil ise 8 Error ,2 Warning veriyor.
(https://s30.postimg.cc/o2pvhvpul/image.gif) (https://postimg.cc/image/o2pvhvpul/)
4-C mode 99 seçili ,diğer c dosyaları ekli ise 0 Error, 3 Warning veriyor. Kite yüklendiğinde hatasız çalışıyor.
(https://s29.postimg.cc/mzkn02vhv/image.gif) (https://postimg.cc/image/mzkn02vhv/)
C mode 99 önemli bir özellikmiş.
Teşekkürler.
Merhabalar, C'nin hangi türüne mutaassıp olduğunu bilmiyorum ama şu tür bir yazım ile karşılaştım ne anlama geliyor, ne amaçla kullanılıyor bilmiyorum. Aşağıda buluna kod parçasında parantezler ne bir if ne de herhangi bir döngü için kullanılmış bu süslü parantezlerin kullanım amacı nedir ?
int16_t data;
{
int16_t data;
data = 3;
}
Alıntı yapılan: unknownperson - 29 Eylül 2017, 14:09:31
Merhabalar, C'nin hangi türüne mutaassıp olduğunu bilmiyorum ama şu tür bir yazım ile karşılaştım ne anlama geliyor, ne amaçla kullanılıyor bilmiyorum. Aşağıda buluna kod parçasında parantezler ne bir if ne de herhangi bir döngü için kullanılmış bu süslü parantezlerin kullanım amacı nedir ?
int16_t data;
{
int16_t data;
data = 3;
}
Yanlış yazılmış. Belki bir if statement vardı fakat onu silip braketleri silmeyi unutmuş olabilir. Braketleri öyle bir kullanımı yok yani.
Yanlış değil.
Ona blok açmak deniyordu sanırım.
"C ile Programlama Prof.Dr.Mitat Uysal"
2.Baskı Sayfa 209
Kısaca değişken tanımlandığı blok dışında kullanılamaz.
Alıntı yapılan: unknownperson - 29 Eylül 2017, 14:09:31
Merhabalar, C'nin hangi türüne mutaassıp olduğunu bilmiyorum ama şu tür bir yazım ile karşılaştım ne anlama geliyor, ne amaçla kullanılıyor bilmiyorum. Aşağıda buluna kod parçasında parantezler ne bir if ne de herhangi bir döngü için kullanılmış bu süslü parantezlerin kullanım amacı nedir ?
int16_t data;
{
int16_t data;
data = 3;
}
Scope yaratmada kullanilir. Bazen belli degiskenlerin kisa omurlu olsun, bir scope icinde kalsin isteyebilirsin.
Misal:
#include "stdio.h"
int main()
{
int num = 0;
printf("num: %d\n", num);
{
int num = 0;
num = 5;
printf("num: %d\n", num);
}
printf("num: %d\n", num);
}
Bu kod parcasi asagidaki ciktiyi verecektir:
num: 0
num: 5
num: 0
Farkettiysen 5 degerini atadigimiz "num" degiskeni scope'un disina ciktiginda ucup gitti.
Ayni kodu asagidaki gibi degistirirsek:
#include "stdio.h"
int main()
{
int num = 0;
printf("num: %d\n", num);
{
int num1 = 0;
num = 5;
printf("num: %d\n", num);
}
printf("num1: %d\n", num1);
}
Soyle bir hata alirsin:
aaa.c:12:24: error: use of undeclared identifier 'num1'; did you mean 'num'?
printf("num1: %d\n", num1);
^~~~
num
aaa.c:5:7: note: 'num' declared here
int num = 0;
^
Burada kendi olusturdugumuz kucuk scope icinde "num" degiskenine erisip onu degistirmekte sorun yok. Ancak, en sondaki printf "num1"in degerini yazmaya calisiyor. C dilinde degiskenler tanimli olduklari scope araliginda varolurlar. Yani buradaki hata "num1"e scope disinda erismeye calismak.
Tabi verdigin kod cok eski bir kod ise pre-ANSI C donemlerinde baska bir kullanimi daha var {}'in ama bosuna kafa sisirmeyelim :)
Çok iyi anlatmışsınız aslında kodu biraz salladım başka bir yerde görmüştüm bu iki parantez arası işlem yaptırıyordu. Ben de sizin dediğiniz gibi tahmin etmiştim parantezler arası tanımlı oluyor diye. Fakat bu dediğim süslü parantezler sık kullanılıyor genelde main boardlarda. Sizin dediğinize göre sanırım sadece o parantezler arası tanımlı olduğundan oradan çıkınca değer uçuyor ve az hafıza kullanıyor şeklinde yani az alan kapsaması için mi kullanılıyor ? Yoksa başka amaçlar içinde kullanılabilir mi mesela pre-ANSI C 'den az bahsedebilir misiniz ?
Evet bir degiskenin run-time omrunu azaltmak icin scope kullanabilirsin/kullanmalisin. Scope disina ciktiginda stack'ten silinirler. Boylece RAM'den birazcik kar edersin :)
Ya da ayni kod parcasini ya da degisken ismini tekrar kullanmak istiyorsan o kod parcasini/degisken tanimlamasini kopyalayip {} icine koyabilirsin. Boylece bir sikinti olmaz.
Yanlis hatirlamiyorsam pre-ANSI C'de fonksiyonlar soyle tanimlaniyordu.
int sum(a, b)
int a;
int b;
{
return a+b;
}
Soyle de bir durum var C99 standardi oncesinde kafana gore bir yerde degisken tanimlayamazsin. Bir scope'un en basinda tanimlaman gerekir.
Mesela asagidaki kodu C90 standardi ile derleyelim:
int main()
{
int x1 = 1;
x1 = 5;
int x2 = 3;
printf("Sum: %d\n", x1 + x2);
return 0;
}
Asagidaki gibi bir uyari aliriz:
aaa.c:7:7: error: ISO C90 forbids mixing declarations and code [-Werror,-Wdeclaration-after-statement]
int x2 = 3;
^
Ama bir scope olusturup bunun en basinda tanimlarsan bir sorun olmaz. Bu arada scope olusturmak icin illa basi bos {} yapmaya gerek yok. Bir if{} de bir scope'dur, bir while(){} da.
Kodu asagidaki gibi degistirelim:
int main()
{
int x1 = 1;
x1 = 5;
if (x1 >5) {
int x2 = 3;
printf("Sum: %d\n", x1 + x2);
}
return 0;
}
Gordugun gibi burada if ile bir scope olusturup, en basinda degiskenimi tanimladim. Derleyince herhangi bir hata vermedi. He bana inanmaz da kendin derlemek istersen :) ve gcc kullaniyorsan:
--pedantic-errors
flag'i ile derlemen gerekir. Yoksa gcc'yi C80-90 standardi kullanmaya zorlayamazsin.
Çok çok yararlı oldu
@vitruvius hocam, anlatım için teşekkür ederim :D
Yanlış yere yazıldı.
yeni birşey daha öğrenmiş oldum. Ama bu nasıl kullanılır pek aklım kesmedi işin açığı.
-
İlk değer verilmemiş ya da bir atama yapılmamış değişkenlerin davranışını aşağıdaki gibi öğrenmiştim.
Yerel Değişken-> Çöp bir değer ile başlar (O an bellekte o değişken için ayrılmış yerde bulunan 1 ve 0 bitlerinin oluşturduğu değer)
Statik Yerel Değişken , Global Değişken -> Sıfır değeri ile başlaması derleyici tarafından sağlanır.
Şimdi aşağıdaki programı Borland Dev C++ 5.4 ile derlediğimde görüyorum ki , hem yerel değişken hem de global değişken SIFIR değeri ile başlamış.Global değişkenim için bu değer(SIFIR) doğru fakat yerel değişken içinde çöp bir değer olması gerekmez mi?
#include<stdio.h>
int globalVariable;
int main(void){
int localVariable;
printf("LocalV: %d\n",localVariable);
printf("GlobalV: %d",globalVariable);
return 0;
}
(https://i.hizliresim.com/rO8L0P.jpg)
Alıntı yapılan: l0rd - 26 Ocak 2018, 18:45:06
İlk değer verilmemiş ya da bir atama yapılmamış değişkenlerin davranışını aşağıdaki gibi öğrenmiştim.
Yerel Değişken-> Çöp bir değer ile başlar (O an bellekte o değişken için ayrılmış yerde bulunan 1 ve 0 bitlerinin oluşturduğu değer)
Statik Yerel Değişken , Global Değişken -> Sıfır değeri ile başlaması derleyici tarafından sağlanır.
Şimdi aşağıdaki programı Borland Dev C++ 5.4 ile derlediğimde görüyorum ki , hem yerel değişken hem de global değişken SIFIR değeri ile başlamış.Global değişkenim için bu değer(SIFIR) doğru fakat yerel değişken içinde çöp bir değer olması gerekmez mi?
#include<stdio.h>
int globalVariable;
int main(void){
int localVariable;
printf("LocalV: %d\n",localVariable);
printf("GlobalV: %d",globalVariable);
return 0;
}
(https://i.hizliresim.com/rO8L0P.jpg)
Cop derken? O an o hafiza alaninda ne varsa onu alir. Demek ki sifir varmis. C Standardini acip bakarsan:
C99 standardi, 6.7.8 Initialization der ki:
Alıntı YapIf an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static storage duration is not initialized explicitly, then:
— if it has pointer type, it is initialized to a null pointer;
— if it has arithmetic type, it is initialized to (positive or unsigned) zero;
— if it is an aggregate, every member is initialized (recursively) according to these rules;
— if it is a union, the first named member is initialized (recursively) according to these rules.
Alıntı yapılan: vitruvius - 26 Ocak 2018, 19:29:07
Cop derken? O an o hafiza alaninda ne varsa onu alir. Demek ki sifir varmis. C Standardini acip bakarsan:
C99 standardi, 6.7.8 Initialization der ki:
Sanırım dediğiniz ki .. SAĞOLUN ( aşağıda sağlamasını yapmaya çalıştım )
(https://image.ibb.co/bQuxGw/1.jpg)
(https://image.ibb.co/ceZa3b/2.jpg)
Struct türünden bir pointer tanımladım ve pointer ile struct elemanlarına erişmeyi denedim . Yazdığım test programı aşağıdadır .
1.char 0x000000000062FE30 adresinden baslamıs 0x000000000062FE34 adresinde bitmis yani 4 byte , diğer türler içinde bu geçerli olmuş.(Ekran görüntüsü 2 ye bakabilirsiniz) Neden 4 byte ? Ben 1 byte diye biliyordum..
2.Struct içindeki elemanların adreslerini * operatörü ve & operatörünü aynı anda kullanmadan nasıl gösterebiliriz ? Yani &(*pointer).eleman seklinde kullanmadan?
ben pointer.eleman denedim hata verdi , *pointer.eleman denedim olmadıı...
#include<stdio.h>
int main(void){
struct myStr {
char myChVar;
int myIntVar;
float myFltVar;
}myStrVar={'k',50,5.4} , *myPtrVar;
myPtrVar=&myStrVar;
printf("Degisken ile erisim Ch:%c Int:%d Flt:%f \n",myStrVar.myChVar,myStrVar.myIntVar,myStrVar.myFltVar);
printf("Gosterici ile erisim Ch:%c Int:%d Flt:%f \n",myPtrVar->myChVar,myPtrVar->myIntVar,myPtrVar->myFltVar);
printf("Struct un adresi:%p \n",myPtrVar);
printf("Elemanlarin adresleri(degiskenin adresi ile erisim) Ch:%p Int:%p Flt:%p \n",&myStrVar.myChVar,&myStrVar.myIntVar,&myStrVar.myFltVar);
printf("Elemanlarin adresleri(Gosterici ile erisim) Ch:%p Int:%p Flt:%p",&(*myPtrVar).myChVar,&(*myPtrVar).myIntVar,&(*myPtrVar).myFltVar);
return 0;
}
(https://i.hizliresim.com/oO8ZMb.jpg)
(https://i.hizliresim.com/azMD64.jpg)
Char 8bit, İnt 16 bit, Float 32 bit değişkenlerdir. Senin verileri tuttuğun bellek kaç bit işe ona göre bellek adreslerine yerleşirler. Bu ne demek. Misal bellek 8 bit işe, char 1 adrese int 2 adrese, float 4 adrese yayılır, toplam adres sayısı 7 olur.
Struct pointer in elemanlarına -> operatörü ile erişebilirsin.
Alıntı yapılan: l0rd - 27 Ocak 2018, 00:21:04
Struct türünden bir pointer tanımladım ve pointer ile struct elemanlarına erişmeyi denedim . Yazdığım test programı aşağıdadır .
1.char 0x000000000062FE30 adresinden baslamıs 0x000000000062FE34 adresinde bitmis yani 4 byte , diğer türler içinde bu geçerli olmuş.(Ekran görüntüsü 2 ye bakabilirsiniz) Neden 4 byte ? Ben 1 byte diye biliyordum..
2.Struct içindeki elemanların adreslerini * operatörü ve & operatörünü aynı anda kullanmadan nasıl gösterebiliriz ? Yani &(*pointer).eleman seklinde kullanmadan?
ben pointer.eleman denedim hata verdi , *pointer.eleman denedim olmadıı...
1) Adreslere bakip bir elemanin adresi 62FE30'dan basliyor, bir sonraki eleman da 62FE34'ten basliyor diye onceki elemanin 4 byte kapladigini soylemek yanlis olur. Detayli bilgi icin Byte Alignment konusunu buradan (https://wr.informatik.uni-hamburg.de/_media/teaching/wintersemester_2013_2014/epc-14-haase-svenhendrik-alignmentinc-paper.pdf) okuyabilirsin.
2) Bir degiskenin adresine ulasmak istiyorsan & operatorunu kullanmalisin.
Merhaba
Yazdıkların ile bilgisayarının 64 bit lik işletim sisteminde bellekte ayrılmış yapı nesnelerinin adreslerini görüyorsun. Bu arada Dikkat et belirsiz adreslere yazacağın bilgiler sistemini çökertebilir. Malloc gibi fonksiyonları kullanmanı tavsiye ediyorum.
Eğer pic, arm, atmel...vs gibi işlemciler ile program yazmak istiyorsan ki bu forumda sana yardımcı olan üstadların ana bilim dalılarıdır o halde seçeceğin çip ile uyumlu derleyici ! İle çalışmalısın.
Bu konuda forum senin temel kaynağın olsun.
Sevgiler
Alıntı yapılan: vitruvius - 27 Ocak 2018, 13:52:32
1) Adreslere bakip bir elemanin adresi 62FE30'dan basliyor, bir sonraki eleman da 62FE34'ten basliyor diye onceki elemanin 4 byte kapladigini soylemek yanlis olur. Detayli bilgi icin Byte Alignment konusunu buradan (https://wr.informatik.uni-hamburg.de/_media/teaching/wintersemester_2013_2014/epc-14-haase-svenhendrik-alignmentinc-paper.pdf) okuyabilirsin.
2) Bir degiskenin adresine ulasmak istiyorsan & operatorunu kullanmalisin.
Teşekkürler verdiğiniz kaynaktaki padding kavramını okudum ve neden 4byte olduğunu anladım..Ama 2. soruda demek istediğim struct içindeki herhangi bir elemanın adrese erişmek için &(*structpointer).eleman dışında bir kullanımın olup olmadığı ?
Alıntı yapılan: Pyrodigy - 27 Ocak 2018, 14:52:11
Merhaba
Yazdıkların ile bilgisayarının 64 bit lik işletim sisteminde bellekte ayrılmış yapı nesnelerinin adreslerini görüyorsun. Bu arada Dikkat et belirsiz adreslere yazacağın bilgiler sistemini çökertebilir. Malloc gibi fonksiyonları kullanmanı tavsiye ediyorum.
Eğer pic, arm, atmel...vs gibi işlemciler ile program yazmak istiyorsan ki bu forumda sana yardımcı olan üstadların ana bilim dalılarıdır o halde seçeceğin çip ile uyumlu derleyici ! İle çalışmalısın.
Bu konuda forum senin temel kaynağın olsun.
Sevgiler
teşekkürler , haklısınız bir denetleyici alıp onun üzerinde denemeler yapmak mantıklı
#include<stdio.h>
int main()
{
unsigned short uSh; //2byte
char ch; //1byte
uSh=0xFF10;
ch=uSh;
printf("uSh: %d , Ch:%d",uSh,ch); //uSh:65296 Ch:16
return 0;
}
#include<stdio.h>
int main()
{
unsigned short uSh; //2byte
char ch; //1byte
uSh=0xFF10;
ch=(char)uSh;
printf("uSh: %d , Ch:%d",uSh,ch); //uSh:65296 Ch:16
return 0;
}
Bu iki program arasında fark nedir?Tür dönümü yapsam da yapmasam da aynı sonucu alıyorum..
Alıntı yapılan: l0rd - 28 Ocak 2018, 13:19:56
Bu iki program arasında fark nedir?Tür dönümü yapsam da yapmasam da aynı sonucu alıyorum..
Cunku C99 Standardi, 6.5.16.1 Simple assignment, Semantics, Madde 2 der ki:
Alıntı YapIn simple assignment (=), the value of the right operand is converted to the type of the assignment expression and replaces the value stored in the object designated by the left operand.
#include<stdio.h>
int main(){
int num1=1,num2=2;
float div;
div=num1/num2;
printf("%f",div);
}
#include<stdio.h>
int main(){
int num1=1,num2=2;
float div;
div=(float)num1/num2;
printf("%f",div);
}
Ozaman bu iki programın sonucunun aynı çıkmamasının sebebi (yani C99 a göre sağ taraf değerinin ,sol taraf değerinin türüne değiştirildikten sonra, sol taraf değerinde depolanmamasının sebebi) Eşittir(=) ifadesinden sonra bir işlem olması mı?
"simle assignment" demek verdiğim örneklerdeki gibi mi ( sadece sol taraf deferi = sağ taraf değeri olan)
a=b;
a=45;
a=0x055F;
int* ptr
ptr=5; Burada int türünü (int *) türüne atarken
Alıntı yapılan: l0rd - 28 Ocak 2018, 16:12:19
Ozaman bu iki programın sonucunun aynı çıkmamasının sebebi (yani C99 a göre sağ taraf değerinin ,sol taraf değerinin türüne değiştirildikten sonra, sol taraf değerinde depolanmamasının sebebi) Eşittir(=) ifadesinden sonra bir işlem olması mı?
Oradaki durum farkli. Arithmetic bir islem var orda. Onun icin standardin farkli bir bolumunu okuman lazim (6.3.1 Arithmetic Operands). Kisaca, ilk orneginde integer division var. Iki integer sayiyi bolersen sonuc olarak integer elde edersin. Ikinci orneginde float bir sayiyi integer bir sayiya boluyorsun, bu yuzden sonuc olarak float bir deger elde ediyorsun.
Compiler'lar her islem icin gerekli degisken turunu hesaplar ve aksi belirtilmezse gerekli gordugu yerde buna gore kendisi cast islemi yapar (implicit cast). Bunlari gormek her zaman kolay olmayabilir ve bulmasi zor hatalara sebep olabilir. Bu konulari daha iyi anlaman icin implicit cast, integer promotions, conversions, arithmetic operands gibi konulari her sabah kahvaltidan sonra okumani tavsiye ederim.
Alıntı yapılan: vitruvius - 28 Ocak 2018, 21:39:16
Oradaki durum farkli. Arithmetic bir islem var orda. Onun icin standardin farkli bir bolumunu okuman lazim (6.3.1 Arithmetic Operands). Kisaca, ilk orneginde integer division var. Iki integer sayiyi bolersen sonuc olarak integer elde edersin. Ikinci orneginde float bir sayiyi integer bir sayiya boluyorsun, bu yuzden sonuc olarak float bir deger elde ediyorsun.
Compiler'lar her islem icin gerekli degisken turunu hesaplar ve aksi belirtilmezse gerekli gordugu yerde buna gore kendisi cast islemi yapar (implicit cast). Bunlari gormek her zaman kolay olmayabilir ve bulmasi zor hatalara sebep olabilir. Bu konulari daha iyi anlaman icin implicit cast, integer promotions, conversions, arithmetic operands gibi konulari her sabah kahvaltidan sonra okumani tavsiye ederim.
Teşekkür ederim , öğrenecek çok şey varmış :) bunları da araya sıkıştıracağım
(int *) türden bir pointer tanımlayalım , tanımladığımız bu pointerı artırıp azalttığımızda bize güvenli hafıza bölgesinden mi yer ayırır ? Bir sonraki/bir önceki adresin kullanılabilirlik durumu/reserved durumu vs bakar mı?
mesela şöyle bir program olsun
#include<stdio.h>
#define COUNT 2
int main(void){
int sayi;
int i=0;
int *ptr;
ptr=&sayi;
while(i<COUNT){
printf("sayi gir\n");
scanf("%d",ptr);
printf("girilen sayi %d \n",*ptr);
++ptr;
}
return 0;
}
burada ++p yaparak bir sonraki adrese yeni bir değer girdim , o adresin güvenlilik durumu nedir?
Yok bakmaz, sıradakine yazmaya çalışır ve her türlü probleme müsaittir. Eğer COUNT değerin int boyutundan büyük olsaydı tehlike başlamıştı diyebiliriz.
Burada stack boyutu ile ilgili bir sorun çıkabilir.
İşin kısacası yazılmaması gereken bir kod
(https://i.hizliresim.com/76gWQP.jpg)
Alıntı yapılan: SpeedyX - 01 Şubat 2018, 20:28:51
Eğer COUNT değerin int boyutundan büyük olsaydı tehlike başlamıştı diyebiliriz.
COUNT:2 ve int türü 4byte olduğu için bir sonraki eleman 4 byte sonrasına yerleşecek.Yani 1 integer saklayacak alanı aştık bile. Sormak istediğim bir sonraki integer in saklanacağı alanın güvenilirliğiydi , sanırım emin olamıyoruz o alanın güvenilirliği hakkında..
Alıntı yapılan: mir_as82 - 01 Şubat 2018, 22:57:01
Burada stack boyutu ile ilgili bir sorun çıkabilir.
her eleman için 4 byte ayıracak , boyut sınırı olmacağını düşünmüyorumda.Bu yer derleyici tarafından ayrılmıyor mu da güvensiz orayı anlayamadım.
Mesela yukarıdaki programda 000000000062FE44 adresi derleyici tarafından ayrılıyor bundan eminim ve orası güvenli (kitapta okumustum) ama adresi bir artırdığımda elde ettiğimiz 000000000062FE48 adresini ben belirlemiş oldum , derleyici belirlemediği için güvensiz olma ihtimali olabilir mi?
Sonraki adres, başka bir değişken için ayrılmış bir alan olabileceği gibi geçersiz bir adres de olabilir yada iyi ihtimalle kullanılmayan geçerli bir adres olabilir.
Hocam benim tahminim, senin son tanımladığın değişken int *ptr olduğu için veya döngün az sayıda olduğu için sorun olmuyor. Onun için başka değişkenleri ezmiyor. Bunu denemek için döngü sayısını arttırıp deneyin.
Daha sonra int *ptr yi programın en başında tanımlayın daha sonra ondan sonra değişken tanımlarsanız ve onlara değerler verirseniz o değişkenleri ezeceğiniz aşikar bellidir.
Selamlar
STM32'de STRTOL fonksiyonunu kullanmam gerekti ama bir sorun yaşıyorum. STM32 çipimde Usart Kesmesi Timer Kesmesi gibi donanımlar çalışıyor bazı rutin işler yapıyorum. Uart Üzerinden String olarak Hexadesimal veriler alıyorum. "55", "A7" gibi. Bu değerleri integer türünde hexadesimal değerlere çevirmem gerekiyor. Bunun için STRTOL fonksiyonunu kullandım. Aşağıdaki gibi bir kullanımı var.
Addr=strtol(substr,NULL,16);
Tek başına iyi çalışıyor fakat timer kesmesi geldiği anda işlemci hardfaulta düşüyor. Kesmelerle birlikte çalışmıyor bu fonksiyon.
Bu neden olur daha önce başına gelen varmı? Bu fonksiyonun yaptığı işi kendim sade bir şekilde nasıl yaparım?
Ekleme: Gerek Kalmadı Kendim benzer bir fonksiyon yazarak hallettim.
string halde gelen hexadesimal verileri integere dönüştüren programç
uint8_t mystrtol(char *ptr)
{
uint8_t asciint=0,sayi=0;
while (*ptr!='\0')
{
if(*ptr>='0' && *ptr<='9')
{
asciint=*ptr-48;
}
else if(*ptr>='A' && *ptr<='F')
{
asciint=(10+*ptr-65);
}
else
{
asciint=0;
}
sayi=sayi*16+asciint;
ptr++;
}
return sayi;
}
prototipi bu mu? strtol long int strtol(const char *nptr, char **endptr, int base)
exception firlatiyor olabilir mi? veya basarili bir sekilde geri donup donmedigine bakiyor musun? veya hatali bir degeri dondurdugunden dolayi islemci ben oynamiyorum moduna giriyor olabilir mi?
Evet prototipi o şekilde. Yazdığım kod anlık ürettiğim çözümdü, Çalışıyor.
Sorunun sebebini aslında anlayamadım. Çünkü İşlemci içerisinde Herhangi bir kesme açık değilken fonksiyon aynı şekilde çalışıyor. Fakat kesmeler açık iken fonksiyonu çalıştırsam işlemci çalışmayı bırakıyor.
gömülü tarafta string fonksiyonları kullanılmaz.Bu fonksiyonlarda memset ve free oldugundan islemci çakılır.Dolayısılya memset ile bellekten dinamik yer alıp free ile sürekli verirseniz gene hardfaulta düsebilirsiniz.Bunun dısında NULL bellek adresine değer yazmak ve arrayin dısına çıkmak da hardfault sebebidir.Memcpy dısında fonksiyon kullanmasını onermem.
Addr=strtol(substr,NULL,16);
Yukarıdaki kullanım hatalı. Null değil substr'ın kendisini veya bir başka char pointer vermelisin fonksiyona.
Diyelim ki elinde şöyle bir data var; char * aaa= "123 456 252". Burada sayıları teker teker sıralı olarak int e dönüştürmek için fonksiyon 123'ü dönüştürdükten sonra kaldığı yer için 2. pointerı kullanıyor. Senin durumunda 0x00 a yazmaya çalışıyor ve mcu ve hard faulta düşüyor.
Addr=strtol(substr,substr,16); şeklinde kullanmalısın.
Alıntı yapılan: kantirici - 11 Mart 2018, 16:49:16
Addr=strtol(substr,NULL,16);
Yukarıdaki kullanım hatalı. Null değil substr'ın kendisini veya bir başka char pointer vermelisin fonksiyona.
Diyelim ki elinde şöyle bir data var; char * aaa= "123 456 252". Burada sayıları teker teker sıralı olarak int e dönüştürmek için fonksiyon 123'ü dönüştürdükten sonra kaldığı yer için 2. pointerı kullanıyor. Senin durumunda 0x00 a yazmaya çalışıyor ve mcu ve hard faulta düşüyor.
Addr=strtol(substr,substr,16); şeklinde kullanmalısın.
Normal olarak neden çalışıyor peki? kesme olarak Timer kesmesi kullanılıyor sadece, birde uart rx kesmesi var ama bu fonksiyon çalışıyorken kesme gelmiyor uarttan.
Derleyicin iar sa kullanma klavuzunda yazanlara bakildiginda null vermemen gerekiyormus gibi duruyor.
@kantirici nin dedigi sekilde yaparsan sorun cozulecek gibi.
strtol un ikinci paramaetresinin null olmasında bir problem yok. ikinci parametre birden fazla değer içeren bir char array'in sırayla tek tek çevrilmesi için kullanılıyor.
Dolayısıyla çevrilecek sadece 1 değer var ise bu parametre null olabilir. Buraya null koymayıp bir pointer'da koysanız o pointer'da sonunda null olacak zaten.
@eowememset yerine malloc demek istedin sanırım. memset bir array'e istenilen ilk değeri vermek için kullanılır, genelde array sıfırlanır.
c++ daki string ile c'deki karakter dizisi (char array) farklı şeylerdir. gömülü tarafta karakter dizisi kullanmanın hiçbir sakıncası yoktur. Başka alternatif de yok zaten.
karakter dizisinin boyutunu baştan verirseniz dinamik hafızaya gerek kalmaz.
Alıntı yapılan: controller - 12 Mart 2018, 09:27:01
strtol un ikinci paramaetresinin null olmasında bir problem yok. ikinci parametre birden fazla değer içeren bir char array'in sırayla tek tek çevrilmesi için kullanılıyor.
Dolayısıyla çevrilecek sadece 1 değer var ise bu parametre null olabilir. Buraya null koymayıp bir pointer'da koysanız o pointer'da sonunda null olacak zaten.
@controller Yanlisiniz var! pointerin NULL olmasi ile pointer degerinin NULL olmasi ayni sey degil. Kullanilan derleyicide NULL nasil implement olduguna bagli olarak buyuk ihtimalle 00000 konumuna bir sonraki dizini yazacaktir.
Doğru pointer null adresi gösterebilir ancak strtol özelinde bu ikisinin farkı yok çünkü endptr null ise zaten pas geçiyor.
Alıntı yapılan: controller - 12 Mart 2018, 09:27:01
strtol un ikinci paramaetresinin null olmasında bir problem yok. ikinci parametre birden fazla değer içeren bir char array'in sırayla tek tek çevrilmesi için kullanılıyor.
Dolayısıyla çevrilecek sadece 1 değer var ise bu parametre null olabilir. Buraya null koymayıp bir pointer'da koysanız o pointer'da sonunda null olacak zaten.
@eowe
memset yerine malloc demek istedin sanırım. memset bir array'e istenilen ilk değeri vermek için kullanılır, genelde array sıfırlanır.
c++ daki string ile c'deki karakter dizisi (char array) farklı şeylerdir. gömülü tarafta karakter dizisi kullanmanın hiçbir sakıncası yoktur. Başka alternatif de yok zaten.
karakter dizisinin boyutunu baştan verirseniz dinamik hafızaya gerek kalmaz.
memset bir array'e istenilen ilk değeri vermek için kullanılır, genelde array sıfırlanır. Arkadasın ne dedigini anlayan var mı?Memset bellekteki alanı set eder.
gömülü tarafta karakter dizisi kullanmanın hiçbir sakıncası yoktur. Bazı fonksiyonlar hardfault sebebidir.Bilip bilmeden konusmayın.Her yoruma cevap atmak mı zorundasınız?
karakter dizisinin boyutunu baştan verirseniz dinamik hafızaya gerek kalmaz.Buda zaten konuyla ne kadar alakalı oldugunuzu gosteriyor...
tamam sensin.
@eowe 'Memset bellekteki alanı set eder' ile kastettiğiniz nedir?
Bu cümlenin
@controller ın söylediği 'memset bir array'e istenilen ilk değeri vermek için kullanılır' dan farkı nedir?
Ayrıca gömülü sistemlerde string fonksiyonları kullanmanın bir sakıncası yoktur.
Dinamik bellek kullanmaktan bahsediyosanız bir nebze haklısınız.RAM i küçük bi mikro da dinamic bellek fonksiyonun kullanmak çok doğru olmaz.
Fakat yine de illa da kullanmak gerekiyosa bazı teknikler ile sorunsuz bir şekilde kullanılabilir.
typedef struct
{
__IO uint32_t KR; /*!< IWDG Key register, Address offset: 0x00 */
__IO uint32_t PR; /*!< IWDG Prescaler register, Address offset: 0x04 */
__IO uint32_t RLR; /*!< IWDG Reload register, Address offset: 0x08 */
__IO uint32_t SR; /*!< IWDG Status register, Address offset: 0x0C */
} IWDG_TypeDef;
Böyle bir yapıda ilk elemanın adresinin bu yapı türünden tanımlanan değişkenin adresine eşit olması , diğer elemanların ise bu adresten belirlenen tür kadar(4byte) uzak olması daima garantimidir? Bu yuzden mi offset adreslerine göre dizilim yapılmış?
Garanti olmasını istiyorsan "packed" keywordunu kullanman lazım. Kullanımı derleyiciden derleyiciye değişebilir, nasıl kullanıldığı derleyicinin manuelinde yazar.
4 degiskenin her biri integer (32) bit oldugundan her biri 4 byte yer kaplar.
Birincisi relatif 0 da oldugundan digerlerinin adresinin 4,8,12 olmasi cok dogal.
Bu 4 degisken de integer oldugu surece aralarindaki uzaklik her zaman 4 byte dir.
Alıntı yapılan: l0rd - 14 Mayıs 2018, 21:06:34typedef struct
{
__IO uint32_t KR; /*!< IWDG Key register, Address offset: 0x00 */
__IO uint32_t PR; /*!< IWDG Prescaler register, Address offset: 0x04 */
__IO uint32_t RLR; /*!< IWDG Reload register, Address offset: 0x08 */
__IO uint32_t SR; /*!< IWDG Status register, Address offset: 0x0C */
} IWDG_TypeDef;
Datasheet e bakıp IWDG'nin adresini buldum.
(https://image.ibb.co/gjAEiy/iwdg.png)
Burada başlangıç adresinin 0x40003000 olduğu yazıyor.O halde ,
IWDG_KR 0x40003000
IWDG_PR 0x40003004
IWDG_RLR 0x40003008
IWDG_SR 0x4000300C
IWDG için sınır : 0x400033FF
O halde 0x40003010 ile 0x400033FF adresi arasında ne var ? ve Ne olduğunu nereden öğrenebilirim.
2. IWDG_SR ye 0x00000001 yazmak istiyorum.
yukardaki structure tanımlamasını kullanırsam;
IWDG_TypeDef* ptr;
ptr=(IWDG_TypeDef*)0x40003000;
ptr->SR=0x00000001;
structureyi kullanmadan
*0x4000300C =0x00000001;
böyle bir atamalar doğru olabilir mi ?
(https://image.ibb.co/eqHVqd/iwdg_off.png)
int *p;
p = (int*) 0x400033FF;
* p = 0x00000001;
veya
* (int*) 0x400033FF = 0x00000001;
o arada boşlukta neler olduğu işlemcinin ilgili dökümanında yazar, yazmıyorsa zaten senin bilmene ve ellemene gerek yoktur.
*0x4000300C =0x00000001;
böyle atama olmaz. şu şekilde yaparsın, çalışadabilir. muhtemelen derleyici hata uyarısı verir. ama çalışsa bile bunun birkaç sakıncası var. birincisi kodu okuyan kişi(bu senden başkasıda olabilir) bu atamanın ne amaçla yapıldığını anlayamaz, belki birkaç saat döküman karıştırması gerekir. ikincisi ise pointer'ın type'ı nerde? senin verdiğin adrese istediğin değeri yazacak, fakat o adresin kapasitesi ne? diyelim 16 bit olsun kapasite, yazılımcı gitti 32 bit değer yazmaya kalktı, ne olacak? yandaki alana taşacak verdiğin değer ve belkide istemediğin bir sonuç doğuracak. pointer'ın type'ı olmadığı için derleyici type check yapamayapacak.
'implicit declaration of function is invalid in c99' Keil'da stm32 için kod yazarken bu uyarıyı alıyorsam ne yapmam gerekir?
Yazdığınız fonksiyon tipini oluşturmadığınız anlamına geliyor.
void, int vb. gibi bir fonksiyon tipi ile yazmamışsınız. C99'da bu tip fonksiyonlar geçersiz sayılır.
Merhaba
GPIO->MODER &=~1<<4 ;
Yazmak yerine
GPIO->MODER &=~ (3UL<<4)
yazmış
Buradaki L düşük bitli registeri mi anlatiyor
4. Biti 1 yapma diyor ama neden böyle karisik bir ifade seçilmiş
neden 3 .5 değil,7 değil
neden UL yada neden neden UH değil?
UL unsigned long demektir. Yani işaretsiz 32 biti temsil eder. Bu kod satırı bitleri sıfırlama veya işlemciye göre pinleri input olarak ayarlamaya yarar. UL yazmak implicit dönüşümden kaçmak için kullanılır.
Arkasında UL gibi ekler olmayan sayılar (literal) int türünden sayılır, yani işaretli kabul edilir. C'de işaretli bir sayı üzerinde kaydırma işlemi yapılması tehlikeli bir işlemdir ve bazı durumlarda "undefined behavior" sayılır, yani duruma göre çalışma ihtimali olsa da dil standartında bir kurala bağlanmadığı için tehlikeli bir işlemdir. Bu sebeple kurallar dahilinde kalmayı garantilemek için sayının işaretsiz olduğu belirtilmiş. Sadece U yazsaydı da olurdu bence.
Not: C'yi bilmiyorum ama C++20'den itibaren işaretli sayıların kaydırılması işlemi artık "undefined behavior" değil. Yine de olaya temkinli yaklaşmak lazım.
Cevaplariniz için teşekkür ederim
UL harfinin yanindaki sayilari ve değeri nasil açiklayabiliriz,logik 1 yerine 3 yazilmiş,4.biti 3 yapma desek anlami olmaz.
o satırı şöyle okuyabilirsiniz 3(0011) yazıp 4 tane sola kaydırıp registerın kendisiyle and işlemine sokuyor ve tersini alıyor büyük ihitimalle registerın ilgili bitlerini 0'lamak için kullanılıyor.
Teşekkür ederim
4 adım gitmesi mantikli olmaz,3 adim gitse yine 4.biti 1 yapma,anlamina gelir,işin mantigi anlatilinca 6UL<<7 de olabileceği anlaşılır
MODER bitleri 2'şerli gruplar halinde. Her bir bacağın hangi modda olduğunu 2 bit belirliyor yani. 4 defa kaydırmak demek, ilgili portun 2 numaralı bacağına (0 ve 1'i atlayıp) ulaşmak demek. Yeni ayarları yapmadan önce maskenin tersi ile AND'leyerek ilgili 2 biti sıfırlamış.
Ben olsam ön tanımlı maske adını kullanırdım ama. Şu anda aklımda olmadığı için örnek veremiyorum. GPIO_MODER_MODE2 falan gibi bir şey olsa gerek, yani GPIO->MODER &= ~GPIO_MODER_MODE2; yazılabilirdi (maske adını yanlış hatırlıyor olabilirim tabi)
Profesyonel bir ifade, Gökçe hocam , iyi çalışmalar