Picproje Elektronik Sitesi

MİKRODENETLEYİCİLER => Microchip PIC => Konuyu başlatan: ziftinpeki - 09 Mayıs 2013, 11:48:07

Başlık: timer ile gecikme yapma
Gönderen: ziftinpeki - 09 Mayıs 2013, 11:48:07
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
Başlık: Ynt: timer ile gecikme yapma
Gönderen: 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;
}

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...
Başlık: Ynt: timer ile gecikme yapma
Gönderen: ziftinpeki - 09 Mayıs 2013, 15:55:14
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++);
  }
}
Başlık: Ynt: timer ile gecikme yapma
Gönderen: Mefe - 09 Mayıs 2013, 17:35:02
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.
Başlık: Ynt: timer ile gecikme yapma
Gönderen: ziftinpeki - 10 Mayıs 2013, 00:14:10
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
}
}
Başlık: Ynt: timer ile gecikme yapma
Gönderen: ziftinpeki - 10 Mayıs 2013, 14:45:37
(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);
}
Başlık: Ynt: timer ile gecikme yapma
Gönderen: mufitsozen - 11 Mayıs 2013, 15:34:02
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.
Başlık: Ynt: timer ile gecikme yapma
Gönderen: Erol YILMAZ - 11 Mayıs 2013, 15:54:27
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 ?
Başlık: Ynt: timer ile gecikme yapma
Gönderen: mufitsozen - 11 Mayıs 2013, 16:18:08
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 (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.