Kali ini kita akan menggunakan 4 buah 7 segment untuk membuat jam sederhana
"wahhh..kalo banyak 7 segmentnya, ngabisin banyak port dong ?"
Jangan khawatir, kita pake teknik " SCANNING", artinya kita hidupin segment satu persatu, tiap segment diparalel saja...tp kita hidupin dengan memberikan switch/saklar ke common port 7segment yg dikontrol oleh port micro ..dan scanningnya cepetttt...sehingga mata kita melihatnya seperti nyala biasa aja.
jadi untuk bikin 7-segment 4 buah, diperlukan 7 port display(diparalel) + 4 port control
rangkaiannya seperti berikut :
klik untuk memperbesar gambar
Biasanya untuk display yg agak besar, kita perlu transistor untuk mengatur scanning, tp karena contoh kali ini memakai segment yg kecil maka tidak memerlukan kontrol memakai transistor ( coba pake transistor dijamin nyalanya redup !!)
Prinsip jam kali ini menggunakan prinsip DELAY, jadi tidak terlalu akurat.
Sebenernya mau seh membagi ilmu untuk jam yg super akurat, tapi ntar aja yahh..soalnya memerlukan pengetahuan mengenai "Timer/Counter" dari microcontroller
source code nya sebagai berikut :
#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>
int jam=0, min=0, detik=0; //variable global untuk menyimpan data2 waktu
void segmen (int angka)
{
switch (angka)
{
case 0 : { PORTB =0b1000000; break ; }
case 1 : { PORTB =0b1111001; break ; }
case 2 : { PORTB =0b0100100; break ; }
case 3 : { PORTB =0b0110000; break ; }
case 4 : { PORTB =0b0011001; break ; }
case 5 : { PORTB =0b0010010; break ; }
case 6 : { PORTB =0b0000010; break ; }
case 7 : { PORTB =0b1111000; break ; }
case 8 : { PORTB =0b0000000; break ; }
case 9 : { PORTB =0b0010000; break ; }
case 10 : { PORTB =0b1111111; break ; } //blank biar ga berbayang
}
}
void clock (void) //fungsi penambah waktu
{
detik ++; //jika fungsi dipanggil maka var detik ditambah
if ( detik == 60) // tambahkan menit jika 60 detik
{ detik=0; //untuk kembali ke 0
min++;
}
if ( min == 60) // tambahkan jam jika 60 menit
{ min = 0; //untuk kembali ke 0
jam++ ;
}
if (jam == 24) jam=0; //untuk kembali ke 0
}
int main(void)
{
int counter=0; //variabel delay
int digit; //variabel digit yang ditampilkan
// Port untuk display 7 segment
DDRB |= (1<<PB0)|(1<<PB1)|(1<<PB2)|(1<<PB3)|(1<<PB4)|(1<<PB5)|(1<<PB6);
//port untuk scanning ( PD0-4) dan dot ":" (PD6)
DDRD |= (1<<PD0)|(1<<PD1)|(1<<PD2)|(1<<PD3) |(1<<PD6);
//tombol untuk nambah jam/menit
DDRD &= ~(1<<PD4) & ~(1<<PD5) ;
PORTD = (1<<PD6) ; // blink untuk ":"
while(1)
{
counter++ ; //bikin delay nambah terusss
// sesuaikan nilai max counter dengan detik yg pas, tentunya tidak akurat
if(counter == 30) { counter =0 ; clock(); }
// nilai 1/2 dari counter untuk blink ":"
if(counter == 15) PORTD ^=(1<<PD6) ;
else{
segmen(10); // kasi display "mati' agar tidak berbayang
//digit pertama
digit = jam/10;
PORTD |= (1<<PD0); // 7 segment no1 hidup..yg laen mati
PORTD &= ~(1<<PD1) & ~(1<<PD2) & ~(1<<PD3) ;
segmen(digit);
_delay_ms(5);
//digit ke 2
segmen(10);
digit = jam%10;
PORTD |= (1<<PD1); // 7 segment no2 hidup..yg laen mati
PORTD &= ~(1<<PD0) & ~(1<<PD2) & ~(1<<PD3) ;
segmen(digit);
_delay_ms(5);
//digit ke 3
segmen(10);
digit = min/10;
PORTD |= (1<<PD2); // 7 segment no3 hidup..yg laen mati
PORTD &= ~(1<<PD1) & ~(1<<PD0) & ~(1<<PD3) ;
segmen(digit);
_delay_ms(5);
//digit ke 4
segmen(10);
digit = min%10;
PORTD |= (1<<PD3); // 7 segment no4 hidup..yg laen mati
PORTD &= ~(1<<PD1) & ~(1<<PD2) & ~(1<<PD0) ;
segmen(digit);
_delay_ms(5);
}
if (bit_is_set(PIND, PIND4)) //tombol nambah jam
{
jam++;
if(jam==24) jam =0;
_delay_ms(100);
}
if (bit_is_set(PIND, PIND5)) //tombol nambah menit
{
min++;
if(min==60) min=0;
_delay_ms(100);
}
}
return 0;
}
jika ingin mengetest/kalibrasi delay detik, ganti salah satu digit untuk menampilkan detik
//digit pertama
digit = detik/10;
PORTD |= (1<<PD0); // 7 segment no1 hidup..yg laen mati
PORTD &= ~(1<<PD1) & ~(1<<PD2) & ~(1<<PD3) ;
segmen(digit);
_delay_ms(5);
//digit ke 2
segmen(10);
digit = detik%10;
PORTD |= (1<<PD1); // 7 segment no2 hidup..yg laen mati
PORTD &= ~(1<<PD0) & ~(1<<PD2) & ~(1<<PD3) ;
segmen(digit);
_delay_ms(5);
Bagaimana dengan jam akurat ? disini nih kuncinya ...menggunakan xtal 4Mhz
/* ===================
GUNAKAN XTAL 4MHZ dan 2 buah capacitor 22pf
dan sambungkan seperti gambar di petunjuk awal
di bagian menggunakan xtal dan ubah dusebit
rangkaian tetap sama seperti jam_sederhana
hanya tambahan xtal pada kaki 4 dan 5 serta
masing kaki xtal dihubungkan ke GND oleh
capacitor 22pf
*/
#define F_CPU 4000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
int jam=0, min=0, detik=0;
void segmen (int angka)
{
switch (angka)
{
case 0 : { PORTB =0b1000000; break ; }
case 1 : { PORTB =0b1111001; break ; }
case 2 : { PORTB =0b0100100; break ; }
case 3 : { PORTB =0b0110000; break ; }
case 4 : { PORTB =0b0011001; break ; }
case 5 : { PORTB =0b0010010; break ; }
case 6 : { PORTB =0b0000010; break ; }
case 7 : { PORTB =0b1111000; break ; }
case 8 : { PORTB =0b0000000; break ; }
case 9 : { PORTB =0b0010000; break ; }
case 10 : { PORTB =0b1111111; break ; } //blank biar ga berbayang
}
}
ISR(TIMER1_COMPA_vect)
{
detik ++;
if ( detik == 60)
{ detik=0;
min++;
}
if ( min == 60)
{ min = 0;
jam++ ;
}
if (jam == 24) jam=0;
}
int main(void)
{
int digit;
TCCR1B |= (1 << WGM12); // Configure timer 1 for CTC mode
TIMSK |= (1 << OCIE1A); // Enable CTC interrupt
OCR1A = 62499; //compare the CTC A
TCCR1B |= (1 << CS11)|(1 << CS10); // Start timer at Fcpu/64
DDRB |= (1<<PB0)|(1<<PB1)|(1<<PB2)|(1<<PB3)|(1<<PB4)|(1<<PB5)|(1<<PB6);
DDRD |= (1<<PD0)|(1<<PD1)|(1<<PD2)|(1<<PD3) |(1<<PD6);
DDRD &= ~(1<<PD4) & ~(1<<PD5) ;
sei();
while(1)
{
if(TCNT1 < 31250) PORTD |=(1<<PD6) ;
else PORTD &=~(1<<PD6) ;
segmen(10);
digit = jam/10;
PORTD |= (1<<PD0);
PORTD &= ~(1<<PD1) & ~(1<<PD2) & ~(1<<PD3) ;
segmen(digit);
_delay_ms(5);
segmen(10);
digit = jam%10;
PORTD |= (1<<PD1);
PORTD &= ~(1<<PD0) & ~(1<<PD2) & ~(1<<PD3) ;
segmen(digit);
_delay_ms(5);
segmen(10);
digit = min/10;
PORTD |= (1<<PD2);
PORTD &= ~(1<<PD1) & ~(1<<PD0) & ~(1<<PD3) ;
segmen(digit);
_delay_ms(5);
segmen(10);
digit = min%10;
PORTD |= (1<<PD3);
PORTD &= ~(1<<PD1) & ~(1<<PD2) & ~(1<<PD0) ;
segmen(digit);
_delay_ms(5);
if (bit_is_set(PIND, PIND4))
{
jam++;
if(jam==24) jam =0;
_delay_ms(100);
}
if (bit_is_set(PIND, PIND5))
{
min++;
if(min==60) min=0;
_delay_ms(100);
}
}
return 0;
}
hasilnya dapat dilihat seperti berikut :