Wednesday 7 November 2007

Small Device C Compiler (MCS-51)

Mengapa SDCC ?


SDCC Merupakan open source , retargetable, optimizing C compiler yang pertama kali dikembangkan oleh Sandeep Dutta untuk mikrokontroller/mikroprosesor 8-bit, SDCC mendukung beberapa arsitektur mikrokontroller/mikroprosessor 8-bit antara lain: Intel MCS-51,Zilog Z80, Atmel AVR, Microchip PIC, Freescale (Motorola) HC08. Disini kita akan bahas penggunaan SDCC untuk MCS-51 Family yang cukup banyak dipakai saat ini


Pemrograman dengan bahasa C lebih mudah di bandingkan menggunakan bahasa assembly (bahasa mesin), SDCC merupakan C compiler gratis (freeware) sehingga anda tidak perlu mengeluarkan biaya untuk membeli compiler komersial yang harganya cukup mahal, dari segi code yang dihasilkan optimasi sdcc sangat bagus


Sebelumnya anda sudah harus mengerti pemrogramman dasar menggunakan bahasa C untuk PC


Instalasi SDCC


Sebelum anda bereksperimen dengan SDCC maka sebelumnya anda harus menginstall SDCC pada komputer anda.


langkah - langkah Instalasi SDCC :


1. Download Win 32 SDCC Setup file pada situs sdcc.sourceforge.net


2. Jalankan file setup yang telah anda download tadi


3. Ikuti langkah yang mucul pada dialog yang muncul, dan gunakan nilai defaultnya, terakhir ketika installer menanyakan untuk menambah path ke system path, pilih Yes sehingga anda akan dapat meng-compile dari sembarang folder


Path


4. Setelah selesai restart komputer anda.


5. Test apakah SDCC sudah terinstall dengan benar, dengan masuk ke command prompt ketik sdcc -v untuk menampilkan versi sdcc yang anda install, berikut langkahnya :



  1. Klik Start->Run kemudian ketik cmd , klik Ok maka akan muncul window command prompt

  2. Ketik sdcc -v, jika tampil versi SDCC maka SDCC telah terinstall dengan benar


Check SDCC Ver


Tipe Data


SDCC medukung beberapa tipe data standar sebagai berikut :




  • bool 1 Bit (0,1)

  • char 8 bits (signed -128~+127, unsigned 0~255)

  • int 16 bits (signed -32768~ +32767, unsigned 0~ +65535)

  • long 32 bits(signed -2147483648~ +2147483647, unsigned 0~ +4294967296)

  • float 32 bits (4 bytes IEEE 754)


SDCC juga mendukung  tipe data spesifik sesuai dengan arsitektur MCS 51 antara lain :


near/data

mendeklarasikan variabel menggunakan storage class near/data akan menyebabkan variabel diletakkan dalam directly Adressable RAM MCS-51 (internal RAM), MCS-51 mempunyai 128 directly Adressable RAM MCS-51


far/xdata

mendeklarasikan variabel menggunakan storage class far/xdata akan menyebabkan variabel diletakkan dalam RAM eksternal


idata

mendeklarasikan variabel menggunakan storage class idata akan menyebabkan variabel diletakkan dalam indirectly Adressable memory


code

mendeklarasikan variabel menggunakan storage class code akan menyebabkan varibel diletakkan dalam program memory, variabel ini mempunyai sifat read-only (constant) dan biasanya digunakan untuk menyimpan suatu look up table/konstanta


   
#include <at89x51.h>

code unsigned char pola[10] = {0x00,0xff,0xF0,0x0f,0x81}; // Tabel llok

void delay()
{
int i;
for(i=0;i<50000;i++); // Loop 50000 kali
}

void main(void)
{
data unsigned char i = 0;

while (1) // program loop
{
P0 = pola[i++];
delay();
if (i==5)
i=0;
}
}


bit

Deklarasi variabel menggunakan storage class bit akan
menyebabkan variabel ini disimpan dalam bit adressable memory pada MCS-51, jumlah total variabel ini adalah 128 (MCS-51 hanya mempunyai 128 bit-adressable memory)


sfr

storage class sfr digunakan untuk mengakses Special Function Register (SFR) MCS-51


sbit

storage class sbit digunakan untuk mengakses Bit Adressable pada Special Function Register (SFR) MCS-51


 


In line Assembler


Anda dapat menyisipkan kode assember MCS-51 dalam program c anda ( in line Assembler), dengan dimulai keyword _asm dan di akhiri oleh keyword _endasm; contoh:


   
#include <at89x51.h> // header, definisi port ada pada file ini
_asm
mov P1,#200
mov P2,#255
nop
nop
_endasm;




I/O Port Acess


I/O Port access dapat langsung dilakukan dengan memberikan nilai pada nama port yang ingin anda akses, port yang tersedia disesuaikan mikrokontroler yang digunakan. Nama port haruslah huruf kapital mis: P0,P1,P2,P3 sesuai dengan file header, penggunaan huruf kecil akan menimbulkan kesalahan, contoh:


   
#include <at89x51.h> // header, definisi port ada pada file ini

P1 = 0xF0 ; // memberikan nilai 0x kepada port 1
P2 = 200 ; // memberikan nilai 200 kepada port 2
i = P2 ; // membaca nilai pada P2 dan nilainya di berikan ke variabel i


akses port secara bit dilakukan dengan cara
menggukanan keyword PX_Y
, sesuai dengan definisi di file headernya, X diganti dengan port yang akan diakses, sedangkan Y diganti dengan dengan bit yang akan di akses, mis: P1_0 artinya Port 1 bit ke 0 (P1.0)
, bit hanya mempunyai dua keadaan logika yaitu on(1)/off(0). Berikut contoh pengaksesan port secara bit:


   
#include <at89x51.h> // header, definisi port ada pada file ini

bit i;

P1_0 = 1 ; // memberikan nilai 1 kepada port P1.0
P1_1 = 0 ; // memberikan nilai 0 kepada port P1.1
i = P1_0 ; // membaca nilai pada P1.0 dan nilainya di berikan ke variabel i

Definisi file header device untuk SDCC dapat dilihat pada folder include-mcs51 berikut merupakan contoh header, penggunaan file header ini disesuaikan dengan mikrokontroller yang digunakan.




/*-------------------------------------------------------------------------
Register Declarations for ATMEL 89x51 Processors

Written By - Bernd Bartmann
Bernd.Bartmann@picard.isdn.cs.tu-berlin.de (1999)
based on reg51.h by Sandeep Dutta sandeep.dutta@usa.net
KEIL C compatible definitions are included

This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

In other words, you are welcome to use, share and improve this program.
You are forbidden to forbid anyone else to use, share and improve
what you give them. Help stamp out software-hoarding!
--------------------------------------------------------------------------*/

#ifndef AT89x51_H
#define AT89x51_H

/* BYTE addressable registers */
__sfr __at 0x80 P0 ;
__sfr __at 0x81 SP ;
__sfr __at 0x82 DPL ;
__sfr __at 0x83 DPH ;
__sfr __at 0x87 PCON ;
__sfr __at 0x88 TCON ;
__sfr __at 0x89 TMOD ;
__sfr __at 0x8A TL0 ;
__sfr __at 0x8B TL1 ;
__sfr __at 0x8C TH0 ;
__sfr __at 0x8D TH1 ;
__sfr __at 0x90 P1 ;
__sfr __at 0x98 SCON ;
__sfr __at 0x99 SBUF ;
__sfr __at 0xA0 P2 ;
__sfr __at 0xA8 IE ;
__sfr __at 0xB0 P3 ;
__sfr __at 0xB8 IP ;
__sfr __at 0xD0 PSW ;
__sfr __at 0xE0 ACC ;
__sfr __at 0xE0 A ;
__sfr __at 0xF0 B ;


/* BIT addressable registers */
/* P0 */
__sbit __at 0x80 P0_0 ;
__sbit __at 0x81 P0_1 ;
__sbit __at 0x82 P0_2 ;
__sbit __at 0x83 P0_3 ;
__sbit __at 0x84 P0_4 ;
__sbit __at 0x85 P0_5 ;
__sbit __at 0x86 P0_6 ;
__sbit __at 0x87 P0_7 ;

/* TCON */
__sbit __at 0x88 IT0 ;
__sbit __at 0x89 IE0 ;
__sbit __at 0x8A IT1 ;
__sbit __at 0x8B IE1 ;
__sbit __at 0x8C TR0 ;
__sbit __at 0x8D TF0 ;
__sbit __at 0x8E TR1 ;
__sbit __at 0x8F TF1 ;

/* P1 */
__sbit __at 0x90 P1_0 ;
__sbit __at 0x91 P1_1 ;
__sbit __at 0x92 P1_2 ;
__sbit __at 0x93 P1_3 ;
__sbit __at 0x94 P1_4 ;
__sbit __at 0x95 P1_5 ;
__sbit __at 0x96 P1_6 ;
__sbit __at 0x97 P1_7 ;

/* SCON */
__sbit __at 0x98 RI ;
__sbit __at 0x99 TI ;
__sbit __at 0x9A RB8 ;
__sbit __at 0x9B TB8 ;
__sbit __at 0x9C REN ;
__sbit __at 0x9D SM2 ;
__sbit __at 0x9E SM1 ;
__sbit __at 0x9F SM0 ;

/* P2 */
__sbit __at 0xA0 P2_0 ;
__sbit __at 0xA1 P2_1 ;
__sbit __at 0xA2 P2_2 ;
__sbit __at 0xA3 P2_3 ;
__sbit __at 0xA4 P2_4 ;
__sbit __at 0xA5 P2_5 ;
__sbit __at 0xA6 P2_6 ;
__sbit __at 0xA7 P2_7 ;

/* IE */
__sbit __at 0xA8 EX0 ;
__sbit __at 0xA9 ET0 ;
__sbit __at 0xAA EX1 ;
__sbit __at 0xAB ET1 ;
__sbit __at 0xAC ES ;
__sbit __at 0xAF EA ;

/* P3 */
__sbit __at 0xB0 P3_0 ;
__sbit __at 0xB1 P3_1 ;
__sbit __at 0xB2 P3_2 ;
__sbit __at 0xB3 P3_3 ;
__sbit __at 0xB4 P3_4 ;
__sbit __at 0xB5 P3_5 ;
__sbit __at 0xB6 P3_6 ;
__sbit __at 0xB7 P3_7 ;

__sbit __at 0xB0 RXD ;
__sbit __at 0xB1 TXD ;
__sbit __at 0xB2 INT0 ;
__sbit __at 0xB3 INT1 ;
__sbit __at 0xB4 T0 ;
__sbit __at 0xB5 T1 ;
__sbit __at 0xB6 WR ;
__sbit __at 0xB7 RD ;

/* IP */
__sbit __at 0xB8 PX0 ;
__sbit __at 0xB9 PT0 ;
__sbit __at 0xBA PX1 ;
__sbit __at 0xBB PT1 ;
__sbit __at 0xBC PS ;

/* PSW */
__sbit __at 0xD0 P ;
__sbit __at 0xD1 FL ;
__sbit __at 0xD2 OV ;
__sbit __at 0xD3 RS0 ;
__sbit __at 0xD4 RS1 ;
__sbit __at 0xD5 F0 ;
__sbit __at 0xD6 AC ;
__sbit __at 0xD7 CY ;


/* BIT definitions for bits that are not directly accessible */
/* PCON bits */
#define IDL 0x01
#define PD 0x02
#define GF0 0x04
#define GF1 0x08
#define SMOD 0x80

#define IDL_ 0x01
#define PD_ 0x02
#define GF0_ 0x04
#define GF1_ 0x08
#define SMOD_ 0x80

/* TMOD bits */
#define M0_0 0x01
#define M1_0 0x02
#define C_T0 0x04
#define GATE0 0x08
#define M0_1 0x10
#define M1_1 0x20
#define C_T1 0x40
#define GATE1 0x80

#define M0_0_ 0x01
#define M1_0_ 0x02
#define C_T0_ 0x04
#define GATE0_ 0x08
#define M0_1_ 0x10
#define M1_1_ 0x20
#define C_T1_ 0x40
#define GATE1_ 0x80

#define T0_M0 0x01
#define T0_M1 0x02
#define T0_CT 0x04
#define T0_GATE 0x08
#define T1_M0 0x10
#define T1_M1 0x20
#define T1_CT 0x40
#define T1_GATE 0x80

#define T0_M0_ 0x01
#define T0_M1_ 0x02
#define T0_CT_ 0x04
#define T0_GATE_ 0x08
#define T1_M0_ 0x10
#define T1_M1_ 0x20
#define T1_CT_ 0x40
#define T1_GATE_ 0x80

#define T0_MASK 0x0F
#define T1_MASK 0xF0

#define T0_MASK_ 0x0F
#define T1_MASK_ 0xF0


/* Interrupt numbers: address = (number * 8) + 3 */
#define IE0_VECTOR 0 /* 0x03 external interrupt 0 */
#define TF0_VECTOR 1 /* 0x0b timer 0 */
#define IE1_VECTOR 2 /* 0x13 external interrupt 1 */
#define TF1_VECTOR 3 /* 0x1b timer 1 */
#define SI0_VECTOR 4 /* 0x23 serial port 0 */

#endif


Interrupt Routine


Interrupt/Interrupsi adalah pembelokan(vector) eksekusi program utama ke suatu program interrupt (intterupt routine). Interupsi diakibatkan oleh suatu event yang telah ditentukan sebelumnya mis: timer overflow, serial port, external interrupt. interrupt routine ini dikenal dengan istilah ISR (Interrupt Service Routine).


interrupt Routine di implementasikan dengan format sebagai berikut :


   
void nama_fungsi_interrupt (void) interrupt nomor_interrupt using nomor_bank
{
...
}

nama_fungsi_intterupt adalah nama fungsi yang dapat berupa sembarang nama yang valid untuk sebuah fungsi, nomor_interrupt disesuaikan dengan jenis interrupt yang akan di handle oleh fungsi ini sesuai dengan tabel dibawah, sedangkan nomor_bank merupakan parameter opsional unttuk memilih bank yang akan digunakan untuk menyimpan variabel dalam routine interrupt ini.


















































Tabel Nomor Interrupt
Interrupt
Deskripsi
Alamat Vector
0
External Interrupt 0
0x03
1
Timer 0 Overflow
0x0B
2
External Interrupt 1
0x13
3
Timer 1 Overflow
0x1B
4
Serial Port
0x23
5
Timer 2 (8052)
0x2B
...
-
...
n
-
0x03+8*n

Aturan dalam penggunaan interrupt :



  • Variabel global yang digunakan/diakses dari ISR harus dideklarasikan volatile, agar compiler tidak melakukan optimisasi pada varibel ini

  • Hindari memangil suatu fungsi dari ISR, jika harus dilakukan maka fungsi harus dideklarasikan sebagai reentrant

  • Disable intterupt ketika melakukan operasi yang menggunakan data 16 bit /32 bit


Contoh :



#include <at89x51.h> // header

volatile unsigned char n ; // variabel global

void SerialISR (void) interrupt 4
{
if (RI)
{
n = SBUF; // Save Rx byte
RI = 0; // Reset Rx interrupt flag
}
else if (TI)
{
SBUF = n; // Load byte to Tx
TI = 0; // Reset Tx interrupt flag
}
}

void main(void)
{
// 1. Inisialissasi Serial Port
EA = 0; // Disable global interrupt mask
SCON1 = 0x50; // Set UART to 8N1, Rx enabled
TMOD |= 0x20; // Set Timer 1 as Mode 2
TH1 = 0xDD; // Set SCI_1 for 2400 baud
TR1 = 1; // Enable Timer 1
ES = 1; // Enable interrupts for serial port
EA = 1; // Enable global interrupt mask

// 2. mengirim data (Tx) 0x53
n = 0x53 ;
SBUF1 = n;

// 3. Program loop...
while (1);
}

Model Memory


SDCC mendukung dua model memory yaitu :



  • Small (RAM internal)

  • Large (RAM eksternal)


Secara default SDCC akan menggunakan model memory small, dan semua variabel tanpa storage class akan dilokasikan di RAM Internal, ketika menggunakan model memory large maka semua variabel tanpa storage class akan dialokasikan di RAM eksternal. untuk menggunakan model memory large maka pada saat compile harus diikutkan parameter --model-large contoh :



sdcc --model-large nama_file_source.c



Langkah Pemrogramman



  1. Pembuatan source program, pembuatan source program dapat dilakukan menggunakan sembarang teks editor mis : notepad, tetapi langkah baiknya jika dibuat di teks editor yang mempunyai fasilitas syntax highlighting (Programmer Notepad), kemudian simpan file source yang telah dibuat dengan ekstensi .c

  2. Compile source program, jika terjadi kesalahan cek kesalahan sesuai dengan pesan yang muncul, setelah proses compile berhasil maka akan terbentuk suatu file hex(.ihx) yang merupakan kode biner dari program yang telah kita buat.

  3. Pemrograman ke dalam mikrokontroller menggunakan programmer, file hex siap untuk di masukkan kedalam mikrokontroller

  4. Mikrokontroller dijalankan pada rangkainnya (Run)



sdcc nama_file_source.c


No comments: