Önceki bölümde bahsettiğim gibi bu bölümde alarm ayarlama kısmını paylaşacağım. Ayarladığımız saat ve dakika bilgisini eeprom içinde tutuyorum. Pil ile sürekli enerji olacağını düşünürsek buna gerek kalmayabilir. Eeprom için “avr/eeprom.h” kütüphanesini kullanıyorum. Nongnu.org burada bir çok kütüphanenin nasıl kullanılacağı anlatılmış, bu yüzden detaya inmeyeceğim. Aşağıda “main” fonksiyonunu tekrar paylaşıyorum. Gördüğünüz gibi “alarmSaat=eeprom_read_byte((uint8_t*)0);” ve “alarmDakika=eeprom_read_byte((uint8_t*)1);” olarak iki değişkeni eepromdan okuyarak değer veriyoruz. “ayarAlarm_saat=alarmSaat;” ve “ayarAlarm_dakika=alarmDakika;” kısmıysa alarm ayarlarken kullandığım değişkenler. Bu atamayı yapmazsam alarm ayarlama ekranında saat ve dakikayı “0” olarak görürüm bu atama sayesinde önceki ayarlı değeri görerek ayarlamaya başlayabiliyorum.
int main(void){
lcd_basla();
_delay_ms(2000);
lcd_krk(0,zil);
alarmSaat=eeprom_read_byte((uint8_t*)0);
alarmDakika=eeprom_read_byte((uint8_t*)1);
ayarAlarm_saat=alarmSaat;
ayarAlarm_dakika=alarmDakika;
adcBasla();
DS_OUT;
DDRB|=(1<<PORTB2); //alarm için pin ayarlandı
PORTB|=(1<<PORTB2);
while (1) {
saat_oku();
tarih_oku();
ekran_yaz[ekran]();
buton_kontrol();
alarm_kontrol();
_delay_ms(50);
LCD_CL;
_delay_ms(2);
}
}
|
“while” döngüsü içinde
“alarm_kontrol” fonksiyonu çağrılıyor. Saat ve dakikanın kontrolü bu fonksiyon
tarafından yapılıyor. Saat - alarm saat, dakika -alarm dakikayı ve alarmın açık
ya da kapalı olmasını kontrol ettiğimiz alarm değişkeni istenen şartı yerine
getirdiğinde alarm çalışmaya başlıyor. Ben burada 3 döngüde bir ekran ışığını
açacak şekilde ayarladım. Dilediğiniz pini “1” yaparak ses ya da ışıklı bir
uyarıcı oluşturabilirsiniz.
void alarm_kontrol(){
if ((alarm==1)&&(saat==alarmSaat)&&(dakika==alarmDakika)){
if (ekran_say>=3){
ekran_say=0;
PORTB|=(1<<PORTB2);
}else {
PORTB&=~(1<<PORTB2);
}
ekran_say++;
}else{
PORTB|=(1<<PORTB2);
}
}
|
Alarm durumunu bu
şekilde kontrol ettik ayarlama kısmını oluşturacağınız ekranda “buton_kontrol”
fonksiyonu ya da farklı bir fonksiyonla değerleri değiştirip
ayarlayabilirsiniz. Sadece son kayıt
işleminde eeproma yazma işlemini yapmanız gerekir. Kodu aşağıda paylaştım.
eeprom_update_byte((uint8_t*)0,ayarAlarm_saat);
eeprom_update_byte((uint8_t*)1,ayarAlarm_dakika);
alarmSaat=ayarAlarm_saat;
alarmDakika=ayarAlarm_dakika;
|
Menüler arası geçiş ya
da birden fazla seçenek olduğunda genellikle eşitlik söz konusu ise “switch
case” büyük-küçük ilişkisi söz konusu
ise “if else” kullanmaya çalışıyorum. Bu basit saat programında her menü ayrı
bir “ekran” yazan fonksiyondan oluşuyor. Bunu “switch case” ya da “if else” ile
de yapabilirdim. Fakat çok karmaşık ve kontrol etmesi zor bir programla karşı
karşıya kalacaktım. Facebook grubunda bir paylaşımda gördüğüm “jump table”
nedir diye araştırmaya başladım. Daha önce yüzeysel olarak geçtiğim
işaretçiler (pointer) konusuna tekrar döndüm birçok kaynaktan okudum. Taha
Yasin Erkan sitesinde bu konuyu anlaşılır şekilde anlatmış. Detaya inmeden
olayın özü her fonksiyon ismi aynı zamanda adres tıpkı dizi isimleri gibi
fonksiyonun adresini tutuyor. Fonksiyon isimlerinden işaretçi dizisi
oluşturabiliyoruz. Nasıl “int *ptr; “ gibi bir işaretçi tanımlayıp adres değeri
saklayabiliyorsak. “void (*foknsiyon) (void);” şeklinde fonksiyon işaretçi
tanımlayabiliyoruz. Burada parantezlerin önemli olduğu yazılıydı. Bizim
tanımlamamız void (*foknsiyon[]) (void)={a,b,c} şeklide olacak a,b ve c
fonksiyon isimleridir. Aşağıda paylaştım dikkat ederseniz aynı dizi
elemanlarında olduğu gibi fonkiyonların sırası da önemli. Main fonksiyonu
paylaşımıma bakarsanız döngü içinde “ekran_yaz[ekran]();” şeklide çağrılıyor. Ekran
değişkeni değeri kaç ise hemen o fonksiyona gidiliyor.
void (*ekran_yaz[10])(void)={
ana_ekran,
prog_gun,
prog_ay,
prog_yil,
prog_saat,
prog_dakika,
alarm_ekran,
prog_alarm_saat,
prog_alarm_dakika
};
|
Umarım faydalı
olmuştur. Burada kodun tamamını paylaşmayacağım. Bazı kısımlarını bilerek
eklemiyorum. Kopyalayıp alırsanız çalışmaz bunu tekrar bir araya getirmek için
emek harcamanız dolayısıyla öğrenmeniz gerekecek.
/*
* alarm_saat.c
*
* Created: 26.02.2019 19:23:16
* Author : haluk
*/
//kütüphaneler
#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/eeprom.h>
#include <util/delay.h>
#include <stdlib.h>
#include <stdio.h>
//pin-port tanımları
#define DATA_PORT PORTD
#define CMD_PORT PORTB
#define DS_PORT PORTB
#define EN_ PB1
#define RS_ PB0
#define CE_ PB3
#define IO_ PB4
#define CLK_ PB5
#define DATA_7 PD7
#define DATA_6 PD6
#define DATA_5 PD5
#define DATA_4 PD4
//io tanımları
#define DATA_OUT DDRD|=(1<<DATA_7)|(1<<DATA_6)|(1<<DATA_5)|(1<<DATA_4)
#define DS_OUT DDRB|=(1<<CE_)|(1<<CLK_)
#define IO_OUT DDRB|=(1<<IO_)
#define IO_IN DDRB&=~(1<<IO_)
#define CMD_OUT DDRB|=(1<<RS_)|(1<<EN_)
//
#define EN_HIGH CMD_PORT|=(1<<EN_)
#define EN_LOW CMD_PORT&=~(1<<EN_)
#define RS_HIGH CMD_PORT|=(1<<RS_)
#define RS_LOW CMD_PORT&=~(1<<RS_)
#define CE_HIGH DS_PORT|=(1<<CE_)
#define CE_LOW DS_PORT&=~(1<<CE_)
#define IO_HIGH DS_PORT|=(1<<IO_)
#define IO_LOW DS_PORT&=~(1<<IO_)
#define CLK_HIGH DS_PORT|=(1<<CLK_)
#define CLK_LOW DS_PORT&=~(1<<CLK_)
//lcd komutlar
//saat tanımları
#define Y_SAN 0x80
#define O_SAN 0x81
#define Y_DAK 0x82
#define O_DAK 0x83
#define Y_SAT 0x84
#define O_SAT 0x85
#define Y_GUN 0x86
#define O_GUN 0x87
#define Y_AY 0x88
#define O_AY 0x89
#define Y_YIL 0x8C
#define O_YIL 0x8D
//buton tanımları
#define yukari 1
#define asagi 2
#define sol 3
#define sag 4
#define sec 5
#define bos 0
//değişkenler
int8_t ayarGun, ayarAy,ayarYil,ayarSaat,ayarDakika;
int8_t ayarAlarm_saat,ayarAlarm_dakika;
uint8_t saat,dakika,saniye,alarm,gun,ay, yil,alarmSaat,alarmDakika;
uint8_t ekran_say,sagSay=0,solSay=0,ekran=0;
char csaat[3],cdakika[3],csaniye[3],cgun[3],cay[3],cyil[3],cAlarm_saat[3],cAlarm_dakika[3];
uint8_t zil[8] =//0 adresi
{
0x04, 0x0E,0x0E, 0x0E,0x1F,0x1F, 0x04, 0x00
};
void adcBasla(){
ADMUX=(1<<REFS0);
ADCSRA=(1<<ADEN)|(1<<ADPS0)|(1<<ADPS1)|(1<<ADPS2);
}
uint16_t adcOku(uint8_t kanal){
kanal &=0x07;
ADMUX=(ADMUX & 0xF8) | kanal;
ADCSRA |=(1<<ADSC);
while(ADCSRA & (1<<ADSC));
return (ADC);
}
uint8_t buton_durum(){
uint16_t butdeg= adcOku(0);
if(butdeg<50){
_delay_ms(150);
return sag;}
if(butdeg<150) {
_delay_ms(150);
return yukari;}
if(butdeg<300){
_delay_ms(150);
return asagi;}
if(butdeg<450) {
_delay_ms(250);
return sol;}
if(butdeg<700) {
_delay_ms(150);
return sec;}
return bos;
}
void buton_kontrol(){
uint8_t buton=buton_durum();
if (buton==yukari)
switch (ekran){
case 1:
ayarGun++;
if (ayarGun>=32){ayarGun=1;}
break;
case 2:
ayarAy++;
if (ayarAy>=13){ayarAy=1;}
break;
case 3:
ayarYil++;
if (ayarYil>=100){ayarYil=0;}
break;
case 4:
ayarSaat++;
if (ayarSaat>=24){ayarSaat=0;}
break;
case 5:
ayarDakika++;
if (ayarDakika>=60){ayarDakika=0;}
break;
case 6:
break;
case 7:
ayarAlarm_saat++;
if (ayarAlarm_saat>=24){ayarAlarm_saat=0;}
break;
case 8:
ayarAlarm_dakika++;
if (ayarAlarm_dakika>=60){ayarAlarm_dakika=0;}
break;
default:
break;
}
if(buton==asagi)
switch (ekran){
case 1:
ayarGun--;
if (ayarGun<1){ayarGun=31;}
break;
case 2:
ayarAy--;
if (ayarAy<1){ayarAy=12;}
break;
case 3:
ayarYil--;
if (ayarYil<0){ayarYil=99;}
break;
case 4:
ayarSaat--;
if (ayarSaat<0){ayarSaat=23;}
break;
case 5:
ayarDakika--;
if (ayarDakika<0){ayarDakika=59;}
break;
case 6:
break;
case 7:
ayarAlarm_saat--;
if (ayarAlarm_saat<0){ayarAlarm_saat=23;}
break;
case 8:
ayarAlarm_dakika--;
if (ayarAlarm_dakika<0){ayarAlarm_dakika=59;}
break;
default:
break;
}
if(buton==sec){
ekran++;
if (ekran>=1){
ayarGun=gun;
ayarAy=ay;
ayarYil=yil;
}
if(ekran>=2){
ekran=0;
}
}
if (buton==sag){
sagSay ++;
if (ekran==3){
ayarSaat=saat;
ayarDakika=dakika;
}
}
if (buton==sol)
solSay ++;
}
void ds_data (uint8_t dsdata){
IO_OUT;
for (uint8_t i=0;i<=7;i++)
{
if (dsdata&0x01)
{
IO_HIGH;
}else{
IO_LOW;
}
dsdata>>=1;
CLK_HIGH;
_delay_us(10);
CLK_LOW;
}
}
uint8_t ds_oku (uint8_t dsadr){
CE_HIGH;
ds_data(dsadr);
IO_IN;
uint8_t dsoku=0x00;
for (uint8_t i=0;i<=7;i++)
{
dsoku>>=1;
if (PINB&(1<<IO_))
{
dsoku|=0x80;
}
CLK_HIGH;
_delay_us(10);
CLK_LOW;
}
IO_OUT;
CE_LOW;
return dsoku;
}
uint8_t bcd_yaz(uint8_t bcdyaz){
return (((bcdyaz/10)<<4)+(bcdyaz%10));
}
uint8_t bcd_oku(uint8_t bcdoku){
return ((bcdoku>>4)*10)+(bcdoku&0x0F);
}
void saat_ayar(uint8_t _st,uint8_t _dk,uint8_t _san){
CE_HIGH;
ds_data(Y_SAN);
ds_data(bcd_yaz(_san));
CE_LOW;
_delay_us(2);
CE_HIGH;
ds_data(Y_DAK);
ds_data(bcd_yaz(_dk));
CE_LOW;
_delay_us(2);
CE_HIGH;
ds_data(Y_SAT);
ds_data(bcd_yaz(_st));
CE_LOW;
}
void tarih_ayar(uint8_t _gn,uint8_t _ayy,uint8_t _yl){
}
void saat_oku (){
saniye= bcd_oku(ds_oku(O_SAN));
_delay_us(2);
dakika= bcd_oku(ds_oku(O_DAK));
_delay_us(2);
saat= bcd_oku(ds_oku(O_SAT));
}
void tarih_oku (){
}
void alarm_kontrol(){
if ((alarm==1)&&(saat==alarmSaat)&&(dakika==alarmDakika)){
if (ekran_say>=3){
ekran_say=0;
PORTB|=(1<<PORTB2);
}else {
PORTB&=~(1<<PORTB2);
}
ekran_say++;
}else{
PORTB|=(1<<PORTB2);
}
}
void tarih_sablon (){
lcd_git(0,0);
lcd_dizi("Tarih");
lcd_git(8,0);
lcd_yaz('.');
lcd_git(11,0);
lcd_yaz('.');
}
void saat_sablon (){
}
void alarm_sablon(){
lcd_git(6,0);
lcd_dizi("Alarm");
lcd_git(8,1);
lcd_yaz(':');
}
void gun_yaz (uint8_t _gun){
sprintf(cgun,"%d",_gun);
lcd_git(6,0);
if (_gun<10){
lcd_yaz('0');
}
lcd_dizi(cgun);
}
void ay_yaz(uint8_t _ay){
}
void yil_yaz(uint8_t _yil){
}
void saat_yaz (uint8_t _saat){
sprintf(csaat,"%d",_saat);
lcd_git(6,1);
if (_saat<10)
{
lcd_yaz('0');
}
lcd_dizi(csaat);
}
void dakika_yaz (uint8_t _dakika){
}
void saniye_yaz (uint8_t _saniye){
}
void alarm_saat_yaz(uint8_t _alarmSaat){
sprintf(cAlarm_saat,"%d",_alarmSaat);
lcd_git(6,1);
if (_alarmSaat<10)
{
lcd_yaz('0');
}
lcd_dizi(cAlarm_saat);
}
void alarm_dakika_yaz(uint8_t _alarmDakika){
}
void menu_kontrol(){
if (sagSay==1){
if (ekran==0){
alarm++;
if (alarm>=2){
alarm=0;}
sagSay=0;
}else if (ekran==3){
tarih_ayar(ayarGun,ayarAy,ayarYil);
ekran++;
sagSay=0;
}else if (ekran==5){
saat_ayar(ayarSaat,ayarDakika,0);
ekran=0;
sagSay=0;
}else if (ekran==8){
eeprom_update_byte((uint8_t*)0,ayarAlarm_saat);
eeprom_update_byte((uint8_t*)1,ayarAlarm_dakika);
alarmSaat=ayarAlarm_saat;
alarmDakika=ayarAlarm_dakika;
ekran=0;
sagSay=0;
}else {
ekran++;
sagSay=0;
}
}
if (solSay==1){
if (ekran==0){
ekran=6;
solSay=0;
}else if (ekran==6){
ekran=0;
solSay=0;
}else {
ekran--;
solSay=0;
}
}
}
void ana_ekran(){
tarih_sablon();
saat_sablon();
gun_yaz(gun);
ay_yaz(ay);
yil_yaz(yil);
saat_yaz(saat);
dakika_yaz(dakika);
saniye_yaz(saniye);
if (alarm==1){
lcd_git(15,1);
lcd_yaz(0);
}
menu_kontrol();
}
void prog_gun (void){
tarih_sablon();
if (ekran_say>=3){
ekran_say=0;
}else {
gun_yaz(ayarGun);
}
ay_yaz(ayarAy);
yil_yaz(ayarYil);
menu_kontrol();
ekran_say++;
}
void prog_ay (void){
}
void prog_yil (void){
}
void prog_saat (void){
saat_sablon();
if (ekran_say>=3){
ekran_say=0;
}else {saat_yaz(ayarSaat);
}
dakika_yaz(ayarDakika);
saniye_yaz(saniye);
menu_kontrol();
ekran_say++;
}
void prog_dakika (void){
}
void alarm_ekran(){
alarm_sablon();
alarm_saat_yaz(alarmSaat);
alarm_dakika_yaz(alarmDakika);
menu_kontrol();
}
void prog_alarm_saat (void){
alarm_sablon();
if (ekran_say>=3)
{ekran_say=0;
}else {alarm_saat_yaz(ayarAlarm_saat);
}
alarm_dakika_yaz(ayarAlarm_dakika);
menu_kontrol();
ekran_say++;
}
void prog_alarm_dakika (void){
}
void (*ekran_yaz[10])(void)={
ana_ekran,
prog_gun,
prog_ay,
prog_yil,
prog_saat,
prog_dakika,
alarm_ekran,
prog_alarm_saat,
prog_alarm_dakika
};
int main(void){
lcd_basla();
_delay_ms(2000);
lcd_krk(0,zil);
alarmSaat=eeprom_read_byte((uint8_t*)0);
alarmDakika=eeprom_read_byte((uint8_t*)1);
ayarAlarm_saat=alarmSaat;
ayarAlarm_dakika=alarmDakika;
adcBasla();
DS_OUT;
DDRB|=(1<<PORTB2); //alarm için pin ayarlandı
PORTB|=(1<<PORTB2);
while (1) {
saat_oku();
tarih_oku();
ekran_yaz[ekran]();
buton_kontrol();
alarm_kontrol();
_delay_ms(50);
LCD_CL;
_delay_ms(2);
}
}
|
Hiç yorum yok:
Yorum Gönder