Pic16f877

ivit

Üye
Katılım
9 Nis 2022
Mesajlar
55
Puanları
1
Selamün aleyküm ustam kendimi geliştirmek için yaptığım dijital saat uygulaması var her şey sorunsuz lakin ortam ısısını ölçen LM35 entegresini kullandım artı değerleri alıyorum bunda da sıkıntı yok şunu fark ettim eksi(-1,-2,-5....vs) değerleri alamıyorum.
pic16f877 kodladım CCS C 'de.

 
programı görmeden ne desek boş
#include <16f877a.h>
#device ADC=10
#fuses NOWDT, XT, NOBROWNOUT, NODEBUG,NOWRT,PROTECT,NOLVP
#use delay(clock = 4000000)
#use fast_io(a)
#use fast_io(b)
#use fast_io(c)
#use fast_io(d)
#define LED PIN_C4

//Prototip
void lede_gonder(unsigned int bin, unsigned int yuz, unsigned int on, unsigned int bir);
void menu(unsigned int bin, unsigned int yuz, unsigned int on, unsigned int bir);

unsigned int display_digit[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; // ortak anotlu için
unsigned int saat=0,dk=0,k_saat=0,k_dk=10,a_saat=0,a_dk=30;
int sicaklik=0;
unsigned long int timer_count=0;
BOOLEAN ac = TRUE; // ac/kapa icin
unsigned int mod=0;
/* 0 -> saati gosterir
1 -> LEd açma saatini gosterir
2 -> led kapatma saatini gosterir
3 -> anlık sıcaklık
*/

//Interruptlar
#INT_TIMER0
void timer0_interrupt(){
//clock = 4,000 (internal clock)
//Prescalar 1/32 iken 122 sayim yapmasi lazım 1 sn'de
if( ++timer_count >= 122){
//saat islemi ve dakika islemleri
timer_count =0;
if(++dk >=60){
if(saat==23) {saat=0;} else{saat++;}
dk=0;
}
//sicaklik degerini oku
sicaklik = read_adc()/2;

clear_interrupt(INT_TIMER0);
if(dk==k_dk && saat == k_saat && ac){
output_bit(LED,0); //LED i kapat
//delay_ms(1);
}
if(dk==a_dk && saat == a_saat && ac){
output_bit(LED,1); //ledi ac
}

}
}
#int_rb
void portb_interrupt(){
delay_ms(2);
//rb7-dw rb6-up rb4-ac/kapa
if(!input(PIN_B7)){ //down pini
switch(mod){
case 0:
if(dk==0){dk=59; if(saat==0)saat=23;else saat--;}
else
dk--;
break;
case 1 :
if(a_dk==0){a_dk=59;if(a_saat==0)a_saat=23;else a_saat--;}
else
a_dk--;
break;
case 2:
if(k_dk==0){k_dk=59;if(k_saat==0)k_saat=23;else k_saat--;}
else
k_dk--;
break;
}
}
else if(!input(PIN_B6)){ // up pini
switch(mod){
case 0:
if(dk==59){dk=0; if(saat==23)saat=0;else saat++;}
else
dk++;
break;
case 1 :
if(a_dk==59){a_dk=0; if(a_saat==23)a_saat=0;else a_saat++;}
else
a_dk++;
break;
case 2:
if(k_dk==59){k_dk=0; if(k_saat==23)k_saat=0;else k_saat++;}
else
k_dk++;
break;

}
}
else if(!input(PIN_B5))
ac = !ac;
clear_interrupt(INT_RB);
}
#int_ext
void mod_interrupt(){
delay_ms(5);
if(++mod >3)
mod=0;
//interrupt bayrağını sil
clear_interrupt(INT_EXT);
switch(mod){
case 0:
menu(0x92,0x88,0x88,0x87);
break;
case 1:
menu(0x88,0xc6,0xff,0xff);//AC
break;
case 2:
menu(0x87,0x88,0x8c,0x88);//Kapa
break;
default :
menu(0x92,0xf9,0xc6,0xff);//anlık sıcaklık
}

}

void main(){
//led data icin d portu
set_tris_a(0xff);
set_tris_d(0);
//led kontrol icin c portu
set_tris_c(0);
set_tris_b(0xff); //port b input
//interruplar
enable_interrupts(GLOBAL);
enable_interrupts(INT_EXT);
ext_int_edge(0);
enable_interrupts(INT_RB);
enable_interrupts(INT_TIMER0);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_32|RTCC_8_BIT);//div_by 32
delay_us(10);
output_bit(LED,1);
delay_ms(1);
setup_adc(ADC_CLOCK_INTERNAL);
setup_adc_ports(ALL_ANALOG);
set_adc_channel(0);

while(TRUE){
if(ac){
switch (mod){
case 0: //saat modu
lede_gonder(display_digit[saat/10],display_digit[saat%10],display_digit[dk/10],display_digit[dk%10]);
delay_ms(2);
break;
case 1: //acma saati
lede_gonder(display_digit[a_saat/10],display_digit[a_saat%10],display_digit[a_dk/10],display_digit[a_dk%10]);
delay_ms(2);
break;
case 2: //kapatma saati
lede_gonder(display_digit[k_saat/10],display_digit[k_saat%10],display_digit[k_dk/10],display_digit[k_dk%10]);
delay_ms(2);
break;
default: //anlık sıcaklık göster
lede_gonder(display_digit[(int)sicaklik/100],display_digit[(int)(sicaklik/10)%10],display_digit[(int)sicaklik%10],0x9c);
}
}

}
}

void lede_gonder(unsigned int bin, unsigned int yuz, unsigned int on, unsigned int bir){ //ortak anot icin
//binler basamagi
output_bit(PIN_C0,1);
output_d(bin);
delay_ms(1);
output_bit(PIN_C0,0);

//yuzler basamagi
output_bit(PIN_C1,1);
output_d(yuz);
delay_ms(1);
output_bit(PIN_C1,0);

//onlar basamagi
output_bit(PIN_C2,1);
output_d(on);
delay_ms(1);
output_bit(PIN_C2,0);

//birler basamagi
output_bit(PIN_C3,1);
output_d(bir);
delay_ms(1);
output_bit(PIN_C3,0);

}
void menu(unsigned int bn, unsigned int yz, unsigned int n, unsigned int br){
unsigned int x;
for(x=0;x<100;x++){
lede_gonder(bn,yz,n,br);
}
}
 
lm35 çıkışında sıcaklığa bağlı analog voltaj ürettiği için negatif değerler için negatif voltaj üretir. Bunu lm35'in gnd pinine 2 tane diyot bağlayarak. Gnd noktasını diyorların vf değerine bağlı olarak yaklaşık 1.4 volt yukarı atarak sağlayabiliriz. Tabi lm35'in hem gnd pinini hemde vout pinine birer adc bağlayarak iki voltaj arasındaki farkı ölçmemiz gerekiyor. Eğer vout gnd pininden daha aşağıda bir voltaj üretirse demekki sıcaklık negatife dönüşmüştür. Geriye kalan formül aynıdır. Yani derece başına 10mV üretir. Mesela gnd-vout 100mV ise sıcaklık -10 derecedir. Aşağıdaki devreye göre kendi devreni tasarlayabilirsin.



Bana kalırsa d18b20 gibi dijital sıcaklık ölçen bir sensör kullanıp tüm bu dertlerden kurtul.
 

ustam teşekkürler lakin ds18b20 buldum araştırdım bağlama şeklini de buldum bağladım lakin kod da oynamam gerekiyor şimdi.
 
Bu siteyi kullanmak için çerezler gereklidir. Siteyi kullanmaya devam etmek için onları kabul etmelisiniz. Daha fazla bilgi edin…