BASIC kullanıcılarını C'ye alıştırma turları

Başlatan bunalmis, 28 Ekim 2011, 18:48:32

z

Alıntı yapılan: rree - 14 Ocak 2012, 12:22:54
volatile unsigned int8 *P,A;

void main()

    P=&A;
   *P=0x10;

Senin yazdigin bu programda da 2 tane * var.

Simdi bu yildizlarin hangisi, #define B0       *(volatile unsigned int1*)0x30  satirindaki yildiza denk geliyor?
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

rree

Birinci yıldız   
     volatile unsigned int8 *P,A;
     P diye bir pointer tanımlıyor.
İkinci yıldız
     *P=0x10;
     Pointerin gösterdiği adrese 0x10 atıyor.

Sırayla aynı anlama geldiğini düşünsem.
   #define B0       *(int1*)0x30
   ikinci yıldız niçin parentrez içinde


Klein

C esnek bir dil. nereye ne yazarsanız kabul eder. Ama konu Pointer olunca bir anda tüm kurallar katılaşır. Bu yüzden pointerler üzerinde işlem yaparken, pointer'e adresini atacağınız verinin tiplerinin aynı olması gerekir. Hatta bu aynılık sadece verinin kapladığı alanla bile sınırlı değildir. Tiplerinin bir'e bir aynı olması gerekir.
Örneğin:
int a;
unsigned int *b;

her ikisi de bellekte aynı yeri kaplıyor olmasına rağmen

b= &a; diyemezsiniz. Derleyici hatası oluşur. Halbu ki bellekte aynı uzunlukta yer kaplarlar. gerçekte hiç bir sıkıntı çıkarmadan çalışabilir. Ama C buna izin vermez.
Ama bazen bizim bu adreslerdeki veriye , tipfarkı olsa da ulaşıp veri üzerinde işlem yapmamız gerekir.
C'ye bu farkı görmezden gel, ben ne yaptığımı biliyorum, bu seferlik idare et dememiz gerekir.
bunun için kasıt operatörünü kullanırız.

eğer yukarıdaki adres atamasını şu şekilde yaparsak :

b = (unsigned int *) &a; dersek derleyici bu işe izin verecektir.

Peki tipleri farklı verilerde ne olacak.
diyelim ki :

char *ptr;
char a;
int b;

değişkenlerimiz var. 
bizim b değişkeninin alt 8 bitlik kısmını almamız gerek. Örneğin I2C eeprom'a yazacağız ve eeprom'a veriyi 8 bit olarak gönderiyoruz.
Verimiz 16 bit ama almamız gereken değer 8 bit.

derleyiciye ptr = &b dersek, derleyici kızar. Senin istediğin adres tek baytlık ama sen iki baytlık bir adres istiyorsun. Ben bunu vermem.
Derleyiciyi ikna etmek için  ptr = (char *) &b dememiz gerekir.

Peki kasıt operatörünü kullanmazsak derleyici niye kızar.

bir array düşün.
int arr[3]; bu aray bellekte şu şekilde yerleşmiş olsun:
char *ptr;
int a;
arr[0] 0x0000 adresine , arr[1] 0x0002 , arr[2] de 0x0004 adresinde olsun.  İçerikleri de 0x4600,0x2739,0x1678 olsun.
bellek düzeni ise şöyle olacaktır
0x46,0x00,0x27,0x39,0x16,0x78

ptr = &arr[0] dersek ve derleyici buna kızmazsa ptr işaretçimizin içeriği 0x0000 olur.

a= *ptr dersek a'nın içeriği  0x4600 olur. Buraya kadar sorun yok.
peki  ptr++ dersek ne olur? ptr nin gösterdiği adres 0x01 olur. Çünkü işaretçimizin tipi char.

şimdi a= *ptr dediğimizde a'nın içeriği 0x0027 olur. Çünkü a değişkenimiz 2 byte ve biz buna bir atama yaptığımızda 2 byte atanır.
Bu değeri bir program içinde bir yerde kullanmaya kalktığımızda başımıza iş alabiliriz.
İşte bu yüzden derleyiciye , ben ne yaptığımı biliyorum dememiz gerekir.

rree

Eline sağlık güzel açıklama oldu.
fahri-  arkadaşımın out fonksiyonunu biliyorum. pointer konusunda anlamadığım noktaları öğrenmek istedim.
Bir sorum daha olacak.
#include <main.h>
#include <mainSetup.c>

#define PortB    *(volatile unsigned int8*)0x06
#define B0       *(volatile unsigned int1*)0x06
void main()
{ msetup();
   set_tris_b (0b00000000);
   PortB=0b01010111; 
   B0=0;  
  While(True){}
}


Bu yöntem ile  PortB nin 2. bitinini yani B1 tanımlayabilirmiyim.

LukeSkywalker

Merhaba.
GPIOD->MODER


Şe4klindeki bir yazımdan derleyici tam olarak ne anlıyor?
İşlemcinin dökümanında "GPIOx_MODER" adında bir register zaten var.
GPIOD->MODER=0x55000000;

yerine
GPIOD_MODER=0x55000000;

yazamaz mıyız?

muhittin_kaplan

Cevabı Basit bir sorudur muhtemelen ama aklıma takıldı.

PC de program yazarken uygulanan yöntem ;

Public HerhangiFonksiyon(Port as SerialPort,  Kanal as integer)
     OkunacakPort(Port)
     OkunacakKanal=Kanal
End Function
yukardaki sözde fonksiyonda serial port olarak önceden tanımlanmış bir nesneyi fonksiyona parametre olarak gönderebiliyorum. Bunu C de nasıl yapacağım.

örneğin

void ADC_Port_Config (Port,Pin)
{
   GPIO_InitTypeDef GPIO_InitStructure;
   GPIO_InitStructure.GPIO_Pin = Pin;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_Init(PORT, &GPIO_InitStructure);
}

Şeklinde nasıl yapabilirim

Klein

ST nin standart kütüphanesini veya  daha önce verdiğim alternatif header veya C++ öneklerini incelersen, cevap orada var. Ama kısaca bahsedeyim.

Stm32f4xx.h dosyasında portlar için

GPIO_TypeDef  isimli bir struct var.
Ayrıca tüm donanımlar için benzer tapılar var.  Bu yapıyı fonksiyonuna pointer olarak geçeceksin.

void ADC_Port_Config (GPIO_TypeDef *port , uint32_t Pin)
{
uint32_t pin_mask = 1 << pin;
   GPIO_InitTypeDef GPIO_InitStructure;
   GPIO_InitStructure.GPIO_Pin =pin_mask;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_Init(PORT, &GPIO_InitStructure);
}