Takvim/Saat/Termometre Projem

Başlatan cyberlight, 19 Haziran 2003, 13:09:55

cyberlight

Bu program benim bitirme tezim. Sizinde görüşlerinizi almak istedim.
Proteustaki simülasyon şemasınıda yollamak isterdim ama hem resim eklemeyi bilmiyorum hemde pek zamanım yok.
Devre oldukça basit ve gayet iyi çalışıyor. Bi şüpheniz olmasın
Kullandığım devre elemanları :
PIC16F877
2x16 LCD
LM78L05 (9V’luk pil gerilimini 5V’a düşürmek için)
LM35DZ (ısı sensörü)
BC537 (transistor, backlight için)
4 Mhz Kristal
2 Kapasite (22pF)
Buzzer
Dirençler (lcd bağlantısı ve transsitör için)
4 buton (3’ü ayar için, 1’ide alarm on/off için)



Nokia 5210’un kronometre ve termometresi ile ölçüm yaptım.10 saat için bire bir gidiyolar.Kronometre 10 saatlik olduğu için daha sonrasını bilmiyorum ama olsa olsa günde max 1 saniyelik sapma olur heralde. Sıcaklık algılamada da bir problem yok, birebir.
LCD nin ilk satırında saat  ve alarm on/off durumu, ikinci satırında ise takvim ve sıcaklık bilgisi gösteriliyor. Programda zaten bacak bağlantıları ve bir çok şey açıklanmış durumda.

Programın çalışmasındaki anahtar işlev Timer kesmesinin kullanılmasıdır. Timer kesmesi programcının belirlediği zaman aralıklarında bir kesme üretir. Bu programda kesme zaman aralığı OPTION_REG = $55 komutuyla 16,348ms'ye ayarlanmıştır.
Tmr0 ı saniyede bir kez 255-246 =10 a kurarsak
10 * 64 = 640
61(tick)*16,384= 999,424
1(tick)*640=640
640+999,424 = 1,000,064 usec = 1 saniye  elde ederiz (osc tam 4 MHz ise)  
Aslında teorik olarak Tmr0 saniyede bir kez 9 a kurarsak TAM 1 saniye elde ederiz ancak pratikte bu doğru sonuç vermiyo.Bu da kristalden kaynaklanıyo sanırım. Yaptığım denemeler sonucunda en ideal çözümün bu olduğunu gördüm.

Buradaki 1 komut çevrim süresi (4MHz için 1us), 64 bizim seçtiğimiz ön ölçekleme oranı ve 256’da TMR0’ın sayma sayısıdır. TMR0 00h-FFh değerine kadar toplam 256 defa sayar. Kesmeyi aktif hale getirmek için INTCON yazmacı $A0'a ayarlanır.
62 adet kesme oluştuğunda 1sn olacağından "saniye" değişkenimiz bir artırılır ve LCD güncellenmesi aktif hale getirilir.
PortA.0’a LM35DZ’in çıkışından uygulanan gerilim Adcin komutu ile once sayısal hale daha sonrada uygun dönüşüm ile LCD’de görüntülenecek olan sıcaklık bilgisine dönüştürülür.
B3 butonu backlight’ı açma veya kapama için,
B2 butonu alarm zamanını görüntülemek için ,
B1 butonuda ayar menüsüne giriş için kullanılır.
Ayar menüsündeyken B2 butonu saat-tarih-alarm bilgisini artırmak için, B3 butonuda saat-tarih-alarm bilgisini azaltmak için kullanılır.
B4 anahtarıda alarm On/Off durumunu belirlemek için kullanılır.
Alarm kısmına gelince sound komutundan tam anlamıyla yararlanmak mümkün olmadı, komutta kullanılması gereken bekleme süresi Tmr0 kesmesine engel olmaması için 1ms olarak seçildi. Böyle oluncada doğru düzgün bir melodi elde etmek pek kolay olmuyor. Sound komutunu kullanmak yerine bir role yardımıyla küçük bi alarm devresi sürülmesi daha iyi olur.
Bide girişte sizinde farkedebileceğiniz gibi kayan yazı kısmı var.
Yalnız bi problem var. Ayar menüsüne girip ayar yaptığımızda bir miktar  gecikme meydana geliyor. Çok ciddi bir gecikme değil ama yinede rahatsız ediyor.Bunun üstesinden gelemedim. O yüzden ikide bir ayar yapmamak lazım :)
Başta dediğim gibi yorumlarınızı bekliyorum ve ne tür iyileştirmeler yapılabilir?

'****************************************************************
'*  Name    : Takvim & Saat & Termometre                                                        
'*  Author  : Fatih BİLGİLİ                                                                                      
'*  Notice  : Copyright (c) 2003                                                                                  
'*                                                                                                                          
'*  Date    : 28.05.2003                                                                                        
'*  Version : 3.0                                                                                                    
'*                                                                                                                          
'****************************************************************

Define  LCD_DREG        PORTD         ' LCD data portunu belirler
Define  LCD_DBIT          4                    ' 4 bit'lik veri yolu
Define  LCD_RSREG      PORTE          ' LCD register seçme portunu belirler  
Define  LCD_RSBIT       0                     ' LCD register seçme bitini belirler
Define  LCD_EREG        PORTE          ' LCD enable portunu belirler
Define  LCD_EBIT          1                    ' LCD enable bitini belirler
Define  LCD_LINES        2                   ' LCD'deki satır sayısı

Define ADC_BITS                 10      ' ADC sonucu 10 bitlik
Define ADC_CLOCK            1        ' ADC saat kaynağı( foscillator/8 )
DEFINE ADC_SAMPLEUS  50      ' ADC örnekleme zamanı us cinsinden

Saat          var     byte     ' Saat değişkeni
dSaat        var     byte     ' Display'de görünecek saat değişkeni
Dakika     var     byte     ' Dakika değişkeni
Saniye      var     byte     ' Saniye değişkeni
Tick          var     byte     ' Saniye parçacıkları
Guncelle  var     byte     ' LCD güncellenme değişkeni
i                var    byte      ' Döngü değişkeni
CounterC var     byte     ' Döngü değişkeni
TimeOut  var     word    ' Döngü değişkeni
Gun          var     byte     ' Gün değişkeni
Ay            var     byte     ' Ay değişkeni
Yil            var     byte     ' Yıl değişkeni
X              var     byte     ' Hangi ayın kaç gün çektiğini belirlemek için

as              var    byte     ' Alarm değişkeni (saat)
ad              var    byte    ' Alarm değişkeni (dakika)
z                var    byte    ' Backlight On/Off değişkeni
k                var    byte    ' Kayan yazı değişkeni
d            var    byte    ' Kayan yazı değişkeni  
p            var    word   ' Kayan yazı değişkeni
AD_Rez    var    word   ' ADC işleminin sonucu 16 bit
C               var     byte    ' ADC işlemi için

       TRISA = %11111111          ' Port A giriş
       TRISC = %01111111          ' Port C giriş (8. pin hariç)
       ADCON1 = %10000010     ' Port A analog ve Port E dijital modda
       Low PORTE.2                     ' LCD'yi yazma moduna geçir
       Pause 300                             ' LCD 'nin açılması için bekle

       Saat       =  0        ' Başlangıç zamanı olarak 00:00:00'ı ayarla
       Dakika  =  0
       Saniye  =  0
       Tick      =  0
       Gun      =  1        ' Başlangıç tarihi olarak 01.06.2003 ü ayarla
       Ay        =  6              
       Yil        = 03              
       as          =  1        ' Başlangıçta Alarm 01:00’a kurulu
       ad         =  0

' Girişteki kayan yazı
   k      =  0
   d      =  0
While k =< 21 AND d =< 21
       Lcdout $fe, $8F - k ,   "B"  
       Lcdout $fe, $90 - k ,   "i"  
           Lcdout $fe, $91 - k ,   "T"
                   Lcdout $fe, $92 - k ,   "i"
           Lcdout $fe, $93 - k ,   "R"
           Lcdout $fe, $94 - k ,   "M"
           Lcdout $fe, $95 - k ,   "E"

      Lcdout $fe, $BF + d ,   "i"  
                  Lcdout $fe, $BE + d ,   "Z"  
          Lcdout $fe, $BD + d ,   "E"
          Lcdout $fe, $BC + d ,   "T"

      If k <> 10 then p=150
                  If k = 10 then p=3000
          Pause p  
                    Lcdout $fe,1            
          k = k + 1
                 d = d + 1
   wend  
         
   Low PortC.7               ' Buzzer bağlantı pini      
   Low PortC.1             ' PortC.1 sıfırlanır, Backlight kapalı                                                          
Guncelle = 1      ' Güncelleme aktif
' TMR0 'ı her 16,384 milisaniye de bir kesme üretecek şekilde kur.
       OPTION_REG = $55           ' TMR0 konfigurasyonunu ayarla ve PORTB                                                                                                                    
                                                     ' pullup'larını etkinleştir.
       INTCON = $A0                     ' TMR0 interrupt'ını etkinleştir.
       On Interrupt Goto Tickint     ' Interrupt oluşursa Tickint altprogramına git

' Ana Program Döngüsü
ANADONGU:
       PORTB = 0         ' PORTB pinlerini düğmeleri okumak için LOW konumuna al
       TRISB = $f0       ' PORTB 'nin düğmelere bağlı pinlerini giriş diğerlerini çıkışa
                                   ' ayarla
                   
ADCIN 0, AD_Rez   ' A/D dönüştürme işlemini yürüt ve sonucu AD_Rez                  
                                  ' değişkeninde sakla
' LCD görüntülenecek olan sıcaklık bilgisinin hesaplanması
If  (AD_Rez>=0) AND (AD_Rez<=20) AND (AD_Rez // 2) = 0 then C = (AD_Rez)/2
If  (AD_Rez>21) AND (AD_Rez<=65) AND (AD_Rez // 2) != 0 then C = (AD_Rez-1)/2
If  (AD_Rez>=68) AND (AD_Rez<=110) AND (AD_Rez // 2) = 0 then C = (AD_Rez-2)/2
If  (AD_Rez>=113) AND (AD_Rez<=155) AND (AD_Rez // 2) != 0 then C = (AD_Rez-3)/2
If  (AD_Rez>=158) AND (AD_Rez<=198) AND (AD_Rez // 2) = 0 then C = (AD_Rez-4)/2

           ' Zamanı ayarlamak için set düğmesine basılmışmı?
If PORTB.4 = 0 Then
      Gosub SetButtonRelease
   Goto Setup
   Endif   

           ' Backlight On/Off
   If PORTB.6 = 0 Then
      z = z +1        ' Her basışta z değişkenini 1 artır
   Gosub debounce
   Endif
   If (z // 2) = 0 then      ' z'in 2'ye bölümünden kalan 0 ise backlight On   
           Low PortC.1                      
Else                            ' değilse backlight Off
           High PortC.1
           Endif    

           ' Alarm zamanı geldiyse Alarm alt programına dallan          
If (Saat = as ) AND (Dakika = ad) AND PORTC.0 = 0 Then Goto Alarm  
If PORTC.0 = 1 then
Low PortC.7  
Endif           

' Ekran güncellenecek mi?
Kontrol:  If Guncelle = 1 Then
               Lcdout $fe, 1   ' Ekranı sil
      
               ' Zamanı tt:dd:ss formatında göster t-saat,d-sakika,s-saniye
               dSaat = Saat    ' Saati 0-12 aralığına getir
              If (Saat // 12) = 0 Then
                       dSaat = dSaat + 12
              Endif

               ' AM mi PM mi kontrol et
              If Saat < 12 Then
             Lcdout dec2 dSaat, ":", dec2 Dakika, ":", dec2 Saniye, " AM"
              Else
                       Lcdout dec2 (dSaat - 12), ":", dec2 Dakika, ":", dec2 Saniye, " PM"
              Endif
               
      Low PortC.0       ' PortC.0 sıfırlanır, alarm açık  
      If PORTC.0 = 0 then
      Lcdout $fe, $8D, "*))"
              Endif                    
               
               ' Tarihi gg.aa.yyyy formatında göster g-gün, a-ay, y-yıl
                       Lcdout $fe, $c0, dec2 Gun, ".", dec2 Ay, ".20", dec2 Yil
      Lcdout $fe, $c0 + 12, dec2 C , %11011111, "C"
                 
              If PORTB.5 = 0 Then
                 Lcdout $fe, 1
            Lcdout "Alarm at ", dec2 as, ":", dec2 ad
             Endif
              Guncelle = 0      ' Ekran güncellendi
              Endif
Goto ANADONGU   ' Sonsuz döngü sağla
Setup:
   CounterC=0      ' Setup başlangıcını ayarla ( 0-6 arası yedi adım )
   TimeOut=0      ' Zaman aşımı sayacını sıfırla

SetupLoop:
   LCDOut $FE,1,"Set "

      '   Data giriş menüsünün görüntülenmesi
      '   ----------------------------------------------
   If CounterC=0 then
      LCDOut "Hour"
   Endif
   If CounterC=1 then
      LCDOut "Minute"
   Endif
   If CounterC=2 then
      LCDOut "Year: 20"
   Endif
   If CounterC=3 then
      LCDOut "Month"
   Endif
   If CounterC=4 then
      LCDOut "Day"
   Endif
   If CounterC=5 then
      LCDOut "AHour"
   Endif
   If CounterC=6 then
      LCDOut "AMinute"
   Endif
   
   If CounterC<>2 then
      LCDOut ":"
           Endif

'   Dataların görüntülenmesi
      '   -------------------------------
SetupDisplayLoop:
   If CounterC=0 then
      dSaat = Saat    ' Saati 0-12 aralığına getir
               If (Saat // 12) = 0 Then
                       dSaat = dSaat + 12
               Endif

               ' AM mi PM mi kontrol et
               If Saat < 12 Then
                       LCDOut $FE,$8A
              Lcdout dec2 dSaat, " AM"
               Else
             LCDOut $FE,$8A
                      Lcdout dec2 (dSaat - 12), " PM"
               Endif                  
   Endif                  
                            
   If CounterC=1 then
             LCDOut $FE,$8C            
                              Lcdout dec2 Dakika
   Endif

   If CounterC=2 then
     LCDOut $FE,$8C      
                     Lcdout dec2 Yil      
Endif                
                                           
   If CounterC=3 then
                     LCDOut $FE,$8B      
                       Lcdout dec2 Ay       
   Endif                                      
                                               
   If CounterC=4 then
                             LCDOut $FE,$89      
                     Lcdout dec2 Gun      
   Endif            
                           
   If CounterC=5 then
            LCDOut $FE,$8B      
                     Lcdout dec2 as      
   Endif                      
                                         
   If CounterC=6 then
            LCDOut $FE,$8D      
                     Lcdout dec2 ad      
   Endif        
               











      '   Data girişi
      '   -----------
SetupEntryLoop:
         
         '   Artırma butonuna basılırsa
         '   --------------------------------
       If PORTB.5 = 0 Then
      
      If CounterC=0 then              ' Saati Artır
      Saat = Saat + 1
             If Saat >= 24 Then
                 Saat = 0
         Endif    
                       Endif                                                                                                                                                                 
   
If CounterC=1 then          ' Dakikayı Artır
               Dakika = Dakika + 1
                If Dakika >= 60 Then
                     Dakika = 0
                     Endif             
           Endif
                  
      If CounterC=2 then      ' Yılı Artır
      Yil = Yil + 1    
          Endif   
         
      If CounterC=3 then      ' Ayı Artır   
      Ay = Ay + 1
               If Ay >= 13 Then
           Ay = 1
          Endif
      Endif      
      If CounterC=4 then      ' Günü Artır
               Gun = Gun + 1
                  Gosub Look
                     If gun >= X+1 Then
                     Gun = 1
                     Endif
      Endif   

      If CounterC=5 then      ' Alarm saatini artır
      as = as + 1
if   as > 24 Then
                          as = 1
          Endif
      Endif       

      If CounterC=6 then      ' Alarm dakikasını artır
      ad = ad + 1
                            if ad >= 60 Then
                     ad = 0
                     Endif
      Endif    

      Gosub debounce
      TimeOut=0
      Goto SetUpDisplayLoop
       endif
                           
   




      '   Azaltma butonuna basılırsa
         '   ---------------------------------
       If PORTB.6 = 0 Then

CounterC=0 then
           Saat = Saat - 1
                If Saat >= 24 Then
                            Saat = 23
                Endif
      Endif
            
      If CounterC=1 then
      Dakika = Dakika - 1
                 If Dakika >= 60 Then
           Dakika = 59
                       Endif   
          Endif

      If CounterC=2 then
      Yil = Yil - 1
      Endif

      If CounterC=3 then
      Ay = Ay - 1
                          If Ay >= 13 Then
                                   Ay = 12
           Endif
                                   If Ay = 0 Then
                                   Ay = 12
                  Endif
      Endif

      If CounterC=4 then
      Gun = Gun - 1
                       Gosub Look
               If Gun >= X+1 Then
                     Gun = X
               Endif
               If Gun = 0 Then
                     Gun = X
               Endif
      Endif
      
      If CounterC=5 then
      as = as - 1
         If as >= 24 Then
           as = 23
                Endif
      Endif          

      If CounterC=6 then
      ad = ad - 1
         If ad >= 60 Then
                     ad = 59
                Endif
      Endif          
            
      Gosub debounce
      TimeOut=0
      Goto SetupDisplayLoop
       Endif
                                      
   

      '   Set Butonuna basılırsa
         '   ---------------------------
       If PORTB.4 = 0 Then
      CounterC=CounterC+1       ' C sayacını bir artır
           Gosub debounce                  ' Ark söndürme
                                 ' Menu itemini artırma
      TimeOut=0                          ' Zaman aşımı sayacını sıfırla

      If CounterC > 6  then
      LCDOut $FE,1, "Memorised"
                  Goto time
       Endif          
      
      Gosub SetButtonRelease       ' Ark söndürme
      Goto SetupLoop             ' Bir sonraki menü itemi için döngü                 
       Endif

time :        
   Pause 1         ' 1ms bekle
   TimeOut=TimeOut+1
   If TimeOut>10000 then Goto ANADONGU
               ' Kullanıcı 10 saniyeden fazla beklerse
               ' ayar menüsünden çık
   Goto SetupEntryLoop   ' Bir Butona basılırsa SetupEntryLoop'a git

Alarm :
           Sound PORTC.7, [50,1]      
   Sound PORTC.7, [0,1]      
   Sound PORTC.7, [50,1]      
   Sound PORTC.7, [0,1]      
   Sound PORTC.7, [50,1]      
           Sound PORTC.7, [0,1]      
   Sound PORTC.7, [50,1]      
   Sound PORTC.7, [0,1]      
   Sound PORTC.7, [50,1]      
   Sound PORTC.7, [0,1]      
       Sound PORTC.7, [50,1]      
   Sound PORTC.7, [0,1]      
   Sound PORTC.7, [50,1]      
   Sound PORTC.7, [0,1]      
           Sound PORTC.7, [50,1]      
   Sound PORTC.7, [0,1]      
   Sound PORTC.7, [50,1]      
   Sound PORTC.7, [0,1]      
   Sound PORTC.7, [50,1]    
   Goto Kontrol

Look :
   If Ay = 1  Then X = 31            ' Ocak
   If ( Yil // 4 ) <> 0 AND Ay = 2 Then X = 28    ' Şubat, her 4 yılda bir 29 gelecek
           If ( Yil // 4 )  =  0 AND Ay = 2 Then  X = 29   ' şekilde ayarla
   If Ay = 3  Then X = 31                         ' Mart   
   If Ay = 4  Then X = 30                            ' Nisan
   If Ay = 5  Then X = 31                                      ' Mayıs
   If Ay = 6  Then X = 30            ' Haziran
   If Ay = 7  Then X = 31            ' Temmuz   
   If Ay = 8  Then X = 31            ' Ağustos
   If Ay = 9  Then X = 30            ' Eylül   
   If Ay = 10 Then X = 31                                ' Ekim
   If Ay = 11 Then X = 30            ' Kasım
   If Ay = 12 Then X = 31            ' Aralık
       

' Her Timer kesmesini işleyecek Interrupt rutini
       disable         ' Interrupt lar devre dışı
TickInt: Tick = Tick + 1              ' Saniye parçacıklarını say
       If Tick =! 62 Then tmr0 = 0
       If Tick = 62 Then  tmr0 = 246
       If Tick < 62 Then Ticik       ' 61 * 16,384ms = 1sn
' Bir saniye geçti zamanı güncelle
       Tick = 0
       Saniye = Saniye + 1
                If Saniye >= 60 Then   
                         Saniye = 0
 Dakika = Dakika + 1                
                         If Dakika >= 60 Then
                                  Dakika = 0
                                  Saat = Saat + 1
                                          If Saat >= 24 Then
                                                Saat = 0
                       Gun = Gun + 1
                                                If Gun >= X Then
                                                            Gun = 1
                           Ay = Ay + 1
                       If Ay >=13 Then
                                  Ay = 1
                                  Yil = Yil + 1
                                                                                    Endif
                    Endif                                      
                           Endif
                      Endif
                Endif
       Guncelle = 1    ' Ekran güncellenmesi aktif
Ticik: INTCON.2 = 0    ' Timer Interrupt bayrağını sıfırla
         Resume         ' Alt programdan çık

' 250ms bekle
debounce: For i = 1 to 20
               Pause 10  ' Her defasında 10ms bekle (Hiçbir interrupt'ın  kaybolmaması için)
                Next i                
       Guncelle = 1    ' Ekran güncellenmesi aktif
       Return
SetButtonRelease:            
        LCDOut $FE,1
        For i = 1 to 15
                Pause 10  ' Her defasında 10ms bekle (Hiçbir interrupt'ın  kaybolmaması için)
                Next i
       Return
       End

cozturk

Kardeş,

Proteus proceni aşağıdaki  bölgeye upload edebilirsin.  ben 1-2 tane göndermiştim.(Dimmer ve voltmeter)

http://www.mcu.cz/atm/index.php?direction=&order=&directory=CAD/Proteus/Projects&

Kolay gelsin


cyberlight

Projenin DSN dosyasını verilen adrese upload ettim.İlgilenen bakabilir.(Tsdeneme.dsn)
Proteustaki LCD modelinin backlight özelliği olmadığı için bi led kullandım.

Ayrıca "ne eeeeeeeeeee'si " diyen arkadaşa : :)
Proje hakkında yorum yapmanız için illede malzemeleri alıpta devreyi kurmanız veya simulasyon yapmanız gerekmez.
Programa bakıpta yorumlar yapılabilir ki benimde istediğim buydu.

cozturk

Saati ayarladıktan sonra nereye basılacak? Ayar modundan çıkılamıyor

Timebase olarak,  piyasada 1-2 milyona satılan quartz saaatler var..
gayet doğru çalışıyor. Bu saatlerde çip, Her saniye kısa bir darbe ile bobini sürüyor.
Bu sayede saniye vb. dönüyor. Saat de gayet doğru çalışıyor. Kanaatimce  bu ucuz saat lerin çipi bir transistörle sürülerek pice 1 Hz uygulansa zaman sorunu kökünden çözülür..

Unutmadan, bu çipler  3.2768 kristal kullanıyor. PIC te de bu frekans kullanılırsa 1Hz'i elde etmek çok kolay..

Ayrıca  kodu buradan kopyalayıp derleyince bazı yazım hataları vb. çıkmıştı. (if vb. eksik.) Bunları değiştirdim. belki de bu yüzden bazı hatalar çıkmıştır. Değiştirilen kod:

'****************************************************************
'* Name : Takvim & Saat & Termometre
'* Author : Fatih BİLGİLİ
'* Notice : Copyright (c) 2003
'*
'* Date : 28.05.2003
'* Version : 3.0
'*
'****************************************************************

Define LCD_DREG PORTD ' LCD data portunu belirler
Define LCD_DBIT 4 ' 4 bit'lik veri yolu
Define LCD_RSREG PORTE ' LCD register seçme portunu belirler
Define LCD_RSBIT 0 ' LCD register seçme bitini belirler
Define LCD_EREG PORTE ' LCD enable portunu belirler
Define LCD_EBIT 1 ' LCD enable bitini belirler
Define LCD_LINES 2 ' LCD'deki satır sayısı

Define ADC_BITS 10 ' ADC sonucu 10 bitlik
Define ADC_CLOCK 1 ' ADC saat kaynağı( foscillator/8 )
DEFINE ADC_SAMPLEUS 50 ' ADC örnekleme zamanı us cinsinden

Saat var byte ' Saat değişkeni
dSaat var byte ' Display'de görünecek saat değişkeni
Dakika var byte ' Dakika değişkeni
Saniye var byte ' Saniye değişkeni
Tick var byte ' Saniye parçacıkları
Guncelle var byte ' LCD güncellenme değişkeni
i var byte ' Döngü değişkeni
CounterC var byte ' Döngü değişkeni
TimeOut var word ' Döngü değişkeni
Gun var byte ' Gün değişkeni
Ay var byte ' Ay değişkeni
Yil var byte ' Yıl değişkeni
X var byte ' Hangi ayın kaç gün çektiğini belirlemek için

as var byte ' Alarm değişkeni (saat)
ad var byte ' Alarm değişkeni (dakika)
z var byte ' Backlight On/Off değişkeni
k var byte ' Kayan yazı değişkeni
d var byte ' Kayan yazı değişkeni
p var word ' Kayan yazı değişkeni
AD_Rez var word ' ADC işleminin sonucu 16 bit
C var byte ' ADC işlemi için

TRISA = %11111111 ' Port A giriş
TRISC = %01111111 ' Port C giriş (8. pin hariç)
ADCON1 = %10000010 ' Port A analog ve Port E dijital modda
Low PORTE.2 ' LCD'yi yazma moduna geçir
Pause 300 ' LCD 'nin açılması için bekle

Saat = 0 ' Başlangıç zamanı olarak 00:00:00'ı ayarla
Dakika = 0
Saniye = 0
Tick = 0
Gun = 1 ' Başlangıç tarihi olarak 01.06.2003 ü ayarla
Ay = 6
Yil = 03
as = 1 ' Başlangıçta Alarm 01:00’a kurulu
ad = 0

' Girişteki kayan yazı
k = 0
d = 0
While k =< 21 AND d =< 21
Lcdout $fe, $8F - k , "B"
Lcdout $fe, $90 - k , "i"
Lcdout $fe, $91 - k , "T"
Lcdout $fe, $92 - k , "i"
Lcdout $fe, $93 - k , "R"
Lcdout $fe, $94 - k , "M"
Lcdout $fe, $95 - k , "E"

Lcdout $fe, $BF + d , "i"
Lcdout $fe, $BE + d , "Z"
Lcdout $fe, $BD + d , "E"
Lcdout $fe, $BC + d , "T"

If k <> 10 then p=150
If k = 10 then p=3000
Pause p
Lcdout $fe,1
k = k + 1
d = d + 1
wend

Low PortC.7 ' Buzzer bağlantı pini
Low PortC.1 ' PortC.1 sıfırlanır, Backlight kapalı
Guncelle = 1 ' Güncelleme aktif
' TMR0 'ı her 16,384 milisaniye de bir kesme üretecek şekilde kur.
OPTION_REG = $55 ' TMR0 konfigurasyonunu ayarla ve PORTB
' pullup'larını etkinleştir.
INTCON = $A0 ' TMR0 interrupt'ını etkinleştir.
On Interrupt Goto Tickint ' Interrupt oluşursa Tickint altprogramına git

' Ana Program Döngüsü
ANADONGU:
PORTB = 0 ' PORTB pinlerini düğmeleri okumak için LOW konumuna al
TRISB = $f0 ' PORTB 'nin düğmelere bağlı pinlerini giriş diğerlerini çıkışa
' ayarla

ADCIN 0, AD_Rez ' A/D dönüştürme işlemini yürüt ve sonucu AD_Rez
' değişkeninde sakla
' LCD görüntülenecek olan sıcaklık bilgisinin hesaplanması
If (AD_Rez>=0) AND (AD_Rez<=20) AND (AD_Rez // 2) = 0 then C = (AD_Rez)/2
If (AD_Rez>21) AND (AD_Rez<=65) AND (AD_Rez // 2) != 0 then C = (AD_Rez-1)/2
If (AD_Rez>=6) AND (AD_Rez<=110) AND (AD_Rez // 2) = 0 then C = (AD_Rez-2)/2
If (AD_Rez>=113) AND (AD_Rez<=155) AND (AD_Rez // 2) != 0 then C = (AD_Rez-3)/2
If (AD_Rez>=158) AND (AD_Rez<=198) AND (AD_Rez // 2) = 0 then C = (AD_Rez-4)/2

' Zamanı ayarlamak için set düğmesine basılmışmı?
If PORTB.4 = 0 Then
Gosub SetButtonRelease
Goto Setup
Endif

' Backlight On/Off
If PORTB.6 = 0 Then
z = z +1 ' Her basışta z değişkenini 1 artır
Gosub debounce
Endif
If (z // 2) = 0 then ' z'in 2'ye bölümünden kalan 0 ise backlight On
Low PortC.1
Else ' değilse backlight Off
High PortC.1
Endif

' Alarm zamanı geldiyse Alarm alt programına dallan
If (Saat = as ) AND (Dakika = ad) AND PORTC.0 = 0 Then Goto Alarm
If PORTC.0 = 1 then
Low PortC.7
Endif

' Ekran güncellenecek mi?
Kontrol: If Guncelle = 1 Then
Lcdout $fe, 1 ' Ekranı sil

' Zamanı tt:dd:ss formatında göster t-saat,d-sakika,s-saniye
dSaat = Saat ' Saati 0-12 aralığına getir
If (Saat // 12) = 0 Then
dSaat = dSaat + 12
Endif

' AM mi PM mi kontrol et
If Saat < 12 Then
Lcdout dec2 dSaat, ":", dec2 Dakika, ":", dec2 Saniye, " AM"
Else
Lcdout dec2 (dSaat - 12), ":", dec2 Dakika, ":", dec2 Saniye, " PM"
Endif

Low PortC.0 ' PortC.0 sıfırlanır, alarm açık
If PORTC.0 = 0 then
Lcdout $fe, $8D, "*))"
Endif

' Tarihi gg.aa.yyyy formatında göster g-gün, a-ay, y-yıl
Lcdout $fe, $c0, dec2 Gun, ".", dec2 Ay, ".20", dec2 Yil
Lcdout $fe, $c0 + 12, dec2 C , %11011111, "C"

If PORTB.5 = 0 Then
Lcdout $fe, 1
Lcdout "Alarm at ", dec2 as, ":", dec2 ad
Endif
Guncelle = 0 ' Ekran güncellendi
Endif
Goto ANADONGU ' Sonsuz döngü sağla
Setup:
CounterC=0 ' Setup başlangıcını ayarla ( 0-6 arası yedi adım )
TimeOut=0 ' Zaman aşımı sayacını sıfırla

SetupLoop:
LCDOut $FE,1,"Set "

' Data giriş menüsünün görüntülenmesi
' ----------------------------------------------
If CounterC=0 then
LCDOut "Hour"
Endif
If CounterC=1 then
LCDOut "Minute"
Endif
If CounterC=2 then
LCDOut "Year: 20"
Endif
If CounterC=3 then
LCDOut "Month"
Endif
If CounterC=4 then
LCDOut "Day"
Endif
If CounterC=5 then
LCDOut "AHour"
Endif
If CounterC=6 then
LCDOut "AMinute"
Endif

If CounterC<>2 then
LCDOut ":"
Endif

' Dataların görüntülenmesi
' -------------------------------
SetupDisplayLoop:
If CounterC=0 then
dSaat = Saat ' Saati 0-12 aralığına getir
If (Saat // 12) = 0 Then
dSaat = dSaat + 12
Endif

' AM mi PM mi kontrol et
If Saat < 12 Then
LCDOut $FE,$8A
Lcdout dec2 dSaat, " AM"
Else
LCDOut $FE,$8A
Lcdout dec2 (dSaat - 12), " PM"
Endif
Endif

If CounterC=1 then
LCDOut $FE,$8C
Lcdout dec2 Dakika
Endif

If CounterC=2 then
LCDOut $FE,$8C
Lcdout dec2 Yil
Endif

If CounterC=3 then
LCDOut $FE,$8B
Lcdout dec2 Ay
Endif

If CounterC=4 then
LCDOut $FE,$89
Lcdout dec2 Gun
Endif

If CounterC=5 then
LCDOut $FE,$8B
Lcdout dec2 as
Endif

If CounterC=6 then
LCDOut $FE,$8D
Lcdout dec2 ad
Endif












' Data girişi
' -----------
SetupEntryLoop:

' Artırma butonuna basılırsa
' --------------------------------
If PORTB.5 = 0 Then

If CounterC=0 then ' Saati Artır
Saat = Saat + 1
If Saat >= 24 Then
Saat = 0
Endif
Endif

If CounterC=1 then ' Dakikayı Artır
Dakika = Dakika + 1
If Dakika >= 60 Then
Dakika = 0
Endif
Endif

If CounterC=2 then ' Yılı Artır
Yil = Yil + 1
Endif

If CounterC=3 then ' Ayı Artır
Ay = Ay + 1
If Ay >= 13 Then
Ay = 1
Endif
Endif
If CounterC=4 then ' Günü Artır
Gun = Gun + 1
Gosub Look
If gun >= X+1 Then
Gun = 1
Endif
Endif

If CounterC=5 then ' Alarm saatini artır
as = as + 1
if as > 24 Then
as = 1
Endif
Endif

If CounterC=6 then ' Alarm dakikasını artır
ad = ad + 1
if ad >= 60 Then
ad = 0
Endif
Endif

Gosub debounce
TimeOut=0
Goto SetUpDisplayLoop
endif






' Azaltma butonuna basılırsa
' ---------------------------------
If PORTB.6 = 0 Then
   if CounterC=0 then
       Saat = Saat - 1
       If Saat >= 24 Then Saat = 23
   Endif
Endif

If CounterC=1 then
Dakika = Dakika - 1
If Dakika >= 60 Then
Dakika = 59
Endif
Endif

If CounterC=2 then
Yil = Yil - 1
Endif

If CounterC=3 then
Ay = Ay - 1
If Ay >= 13 Then
Ay = 12
Endif
If Ay = 0 Then
Ay = 12
Endif
Endif

If CounterC=4 then
Gun = Gun - 1
Gosub Look
If Gun >= X+1 Then
Gun = X
Endif
If Gun = 0 Then
Gun = X
Endif
Endif

If CounterC=5 then
as = as - 1
If as >= 24 Then
as = 23
Endif
Endif

If CounterC=6 then
ad = ad - 1
If ad >= 60 Then
ad = 59
Endif
Endif

Gosub debounce
TimeOut=0
Goto SetupDisplayLoop
'Endif



' Set Butonuna basılırsa
' ---------------------------
If PORTB.4 = 0 Then
CounterC=CounterC+1 ' C sayacını bir artır
Gosub debounce ' Ark söndürme
' Menu itemini artırma
TimeOut=0 ' Zaman aşımı sayacını sıfırla

If CounterC > 6 then
LCDOut $FE,1, "Memorised"
Goto time
Endif

Gosub SetButtonRelease ' Ark söndürme
Goto SetupLoop ' Bir sonraki menü itemi için döngü
Endif

time :
Pause 1 ' 1ms bekle
TimeOut=TimeOut+1
If TimeOut>10000 then Goto ANADONGU
' Kullanıcı 10 saniyeden fazla beklerse
' ayar menüsünden çık
Goto SetupEntryLoop ' Bir Butona basılırsa SetupEntryLoop'a git

Alarm :
Sound PORTC.7, [50,1]
Sound PORTC.7, [0,1]
Sound PORTC.7, [50,1]
Sound PORTC.7, [0,1]
Sound PORTC.7, [50,1]
Sound PORTC.7, [0,1]
Sound PORTC.7, [50,1]
Sound PORTC.7, [0,1]
Sound PORTC.7, [50,1]
Sound PORTC.7, [0,1]
Sound PORTC.7, [50,1]
Sound PORTC.7, [0,1]
Sound PORTC.7, [50,1]
Sound PORTC.7, [0,1]
Sound PORTC.7, [50,1]
Sound PORTC.7, [0,1]
Sound PORTC.7, [50,1]
Sound PORTC.7, [0,1]
Sound PORTC.7, [50,1]
Goto Kontrol

Look :
If Ay = 1 Then X = 31 ' Ocak
If ( Yil // 4 ) <> 0 AND Ay = 2 Then X = 28 ' Şubat, her 4 yılda bir 29 gelecek
If ( Yil // 4 ) = 0 AND Ay = 2 Then X = 29 ' şekilde ayarla
If Ay = 3 Then X = 31 ' Mart
If Ay = 4 Then X = 30 ' Nisan
If Ay = 5 Then X = 31 ' Mayıs
If Ay = 6 Then X = 30 ' Haziran
If Ay = 7 Then X = 31 ' Temmuz
If Ay = 8 Then X = 31 ' Ağustos
If Ay = 9 Then X = 30 ' Eylül
If Ay = 10 Then X = 31 ' Ekim
If Ay = 11 Then X = 30 ' Kasım
If Ay = 12 Then X = 31 ' Aralık


' Her Timer kesmesini işleyecek Interrupt rutini
disable ' Interrupt lar devre dışı
TickInt: Tick = Tick + 1 ' Saniye parçacıklarını say
If Tick =! 62 Then tmr0 = 0
If Tick = 62 Then tmr0 = 246
If Tick < 62 Then Ticik ' 61 * 16,384ms = 1sn
' Bir saniye geçti zamanı güncelle
Tick = 0
Saniye = Saniye + 1
If Saniye >= 60 Then
Saniye = 0
Dakika = Dakika + 1
If Dakika >= 60 Then
Dakika = 0
Saat = Saat + 1
If Saat >= 24 Then
Saat = 0
Gun = Gun + 1
If Gun >= X Then
Gun = 1
Ay = Ay + 1
If Ay >=13 Then
Ay = 1
Yil = Yil + 1
Endif
Endif
Endif
Endif
Endif
Guncelle = 1 ' Ekran güncellenmesi aktif
Ticik: INTCON.2 = 0 ' Timer Interrupt bayrağını sıfırla
Resume ' Alt programdan çık

' 250ms bekle
debounce: For i = 1 to 20
Pause 10 ' Her defasında 10ms bekle (Hiçbir interrupt'ın kaybolmaması için)
Next i
Guncelle = 1 ' Ekran güncellenmesi aktif
Return
SetButtonRelease:
LCDOut $FE,1
For i = 1 to 15
Pause 10 ' Her defasında 10ms bekle (Hiçbir interrupt'ın kaybolmaması için)
Next i
Return
End

mhk

Pic te kesme işlemi için 3.2768 Mhz. kristal kullanılırsa oldukça doğru sonuç veren saat yapılabilir. En azından benim okul için yaptığım programlanabilir okul saati projesinde nerdeyse 1,5 yıl olacak bir problemle karşılaşmadım.
"Ya olduğun gibi görün, Ya da göründüğün gibi ol..." Mevlana

cyberlight

Aynı adrese progrqamın bas ve hex dosyalarınıda upload ettim.
Ayar menüsünden otomatik olarak çıkılıyor.
10 saniye düğmelere basmazsanız çıkıyosunuz.

Daha önce dediğim gibi 10 saat için kronometre ile birebir gitti.Sonrasını bilmiyorum ama.

3.2768 Mhz lik kristal bu program için uygun değil. Denedim. Program uzun olduğundan yeterli gelmiyo heralde.

Bide girişteki kayan yazı 2x16 lık lcd için ayarlanmıştır.

dideco

Bence sisteme bir RTC entegresi veya time keeper entegresi de bağlarsan pek çok problemi halledersin. Herşeyden önce bu küçük entegreler tarih, saat, gün, ay yıl gibi bilgileri istenilen formatta tutuyorlar. Ikıncisi elektrik kesilmelerinden etkilenmiyorlar çünkü kendilerinin bağımsız bir pilleri var. Fiyatlatı 1-1.5 USD$ veya daha aşağısı mertebelerinde. Tek sorun uygun çipin datasheetini okumak ve I2C Bus ile bağlantıyı sağlamak. Ondan sonra sistem son derece geliştirilmeye açık hale gelecektir...

Kolay gelsin

dideco

Ayrıca yaptığım denemelerde 16F84'te timer oldukça kararlı çalışıyor. İkinin katları olacak bir kristal kullanmaya gerek yok, zaten timer ve bölücüler kulanarak yeterince hasas bir zamanlama yapmak mümkün. Yalnız burada kesme vektörünü gördükten sonra yapılan işlerin süresini tahmin etmek veya hesaplamak sorun olacağı için timerin o anki değeri timer'a eklenerek kesme vektörü süresi daha kararlı hale getirilebilir..

Kolay gelsin

mhk

Evet haklı olabilirsin lakin ben daha önce RTC elemanı kullandım. Onları haberleştirmek kolay değil. Bu başarılabilir daha önemli olanı kullandığım RTC elemanının hata yapması idi. Günde 1 1,5 sn hata yaptı. Belki bu kabul edilebilir bir değer lakin uzun süreli çalışacak sistemlerde hata artacaktır. Hepimizin kullandığı cep telefonları , bilgisayarlar gib cihazlarda RTC elemanı var lakin onlarda günde 1-2 saniye hata yapıyorlar. Ben PIC 16F877 de 3.2768 Mhz. kullanarak hata oranını haftada 3-4 saniyeye indirdim. Kesme kullanıldığında elbette kesme gecikmelerinide hesaba katarak program yazmak kolay değil. RTC lerin avanajları elbette çok fazla mesela harici bir pil ile elektrik kesintilerinde uzun süreli kullanılması vs. Yanlız eğer program hafızası yetiyorsa neden ayrı bir eleman kullanılsın ki? önemli olan en az elemanla en kaliteli projeyi tutturabilmek. İyi çalışmalar diliyorum.
"Ya olduğun gibi görün, Ya da göründüğün gibi ol..." Mevlana

fsan

Alıntı yapılan: "cyberlight"Bu program benim bitirme tezim. Sizinde görüşlerinizi almak istedim.
Proteustaki simülasyon şemasınıda yollamak isterdim ama hem resim eklemeyi bilmiyorum hemde pek zamanım yok.

Selam,
arkadaslar bu foruma yazdigim ilk mesaj, böylesine güzel ve faydali bir yer yaptiginiz icin sizlere cok tesekkür ederim.

@cyberlight
Kardesim ellerine saglik gercekten güzel bir proje olmuş. Baya ilgimi cekti bende Proteus ile bir simülasyon yaptim.. baya güzel oldu :)
Alarm ve bazi kisimlarda biraz degisiklikler yaptim bilmiyorum saatin dogru calismasinda bunun bir etkisi olurmu. Bir kontrol edermisiniz ?


http://groups.yahoo.com/group/PicProjeUP1/files/fsan/

Basarilar..

cyberlight

fsan ;
Verdiğin linke girebilmek için özel bi üyelik gerekiyo dolayısıyla yazdığın programa bakamadım.Dosyayı mail adresime yollayabilirsin, siberm50@yahoo.com
Birazda geç oldu kusura bakma, uzun zamandır girmemiştim siteye.
Bide bişey değil :)

MaxGe

projen aslında cok işime yarar ama bunu lcd ekran değilde ledli panayo (termometreyi cıkartarak) nasıl aktarabilirim?

bir fikrin varmı?

ise

74hc595  ve 4021 kullanarak verileri tek tek seri olarak göndererek yaparsın

zıbam

benim ıcın devrenın bı şemasını yada bana herhangı bı saat devresı gonderır mısın....
acılen cok ıhtıyacım var adresımı verıyorum mertkardas@hotmail.com