timer ile gecikme yapma

Başlatan ziftinpeki, 09 Mayıs 2013, 11:48:07

ziftinpeki

timer ile gecikme nasıl yapılır lütfen yardımcı olur musunuz

delay kütüphanesini kullanmadan
ve for döngülü metot kulllanmadan

bir timer ve bayrakların üzerinden pic de nasıl yapılır kod olarak bir türlü bulamadım biryerden

Klein

Kodlar sembolik. Timer kesmesinin 1ms olduğunu varsaydım.

timer_int
{
      time_tick++;
}


main
{

    if(buton == press) led_delay = time_tick;
   
   if(time_tick > led_delay + 1000)  led = on;
}

veya

time_interrupt
{
   if(led_delay) led_delay--;
}

main
{

    if(buton == press) led_delay = 1000;
   
   if(!Led_dalay)  led = on;
}


veya

time_interrupt
{
   if(++ time_1sec_cnt == 1000)
   {
       time_1sec_cnt=0;
       time_1sec_flag = 0xFF;
   }

   if(++ time_100msec_cnt == 100)
   {
       time_100msec_cnt=0;
       time_100msec_flag = 0xFF;
   }

}

main
{
    if( time_1sec_flag & 0x01)
   {
        time_1sec_flag &=  ~0x001;
        led = !led;
   }
}


vs...
vs...

ziftinpeki

bu kodun içine gecikme metodunun yerine koymak istiyorum ancak dediğiniz kodları pek anlayamadım

#include <htc.h>

#define ASAGI       PORTB=1
#define YUKARI       PORTB=2
#define DUR       PORTB=0
#define BUTONLAR    PORTD
#define DISPLAY    PORTC

void gecikme(void);
void git(int, int, unsigned int);

void main(void)
{
   unsigned int OnKonum = 1;  // önceki konum
   unsigned int HedefKat = 1; // gidilecek kat
     unsigned int i = 0;
 
   TRISD=0xff;
   BUTONLAR=0;   
     TRISC=0x00;
     DISPLAY=0;
     TRISB=0x00;
   PORTB=0;
 
while(1)
  {
    i = BUTONLAR & 0x1F; //Hangi butona basıldı?   
    switch(i)
    {
      case 0x1F-1: HedefKat = 1; //Zemin kat seçildi
                   break;
      case 0x1F-2: HedefKat = 2; //1.kat seçildi
               break;
      case 0x1F-4: HedefKat = 3; //2.kat seçildi
            break;   
      case 0x1F-8: HedefKat = 4; //3.kat seçildi
                   break;
      case 0x1F-16:HedefKat = 5; //4.kat seçildi
            break;
    }   
   if(HedefKat > OnKonum) //Seçilen kat mevcut kattan yukarı mı?
    {
      git(HedefKat - OnKonum,1,OnKonum); // Yukarı hareket
    }
      
    if(HedefKat < OnKonum) // Seçilen kat mevcut kattan aşağı mı?
    {
      git(OnKonum - HedefKat,0,OnKonum); // Aşağı hareket
    }
    OnKonum = HedefKat;    // Yeni mevcut kat

  }
}

void git(int sayi, int yon, unsigned int OnKonum)
{ // 0 aşağı , 1 yukarı
  int i;
  if(yon)
  {
    YUKARI; //Motor yukarı yönde hareket ediyor
    for(i=1; i<=sayi; i++)
    {
      gecikme();
      gecikme();

      DISPLAY=OnKonum+i-1; //Geçilen katlar göstergede görülür
                            
    }
  }
  else
  {
    ASAGI;       // Motor aşağı yönde hareket ediyor
    for(i=1; i<=sayi; i++)
    {
      gecikme();
      gecikme();
     
      DISPLAY=OnKonum-i-1; //Geçilen katlar göstergede görülür
                                 
    }
  }
  DUR;      // Hedef kata gelindiğinde motor durur.
}

void gecikme(void)
{   //1sn gecikme
  unsigned int i,j;
  for(i=1; i<=200; i++)
  {
    for(j=1; j<=200; j++);
  }
}

Mefe

Hi-Tech C ile yazılmış bir kod. Burada tam 1s olamasını istiyorsan Timer1 kesmesi kullanacaksın ama bu kesmeyi aktif ve pasif etmen gereken noktaları ustalıkla kullanman gerekecek. Eğer kod tecrüben yoksa bence buna hiç girme.
Programın tepesine:
_XTAL_FREQ 4000000L // 4MHz için


Gecikme fonksiyonu içerisine:
for(i=0;i<8;i++)
    __delay_ms(125)


şeklinde ibare yazarsan kullanımı bir öncekine göre daha hassas olur ama Timer kesmesi kadar hassas olmaz. Bu senin gösterdiğin kod için Timer kesmesini kullanamak biraz tecrübe ister. Zor değil ama sen yukarıdaki kodu anlayamadığına göre bu konuda yenisin galiba. Bu yüzden, bence şimdilik yukarıdaki kodu kullan.
Muhammet EFE || http://muhammetefe.com

ziftinpeki

dediğiniz gibi yaptım suan gayet guel çalışıyor ancak yine de sormak istiyorum bu şekilde bir intterrupt ile yapamaz mıyım
deniyorum ancak yapamıyorum, lütfen yardım edin :)

#include <htc.h>
void main(void) // Ana fonksiyon alanı
{
TRISB=0x00; // PORTB çıkıĢ olarak ayarlanıyor
PORTB=0x00; // PORTB sıfırlanıyor
TMR1H=-50000/256; // TMR1'e 65536-50000 yükleniyor.
TMR1L=-50000%256;
TMR1CS=0; // Dahili osilatör
T1CKPS1=1; // Prescaler 1:4 oluyor
T1CKPS0=0;
T1SYNC=1; // Senkronizasyon yok
TMR1IF=0; // TMR1 kesme bayrağı temizleniyor
TMR1IE=1; // TMR1 kesmesine izin veriliyor
TMR1ON=1; // TMR1 çalıĢtırılıyor
PEIE=1; // Yardımcı kesme izni veriliyor
GIE=1; // Genel kesme izni veriliyor

for(;;); // ĠĢlemci sonsuz döngüde bekletiliyor
}


static void interrupt // Kesme fonksiyonu
isim(void) // Kesme fonksiyon ismi (önemsiz)
{
char i; // DeğiĢkenler tanımlanıyor
if(TMR1IF) // TMR1 kesmesi oluĢmuĢ mu
{
i++; // DeğiĢken 1 artırılıyor
if(i<5) // DeğiĢken 5 olursa led yansın
{
RB0=1;
}
else if(i>5) // DeğiĢken 5'ten büyük olursa led sönsün
{
RB0=0;
}
if(i==10) // 2 saniye olduğunda değiĢken sıfırlansın
i=0;
TMR1H=-50000/256; // TMR1'e 65536-50000 yükleniyor.
TMR1L=-50000%256;
TMR1IF=0; // Tekrar dıĢ kesme alınabilmesi için kesme bayrağı temizleniyor
}
}

ziftinpeki

(niye gecikmeleri iptal edince)  KESME kodları neden etki etmiyor

#include <htc.h>
#include "delay.h"
#define ASAGI 		PORTB=1 //0000 0001
#define YUKARI 		PORTB=2 //0000 0010
#define DUR 		PORTB=0 //0000 0000
#define BUTONLAR 	PORTD
#define DISPLAY 	PORTC

	
	unsigned int OnKonum = 1;  // önceki konum
 	unsigned int HedefKat = 1; // gidilecek kat 
  	unsigned int i = 0;

void gecikme(void);
void git(int, int, unsigned int); 

static void interrupt kesme()
{
	
	if(HedefKat > OnKonum) //Seçilen kat mevcut kattan yukarı mı?
    {
      git(HedefKat - OnKonum,1,OnKonum); // Yukarı hareket
    }
		
    if(HedefKat < OnKonum) // Seçilen kat mevcut kattan aşağı mı?
    {
      git(OnKonum - HedefKat,0,OnKonum); // Aşağı hareket
    }
    OnKonum = HedefKat;    // Yeni mevcut kat

T0IF=0;//TMR0 bayrağını temizle
TMR0=250;
}


void main(void)
{ 
	
  
 	TRISD=0xff;
	BUTONLAR=0;	
  	TRISC=0x00;
  	DISPLAY=0;
  	TRISB=0x00;
	PORTB=0;

T0CS=0;//TMR0 kaynağı-yazılımsal kesme için
PSA=0;	// ön bölücü-TMR0 kesmesi için
PS0=1;
PS1=1;
PS2=1;
TMR0=250;
T0IE=1;//timer 0 izin veriliyor
T0IF=0;
GIE=1;	// Genel kesme izni veriliyor 

while(1) 
  {
    
	i = BUTONLAR & 0x1F; //Hangi butona basıldı?örnek:1111 1110 & 0001 1111  	
    switch(i)
    {
      case 0x1F-1: HedefKat = 1; //Zemin kat seçildi 0001 1110
                   break;
      case 0x1F-2: HedefKat = 2; //1.kat seçildi 0001 1101
   		      break;
      case 0x1F-4: HedefKat = 3; //2.kat seçildi 0001 1011
		      break;	
      case 0x1F-8: HedefKat = 4; //3.kat seçildi 0001 0111
                   break;
      case 0x1F-16:HedefKat = 5; //4.kat seçildi 0000 1111
		      break;
    }	
	

  }
}

void git(int sayi, int yon, unsigned int OnKonum) 
{ // 0 aşağı , 1 yukarı
  int i;
  if(yon)
  { 
    YUKARI; //Motor yukarı yönde hareket ediyor
    for(i=1; i<=sayi; i++)
    {
      gecikme();gecikme();
      DISPLAY=OnKonum+i-1; //Geçilen katlar göstergede görülür 
	                          
    }
  }
  else
  {
    ASAGI;       // Motor aşağı yönde hareket ediyor
    for(i=1; i<=sayi; i++)
    {
      gecikme();gecikme();gecikme();
      DISPLAY=OnKonum-i-1; //Geçilen katlar göstergede görülür 
                                  
    }
  }
  DUR;      // Hedef kata gelindiğinde motor durur.
}


void gecikme(void) 
{	//1sn gecikme
  unsigned int i;
  for(i=0;i<8;i++)
      DelayMs(125); 
}

mufitsozen

#6
Alıntı yapılan: Klein - 09 Mayıs 2013, 13:06:39
Kodlar sembolik. Timer kesmesinin 1ms olduğunu varsaydım.

timer_int
{
      time_tick++;
}


main
{

    if(buton == press) led_delay = time_tick;
   
   if(time_tick > led_delay + 1000)  led = on;
}

.......
vs...
vs...

Sayin @Klein, sembolik kodlarla acikladiginiz temel aciklama ana kavramlari cok guzel bir sekilde aciklamis.

Yinede bu bahisle bir uygulama yapmak isteyen arkadaslarin, yazacaklari kod (C ile oldugunu varsayarak) hakkinda dikkat etmeleri gereken birkac tavsiyem olacak. Bu yazdiklarim, PIC 12/16/18 gibi 8 bit MCUlarin ve 16bit timerlarin kullanildigi varsayimi ile yapilmistir.

Birinci nokta timer-tick degeri timerin baslatildigi deger ile kontrol edildigi deger arasinda overflow edebilir.

yani  ornek koddaki time_tick > led_delay + 1000 satiri hatalar icerir.

ayrica C dilinde signed degiskenlerin overflow'u undefined yani tanimsizdir, compiler'a yada MCUya gore degisebilir. Ama unsigned overflow cok detayli tanimlanmistir. Bu yuzden embedded sistemlerin buyuk bir cogunlugunda bu tip timer overflow problemleri degiskenleri unsigned yaparak halledilebilir.

Ikinci nokta ise 8Bit bir MCUda 16 bir Timer degerlerini High ve Low bytelarini atomik bir sekilde (interrupt edilmeden) okumak mumkun değildir. (interruptlar OFF/ON edilmeden) buda 16bit Timer sayaci eger durdurulmadi ise, yazilma esnasinda LOW byteinin degisebilecegi ihtimalini/hatasini yaratir. Okurkende tek bir okuyusta 16 bit deger okunamadigi icin yine benzer bir durum olusabilir.

Hi-Tech yada CCS C bu durumu dikkate alarak kod uretir.

ikinci hususta biraz eski olmasina ragmen "Microchip DS33023A PIC micro Mid-Range MCU Family Reference Manual" cesitli yontemler onermektedir.

Arkadaslar yeni bir takim teknikler  denerken cikabilecek hatali durumlarin farkinda olmasi bakimindan bahsedeyim istedim.
Aptalca bir soru yoktur ve hiç kimse soru sormayı bırakana kadar aptal olmaz.

Erol YILMAZ

Alıntı yapılan: mufitsozen
Ikinci nokta ise 8Bit bir MCUda 16 bir Timer degerlerini High ve Low bytelarini atomik bir sekilde (interrupt edilmeden) okumak mumkun değildir. (interruptlar OFF/ON edilmeden) buda 16bit Timer sayaci eger durdurulmadi ise, yazilma esnasinda LOW byteinin degisebilecegi ihtimalini/hatasini yaratir. Okurkende tek bir okuyusta 16 bit deger okunamadigi icin yine benzer bir durum olusabilir.

Hi-Tech yada CCS C bu durumu dikkate alarak kod uretir.

Hi-tech ve CCS bu durumu dikkate almadan kod üretiyor diye düşünüyorum.
Bu durum göz ardı edilirse Yüzbinde  bir hata durumu oluştuğunu gördüm sanıyorum.

16 bitlik değişkene birşey yazarken veya okurken INT eğer bu değişkene mudahil oluyorsa burada da hatalar oluşabiliyor...
Bu durumda değişkeni "Volatile" ön-tanımı ile tanımlıyoruz.

Peki Volatile aslında ne yapıyor ?

mufitsozen

Alıntı yapılan: Allegro - 11 Mayıs 2013, 15:54:27
Hi-tech ve CCS bu durumu dikkate almadan kod üretiyor diye düşünüyorum.
Bu durum göz ardı edilirse Yüzbinde  bir hata durumu oluştuğunu gördüm sanıyorum.

16 bitlik değişkene birşey yazarken veya okurken INT eğer bu değişkene mudahil oluyorsa burada da hatalar oluşabiliyor...
Bu durumda değişkeni "Volatile" ön-tanımı ile tanımlıyoruz.

Peki Volatile aslında ne yapıyor ?

Maalesef bu durum dogru degil.

C dilindeki volatile anahtar kelimesi (keyword) degisken olarak taninan yerin compilerin bilgisi disinda degistigi durumlar icin kullanilir. Ornegin bir INPORT register (memory mapped IO) compilerin bilgisi disinda asyncron olarak degisebilir (device status registerlari ornegin), yada bir degisken bir ISR icinde yada multithread ortaminda paylasilirken  degisebilir vb Bu durumda ya compilerin butun optimizasyonlari kapatmak yada volatile kelimesi ile bu degiskeni optimizasyon disinda tutmak gerekir.

Özgür Murat Homurlu'nun blogunda volatile kelimesinin kullanimi ile ilgili daha aciklayici bilgi mevcut. http://ozgurmurat.blogspot.com/2009/05/c-dilinde-volatile-anahtar-kelimesi.html


MCU icin ozel olarak duzenlenmis butun compilerlarda 16 bit register'a 8 bit ile erismek yara 32 bit registera 16 bit ile erismek gibi durumlari goz onune alirlar.

Sizin gozlemlediginiz hatalar baska bir nedenden kaynaklanmis olmali.
Aptalca bir soru yoktur ve hiç kimse soru sormayı bırakana kadar aptal olmaz.