Artikel ini sengaja saya tulis sebagai awal pembelajaran bagaimana membuat sebuah program aplikasi mikrokontroler AVR (khususnya ATMega32 dengan frekuensi kristal 7,3728MHz) untuk membuat animasi LED berjalan dari pin 0 hingga 7.
Rangkaian yang digunakan ditunjukkan pada Gambar 1, sengaja LED
disusun secara CA atau common Anoda, sehingga untuk menyalakan LED harus
dikirimkan logika ‘0′.
Untuk kompilasi digunakan AVR Studio versi 4.0 (silahkan unduh GRATIS
dari http://www.atmel.com). Program kita awali dengan beberapa macam
deklarasi, keterangan sengaja saya masukkan dalam listing program untuk
memudahkan pembelajaran langsung dari listingnya, perhatikan instruksi
yang diawali dengan ‘.’ merupakan directive dari AVR Studio, bukan
instruksi assembly mikrokontroler AVR:
;------------------------------------------
;animasi LED berjalan dalam bahasa Assembly
;untuk mikrokontroler Atmel AVR ATMega32
;frekuensi kristal 7.3728MHz
;http://agfi.staff.ugm.ac.id
;------------------------------------------
.nolist ;bagian ini
.include "m32def.inc" ;tidak perlu ditampilkan dalam
.list ;berkas list
Ingat berkas “m32def.inc” kita sertakan (directive .include)
karena akan digunakan pustaka ATMega32 dalam program kita, tetapi tidak
perlu disertakan dalam hasil berkas LIST-nya (hasil kompilasi
program) menggunakan directive .nolist dan .list.
Selanjutnya dilakukan inisialisasi awal:
;----------inisialisasi konstanta dan register
.equ led=0b01111111 ;portb-7 ON
.def temp=r16 ;temp sebagai alias untuk R16
;====== program utama ====================
.cseg
.org 0000 ;awal kode program pada alamat 0x0000
Variabel LED digunakan untuk menyimpan data yang akan dikeluarkan melalui PORTA, awalnya diisi 0b01111111,
artinya LED-0 akan dinyalakan terlebih dahulu. Variabel TEMP digunakan
variabel alias untuk R16 (register-16), Anda boleh menggunakan nama
alias apa saja, misalnya, tahu, brokoli, wortel dan lain sebagainya
(emang buat sayur yach? he he he)…
Program diawali dengan mendeklarasikan segmen kode (.cseg) dan dimulai alamat 0×0000 (.org)
- ini paling logis kita siapkan di alamat tersebut, silahkan saja kalo
mo diganti dengan alamat lain asalkan tidak konflik dengan kepentingan
lainnya dalam program. Ragu-ragu? Ya sudah ikuti saja pake alamat
0×0000, aman dech…!
Selanjutnya kita lakukan INISIALISASI STACK:
;menyiapkan alamat SP - Stack Pointer
;harus dituliskan sebagai inisialisasi SP pada RCALL
;jika tidak dilakukan program akan macet!
ldi temp,low(ramend)
out spl,temp
ldi temp,high(ramend)
out sph,temp
Jika Anda lupa atau tidak melakukan inisialisasi stack, ada
kemungkinan besar akan terjadi kemacetan pada program, artinya program
seakan-akan stuck. Jika Anda menggunakan simulator semacam Proteus (yang
pernah saya coba menggunakan Proteus 7.6 SP4), program akan berjalan
tanpa kesalahan, namun ketika dicobakan ke rangkaian sesungguhnya
program akan berhenti (stuck). Saran saya, ada baiknya tidak terlalu
mengandalkan simulator mikrokontroler semacam Proteus, usahakan untuk
mencoba di dunia nyata, di rangkaian sesungguhnya. Berikut cuplikan
program untuk menginisialisasi stack di akhir ruang RAM (RAMEND).
Karena STACK pada ATMega32 ukuran 16bit atau 2byte, maka pengisian SP
dilakukan dua kali untuk SP Low atau SPL dan SP High atau SPH. Fungsi Low() dan High() masing-masing digunakan untuk mendapatka bagian LOW atau HIGH dari variabel RAMEND yang
suda tersimpan dalam “m32def.inc”. Pengisian register pada AVR tidak
bisa dilakukan langsung, dalam hal ini melalui variabel TEMP baru
kemudian dipindahkan ke SPL dan SPH. Hal ini berlaku juga untuk penjelasan terkait berikut ini…
Berikutnya, karena kita menggunakan mikrokontroler AVR, sudah wajib
kita menentukan sebuah PORT sebagai masukan atau luaran, jika
masing-masing bit pada register DDRx diberi nilai ‘1′ artinya sebagai
luaran (jika ‘0′ sebagai masukan). Karena digunakan PORTA maka digunakan register DDRA (penulisan ke DDRA (out ddra,temp) tidak bisa langsung, sehingga digunakan variabel TEMP (ldi temp,0b01111111)):
;----------- inisialisasi port---------------------
ldi temp,0b11111111 ;set semua bit register temp
out ddra,temp ;tuliskan ke register DDRA
Selanjutnya program utama dituliskan:
;--------portb telah di seting menjadi luaran ------
ldi temp,led ;isi register temp dengan led7
sec ;set carry flag (agar carry=1, LED mati)
putar:
out porta,temp ;kirim data ke porta (LED)
rcall tunda ;tunda sesaat 0.25 detik
ror temp ;putar satu bit ke kanan melalui carry
rjmp putar ;lompat ke label putar
Data disimpan terlebih dahulu di variabel TEMP (ldi temp,led),
kemudian baru dikeluarkan ke PORTA (out porta,temp), tidak bisa langsung
dikirim ke PORTA. Untuk menggeser dan memutar bit pada variabel TEMP
digunakan instruksi ROR (Rotate Right Using Carry),
karena melewati Carry sedangkan Carry biasanya isinya ‘0′, maka harus
diberi ‘1′ dulu dengan instruksi SEC. Pengulangan dilakukan dengan
melompat kembali ke label ‘putar’ menggunakan rjmp putar.
Bagian akhir dari program adalah subrutin penundaan sekitar 0.25detik
(lihat pada listing program lengkap). Kok bisa ya? Ya pake saja program
AVR Delay Loop Generator, sebagaimana screen shoot-nya ditunjukkan pada Gambar 2, silahkan unduh gratis di-sini.
Memang menggunakan pengulangan register, penundaan 0.25 detik tidak
akan akurat, tetapi lumayan buat melakukan penundaan sesaat. Jika Anda
ingin akurat, gunakan fasilitas Timer/Counter pada mikrokontroler AVR
yang bersangkutan.
Program selengkapnya sebagai berikut (ingat akhiri program dengan .exit)…
;------------------------------------------
;animasi LED berjalan dalam bahasa Assembly
;untuk mikrokontroler Atmel AVR ATMega32
;frekuensi kristal 7.3728MHz
;http://agfi.staff.ugm.ac.id
;------------------------------------------
.nolist ;bagian ini
.include "m32def.inc" ;tidak perlu ditampilkan dalam
.list ;berkas list
;----------inisialisasi konstanta dan register
.equ led=0b01111111 ;portb-7 on
.def temp=r16 ;temp sebagai alias untuk R16
;====== program utama ====================
.cseg
.org 0000 ;awal kode program pada alamat 0x0000
;menyiapkan alamat SP - Stack Pointer
;harus dituliskan sebagai inisialisasi SP pada RCALL
;jika tidak dilakukan program akan macet!
ldi temp,low(ramend)
out spl,temp
ldi temp,high(ramend)
out sph,temp
;----------- inisialisasi port---------------------
ldi temp,0b11111111 ;set semua bit register temp
out ddra,temp ;tuliskan ke register DDRA
;--------portb telah di seting menjadi luara ------
ldi temp,led ;isi register temp dengan led7
sec ;set carry flag (agar carry=1, LED mati)
putar:
out porta,temp ;kirim data ke porta (LED)
rcall tunda ;tunda sesaat 0.25 detik
ror temp ;putar satu bit ke kanan melalui carry
rjmp putar ;lompat ke label putar
; =============================
; delay loop generator
; 1843200 cycles:
; untuk frek 7.3728MHz
; penundaan 0.25 detik
; -----------------------------
; delaying 1843182 cycles:
tunda:
ldi R17, $12
WGLOOP0: ldi R18, $A1
WGLOOP1: ldi R19, $D3
WGLOOP2: dec R19
brne WGLOOP2
dec R18
brne WGLOOP1
dec R17
brne WGLOOP0
; -----------------------------
; delaying 18 cycles:
ldi R17, $06
WGLOOP3: dec R17
brne WGLOOP3
; =============================
ret
; =============================
.exit ;akhir program
Sedangkan dalam Bahasa C Native (menggunakan AVR Studio 4 dan GCC) ditunjukkan lengkap sebagai berikut:
//========================================
// animasi LED di PORTA
//=========================================
#include
#include //pustaka DELAY untuk frek 1MHz
#define PORTLED PORTB //penentuan alias untuk PORTB
#define DDRLED DDRB //penentuan alias untuk DDRB
int main (void)
{
unsigned char temp=0x80; // data untuk LED
DDRLED=0xFF; // PORT sebagai luaran
while(1){
PORTLED=temp; //tulis ke port
_delay_ms(250); //lakukan penundaan sesaat
temp=(temp<<7)|(temp>>1);} //ROR dalam bahasa C
return(0);
}
Silahkan Anda cermati perbedaan penulisan menggunakan Assembly dan Native C (gcc), untuk urusan penundaah digunakan fungsi _delay_ms()
yang sudah didefinisikan di berkas “delay.h” dan berlaku untuk
frekuensi operasional 1MHz. Sedangkan inisialisasi PORT sama seperti
pada Assembly. Yang mungkin Anda pertanyakan adalah pengganti perintah ROR yaitu menggunakan instruksi “temp=(temp<<7)|(temp>>1);“, untuk ROL tinggal Anda ganti dengan “temp=(temp<<1)|(temp>>7);” dan “unsigned char temp=0×80;” menjadi “unsigned char temp=0×01;“.
Demikian penjelasan singkat saya tentang aplikasi animasi LED
berjalan menggunakan bahasa assembly dan C untuk mikrokontroler AVR
ATMega32. Semoga bermanfaat dan sukses selalu untuk Anda!
0 komentar:
Posting Komentar