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
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...
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++);
}
}
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.
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
}
}
(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);
}
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.
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 ?
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.