pic uyku modu

Başlatan enrique_iglesias, 19 Aralık 2008, 04:06:26

enrique_iglesias

Arkadaşlar 4 Adet kalem pil ile çalışan eski bir kumanda kutusu buldum ve bunun içerisini söktüm UDEA'dan bir arx ve atx modüller aldım. Birde kendim butonlarla matris bir numpad yaptım donanım olarakta PORTB'yi kullandım ki değişiklik olduğunu kesme ile bulabileyim diye.

Tarama yaptırarak hangi tuşa bastığımı bulabiliyorum ve işin bu kısımlarını geçtim

1 nci sorum şu : 4 x 1,5V kalem pil 6V enerji veriyor ben bunu küçük 7805 ler ile çözdüm ama forumda okuduğuma göre bu iş gerilim düşmesi ile hiç bir işe yaramıyor.Bende kendi çapımda modülün GND bacağına bir BC547 transistör koydum yazımsal olarak enerji çekmesin diye modülün gücünü kesebiliyorum.Ama buda tek başına çözüm değil 4 kalem pili en tasarruflu nasıl kullanabilirim.Sleep demeyin ikinci sorumda bu olacak :)

2 nci sorum : Forumda çok araştırma yaptım ve bulamadım ben aşağıda kodlarda olduğu gibi PORTB değişiklik ve TIMER0 kesmelerini aktif ettim.
timer0 ile saniyeyi hesaplayabiliyorum.Kafamdan geçen şu ve yapamadım
mesela :

10sn tuşa basılmadığında pic uyku moduna geçecek bunu @SLEEP ile yaptığımızı biliyorum ama nereye yazmalıyım bilmiyorum?

PİC'İ NASIL UYANDIRACAĞIM ONUDA BİLMİYORUM :) şimdiden teşekkür ederim kodlar aşağıdaki gibi kesme rutininde değişiklik kesmesini boş bıraktım..

nclude "modedefs.bas"
CMCON=7

TRISA=0
TRISB=%00110000
PORTA=0
PORTB=0

tx      var PORTB.3
led     VAR PORTA.0
modul   var PORTA.1
ses     var PORTA.2

yon     var byte
tus     var byte
i       var byte
salise  var byte
saniye  var byte
bayrak  var byte


OPTION_REG=%10000101    'Pull up dirençleri İPTAL- Bölme oranı 1/64.
INTCON=%10101000        'Timer0 ve PORTB değişiklik kesmesi aktif edildi
on interrupt goto kesme 'hangi kesmenin olduğu etikette değerlendirilecek
enable

basla:
gosub tara
gosub gonder
goto basla



tara:

PORTB=%00000001
if PORTB=%00010001 then yon=%00000001
if PORTB=%00100001 THEN yon=%00000010
if PORTB=%00000001 THEN tus=0

PORTB=%00000010
if PORTB=%00010010 then yon=%00000100
if PORTB=%00100010 THEN yon=%00001000
if PORTB=%00000010 THEN tus=0

PORTB=%00000100
if PORTB=%00010100 THEN yon=%00010000
if PORTB=%00100100 THEN yon=%00100000
if PORTB=%00000100 THEN tus=0

return


gonder:

for i=0 to 5
    serout2 tx,396,[$AA]
    next i
    for i=0 to 5
    serout2 tx,396,[$00]
    next i
    for i=0 to 5
    serout2 tx,396,[$FF]
    next i
serout2 tx,396,[dec 123,dec yon]

return

disable

kesme:

if intcon.2=0 then goto atla1 'TIMER0 KESMESİ OLMADIYSA atla1'e git
    Salise = Salise + 1      		' Saniye parçacıklarını say
	IF Salise < 61 Then tiCik       ' 61 * 16,384ms = 1sn olmadıysa atla 
	Salise = 0                      'saliseyi 0'la
    Saniye = Saniye + 1             'saniyeyi 1 artır
    IF Saniye >= 60 Then            
    Saniye = 0                      '60 saniye olduysa sıfırla
    EndIF
    tiCik: intcon.2=0  'TIMER0 KESME BAYRAĞI SIFIRLANDI

atla1:
if intcon.0=0 then goto atla2 'PORTB'de değişiklik yoksa atla2'ye git ve kesmeyi bitir

intcon.0=0  'PORTB KESME BAYRAĞI SIFIRLANDI
 
atla2:

resume
enable

Tagli

Şu anda timer0'ı tam olarak nerde kullanıyorsun? Bence tuşa basılmadığının anlaşılması için timer0 kullanılabilir. Eğer saniye sayacı 10'a vardıysa sleep'e girersin. Eğer bir tuşa basılırsa timer0'ı sıfırlarsın. Bu konuda deneyimim yok ama timer0'ın sıfırlanması prescaler'i bozuyor olabilir, emin değilim. Eğer durum böyle ise yeniden ayarlaman gerekebilir.

Uykudan uyanma kesmeler ile olur. Uyanabilmek için ilgili kesmenin enable biti açık olmalıdır ama GIE'nin açık olmasına gerek yok. GIE'nin durumuna göre uykudan uyanma iki şekilde olur: GIE açık ise uyandıktan sonra sleep'ten bir sonraki komutu (ASM komutu) işler ve kesmeye gider. GIE kapalıysa kesmeye girmeden sleep'ten sonra program devam eder.

Ancak uyandırma işlemi her kesme ile yapılamaz. Çünkü bazı kesmelerin oluşabilmesi için PIC'in çalışır durumda olması gerekir. Mesela RB0 kesmesi PIC'i uykudan uyandırabilir ama timer0 kesmesi uyandırma işlemi yapamaz, çünkü uykudayken timer0 da durmuştur ve kesme oluşturması mümkün değildir. WDT uyandırma yapabilir ama, çünkü çalışması PIC'ten bağımsızdır.
Gökçe Tağlıoğlu

enrique_iglesias

Arkadaşlar kodlarım aşağıdaki gibi düzelttim

CMCON=7

TRISA=%00000000
TRISB=%00110000
PORTA=0
PORTB=0

tx      var PORTB.3
led     VAR PORTA.0
modul   var PORTA.1
ses     var PORTA.2

yon     var byte
tus     var byte
i       var byte
salise  var byte
saniye  var byte
bayrak  var byte

on interrupt goto kesme 'hangi kesmenin olduğu etikette değerlendirilecek
OPTION_REG=%10000101    'Pull up dirençleri İPTAL- Bölme oranı 1/64.
INTCON=%10100000        'Timer0  kesmesi aktif edildi
TMR0=0
PORTB=0


high modul   'RF modülün gücünü aç

basla:

gosub tara
if tus=0 then
    if saniye=10 then   '10 saniye boyunca hiç tuşa basılmadıysa uyku moduna geç
        intcon.5=0   'TIMER0 iptal edildi
        TMR0=0
        intcon.3=1   'PORTB kesmesi aktif edildi ve herhangi bir tuş bekleniyor
        low modul    'rf modülün gücünü kapat 
        @ sleep      'UYKU MODUNA GEÇTİ AMAAA PROTEUSTA HATA VERIYOR YANI WDT RESET ÇEKİYOR
    endif
endif

GOTO basla



tara:          'tuşlar taranıyor
PORTB=%00000001
if PORTB=%00010001 then yon=%00000001 
if PORTB=%00100001 THEN yon=%00000010
if PORTB=%00000001 THEN tus=0

pause 2

PORTB=%00000010
if PORTB=%00010010 then yon=%00000100
if PORTB=%00100010 THEN yon=%00001000
if PORTB=%00000010 THEN tus=0

pause 2

PORTB=%00000100
if PORTB=%00010100 THEN yon=%00010000
if PORTB=%00100100 THEN yon=%00100000
if PORTB=%00000100 THEN tus=0
return





disable
kesme:
if intcon.2=0 then goto atla1 'TIMER0 KESMESİ OLMADIYSA atla1'e git
    Salise = Salise + 1      		' Saniye parçacıklarını say
	IF Salise < 61 Then tiCik       ' 61 * 16,384ms = 1sn olmadıysa atla 
	Salise = 0                      'saliseyi 0'la
    Saniye = Saniye + 1             'saniyeyi 1 artır
    IF Saniye >= 60 Then            
    Saniye = 0                      '60 saniye olduysa sıfırla
    EndIF
    tiCik:
    intcon.2=0  'TIMER0 KESME BAYRAĞI SIFIRLANDI

atla1:
if intcon.0=0 then goto atla2 'PORTB'de değişiklik yoksa atla2'ye git ve kesmeyi bitir
intcon.5=1   'timer0 tekrar çalıştırıldı
intcon.3=0   'PORTB kesmesi iptal edildi
intcon.0=0  'PORTB KESME BAYRAĞI SIFIRLANDI
 
atla2:

resume
enable
end


1) pic çalıştığında modüle güç gidiyor ve timer0 çalışmaya başlıyor

2) tuşlar taranıyor

3) eğer 10 saniye boyunca hiç tuşa basılmadıysa timer0 kapatılıp sıfırlanıyor

3) portb donanım kesmesi çalıştırıyor ve kesme bekleniyor

4) rf modülün enerjisi kesiliyor ki enerji çekmesin diye

5) uyku moduna geçiriliyor

işlem bu ama bir sorun var isiste "PROCESSOR HAS BEEN RESET BY WATCHDOG TIMER EXPIRING AT TIME" hatası alıyorum.. yani pic sürekli resete gidiyor ve modülün enerjisi sürekli açılıp kapanıyor.


disable
kesme:
if intcon.2=0 then goto atla1 'TIMER0 KESMESİ OLMADIYSA atla1'e git
    Salise = Salise + 1      		' Saniye parçacıklarını say
	IF Salise < 61 Then tiCik       ' 61 * 16,384ms = 1sn olmadıysa atla 
	Salise = 0                      'saliseyi 0'la
    Saniye = Saniye + 1             'saniyeyi 1 artır
    IF Saniye >= 60 Then            
    Saniye = 0                      '60 saniye olduysa sıfırla
    EndIF
    tiCik:
    intcon.2=0  'TIMER0 KESME BAYRAĞI SIFIRLANDI

atla1:
if intcon.0=0 then goto atla2 'PORTB'de değişiklik yoksa atla2'ye git ve kesmeyi bitir
intcon.5=1   'timer0 tekrar çalıştırıldı
intcon.3=0   'PORTB kesmesi iptal edildi
intcon.0=0  'PORTB KESME BAYRAĞI SIFIRLANDI
 
atla2:

resume
enable


kesme bloğum yukarıdaki gibi uyku moduna geçmeden önce portb kesmesini açmıştım timer0'ı kapatmıştım..

PORTB kesmesi olduğunda timer0'ı tekrar çalıştırdım ve PORTB kesmesini iptal ettirdim çünkü bana sadece 10 sn sonunda kesme SLEEP moduna geçtiğinde bu kesme lazım olacak diye...

ama bir türlü olmuyor neden programım resete gidiyor?

Tagli

Öncelikle bir tanım hatasını düzelteyim: Timer0'ı durduramazsın (harici kaynağa bağlamak ve kaynağı durdurmak hariç). Senin yaptığın şey kesmesini açıp kapamak. Gerçi sen sıfırlamayı da yapmışsın ama uykuya girmeden önce arada başka işlemler de var. Bu sırada timer0 çalışmaya devam eder. Bence uyandıktan sonra ve her tuşa basıldığında sıfırlaman daha doğru olur.

Proteus ile deneyimim yok ama anlaşılan senin WDT açık. Bunu konfigürasyon bitleri ile kapatabilirsin. Kapatmazsan her taşmasında PIC'e reset atacaktır (yanlış hatırlamıyorsam normal şartlarda 18 ms'de bir). Ayrıca WDT PIC'i uykudan da uyandırır. Kapatmaktan başka çaren yok.
Gökçe Tağlıoğlu

enrique_iglesias

Sn.Tagli teşekkür ederim verdiğin bilgiler için

@ __CONFIG_WDT_OFF

programımım başına koydum bu kodu ama sanırım işe yaramadıki yine aynı hatayı verdi devreyi daha kurmadım wdt'yi programlarken kapatabilirim ama kodla kapatamadım çünkü proteusta denemem gerekli...

enrique_iglesias

Arkadaşlar yada bana şu pici uyutacak ve portb'deki değişiklik ile uyandıracak örnek bir kodu olan paylaşabilirmi :S Tek derdim uyutmak ve uyandırmak :)

mech

CLRWDT gibi bir komutla watch dog timer'i sıfırlayacak bir komutu programın belirli yerlerine yazmanı öneririm
Bilginin Efendisi Olmak İçin Çalışmanın Kölesi Olmak Şarttır

Tagli

Alıntı yapılan: "mech"CLRWDT gibi bir komutla watch dog timer'i sıfırlayacak bir komutu programın belirli yerlerine yazmanı öneririm
Bu WDT'ın "uyku kaçırıcı" etkisini engellemez. Yine de denemeye değer. En azından program uyku özelliği kaldırılarak denenebilir bu şekilde. Ama Proteus'ta bunu kapatmanın bir yolu olmalı...
Gökçe Tağlıoğlu

berkay_yalan

Alıntı yapılan: "Tagli"
Alıntı yapılan: "mech"CLRWDT gibi bir komutla watch dog timer'i sıfırlayacak bir komutu programın belirli yerlerine yazmanı öneririm
Bu WDT'ın "uyku kaçırıcı" etkisini engellemez. Yine de denemeye değer. En azından program uyku özelliği kaldırılarak denenebilir bu şekilde. Ama Proteus'ta bunu kapatmanın bir yolu olmalı...

clrvt kardeşim sleep komutunu kullanacaksın...