Timer

Başlatan spear, 20 Haziran 2006, 21:30:48

spear

Merahaba Arkadaşlar,
Timer kullanmak istiyorum. Ama kullanmayı beceremedim. Örnek bi kod olan war mı? Mesela 3sn port A nın 1. biti 1 set olsa, 5 sn sonra da 2. biti set olsa böle bişeyi nasıl yaparım. Yardım ederseniz çok sevinirim...

XX_CİHAN_XX

Bu işlemde pıcın timer sayıcısını mı kullanmak ıstıyorsun(mesela tımer0,tımer1 gibi) yoksa zaman dongulerı ıle mı yapmak ıstıyorsun onu anlamadım.Fakat Soyledıgın ıslemler ıcın Tımer sayıcı sını kullanamana gerek yok basit bir dongu lu  zaman gecıkmesı ıle o işlemleri yapabılırısin
Yirmi yaşındaki bir insan, dünyayı değiştirmek ister . Yetmiş yaşına gelince , yine dünyayı değiştirmek ister, ama yapamayacağını bilir.

murbay

Kodları veriyorum. Ben denedim çalışıyor. Umarım istediğin gibidir.
Burada yeniyim devre şemasının resmini ekleyemedim.

TRISA=%00000001
TRISB=0
PORTB=0
BASLA:
   IF PORTA.0=0 THEN GOTO TIMER
   GOTO BASLA
TIMER:
   HIGH PORTB.0
   PAUSE 3000
   HIGH PORTB.1
   PAUSE 5000
   LOW PORTB.0
   LOW PORTB.1
   GOTO BASLA
   END

Açıklayıcı olun, gizemli yazmak maharet değildir...

murbay

En alttaki
olmayacak:))
Açıklayıcı olun, gizemli yazmak maharet değildir...

spear

timer sayacı nasıl kullanıldığını öğrenmek için sordum. Internal timerın nasıl kullanıldığı baist örnek olarakta onu sordum. Yardımcı olursan sevinirim. Timer kurmayı falan...

XX_CİHAN_XX

http://webelektronik.com/tr/index.php?option=com_content&task=view&id=17&Itemid=41
    org     00
     goto   setup
     org     04
timer_kesme
;timer interrupt ı olustu 


     bcf     intcon,t0if  ;tekrar kesme olusmaması ıcın int. flagini sil
     retfie

setup
     bsf     status,5
     movlw 0x80
     movwf option_reg ;tmr0 bolenı 1/2, portb pull-up disable
     bcf     status,5
     bsf     intcon,gie   ;global interrupt enable
     bsf     intcon,t0ie  ;timer0 interrupt enable
     clrf     tmr0
main

;timer0 her saymayı tamamladıgında      
;org 04 vektorune gider(timer_kesme)
;orada istediğin işlemleri yapar tekrar buraya geri doner
;bolen 1/2 oldugu ıcın 2 saykılda 1 artar timer sayıcısı 
;yanı bu sayıcı her 512 komut saykılında bir interrupt olusur
;bunu bolenden ve kesme vektorune koyacagın bazı sayac regısterlerı ıle
;istediğin uzunlukta zaman gecıkmesı yapabılırsın
;hep hazır olmaz orayıda bıraz sen dusun kafa yor arastır tekrar 
;bizimle paylaş :)

     goto    main

Kolay gelsin ...  8)
Yirmi yaşındaki bir insan, dünyayı değiştirmek ister . Yetmiş yaşına gelince , yine dünyayı değiştirmek ister, ama yapamayacağını bilir.

bsivgin

herşeyden önce işlemciyin komut çevrim süresini bilmelisin Eğer 4 Mhzlik kristal kullanıyorsanız komut işlem süresi 1 mikro saniyedir. yani 1 mikrosaniyede bir iç saat darbeleri oluşur.PIC'de bulunan Tımer0 ve Timer 1 gibi sayıcılar dış dünyadaki olayları sayabileceği gibi iç saat darbelerini de sayabilir. Bunun için şu mantığı ilkönce bilmek gerekir.
1 saniye=1000 milisaniye
1 milisaniye= 1000 mikrosaniye

Eğer timer iç saat darbelerini saymak için ayarlanacaksa bunu OPTION registerinde ayarlayacaksın. Eğer tımer0 iç saat darbelerini doğrudan sayarsa   her darbede bir artar ve azami 256 ya kadar sayar. Bizim komut çevrim süremiz 1 mikrosaniye ise azami 256 mikrosaniyelik bir zamanlama yapabiliriz. Bu aralığı PIC'de bulunan ve bu saat darbelerini 2:4:8:16:32:64:128:256 kademelerine bölerek uzatan frekans bölücü (prescaler) bulunur. Bu kademelerri kullanarak zamanlama aralığını genişletebilirsin. örneğin frekans bölücünün 64 kademesini kullanırsan 1 mikrosaniyelik komut çevrimi ile azami 256X64= 16,384 milisaniyelik bir gecikme elde edebilirsin

Aşağıda ınterrupt tabanlı bir uygulama örneği var inceleyerek genişletebilirisin. Bu örnekte 1 sn sonra PORTA'nın 1 nolu çıkışı, 5 saniye sonra 2 nolu çıkışı aktif edilmektedir

#include P16f628.inc

MILI_SAYAC EQU H'21'
SANIYE_SAYAC EQU H'22'
org 00
goto main

ORG 04
INTERRUPT ALTPROGRAMI
   BTFSS INTCON,T0IF
   RETFIE
   BCF INTCON,T0IF
   MOVLW D'236'
   MOVWF TMR0
   INCF MILI_SAYAC
   MOVF MILI_SAYAC,0
   XORLW D'200'    ; 200 X 5 MS= 1000 MS =1 SANİYE
   BTFSS STATUS,Z
   RETFIE
   CLRF MILI_SAYAC
   INCF SANIYE_SAYAC
   MOVF SANIYE_SAYAC,0
   XORLW d'1'
   BTFSS STATUS,Z
   GOTO KONTROL5
   BSF PORTA,1  ; 1 saniye sonra aktif et
   RETFIE
KONTROL5
   MOVF SANIYE_SAYAC,0
   XORLW d'5'
   BTFSS STATUS,Z
   RETFIE
   BSF PORTA,2   ; 5 saniye sonra aktif et
   BCF INTCON,T0IE
   RETURN
   

org 100
main
   MOVLW 0x07
   MOVWF CMCON
   CLRF MILI_SAYAC
   CLRF SANIYE_SAYAC
   bsf STATUS,RP0
   CLRF TRISA
   MOVLW B'10000111'
   MOVWF OPTION_REG  ; TIMER'IN 256 MİKROSANİYEDE BİR ARTMASI İÇİN
   BCF STATUS,RP0    ; PRESACALER TIMER ATANIP 256'YA BÖLEN kADEMESİNE ALINIR
   MOVLW d'236'  ; 20 X 256 MİKROSANİYE= 5,1 MS  
   MOVWF TMR0    ; 5MS DE BİR INTERRUPT OLUŞUR
   NOP
   NOP
   NOP
   MOVLW B'10100000'
   MOVWF INTCON
   GOTO $
   END


saygılarımla
www.diyot.com

mesaj

arkadaşlar bana zaman sayacı lazım.elimde pulse  dedektör var.sinyalin  gönderilmesi ve alınması sırasında geçen süreyi hassas bir şekilde ölçen devre lazım.yardımcı olursanız sevinirim.

semesu

arkadaslar merhaba ,
bende capture modu ve tımer 1 kullanarak interrupt olusturmak istıyorum. amacım motorun 1 dakıka dakı devrını olcmek.algıyacıyla motorun her devrını pulse seklınde CCp bacagından logıc 0 yada logıc 1 olarak gondedrıyor program ve ona gore capture olusuyor.    ancak yazdıgım programda timer ın saydıgı sayı her yukselen kenar ve dusen kenarda yanı her perıyodda ayrı deger gosterıyor,buna baglı olarakda devir sayısı da dogru degerler vermıyor maalesef  bırturlu cozemedım sorunu.
acaba register ayarlarında mı sorun var onu da anlamadım arastırdım ama goremedım sorunu.
capture modunu heryukselen kenarda dıye ayarladım.
kullandıgım entegre  16F876 ve c dilini kullanıyorum.
bana yol gosterırsenız cok sevınırım arkadaslar cok denedım ama olmuyor.


yazdıgım kod asagıdadır:




#include <pic.h>
#include <delay.c>
# include <lcd.c>
#include <stdio.h>




unsigned char kontrol;

void interrupt kesme (void) {

TMR1H=0;
TMR1L=0;
GIE=0;
kontrol=1;
//TMR1IF=0;
CCP1IF=0;
GIE=1;

}


main (void) {

unsigned long goster [ ]=" ";

unsigned long sayac;
int a=60;
int i=0;
unsigned long deger;
unsigned long devir;  


kontrol=0;
TRISA=0;
TRISB=0;
TRISC=4;  // portc nın  cny70 ın baglı oldugu CCP1 bacağı gırıs olarak ayarlandı.
PORTC=0;
PORTB=0;
PORTA=0;
ADCON1=7;

// capture ayagının ayarlamaları
CCP1IE=1;

//PIR1=4 ;
CCP1CON=5;
T1CON=57; // 00100001 oldugu zaman prescale 1:4 eger bu register 00111001 ise prescale 1:8 olarak ayarlanmıstır.  




//PIR1=5;
GIE=1;
PEIE=1;





 for(;;) {

sayac=0;

sayac=256*CCPR1H + CCPR1L;
//deger= a / (sayac * 0.000001);

deger=a / (sayac* 0.000001);



if(kontrol==1){


devir=(unsigned int)deger;


}

  if(kontrol==0)
   devir=0;

//if(sayac<50000)
//deger=0;

//kontrol=0;


//for(i=0;i<=6;i++) {
lcd_init();
lcd_clear();
lcd_goto(0x00);
lcd_puts("devir sayisi");
DelayMs(250);
lcd_goto(0x40);
sprintf(goster," %1u",devir);
lcd_puts(goster);
DelayMs(250);
DelayMs(250);
DelayMs(250);
//}

}
}
 nerde hatam var birturlu bulamadım arkadaslar .  önerisi olan arkadasım varsa benımle paylasırda cok ıyı olur gercekten cok ugrastım ama bulamadım hatamı.

picusta

sayac ve deger degiskenlerini unsigned long yapmissin yani fixed point.
0.000001 ile çarpinca her zaman sifir çikar, ve sifir ile bölme yapmak istiyorsun.
foruma kod yazarken kod tagini kullan.

semesu

peki nasıl tanımlamam lazım degiskenleri ?
kontrol etmek icin lcye sayac degiskenını yazdırdım ancak her capture aralıgından farklı sayılar hesaplıyor sayac degıskenı ıcın . bunu nasıl halledebılırm ? register ayarlarındamı sorun var acaba datasheetten bakarak yazdım ama ılk defa kullandıgım ıcın emın olamadım.

semesu

programda bazı degsıklıkler yaptım burdada timer dogru sayı vermıyor. her pals geldıgınde farklı deger hesaplayıp sayac degiskenine atıyor.
bana yardımcı olursanız cok sevınırım. cok arastırdım ama bırturlu  bulamadım hata nerde.
ben simulasyon programında deneme yapıyorum ısıste acaba yanıltıyor olabılırmı?

#include <pic.h>
#include <delay.c>
# include <lcd.c>
#include <stdio.h>



void ekran_yaz(void);

unsigned char kontrol;

void interrupt kesme (void) {

TMR1H=0;
TMR1L=0;

GIE=0;
kontrol=1;
TMR1IF=1;
//TMR1IE=1;
CCP1IF=0;
GIE=1;


}


void ekran_yaz(void) {

unsigned int sayac;
unsigned int sonuc []= " ";
int a=60;
unsigned int devir;
unsigned int deger;
float zaman;
//lcd_init();
lcd_clear();

//CCPR1H=0;
//CCPR1L=0;
sayac=(256*CCPR1H + CCPR1L);
zaman=(sayac* 0.000001);
deger=  a /  zaman;
devir=(int)deger;
if (kontrol==1){
sprintf(sonuc,"%1u",devir);
lcd_goto(0X40);
lcd_puts(sonuc);
DelayMs(250);
DelayMs(250);
DelayMs(250);
}
else {
DelayMs(250);
}

}
void  main (void) {


unsigned int sayac;
//kontrol=0;
TRISA=0;
TRISB=0;
TRISC=4;  // portc nın  cny70 ın baglı oldugu CCP1 bacağı gırıs olarak ayarlandı.
ADCON1=7;
PORTC=0;
PORTB=0;
PORTA=0;
//LCD İŞLEMLERİ
DelayMs(250);
lcd_init();
lcd_clear();
lcd_write(0X0C);
lcd_goto(0X00);
lcd_puts("DEVIR SAYISI");
DelayMs(250);
DelayMs(250);
DelayMs(250);









// capture ayagının ayarlamaları
CCP1IE=1;
//PIR1=4 ;
CCP1CON=5;
T1CON=33; // 00100001 oldugu zaman prescale 1:4 eger bu register 00000001 ise prescale 1:1 olarak ayarlanmıstır.  
GIE=1;
PEIE=1;




//DEVİR ÖLÇÜM İŞLEMLERİ
for( ;; ) {


 ekran_yaz( ) ;






}
}