"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 :
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 :