reklam1

reklam1
5- YAZILIM etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
5- YAZILIM etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

31 Temmuz 2012 Salı

SPI0 driver

Mini2440, 2 adet SPI bağlantısına sahip (CON7). SPI haberleşmesini kullanmak için driverlerinin boot esnasında yüklenmesi gerekir. Ancak default olarak gelen kernelde yüklü değil. Yüklemek için aşağıdaki adımları sırasıyla yapmamız gerekiyor. Biz burada SPI0 bağlantısını aktifleştireceğiz.
1- mach-mini2440.c'de aşağıdaki satırları ekleyin. Ben;
...

/* LCD driver info */
...
dan önce ekledim.

...
/* SPI driver info */
static struct spi_board_info __initdata mini2440_spi_board_info[] = {
   // SPI Port 0
   {
      .modalias      = "spidev",
      .max_speed_hz   = 48000000, //48 Mbps
      .bus_num      = 0,
      .chip_select   = 0,   
      .mode          = SPI_MODE_1,
   },
};

static void mini2440_spi0_cs(struct s3c2410_spi_info *spi, int cs, int pol)
{
    s3c2410_gpio_setpin(S3C2410_GPG(2), pol);
}

static struct s3c2410_spi_info mini2440_spi0_platdata = {
    .num_cs = 1,
    .bus_num = 0,
    .set_cs = mini2440_spi0_cs,
};
...
2- mach-mini2440.c'de platform_device' lara spi0 ekle;
...
static struct platform_device *mini2440_devices[] __initdata = {
   &s3c_device_usb,
   &s3c_device_rtc,
   &s3c_device_lcd,
   &s3c_device_wdt,
   &s3c_device_i2c0,
   &s3c_device_spi0,
   &s3c_device_iis,
   &mini2440_device_eth,
   &s3c24xx_uda134x,
   &s3c_device_nand,
   &s3c_device_sdi,
   &s3c_device_usbgadget,
};
...
 
3- mach-mini2440.c 'de  mini2440_machine_init de aşağıdaki satırları ekle;
...

static void __init mini2440_machine_init(void)
{
#if defined (LCD_WIDTH)
   s3c24xx_fb_set_platdata(&mini2440_fb_info);
#endif
   s3c_i2c0_set_platdata(NULL);

   /* setup SPI0 pins */
   s3c2410_gpio_cfgpin(S3C2410_GPE(11), S3C2410_GPE11_SPIMISO0);
   s3c2410_gpio_cfgpin(S3C2410_GPE(12), S3C2410_GPE12_SPIMOSI0);
   s3c2410_gpio_cfgpin(S3C2410_GPE(13), S3C2410_GPE13_SPICLK0);
   s3c2410_gpio_cfgpin(S3C2410_GPG(2), S3C2410_GPIO_OUTPUT);
   s3c_device_spi0.dev.platform_data = &mini2440_spi0_platdata;
   spi_register_board_info(mini2440_spi_board_info,
      ARRAY_SIZE(mini2440_spi_board_info));  
   s3c2410_gpio_cfgpin(S3C2410_GPC(0), S3C2410_GPC0_LEND);

   s3c_device_nand.dev.platform_data = &friendly_arm_nand_info;
   s3c_device_sdi.dev.platform_data = &mini2440_mmc_cfg;
   platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices));
   s3c_pm_init();
}
 ... 

4- tekrar derleyerek yeni zImage oluştur.
artık device listesinde spi0.0 görünecektir. 

8 Mayıs 2012 Salı

Sistem boot ederken aniden resetleniyor...

Linux boot parametrelerini değiştirdiğinizde, (yeni driver yüklemesi vb...) sistem boot ederken bazen resetlenmeye başladıysa WATCHDOG tan reset yemeye başladınız demektir.
DNW den debug edince aşağıdaki mesajı görürsünüz.
"unexpected close, not stopping watchdog."
Nedeni;

CONFIG_S3C2410_WATCHDOG_ATBOOT parametresi set edildiği için boot ederken watchdog çalışıyor.
CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME parametresi default olarak 15'e set edildiği için boot süresi 15 sn yi geçtiğinde watchdog reset yiyorsunuz.

Çözüm 1- Boot ederken bir süre sonra watchdog sayacını sıfırlamalısınız (feed the dog). Bunun için küçük bir program yazıp “/etc/init.d/rcS" nin herhangi bir yerinde (15 sn den önce) bu programı çağırmalısınız.
Örnek:
...
...
fd = open("/dev/watchdog",O_RDONLY );
if(fd < 0) {
perror("/dev/watchdog");
return -1;
}
for(;;) {
ioctl(fd,WDIOC_KEEPALIVE); //keep feeding dog
sleep(3);
}
close(fd);
return 0;
}
...
...

Çözüm 2-"/opt/FriendlyARM/mini2440/linux-2.6.32.2/drivers/watchdog/s3c2410_wdt.c" dosyasinda 50. satir;
#define CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME (15) tanımını değiştirmelisiniz. Ben 30 yaptığımda sorun çözüldü.

5 Mart 2012 Pazartesi

Mini2440 ve DS18B20



DS18b20 sıcaklık sensörünü kullanarak sıcaklık ölçümü yapalım.

aşağıda linki verilen sürücü dosyasını indirin.
http://www.2shared.com/file/dwGnDnkx/myDS18b20.html

#insmod myDS18b20.ko komutu ile sürücüyü yükleyin.
DS18b20 sürücüsü, sensörü char device olarak tanıyor.

programınızda kullanmak için;
...
...
fd = ::open("/dev/myDS18b20", O_RDWR, 0);
...
...

#define K 0.0625

void ReadTemp() {
unsigned int result;
float temperature;
read(fd, &result, sizeof (result));
temperature = (float) result * K;
LCDNumber->display(temperature); //Qt de LCDNumber componenti ile kullanmak için
// printf("Temp : %03f3", temperature);
}

...
...

isterseniz command shell den de kullanabilirsiniz. Bunun için;
#cat /dev/myDS18b20 komutunu girmeniz yeterli.

one-wire sensörün data hattı GPF(3) portuna bağlıdır.
sensörün cihaza bağlantısı aşağıdaki gibidir;






24 Şubat 2012 Cuma

15 Aralık 2011 Perşembe

3 hattan bağlanabilen 2x16 LCD sürücüsü

3 hattan bağlanabilen GLCD (KS0108) sürücüsü yazmıştık. Şimdi de yine 3 hattan bağlanabilen 2x16 LCD sürücüsü yazalım.
12F675, 12F509, 12F683 gibi 8 bacaklı, ucuz, PIC leri kullanabilmek için epey uğraşmak gerekiyor. İki adet besleme bacağını çıkarırsak geriye kalıyor 6 bacak. Bunlardan ikisi osilatör (neyse ki internal osc 8Mhz ayarlanabiliyor ve accuracy mükemmel). Birisi interrupt girişi derken size kalan portlarla neyi kontrol edeceksin, hangi ekranı süreceksin. Basit işler için çok iyi bir seçenek olan bu PIC lerle yapılan işlerde genellikle port sıkıntısı yüzünden ekran kullanılmıyor. Bir iki led'le işler halledilmeye çalışılıyor. Oysa, GLCD için yaptığımız donanım hilesini burada da yapabiliriz. Bir adet 74HC164 ile 3 hattan sürebiliriz. Bu entegre, 8-bit Serial-in, parallel out shift register. Devreyi kurunca çok komik duruyor. (Mikrokontroller, 74HC164 ten daha küçük).
İşte devrenin nasıl kurulacağının şeması;
Burada da sürücü programı (Türkçe desteği -bonus-, ancak X karakterini derece simgesi için kullandım, X olarak kullanacaksanız, düzeltin) ;

#ifndef LCD_E
#define LCD_E PIN_E0
#define LCD_CK PIN_E1
#define LCD_DAT PIN_E2
#endif

boolean turkce;

//========================================
int RS_bit;
#define lcd_type 2 // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line


int8 const LCD_INIT_STRING[4] =
{
0x20 | (lcd_type << 2), // Func set: 4-bit, 2 lines, 5x8 dots
0xc, // Display on
1, // Clear display
6 // Increment cursor
};


//-------------------------------------
void lcd_send_nibble(int8 nibble, int rs_bit)
{

int x;
if(RS_bit==1)
nibble=nibble|0x10;

for(x=0;x<5;x++){
output_bit(LCD_DAT,shift_right(&nibble,1,0));
delay_cycles(1);
output_low(LCD_CK);
delay_us(1);
output_high(LCD_CK);}

output_high(LCD_E);
delay_us(2);
output_low(LCD_E);
}

//----------------------------------------
void lcd_send_byte(int8 address, int8 n)
{
//output_low(LCD_RS);
RS_bit=0;
delay_us(100);


if(address)
//output_high(LCD_RS);
RS_bit=1;
else
//output_low(LCD_RS);
RS_bit=0;

delay_cycles(1);


output_low(LCD_E);

lcd_send_nibble(n >> 4,RS_bit);
lcd_send_nibble(n & 0xf,RS_bit);
}

//----------------------------
void lcd_init(void)
{
int8 i;

//output_low(LCD_RS);
RS_bit=0;

output_low(LCD_E);

delay_ms(20);

for(i=0 ;i < 3; i++)
{
lcd_send_nibble(0x03,RS_bit);
delay_ms(5);
}

lcd_send_nibble(0x02,RS_bit);

for(i=0; i < sizeof(LCD_INIT_STRING); i++)
{
lcd_send_byte(0, LCD_INIT_STRING[i]);

delay_ms(5);

}

}

//----------------------------

void lcd_gotoxy(int8 x, int8 y)
{
int8 address;

if(y != 1)
address = lcd_line_two;
else
address=0;

address += x-1;
lcd_send_byte(0, 0x80 | address);
}

//-----------------------------
void lcd_putc(char c) {
if (turkce) {
if (c=='Ç') c=0;
if (c=='Ğ') c=1;
if (c=='İ') c=2;
if (c=='Ö') c=3;
if (c=='Ş') c=4;
if (c=='Ü') c=5;
if (c=='I') c=6;
if (c=='X') c=7;
}
switch (c) {
case '\f' : lcd_send_byte(0,1);
delay_ms(2);
break;
case '\i' : lcd_gotoxy(1,1); break;
case '\n' : lcd_gotoxy(1,2); break;
case '\b' : lcd_send_byte(0,0x10); break;
default : lcd_send_byte(1,c); break;
}
}

void lcd_setcursor_visible(short visible, short blink) {
lcd_send_byte(0, 0xC|(visible<<1)|blink);
}

void lcd_turkceb() {

// Ç

lcd_send_byte(0,0x40); lcd_send_byte(1,14);
lcd_send_byte(0,0x41); lcd_send_byte(1,17);
lcd_send_byte(0,0x42); lcd_send_byte(1,16);
lcd_send_byte(0,0x43); lcd_send_byte(1,16);
lcd_send_byte(0,0x44); lcd_send_byte(1,16);
lcd_send_byte(0,0x45); lcd_send_byte(1,21);
lcd_send_byte(0,0x46); lcd_send_byte(1,14);
lcd_send_byte(0,0x47); lcd_send_byte(1,4);

// Ğ
lcd_send_byte(0,0x48); lcd_send_byte(1,14);
lcd_send_byte(0,0x49); lcd_send_byte(1,0);
lcd_send_byte(0,0x4A); lcd_send_byte(1,15);
lcd_send_byte(0,0x4B); lcd_send_byte(1,16);
lcd_send_byte(0,0x4C); lcd_send_byte(1,19);
lcd_send_byte(0,0x4D); lcd_send_byte(1,17);
lcd_send_byte(0,0x4E); lcd_send_byte(1,15);
lcd_send_byte(0,0x4F); lcd_send_byte(1,0);

// İ
lcd_send_byte(0,0x50); lcd_send_byte(1,4);
lcd_send_byte(0,0x51); lcd_send_byte(1,0);
lcd_send_byte(0,0x52); lcd_send_byte(1,4);
lcd_send_byte(0,0x53); lcd_send_byte(1,4);
lcd_send_byte(0,0x54); lcd_send_byte(1,4);
lcd_send_byte(0,0x55); lcd_send_byte(1,4);
lcd_send_byte(0,0x56); lcd_send_byte(1,4);
lcd_send_byte(0,0x57); lcd_send_byte(1,0);

// Ö
lcd_send_byte(0,0x58); lcd_send_byte(1,10);
lcd_send_byte(0,0x59); lcd_send_byte(1,0);
lcd_send_byte(0,0x5A); lcd_send_byte(1,14);
lcd_send_byte(0,0x5B); lcd_send_byte(1,17);
lcd_send_byte(0,0x5C); lcd_send_byte(1,17);
lcd_send_byte(0,0x5D); lcd_send_byte(1,17);
lcd_send_byte(0,0x5E); lcd_send_byte(1,14);
lcd_send_byte(0,0x5F); lcd_send_byte(1,0);

// Ş
lcd_send_byte(0,0x60); lcd_send_byte(1,14);
lcd_send_byte(0,0x61); lcd_send_byte(1,17);
lcd_send_byte(0,0x62); lcd_send_byte(1,16);
lcd_send_byte(0,0x63); lcd_send_byte(1,14);
lcd_send_byte(0,0x64); lcd_send_byte(1,1);
lcd_send_byte(0,0x65); lcd_send_byte(1,21);
lcd_send_byte(0,0x66); lcd_send_byte(1,14);
lcd_send_byte(0,0x67); lcd_send_byte(1,4);

// Ü
lcd_send_byte(0,0x68); lcd_send_byte(1,10);
lcd_send_byte(0,0x69); lcd_send_byte(1,0);
lcd_send_byte(0,0x6A); lcd_send_byte(1,17);
lcd_send_byte(0,0x6B); lcd_send_byte(1,17);
lcd_send_byte(0,0x6C); lcd_send_byte(1,17);
lcd_send_byte(0,0x6D); lcd_send_byte(1,17);
lcd_send_byte(0,0x6E); lcd_send_byte(1,14);
lcd_send_byte(0,0x6F); lcd_send_byte(1,0);

// I
lcd_send_byte(0,0x70); lcd_send_byte(1,4);
lcd_send_byte(0,0x71); lcd_send_byte(1,4);
lcd_send_byte(0,0x72); lcd_send_byte(1,4);
lcd_send_byte(0,0x73); lcd_send_byte(1,4);
lcd_send_byte(0,0x74); lcd_send_byte(1,4);
lcd_send_byte(0,0x75); lcd_send_byte(1,4);
lcd_send_byte(0,0x76); lcd_send_byte(1,4);
lcd_send_byte(0,0x77); lcd_send_byte(1,0);

// X
lcd_send_byte(0,0x78); lcd_send_byte(1,2);
lcd_send_byte(0,0x79); lcd_send_byte(1,5);
lcd_send_byte(0,0x7A); lcd_send_byte(1,2);
lcd_send_byte(0,0x7B); lcd_send_byte(1,0);
lcd_send_byte(0,0x7C); lcd_send_byte(1,0);
lcd_send_byte(0,0x7D); lcd_send_byte(1,0);
lcd_send_byte(0,0x7E); lcd_send_byte(1,0);
lcd_send_byte(0,0x7F); lcd_send_byte(1,0);

delay_ms(5);
turkce=TRUE;
}

Dikkat edilmesi gereken tek nokta, sistem enerjilendikten sonra biraz gecikme koyun daha sonra lcd_init yapın.

2 Kasım 2011 Çarşamba

iPhone telefonunuzun dosyalarına erişim

iPhone telefonunuz varsa, ve biraz iOS(iPhone OS) biliyorsanız birşeyler yapmak için işte size fırsat.
Linux'a çok benziyor ancak multi-touch gesture, accelerometer gibi çevre birimlerini direk destekliyor. İşletim sistemi, dört katmandan oluşuyor; abstraction layers, core OS layer, core services layer, media layer ve cocoa touch layer.

Şimdi size iPhone' a uzaktan erişimi nasıl yapacağınızı anlatacağım.
1-İlk önce telefondan, Cydia yı çalıştırın ve openSSH (open Secure Shell) programını yükleyin (yüklü değilse).
2-http://www.putty.org/ adresinden PuTTY programını indirin. Kurulum falan yok direk olarak bir klasöre kopyalayın.
3-Telefonunuzdan Wi-Fi bağlantısını bulun aktif bağlantının yanındaki sağa doğru ok işaretine basın. Buradan telefonun IP numarasını öğrenin.
4- PuTTY programını çalıştırın. IP address bölümüne telefonun IP sini girin. Connection type, SSH olacak. Port numarası 22. Open dediğinizde iPhone içindeki iOS'ta login ekranındasınız.
5- Login:root, password:alpine.
6- Artık iPhone'nin içindesiniz. Klasör açabilirsiniz. Yazdığınız programları kopyalayabilirsiniz.

Yakında bir örnek uygulamayı nasıl kopyalayıp telefonun menüsünde göstereceğimizi ve çalıştıracağımızı anlatacağım.
Kolay gelsin.

19 Ekim 2011 Çarşamba

PIC Web Server interrupt mode

Microchip'in TCP-IP stack kodu polling modda çalışıyor. ENC28J60'ın INT kesmesi aktif edilmemiş. Aktif etmek için enc28j60.c kodunda
static void SendSystemReset(void) fonksiyonunun sonuna aşağıdaki kodu ekleyin.
...
BFCReg( EIR, EIR_TXIF );
BFSReg( EIE, EIE_TXIE | EIE_INTIE | EIE_PKTIE | EIE_LINKIE );
...

PIC kodunuzda gerekli değişikliği yaptıktan sonra artık kesmeli çalışabilirsiniz.

15 Ekim 2011 Cumartesi

PIC Web Server, MINI2440 Web Browser


Uzun zamandır PIC web server'e Mini2440 içinden basit bir browserle ulaşan bir uygulama için vakit bulamıyordum. Nihayet projeyi tamamladım. QT-4.7.3 altında yazdığım browserin kodları aşağıda. Derlemek için WebKit kütüphanesinin yüklü olması gerekir. PIC tarafındaki kod ise Microchip stack kullanıyor.
İşte kodlar;

***browser.h***
#ifndef BROWSER_H
#define BROWSER_H

#include "QApplication"
#include "QtGui"
#include "QtCore"
#include "QtWebKit/QWebView"

class Browser :
public QMainWindow
{
Q_OBJECT
public:
Browser();

private slots:
void loadLinkPage(const QUrl & url);
void loadPage();
void backPage();
void forwardPage();
void reloadPage();
void refreshLine();


private:
void createActions();

void createToolBars();
void createStatusBar();

QToolBar *navigationToolBar;
QAction *backAct;
QAction *forwardAct;
QAction *reloadAct;
QWebView *pageView;
QLineEdit *pageLine;

};

#endif


***browser.cpp***
#include "browser.h"
#include "QtWebKit/QWebView"
#include "QUrl"

Browser::Browser()
{
pageView = new QWebView(this);
pageView->load(QUrl("http://192.168.1.52/"));
setCentralWidget(pageView);
pageView->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);

pageLine = new QLineEdit(this);
pageLine->setText("http://www.baidu.com/");
createActions();
createToolBars();
createStatusBar();

connect(pageView, SIGNAL(loadProgress(int)), this, SLOT(refreshLine()));
connect(pageLine, SIGNAL(returnPressed()), this, SLOT(loadPage()));
connect(pageView, SIGNAL(linkClicked(const QUrl)), SLOT(loadLinkPage(const QUrl)));
}

void Browser::createActions()
{
backAct = new QAction(QIcon(":/images/back.png"), tr("&Back"), this);
backAct->setShortcut(tr("Ctrl+B"));
connect(backAct, SIGNAL(triggered()), this, SLOT(backPage()));

forwardAct = new QAction(QIcon(":/images/forward.png"), tr("&Forward"), this);
forwardAct->setShortcut(tr("Ctrl+F"));
connect(forwardAct, SIGNAL(triggered()), this, SLOT(forwardPage()));

reloadAct = new QAction(QIcon(":/images/reload.png"), tr("&Refresh"), this);
reloadAct->setShortcut(tr("Ctrl+R"));
connect(reloadAct, SIGNAL(triggered()), this, SLOT(reloadPage()));


}

void Browser::createToolBars()
{
navigationToolBar = addToolBar(tr("Navigation"));
navigationToolBar->addAction(backAct);
navigationToolBar->addAction(forwardAct);
navigationToolBar->addAction(reloadAct);
navigationToolBar->addWidget(pageLine);

}

void Browser::createStatusBar()
{
statusBar()->showMessage(tr("Ready"));
}

void Browser::loadPage()
{

pageView->load(QUrl(pageLine->text()));
}

void Browser::backPage()
{
pageView->back();
}

void Browser::forwardPage()
{
pageView->forward();
}

void Browser::reloadPage()
{
pageView->reload();
}

void Browser::refreshLine()
{
pageLine->setText(pageView->url().toString());
}

void Browser::loadLinkPage(const QUrl & url)
{
pageView->load(url);
}

***main.cpp***
#include "QApplication"
#include "QtGui"
#include "QtCore"
#include "browser.h"

int main(int argc, char *argv[])
{
QApplication app(argc, argv);

Browser myBrowser;
myBrowser.show();
return app.exec();
}

6 Ekim 2011 Perşembe

I2C ile haberleşen sensör modülü

Birden fazla Sensörle çalışırken, herbir sensör için port kullanmak çok büyük bir savurganlık.
Bunun yerine sensörler için küçük bir modül yapıp hepsini aynı porttan kullanmak mümkün. Aşağıda 16F88 ile CCS de yazdığım, kendi adresine sahip, Master ile I2C üzerinden haberleşen bir modül örneği var. CCS'de Hardware I2C bazen problem yaratabiliyor. Ancak kodda gerekli düzeltmeler yapılmış ve sorunsuz olarak çalışıyor.
Kodu, haberleşme bölümlerine dokunmadan, kendinize göre düzenleyip kullanabilirsiniz.
Sistemi bu şekilde tasarlamanın başka bir avantajı, DAQ modülünüzü değiştirmeden sensörü değiştirip kullanabiliyoruz. Çünkü sensör kodları modül tarafında bulunuyor. DAQ tarafı her sensör için aynı kalıyor.
Kodda, float değişkenin I2C ile nasıl yollandığı da bulunuyor.
Herbir sensör kendi slave adresini eepromun 1 nolu adresine daha önceden yazılmış değerden öğreniyor.
Çok hassas ölçmeler için koda CRC hata denetimi de ekledim. Her ölçme işleminin sonucunu gönderirken birlikte CRC kodu da gönderilir. Böylece Master CRC hata denetimi yapabilir.

slave.c
#include <16F88.h>
#device adc=10
#define VDD 5.00

#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES NOPUT //No Power Up Timer
#FUSES NOMCLR //Master Clear pin used for I/O
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOFCMEN //Fail-safe clock monitor disabled
#FUSES NOIESO //Internal External Switch Over mode disabled

#use delay(clock=8000000)

#use standard_io(A)

#define _SCL PIN_B4
#define _SDA PIN_B1
#use i2c(SLAVE, FAST, SDA=_SDA, SCL=_SCL, FORCE_HW)

byte _SA;
byte _REV;

#byte SSPSTAT = 0x94
#byte SSPBUF = 0x13

#bit SMP = SSPSTAT.7
#bit CKE = SSPSTAT.6
#bit DA_BIT = SSPSTAT.5
#bit P_BIT = SSPSTAT.4
#bit S_BIT = SSPSTAT.3
#bit RW_BIT = SSPSTAT.2
#bit UA_BIT = SSPSTAT.1
#bit BF = SSPSTAT.0

#byte SSPCON = 0x14
#bit WCOL = SSPCON.7
#BIT SSPOV = SSPCON.6 //Indicates overflow
#bit SSPEN = SSPCON.5
#bit CKP = SSPCON.4
#bit SSPM3 = SSPCON.3
#bit SSPM2 = SSPCON.2
#bit SSPM1 = SSPCON.1
#bit SSPM0 = SSPCON.0

int8 sBUFFER[50];
int8 rBUFFER[50];
byte dREGISTER;
int8 dINDEX = 0;

BYTE _ACTIVED = FALSE;

void WRITE_FLOAT(int n, float data) {
int i;
int8 crc = (int8) 0xff;
BYTE b;
for (i = 0; i < 4; ++i) {
sBUFFER[i+5*n]= *((int8*)&data + i);
crc ^= sBUFFER[i+5*n];
for (b=0; b<8; ++b) {
if (crc & 0x80) crc = (crc << 1) ^ 0x31;
else crc = (crc << 1);
}
}
sBUFFER[5*n+4]=crc;
}

int8 crcbyte(int8 val) {
byte b;
for (b=0; b<8; ++b) {
if (val & 0x80) val = (val << 1) ^ 0x31;
else val = (val << 1);
}
return(val);
}

#define MSGACK 0xA5
#define MSGNACK 0xFF

#INT_SSP
void ssp_interupt () {
byte incoming, tmp;
if(SSPOV) // Make sure the buffer has not overflowed
{
incoming= SSPBUF;
BF=0;
SSPOV=0; // Clear the register
return;
}
if(P_BIT) {
incoming= SSPBUF;
BF=0;
SSPOV=0;
_ACTIVED=FALSE;
SSPSTAT=0;
dINDEX=0;
return;
}
tmp = (SSPSTAT & 0b00101101); // Read the status register and mask with D_A , S , R_W , BF
switch(tmp) {
CASE 0x09 /*0b00001001*/: // D_A=0, S=1, R_W=0, BF=1
incoming= SSPBUF; // Master tx, slave addr
if (incoming == _SA) _ACTIVED=TRUE; // Address bit with write operation
break;
CASE 0x29 /*0b00101001*/: // SSPSTAT bits: D_A=1, S=1, R_W=0, BF=1
if (_ACTIVED) { // Master tx, data
incoming = SSPBUF;
if (dINDEX==0) {
dREGISTER = incoming;
dINDEX++;
}
else {
rBUFFER[dREGISTER+dINDEX] = incoming;
dINDEX++;
}
}
break;
CASE 0x0C/*0b00001100*/: // SSPSTAT bits: D_A=0, S=1, R_W=1, BF=0
if (_ACTIVED) { // Master rx, slave addr+1
CKP=0;
dINDEX=0;
SSPBUF = sBUFFER[dREGISTER+dINDEX];
dINDEX++;
CKP=1;
}
break;
CASE 0x2C/*0b00101100*/: // SSPSTAT bits: D_A=1, S=1, R_W=1, BF=0:
if (_ACTIVED) { // Master rx, data with ack
CKP=0;
SSPBUF = sBUFFER[dREGISTER+dINDEX];
dINDEX++;
CKP=1;
}
break;
CASE 0x28/*0b00101000*/: // NACK --> SSPSTAT bits: S = 1, D_A = 1, R_W = 0, BF = 0
break; // Master rx, data with nack (high)
CASE 0x30: // SSPSTAT bits: D_A=1
break;
default:
if (BF) {
incoming= SSPBUF;
BF = 0;
break;
}
}
}

void main() {
float value;
long int ADCValue;
int i;

setup_adc(ADC_CLOCK_INTERNAL);
setup_adc_ports(sAN0|sAN1|VSS_VDD);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
// setup_oscillator(OSC_8MHZ|OSC_INTRC);//sets internal osc multiplier

// write_eeprom(0,100); //REVISION
// write_eeprom(1,0xA4); //SLAVE ADDRESS
_REV = read_eeprom(0);
_SA= read_eeprom(1);
i2c_slaveaddr(_SA);

bit_set(SSPCON,3); //START STOP Bit Interrupts Enabled

disable_interrupts(GLOBAL); // Turn all off
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL); // Now enable it

set_adc_channel( 0 );
delay_us( 50 );
i=0;
while(TRUE) {
ADCvalue = read_adc();
delay_us( 250 );
value= ADCvalue * 0.00488758553274682307;
WRITE_FLOAT(0,value);
sBUFFER[5]=i;
sBUFFER[6]=crcbyte(i);
i++;
if (i>127) i=0;
delay_ms(10);
}
}

15 Eylül 2011 Perşembe

Linux'ta PIC programlama...

Linux altında SDCC (Small Device C Compiler) derleyicisi ile PIC projelerimizi derleyebiliyoruz...

Derleyici burada.

nasıl yapıldığı burada ayrıntılı olarak açıklanıyor.

Mini2440 için sürücü dosyası derleme...

Oluşturacağımız sürücü dosyasının adı myDevice olsun.
İlk önce Kbuild ve Makefile dosyalarını oluşturmalıyız.

Kbuild dosyasının içeriği;
obj-m:= myDevice.o

Makefile dosyasının içeriği;
KDIR:=/opt/FriendlyARM/mini2440/linux-2.6.32.2
PWD:=$(shell pwd)

all:
[TAB]$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
[TAB]$(MAKE) -C $(KDIR) M=$(PWD) clean

NOT: $(MAKE) satırları mutlaka tab ile başlamalı.

bunları oluşturduktan sonra myDevice.c yi aynı klasöre kopyalamalıyız.
#make komutunu işlettiğimizde aynı klasörde myDevice.ko dosyası oluştu.
Bunu mini2440'a kopyalarız.

sürücüyü yüklemek için;
insmod /path/myDevice.ko

yüklü sürücüleri listelemek için;
lsmod

yüklü sürücüyü kaldırmak için
rmmod /path/myDevice.ko

12 Eylül 2011 Pazartesi

mini2440 boot sırasında çok fazla bilgi mesajı veriyor...

Eğer sistemi powerdown, reboot, vs.. gibi yöntemlerle kapatmayıp güç anahtarından kapatırsanız bir süre sonra açılışta çok fazla
Partially written block ... detected
mesajı almaya başlıyorsunuz. Sistem başlatıldığında DNW ile debug çok zorlaşıyor.
Üstelik bu bilgi mesajı çok fazla gerekli değil. Önlemek için;

/opt/FriendlyARM/mini2440/linux-2.6.32.2/fs/yaffs2/ klasoründeki
yaffs_guts.c dosyasında,

static int yaffs_ScanBackwards(yaffs_Device * dev) fonksiyonu nu bulun.

satır no 6437,

T(YAFFS_TRACE_ALWAYS,
(TSTR("Partially written block %d detected" TENDSTR),
blk));
…..

yukarıdaki satırları aşağıdaki gibi değiştirin.

T(YAFFS_TRACE_SCAN,
(TSTR("Partially written block %d detected" TENDSTR),
blk));
…..

kernel'i tekrar derleyin. Artık bu gereksiz uyarıyı almayacaksınız.

22 Ağustos 2011 Pazartesi

PIC işlemcide C ile fonksiyona pointer atama...

Bugün PIC işlemciyi pert olmadan CCS ile koşturalım ve Fonksiyona pointer ataması yapalım.
Bu şekilde fonksiyonu dinamik olarak tanımlayarak program koştururken içeriğini değiştirelim.

önce func.c dosyası oluşturalım ve aşağıdaki kodu yazalım.

#if !defined(_PCD_)
typedef signed int8 (*_MyFunction) (int val);
#else
typedef signed int16 (*_MyFunction) (int val);
#endif

_Myfunction MyFunction;

signed int PIDproc1(int val) {
printf("\r\nPROC1");
return val+1;
}

signed int PIDproc2(int val) {
printf("\r\nPROC2");
return val+2;
}

void Exec(float value) {
int par1;
par1= value;
if(value > 50) MyFunction=PIDProc2;
else MyFunction=PIDProc1;
//DoIt(par1,MyFunction);
printf("\r\nRET:%u", (*MyFunction)(par1));
}

şimdi de main.c yi yazalım.
#include "func.c"
...
void main() {
...
While (TRUE) {
set_adc_channel(0);
delay_us(20);
value = read_ADC();
fvalue = 0.0977*value;
printf("\r\nVAL: %f",fvalue);
Exec(fvalue);
delay_ms(150);
}

}

Main.c de adc kanalından değer okunuyor. Okunan değer Exec fonksiyonuna gönderiliyor. Exec içinde MyFunc adında foknsiyona pointer tanımı var. Değer kontrol ediliyor. Değer 50 den büyükse pointer PIDProc2'e, değilse PIDProc'e eşitleniyor...

15 Ağustos 2011 Pazartesi

mini2440 için OpenCV Görüntü işleme kütüphanesi kurulumu...

1-http://sourceforge.net/projects/opencvlibrary/files/opencv-unix/2.0/ adresinden OpenCV-2.0.0.tar.baz2 dosyasını indirelim.
2-SRC_DIR=/opt/FriendlyARM/mini2440
3-TGT_DIR=/usr/local/OpenCV
4-export CC=arm-linux-gcc
5-export PKG_CONFIG_PATH=/usr/local/OpenCV/lib/pkgconfig
6-cd $SRC_DIR/OpenCV-2.0.0
7-make uninstall && make clean
8-./configure --prefix=$TGT_DIR --host=arm-linux CPPFLAGS=-I$TGT_DIR/include LDFLAGS=-L$TGT_DIR/lib --with-v4l --without-ffmpeg --without-unicap --without-gthread --disable-shared --enable-static --without-imageio --without-carbon --without-quicktime --without-1394libs --without-python --without-gtk --without-swig --disable-apps --disable-shared CXX=arm-linux-g++
9- make -j3
10-make install
10- TGT_DIR klasöründe; bin, include, lib klasörleri oluştu. Bunları aynı isimle Mini2440'a kopyalayalım (/usr/local/OpenCV/lib gibi...).

11-/etc/init.d/scR' ye export LD_LIBRARY_PATH :/usr/local/OpenCV/lib/:$LD_LIBRARY_PATH satırını ekleyelim.

kurulum tamam...

11- Kamera tanıtımı, initialization, Görüntü yakalamak için;
...
CvCapture *mycamera = NULL;
IplImage *myframe = NULL;

mycamera =cvCreateCameraCapture(0);

while(1) {
cvGrabFrame(mycamera);
myframe = cvRetrieveFrame(mycamera,0);
...

QApplication app(argc, argv);
myCameraWindow *mainWin = new MyCameraWindow(camera);
mainwin->setWindowTitle("OpenCV ile hersey cok kolay");
mainwin->show();
int val = app.exec();
cvReleaseCapture(&mycamera);
return val;
...

12- Qt de QOpenCVWidget oluşturma;
...
QOpenCVWidget::QOpenCVWidget(QWidget *parent): QWidget(parent) {
layout = new QVBoxLayout;
imagelabel = new QLabel;
QImage dummy(240,320,QImage::Format_RGB32);
...

13- Görüntü penceresi;
MyCameraWindow::MyCameraWindow(CvCapture *cam, QWidget *parent): QWidget(parent) {
mycamera = cam;
QVBoxLayout *layout = new QVBoxLayout;
...

ilk deneme de tamam...

10 Ağustos 2011 Çarşamba

Birden fazla DS18B20 ile tek hattan sıcaklık okuma...


DS18B20 sıcaklık sensoru ile yapılan uygulamaların çoğunda bir master(CPU) ve bir slave(Sensör) tasarlanarak sıcaklık okunuyor. Yani bağlı sensörün seri numarasına bakılmadan direk olarak hatta bağlı olan sensor aktif yapılıyor. Oysa tek hatlı iletişimin gücü, birden fazla sensor bağlanmasıyla sağlanıyor. Bu şekilde tasarlanan sistemde eğer birden fazla sensör varsa hatta collision oluşuyor.Bunu önlemek için önce Adres gönderilmesi, adresini doğrulayan sensörün aktif olup cevap vermesi gerekiyor..
Bu örnekte birden fazla sensörle parasitic mode sıcaklık okumanın nasıl yapılacağı gösteriliyor. Tek hatta bağlı sensorlerden hangisinin seri numarası gönderildi ise, o cevap veriyor. Örnekte en fazla 10 adet sensör bağlanabiliyor. Ancak bağlanacak sensör sayısında bir sınırlama yok. İstediğiniz sayıda sensör için kodda gerekli değişikliği yapınız. Uygulama, bağlı bulunan butun DS18B20 leri otomatik buluyor ve daha sonra bağlı olanlardan sıcaklıkları okuyor.

Kaynak kodu buraya yükledim.

9 Ağustos 2011 Salı

3 hattan bağlanabilen GLCD (KS0108) sürücüsü

GLCD lerle yapılan uygulamalarda neredeyse 14 hat LCD bağlantılarına gider. Buda neredeyse 2 Port demektir. Bu bağlantıları 3 e indiren donanım, sürücü programı ve ISIS uygulaması ektedir. Sürücü programı sayesinde GLCD nin pageleriyle de uğrasmıyoruz artık.
örnek:
...
glcd_init();
...
glcd_gotoxy(0,0);
printf(glcd_putc,"test???");
...














Kaynak kodu buraya yükledim

6 Ağustos 2011 Cumartesi

mini2440 için VT6656 wifi sürücüsü kurulumu.

İki günlük çaba sonunda nihayet oldu. Artık yeni oyuncağımda wi-fi de var. İlgilenenler için işte yöntem;

Platform Fedora 9.
ARM Linux versiyonu 2.6.32.2.
Kernel kaynak kodu yolu /opt/FriendlyARM/mini2440/linux-2.6.32.2 (KERNEL_PATH).
1-http://www.viaarena.com/Driver/VT6656_linux_src_v1.20.03_x86.rar dosyasını indirin
ve bir klasöre açın (MODULE_PATH).
2-/usr/src/linux ile KERNEL_PATH arasında sembolik link kurun.
3-cd KERNEL_PATH
4-make oldconfig && make prepare & & make modules_prepare
5-cd MODULE_PATH /driver
6-make -C KERNEL_PATH M=MODULE_PATH/driver modules
7-kernel modulu vntwusb.ko hazır. Bunu Mini2440'a kopyalayın.
8-MAC adresini geçerli bir adres yapın. Default MAC adresi hata veriyor.
9-Mini2440'ta kopyaladığınız klasörde; insmod vntwusb.ko
10-ifconfig dediğinizde işte eth1 karşınızda...
11-ifconfig eth1 up.
12-iwlist scanning.
13- WPA için iwconfig eth1 key ********
14-iwconfig eth1 essid "XXXXXX"
15-ifconfig eth1 xxx.xxx.xxx.xxx netmask 255.255.255.0
16-route add default gw xxx.xxx.xxx.xxx
17-ping www.-----.com

bu kadar.

reklam4

reklam4