Açıklamalı pic16f877 uygulama kodları cod asm c
PIC16F877 C dili ile hazırlanan proje listesi ve örnekler
GrafikLCD.c: T6963C tabanlı Grafik LCD’ye text yazar ve çizgi çizer.
15_1.c: Terminal Projesi
14_13.c: MPX4115 basınç sensörü uygulaması
14_12.c: MT8870 ile DTMF ton kod çözücü uygulaması
14_11_2.c: RF alıcı modülü programı
14_11_1.c: RF verici modülü programı
14_10.c: Rotary pulse encoder ile ses üretme
14_9.c: Rotary pulse encoder uygulaması
14_8.c: DS1868 dijital potansiyometre uygulaması
14_7.c: DS1990(i-button) uygulaması
14_6.c: PCF8583 ile saat uygulaması
14_5.c: DS1307 RTC
14_4.c: DS1302 RTC
14_3.c: DS18B20 ısı sensörü ile ısı ölçümü
14_2.c: DS1621 ısı sensörü ile ısı ölçümü
14_1.c: DS1620 ısı sensörü ile ısı ölçümü
13_3.c: L297 ve L298 ile step motor kontrolü
13_3.c: L297 ve L298 ile step motor kontrolü
13_2.c: Step motor kontrolü (ULN2003 ile)
13_1.c: DC motor hız ve yön kontrolü
// Dosya Adı : 15_1.c // Açıklama : Terminal Projesi // PIC DK 2.1 : PORTB Çıkış ==> LCD display // : A/D seçim anahtarı RA1 A, diğerleri D konumunda // : XT ==> 4 MHz // Hi ve Lo fonksiyonları için başlık dosyası programa katılıyor. #include "built_in.h" // Alarm fonksiyonu ile ilgili tanımlamalar yapılıyor. #define ALARMPORT PORTE #define ALARMTRIS TRISE #define ALARMCIKIS F0 #define ALARMKURULU F1 #define ALARMKAPAT PORTA.F4 // Alarm kesme butonu // Sensörler için analog kanal tanımlamaları yapılıyor. #define LM35 0 // 0. adc kanalına bağlı #define LDR 1 // 1. adc kanalına bağlı // Global değişken tanımlamaları yapılıyor. unsigned short tmp,i; unsigned char ControlReg, TaskControl, RxBuffer; unsigned char saat, dakika, saniye, a_saat, a_dakika, AlarmCnt; unsigned int isi, isik, epadres, adr; unsigned short PWMDuty; // Kesme Alt Programı. void interrupt(void) { // Timer1 kesmesi işleniyor. if (PIR1.TMR1IF) { TaskControl.F3 = 1; TMR1L = 0x00; // Ön değerler atanıyor 4096 artış sonrası TMR1H = 0xF0; // taşma gerçekleşecek PIR1.TMR1IF = 0; } // RX seri iletişim veri alma kesmesi işleniyor. if (PIR1.RCIF) { // alınan karakter RCREG'de if(RCSTA.FERR || RCSTA.OERR) { RCSTA.CREN = 0; asm nop // Bit işlemleri arasında 1us kadar bekle RCSTA.CREN = 1; } PIR1.RCIF = 0; // Alma kesme bayrağını sil. RxBuffer = RCREG; // Alınan veriyi değişkene ata. ControlReg.F7 = 1; // Veri alındı kontrol bitini set et TaskControl.F0 = 1; // Terminal için görev kontrol // bayrağını set et. PIR1.RCIF = 0; } } // EEPROM’a veri yazar. void e2eprom_write(unsigned int adr, unsigned short data) { I2C_Start(); // I2C start sinyali gönder I2C_Wr(0xA0); // I2C donanım adresi + yazma komutu gönder I2C_Wr(Hi(adr)); // Yazılacak adresin yüksek byte'ını gönder I2C_Wr(Lo(adr)); // Yazılacak adresin alçak byte'ını gönder I2C_Wr(data); // Yazılacak veriyi gönder I2C_Stop(); // I2C iletişimi durdur Delay_ms(100); // işlemlerin tamamlanması için 100ms bekle } // EEPROM’dan veri okur. unsigned short e2eprom_read(unsigned int adr) { unsigned short data; I2C_Start(); // I2C start sinyali gönder I2C_Wr(0xA0); // I2C donanım adresi + yazma komutu gönder I2C_Wr(Hi(adr)); // Yazılacak adresin yüksek byte'ını gönder I2C_Wr(Lo(adr)); // Yazılacak adresin alçak byte'ını gönder I2C_Repeated_Start(); // I2C reStart sinyali gönder I2C_Wr(0xA1); // I2C donanım adresi + okuma komutu gönder data = I2C_Rd(0u); // Veriyi oku (NO acknowledge) I2C_Stop(); // I2C iletişimi durdur return data; // okunan veriyi fonksiyon dışına taşı } // USART birminden bir karakter alır. char GetChar() { while(!(ControlReg.F7)); // Seri porttan 1 karakter alınana kadar // bekle ControlReg.F7 = 0; // Karakter alındı bayrağını sil return RxBuffer; // Alınan karakteri çıkışa aktar } // USART'a bir karakter gönderir. void sendChar(char c) { if(!(TXSTA.TXEN)) TXSTA.TXEN = 1; // Veri gönderme kesmesini // etkinleştir. while(!(PIR1.TXIF)); // Veri gönderilene kadar bekle PIR1.TXIF = 0; // Veri gönderildi, bayrağı sil TXREG = c; } // USART'a string yazar. void writeString(const char *s) { char i=0; // Gönderilecek stringin karakter sırası while( s[i]!=0 ) sendChar(s[i++]); // stringin sıradaki // karakterini gönder } // Karakteri hex değere dönüştürür. unsigned short Char_to_Hex(unsigned short gec) { ControlReg.F6 = 0; if (gec>47 && gec<58) { gec=gec-48; return gec; } else if (gec>64 && gec<71) // A, B, C, D, E, F girişleri için { gec=gec-65; gec=gec+0x0A; return gec; } else if (gec>96 && gec<103) // a, b, c, d, e, f girişleri için { gec=gec-97; gec=gec+0x0A; return gec; } // Hatalı karakter ControlReg 6. bit set et. Gerekirse bu bit // kontrol edilerek hatalı girişler engellenebilir. ControlReg.F6 = 1; return 0; } // USART'dan hex bilgi alır ve USART'a gönderir. unsigned short GetSendHexByte() { unsigned short ch; ch = GetChar(); sendChar(ch); tmp = Char_to_Hex(ch); asm swapf _tmp,F ch = GetChar(); sendChar(ch); ch = Char_to_Hex(ch); if (ControlReg.F6) return 0xFF; // Hatalı karakter ise 0xFF // aktar tmp = tmp + ch; return tmp; } // USART'dan desimal bilgi alır ve USART'a gönderir. unsigned short GetSendDecByte() { return Bcd2Dec(GetSendHexByte()); } // USART'a Desimal olarak 1 byte yazar void sendDecByte(unsigned short data) { unsigned short onlar, birler; onlar = 0; birler = 0; while( data>=10) { onlar++; data = data - 10; } birler = data; sendChar('0'+ onlar); sendChar('0'+ birler); } // LCD'ye Desimal olarak 1 byte yazar void LCD_DecWrite(unsigned short data) { unsigned short onlar, birler; onlar = 0; birler = 0; while( data>=10) { onlar++; data = data - 10; } birler = data; Lcd_Chr_Cp('0'+ onlar); Lcd_Chr_Cp('0'+ birler); } // LM35 ISI sensörü ile ilgili fonksiyonlar void IsiOlc() { // LM35'in bağlı olduğu ADC kanalından ısı şiddetini al ve // dönüştür Isi = Adc_Read(LM35) >> 1; // 2'ye bölerek gerçek ısı değerini bul yaklaşık her bir artış // değeri 5 mV, 2 arttığında 10 mV yani 1 derece, Bu nedenle // 2'ye bölüyoruz. Sonuç gerçek ısı değerine çok yakın. // İstenirse yarım derece hassasiyet ile ısı görüntülenebilir. // Ayrıca referans gerilim ayarlanarak daha hassas ve daha doğru // ısı ölçümleri gerçekleştirilebilir. } void IsiGoruntule() { // Isı şiddetini PC terminalinde görüntüle sendDecByte(Isi);sendChar(' ');sendChar('C'); } // LDR IŞIK sensörü ile ilgili fonksiyonlar void IsikOlc() { // LDR'nin bağlı olduğu ADC kanalından ışık şiddetinin en // değersiz byte'ını al Isik = Adc_Read(LDR); } void IsikGoruntule() { // Işık şiddetini PC terminalinde görüntüle sendDecByte(Isik); } // Zaman ile ilgili fonksiyonlar void ZamanAyarla() { saat = GetSendDecByte(); sendChar(':'); dakika = GetSendDecByte(); } void ZamanGoruntule() { // Saati PC terminalinde görüntüle SendDecByte(saat); sendChar(':'); SendDecByte(Dakika); } // Alarm ile ilgili fonksiyonlar void AlarmAyarla() { // Alarm saat ve dakika bilgisini al ve eeproma kaydet a_saat = GetSendDecByte(); sendChar(':'); a_dakika = GetSendDecByte(); Eeprom_Write(0x10, a_saat); Eeprom_Write(0x11, a_dakika); } void AlarmGoruntule() { // Alarmı eepromdan oku ve PC terminalinde görüntüle a_saat = Eeprom_Read(0x10); a_dakika = Eeprom_Read(0x11); sendDecByte(a_saat); sendChar(':'); sendDecByte(a_dakika); } // Saat ile ilgili fonksiyonlar void ZamanIsle() { saniye++; if(saniye>59) { saniye = 0; dakika++; if(dakika>59) { dakika = 0; saat++; if(saat>23) saat = 0; // Her saat başı saat bilgisi ve ısı bilgisi e2eproma // kaydediliyor. IsiOlc(); e2eprom_write(epadres, saat); epadres++; e2eprom_write(epadres, Isi); epadres++; } // 40 dk boyunca alarm susturulmadı ise alarmı kes if (ControlReg.ALARMCIKIS) { AlarmCnt++; if (AlarmCnt>=40) { ControlReg.ALARMCIKIS = 0; ControlReg.ALARMKURULU = 0; ALARMPORT.ALARMCIKIS = 0; AlarmCnt = 0; } } } // Alarm kurulu ise alarm zamanını kontrol et if (ControlReg.ALARMKURULU) if ((saat == a_saat) && (dakika == a_dakika)) { ALARMPORT.ALARMCIKIS = 1; ControlReg.ALARMCIKIS = 1; } // LCD'de saat:dakika:saniye bilgilerini görüntüle Lcd_Out(1,1, ""); LCD_DecWrite(saat);Lcd_Chr_Cp(':'); LCD_DecWrite(dakika);Lcd_Chr_Cp(':'); LCD_DecWrite(saniye); // LCD'de ısı bilgisini görüntüle IsiOlc(); Lcd_Out(2,1, "ISI: "); LCD_DecWrite(Isi); Lcd_Chr_Cp('C'); } // PC ile iletişim kuran terminal fonksiyonu void TerminalProgram() { unsigned short ch,tmp,i; ch=GetChar(); if (ch==13) while(ch!=48) { do { // PC Terminalinde menü yazdırılıyor. writeString("rnrn DK 2.1 Iletisim Menusune Hosgeldiniz"); writeString("rn Copyright © Ayhan DAYANIK - 2006 adayanik@gmail.com"); writeString("rnrn MENU SECENEKLERI:nr"); writeString(" <1> Isi goster..nr"); writeString(" <2> Isik siddeti goster..nr"); writeString(" <3> Saati goster..nr"); writeString(" <4> Alarmi goster..nr"); writeString(" <5> e2eprom'dan saat-isi bilgilerini listele..nr"); writeString(" <6> Saati ayarla..nr"); writeString(" <7> Alarmi kur..nr"); writeString(" <8> PWM darbe genisligi ayarla..nr"); writeString(" <0> Cikis..nrnr"); writeString(" SECIMINIZ: "); ch=GetChar(); // PC terminalinden karakter al } while(ch<48 || ch>57); // Alınan seçim 0-8 arasında // değilse tekrar giriş al // Alınan seçim bilgisini PC terminaline yaz sendDecByte(ch-48);writeString("nr "); // Alınan karakteri kontrol et ve görevi yerine getir. switch(ch) { // Alınan karakter '0' ise ch = 0 olduğundan while // döngüsünden dolayısı ile Terminal Program'dan // çıkılır. case 48:writeString("nr Menuye girmek icin ENTER'e basiniz.. nr"); break; // Isı değerini ölç ve PC terminalinde göster case 49:writeString("nr Isi degeri: "); IsiOlc(); sendDecByte(Isi);sendChar(' ');sendChar('C'); break; // Işık şiddetini ölç ve PC terminalinde göster, Burada ışık şiddeti // işlenmemiş bir şekilde görüntülendi. Işık şiddetini doğru olarak // görüntülemek için okunan değerin logaritmik olarak işlenmesi // gerekmektedir. Projemizde ışık şiddeti ısı kadar önemli // olmadığından ve programın anlaşılırlığını korumak için dönüşüm // yapılmamıştır. İstenirse okunan belirli değerlerde ışık şiddeti // hesaplama yöntemi yerine bilgisayar ortamında hesaplanmış bir // tablo kullanmak daha yerinde olacaktır. case 50:writeString("nr Isik siddeti: "); Isik = Adc_Read(LDR); sendDecByte(Isik); break; // PC terminalinde saat:dakika formatında zaman // görüntülenir. case 51:writeString("nr Saat: "); SendDecByte(saat); sendChar(':'); SendDecByte(Dakika); break; // PC terminalinde alarm kurulu ise alarm zamanını, // kurulu değil ise alarmın kurulu olmadığına dair // mesaj görüntüler. case 52:if(ControlReg.ALARMKURULU) { a_saat = Eeprom_Read(0x10); a_dakika = Eeprom_Read(0x11); writeString("nr Alarm zamani: "); sendDecByte(a_saat); sendChar(':'); sendDecByte(a_dakika); } else writeString("nr Alarm kurulmamis.."); break; // PC terminalinde ESC tuşuna basana kadar ya da eeprom // sonuna yakın bir değere ulaşana kadar 10'ar 10'ar // belirli zamanlarda ölçülmüş ısı değerini görüntüle case 53:adr = 0; tmp = 1; do { writeString("nr Saat - Isi nr"); writeString("nr ----------- nr"); for ( i=0;i<10;i++) { writeString(" "); ch = e2eprom_read(adr); if (ch > 23) {tmp = 0; ch = 27; break;} sendDecByte(ch); writeString(" --- "); adr++; ch = e2eprom_read(adr); sendDecByte(ch); writeString("nr"); adr++; } if (tmp) { writeString("nr Cikis icin ESC tusuna basiniz..nr"); ch = GetChar(); } else { if (adr < 0xFF0) ch = 0; else ch = 27; } } while (ch!=27); break; // PC terminalinden saat:dakika girişini alarak zamanı ayarlar case 54:writeString("nr Saat ve dakika giriniz ( HH:MM ): "); saat = GetSendDecByte(); sendChar(':'); dakika = GetSendDecByte(); break; // PC terminalinden alarma ait saat:dakika girişini alarak // alarm zamanını ayarlar case 55:writeString("nr Alarm zamanini giriniz ( HH:MM ): "); a_saat = GetSendDecByte(); sendChar(':'); a_dakika = GetSendDecByte(); Eeprom_Write(0x10, a_saat); Eeprom_Write(0x11, a_dakika); ControlReg.ALARMKURULU = 1; // Alarm etkinleştirildi break; // PC terminalinden PWM darbe genişliğini alarak darbe // genişliğini ayarlar case 56:writeString("nr PWM darbe genisligini giriniz (00-FF): "); PWMDuty = GetSendHexByte(); PWM_Stop(); PWM_Init(1000); // PWM frekansı 1KHz seçildi PWM_Change_Duty(PWMDuty); PWM_Start(); break; } } } // Kullanılan birimlerin kullanıma hazır getirildiği ve bazı // değişkenlere ilk değer atamalarının yapıldığı alt program void main_init() { TRISC.F1 = 1; // Timer1 için RC1 giriş yapıldı ALARMTRIS.ALARMCIKIS = 0; // Çıkışa yönlendirildi ALARMPORT.ALARMCIKIS = 0; // İlk anda alarm çalmıyor //Port yönlendir TX çıkış, RX giriş TRISC.F6 = 0; // TX ucu çıkış yapıldı TRISC.F7 = 1; // RX ucu girişe ayarlandı TXSTA = 0; // TXSTA ilk anda sıfır RCSTA = 0; // RCSTA ilk anda sıfır // SPBRG = 129; // 20 Mhz de 9600 baud hız için SPBRG = 25; // 4 Mhz de 9600 baud hız için // SPBRG = 50; // 8 Mhz de 9600 baud hız için TXSTA = 0x26; RCSTA = 0x90; PIE1.RCIE = 1; // Saat ile ilgili ilk değerler atanıyor. saat = 0; dakika = 0; saniye = 0; AlarmCnt = 0; // LCD kullanıma hazırlanıyor. Lcd_Config(&PORTB,4,5,7,3,2,1,0); // LCD bağlantı tanımlamaları Lcd_Cmd(LCD_CLEAR); // LCD'yi sil Lcd_Cmd(LCD_CURSOR_OFF); // İmleci gizle I2C_Init(100000); // I2C iletişimi 100 KHz epadres = 0; // eprom adresi sıfırlandı a_saat = Eeprom_Read(0x10); // Alarm saatini oku a_dakika = Eeprom_Read(0x11); // Alarm dakikasını oku T1CON.TMR1ON = 0; // ilk anda timer1 kapalı TMR1L = 0x00; // Ön değerler atanıyor 4096 artış // sonrası 32.768 kHz kristal için TMR1H = 0xF0; // taşma gerçekleşecek T1CON = 0x3A; // 1:8 prescaler, senkronizeli ext. // clock, PIE1.TMR1IE = 1; T1CON.TMR1ON = 1; // zamanlayıcı çalıştırıldı PWM_Init(1000); // PWM frekansı 1KHz seçildi PWM_Change_Duty(0x80); // Duty cycle %50 seçildi PWM_Start(); ADCON1 = 0x84; // RA0, RA1, RA3 analog, diğerleri // dijital, sonuç sağa dayalı TRISA.F4 = 1; // Alarm susturma butonu için giriş // yapıldı ControlReg = 0; // Kontrol kaydedicisini sil TaskControl = 0; // Görev kontrol kaydedicisini sil INTCON.PEIE = 1; // Çevresel kesmeleri etkinleştir. INTCON.GIE = 1; // Etkinleştirilen kesmelere izin ver } // ANA PROGRAM void main() { main_init(); // İlk işlemler alt programını çağır while(1) { // Aşağıda görevler yer almaktadır. Kesme içerisinde set olan // görev bayrakları burada sırası ile işlenirler. Öncelik // sıralaması görevin önceliğine göre tespit edilmelidir. // Seri iletişim görevi, Veri alındı ve işlenmesi gerekiyor if (TaskControl.F0) { TerminalProgram(); // Seri iletişim menüsünü PC'de // göster ve menü işlemlerini yap TaskControl.F0 = 0; // Yeni görev için silinmelidir. } // LM35 ısı sensöründen ısı okuma zamanı geldi if (TaskControl.F1) { IsiOlc(); // Isı şiddeti ölç TaskControl.F1 = 0; // Yeni görev için silinmelidir. } // LDR ışık sensöründen ışık şiddeti okuma zamanı if (TaskControl.F2) { IsikOlc(); // Işık şiddeti ölç TaskControl.F2 = 0; // Yeni görev için silinmelidir. } // 1 sn geçti. Zamanı işle, alarm zamanını kontrol et if (TaskControl.F3) { ZamanIsle(); // Saati işle TaskControl.F3 = 0; // Yeni görev için silinmelidir. } // Alarm susturma ve iptal butonuna basıldı mı? if (!ALARMKAPAT) { ControlReg.ALARMCIKIS = 0; // Alarm çalma bayrağını sil. ControlReg.ALARMKURULU = 0;// Alarm kurulu bayrağını sil ALARMPORT.ALARMCIKIS = 0; // Alarmı sustur AlarmCnt = 0; // Alarm süresi kaydedicisini sil } // Bu bölüme varsa diğer görevler eklenebilir } }
// Dosya Adı : 14_13.c
// Açıklama : MPX4115 basınç sensörü uygulaması
// Notlar : XT ==> 4 MHz
// MPX4115 Basınç sensörünün mikrodenetleyiciye bağlantıları
// tanımlanıyor.
#define mpx4115 PORTA
#define mpx4115_tris TRISA
#define mpx4115_pin 2
// Değişken tanımlamaları yapılıyor.
unsigned int mpx4115_data, ondalik;
char *str=" . kP ";
// Bir byte'lık hexadesimal sayıyı 2 basamaklı desimal sayıya
// dönüştürür.
char Hex2Dec(char ch) // 2 digit dönüşüm
{
char tmp = 0; // Geçici değişkeni sıfırla
// sayının onlar basamağı bulunuyor
while(ch>=10) {tmp++; ch -= 10;}
tmp = (tmp<<4) + ch; // Birler basamağını sayıya ekle
return tmp; // Sonucu fonksiyon dışına taşı
}
// hexadesimal değeri LCD'de görüntülemek için text'e dönüştürür.
void BintoStr(unsigned short tam, unsigned short ondalik)
{
// tam kısım 200 ve üzerinde ise str'nin ilk karakteri 2, değilse
// 100 ve üzerinde olduğu kontrol edilir. 100 ve üzerinde ise
// str'nin ilk karakteri 1. Eğer tam kısım 100'den küçükse str'nin
// ilk karakteri boşluk. Tam kısmın 100 ve üzerindeki değeri tam'dan
// düşülür.
if(tam >= 200) {str[0] = 50; tam -= 200; }
else if (tam >= 100) { str[0] = 49; tam -= 100; } else str[0] = 32;
// tam kısım artık 100'den küçüktür. 2 basamak desimal dönüşüme
// uygundur.
tam = Hex2Dec(tam); // Kalan tam kısmı desimale dönüştür.
str[1]= 48 + ((tam & 0xF0) >> 4); // Onlar basamağını elde et
// Eğer yüzler ve onlar basamağının her ikiside sıfır ise str'de
// onlar basamağına yani str'nin 2. karakterine boşluk yaz
if ((str[0] == 32) && (str[1] == 48)) str[1] = 32;
// en değersiz dört bit text'e dönüştürülüyor
str[2]= 48 + (tam & 0x0F);
// ondalık kısmı str'nin 5. karakterine yazılıyor
str[4]= 48 + ondalik;
}
// Portları ve LCD birimini kullanıma hazırlar.
void init()
{
// Analog girişler seçildi, Vref+ = Vdd, Vref- = Vss seçildi.
ADCON1 = 0x80;
TRISA = 0xFF;
LCD_Config(&PORTB,4,5,7,3,2,1,0);
LCD_Cmd(LCD_CURSOR_OFF);
delay_ms(500);
}
// MPX4115 basınç sensöründen analog basınç bilgisi elde edilir. Bu
// bilgi MPX4115'in bağlandığı analog pinden 10 bit çözünürlüğünde
// sayısal bilgiye dönüştürülür. Elde edilen bilgi işlenerek basınç
// değeri tam ve ondalıklı kısmı elde edilir ve fonksiyon dışına
// taşınır.
unsigned short mpx4115_read()
{
// tam kısmı tutacak değişken tanımlanıyor.
unsigned short tmp;
unsigned i, hata; // döngü ve hata değişkeni tanımlanıyor.
// Basınç değeri sayısal değere dönüştüülüyor
mpx4115_data = Adc_Read(mpx4115_pin);
// 15 kP'lık ilk değer çıkartılıyor.
mpx4115_data -= 56;
hata = 0; // hata payı ilk durumda sıfır.
// Hata oranı tespit ediliyor.
for(i = 9; i <= mpx4115_data ; i +=15) hata++;
mpx4115_data += hata; // Hata payı ekleniyor
// tam kısım elde ediliyor ve 15 kP'lık ilk değer ekleniyor.
tmp = mpx4115_data/10 + 15;
ondalik = mpx4115_data%10; // ondalıklı kısım elde ediliyor.
return tmp; // tam kısım fonksiyon dışına taşınıyor.
}
// Ana program MPX4115 basınç sensöründen analog basınç bilgisini
// alarak sayısal değere dönüştürüp işleyerek basınç değerini %1
// hata payı ile hesaplar. Sonucu LCD display'de 500 ms ara ile
// görüntüler.
void main()
{
// 1 byte işaretsiz geçici değişken tanımlanıyor.
unsigned short tmp;
// Portlar ve LCD kullanıma hazırlanıyor.
init();
do // do - while döngüsü ile sonsuz çevrim başlıyor.
{
// MPX4115'ten basınç değerinin sayısal karşılığının tam kısmı ve
// ondalıklı kısmı elde ediliyor.
tmp = mpx4115_read();
// Tam ve ondalıklı kısım str dizisine aktarılıyor.
BintoStr(tmp, ondalik);
Lcd_Out(1,1, "Basinc= ");
// str dizisi LCD'de görüntüleniyor.
Lcd_Out_Cp(str);
Delay_ms(500);
} while(1); // Ana program çevrimine devam et
}
// Dosya Adı : 14_11_2.c
// Açıklama : RF alıcı modülü programı
// Notlar : XT ==> 4 MHz
// Sabit tanımlamalar yapılıyor.
// Anlamlı bir karakter olması önemli değil. Sonuçta sadece kontrol
// içi kullanılacak LCD ya da terminalde yazdırılmayacak. Ancak
// RF verici modülündeki kodlar ile aynı olmak zorunda.
#define ST1 0xA9
#define ST2 0xAE
// Genel değişken tanımlamaları yapılıyor
unsigned short i, Data[3];
unsigned char ControlReg, RxBuffer;
char txt[]=" ";
char ch;
// RF_read fonksiyonu RF modülünden 1 byte veri alır
unsigned short RF_read()
{
// Yerel geçici değişkenler tanımlanıyor.
unsigned short tmp, i;
i = 0; // Karakter sayacı sıfırlanıyor.
do
{
if (Usart_Data_Ready())
{ // Eğer veri alındı ise
tmp = Usart_Read(); // Alınan veriyi oku
switch(i)
{
// 0. karakter alındı ise ve alınan karakter ST1 kontrol karakterine
// eşitse Data[0]'a kaydet ve i sayacını artır.
case 0: if (tmp == ST1) {Data[0] = tmp; i++;} break;
// 1. karakter alındı ise ve alınan karakter ST2 kontrol karakterine
// eşitse Data[1]'e kaydet ve i sayacını artır. Aksi halde i alınan
// karakter sayacını sıfırla. Çünkü kontrol karakterleri hatalı,
// dolayısıyle veri alımı hatalı olduğundan başa dön ve yeniden
// almaya başla
case 1: if (tmp == ST2) {Data[1] = tmp; i++;} else i = 0; break;
// İlk 2 karakter doğru alındı ise 3. karakterde doğru gelecektir.
// 3. karakter bizim gerçek verimizdir. İstenirse verilerin daha
// hatasız ulaşması için kontrol karakter sayısı artırılabilir.
case 2: Data[2] = tmp; i++; break;
default: break;
}
}
PORTD = tmp;
// 3 karakterde alındı ise do-while döngüsünden çık
} while (i<3);
return tmp; // Son alınan veriyi fonksiyon dışına taşı
}
// LCD ve Usart birimlerini kullanıma hazırlar
void init()
{
Usart_Init(2400);
LCD_Config(&PORTB,4,5,7,3,2,1,0);
LCD_Cmd(LCD_CURSOR_OFF);
}
// Ana program RF modülünden aldığı verileri LCD'de görüntüler
void main()
{
init(); // LCD ve Usart birimlerini kullanıma hazırla
do
{
i = 0;
Lcd_Cmd(LCD_FIRST_ROW);
do
{
// RF modülünden alınan karakteri LCD'ye yaz
ch = RF_read();
Lcd_Chr_Cp(ch);
i++; // karakter sayacını artır
} while (i<16);
} while(1); // Okuma ve görüntüleme işlemine devam
}
// Dosya Adı : 14_10.c
// Açıklama : Rotary pulse encoder ile ses üretme
// Notlar : Proteus programı simülasyonu
// : XT ==> 4 MHz
// Rotary Encoder'in mikrodenetleyiciye bağlantısı tanımlanıyor.
#define RotaryEncoder PORTE
#define RotaryEncoder_tris TRISE
// Rotary Encoder'in mikrodenetleyiciye bağlantısı tanımlanıyor.
#define Buzzer PORTC
#define Buzzer_pin 1
// Global değişken tanımlamaları yapılıyor.
char Encoder, oldEncoder;
unsigned tmp, sayac;
char txt[5];
// Portları ve LCD'yi kullanıma hazırlar, değişkenlere ilk değer
// atamaları yapar.
void init()
{
LCD_Config(&PORTB,4,5,7,3,2,1,0);
LCD_Cmd(LCD_CURSOR_OFF);
// Buzzer'ın bulunduğu port ses çıkışı için hazırlandı
Sound_Init(&Buzzer, Buzzer_pin);
ADCON1 = 0x06; // Analog girişleri kapat.
RotaryEncoder = 0; // Portun ilk durumu sıfırlanıyor.
RotaryEncoder = 0x03; // Rotary Encoder portu giriş yapıldı
// Rotary encoder'in değerini tutan değişkene ilk değer veriliyor.
Encoder = 0x03;
sayac = 0; // sayac değeri sıfırlanıyor.
Lcd_Out(1,1,"Sayac:");
}
// Ana program Rotary encoder'den gelen bilgiyi değerlendirerek sağa
// ya da sola doğru çevrildiğini belirler ve rotary encoder sağa
// çevrilmiş ise sayac değerini 1 artırır, sola çevrildi ise sayacı
// 1 azaltır ve sayac değerini LCD'de görüntüler ve sayac değerinin
// 10 katı frekansta ses üzetir. Aynı zamanda herhangi bir
// değişiklik yoksa değişim olana kadar rotary encoder'den gelen
// bilgiyi bir önceki bilgi ile kıyaslamaya devam eder.
void main()
{
init();
do
{
// yeni değer eski değere yükleniyor
oldEncoder = Encoder;
// 2 byte'lık sayac desimale dönüştürülüyor
tmp = Bcd2Dec16(sayac);
// desimale dönüştürülün değer text'e çevriliyor.
WordToStr(tmp, txt);
Lcd_Out(1,1,"Sayac:");
Lcd_Out(2,4,txt);
// Rotary encoder'in eski değeri ile yeni değerini karşılaştır.
// Birbirinden farklı olana kadar (rotay encoder çevrilene kadar)
// karşılaştırmaya ve sayac frekansında ses üretmeye devam et.
while(Encoder == oldEncoder)
{
// Rotary encoder'in değeri okunuyor
Encoder = RotaryEncoder & 0x03;
// sayac*10 frekansında, 150 peryotluk ses
Sound_Play(sayac, 50);
}
// eski değerin 1. biti yeni değerin 0. bitinden farklı ise ve eski
// değerin 0. biti yeni değerin 1. bitine eşit ise rotary encoder
// sağa doğru çevrilmiştir, bu durumda sayac 254'den küçükse artır.
if(oldEncoder.F1 !=Encoder.F0)
{
if(oldEncoder.F0 == Encoder.F1) if(sayac<254) sayac++;
} else
// eski değerin 0. biti yeni değerin 1. bitinden farklı ise ve eski
// değerin 1. biti yeni değerin 0. bitine eşit ise rotary encoder
// sola doğru çevrilmiştir, bu durumda sayac 0'dan büyükse azalt.
if(oldEncoder.F0 != Encoder.F1)
{
if(oldEncoder.F1 == Encoder.F0) if(sayac>0) sayac--;
}
} while(1); // Ana program çevrimine devam et
}
// Dosya Adı : 14_9.c
// Açıklama : Rotary pulse encoder uygulaması
// Notlar : Proteus programı simülasyonu
// : XT ==> 4 MHz
// Rotary Encoder'in mikrodenetleyiciye bağlantısı tanımlanıyor.
#define RotaryEncoder PORTE
#define RotaryEncoder_tris TRISE
// Global değişken tanımlamaları yapılıyor.
char Encoder, oldEncoder;
unsigned tmp, sayac;
char txt[5];
// Portları ve LCD'yi kullanıma hazırlar, değişkenlere ilk değer
// atamaları yapar.
void init()
{
LCD_Config(&PORTB,4,5,7,3,2,1,0); // LCD bağlantısı tanımlanıyor
LCD_Cmd(LCD_CURSOR_OFF); // imleci gizle
ADCON1 = 0x06; // Analog girişleri kapat.
RotaryEncoder = 0; // Portun ilk durumu sıfırlanıyor.
RotaryEncoder = 0x03; // Rotary Encoder portu giriş yapıldı
// Rotary encoder'in değerini tutan değişkene ilk değer veriliyor.
Encoder = 0x03;
sayac = 0; // sayac değeri sıfırlanıyor.
Lcd_Out(1,1,"Sayac:");
}
// Ana program Rotary encoder'den gelen bilgiyi değerlendirerek sağa
// ya da sola doğru çevrildiğini belirler ve rotary encoder sağa
// çevrilmiş ise sayac değerini artırır, sola çevrildi ise sayacı
// azaltır ve sayac değerini LCD'de görüntüler. Herhangi bir
// değişiklik yoksa değişim olana kadar rotary encoder'den gelen
// bilgiyi bir önceki bilgi ile kıyaslamaya devam eder.
void main()
{
init();
do
{
// yeni değer eski değere yükleniyor
oldEncoder = Encoder;
// 2 byte'lık sayac desimale dönüştürülüyor
tmp = Bcd2Dec16(sayac);
// desimale dönüştürülün değer text'e çevriliyor.
WordToStr(tmp, txt);
Lcd_Out(1,1,"Sayac:");
// sayac değeri LCD'de görüntüleniyor.
Lcd_Out(2,4,txt);
// Rotary encoder'in eski değeri ile yeni değerini karşılaştır.
// Birbirinden farklı olana kadar (rotay encoder çevrilene kadar)
// karşılaştırmaya devam et.
while(Encoder == oldEncoder) Encoder = RotaryEncoder & 0x03;
// eski değerin 1. biti yeni değerin 0. bitinden farklı ise ve eski
// değerin 0. biti yeni değerin 1. bitine eşit ise rotary encoder
// sağa doğru çevrilmiştir, bu durumda sayac 9999'dan küçükse artır.
if(oldEncoder.F1 !=Encoder.F0)
{
if(oldEncoder.F0 == Encoder.F1) if(sayac<9999) sayac++;
} else
// eski değerin 0. biti yeni değerin 1. bitinden farklı ise ve eski
// değerin 1. biti yeni değerin 0. bitine eşit ise rotary encoder
// sola doğru çevrilmiştir, bu durumda sayac 0'dan büyükse azalt.
if(oldEncoder.F0 != Encoder.F1)
{
if(oldEncoder.F1 == Encoder.F0 ) if(sayac>0) sayac--;
}
} while(1); // Ana program çevrimine devam et
}
// Dosya Adı : 14_2.c
// Açıklama : DS1621 ısı sensörü ile ısı ölçümü
// Notlar : Proteus programı simülasyonu
// : XT ==> 4 MHz
// i2c adres tanımlanıyor
#define DS1621_WRITE_ADDR 0x90
#define DS1621_READ_ADDR 0x91
// Komutlar
#define DS1621_ACCESS_CONFIG_CMD 0xAC
#define DS1621_START_CONVERSION_CMD 0xEE
#define DS1621_STOP_CONVERSION_CMD 0x22
#define DS1621_READ_TEMPERATURE_CMD 0xAA
#define DS1621_ACCESS_TEMP_HIGH_CMD 0xA1
#define DS1621_ACCESS_TEMP_LOW_CMD 0xA2
#define DS1621_READ_COUNTER_CMD 0xA8
#define DS1621_READ_SLOPE_CMD 0xA9
// Config kaydedicisinin bit tanımlamaları
#define DS1621_ONE_SHOT_BIT F0
#define DS1621_OUTPUT_POLARITY_BIT F1
#define DS1621_NVRAM_BUSY_BIT F4
#define DS1621_TEMP_LOW_BIT F5
#define DS1621_TEMP_HIGH_BIT F6
#define DS1621_CONVERSION_DONE_BIT F7
// Config kaydedicisinin başlangıç değeri
#define DS1621_CONFIG_INIT_VALUE 0x00
// IsıKontrol kaydedicisinin bit tanımlamaları
#define ERROR F7
#define NEG F6
#define ONDABES F5
//Değişken tanımlamaları
char *str=" ";
char IsiKontrol;
// DS1621 ilk işlemleri gerçekleştirir. Konfigürasyon kaydedicisine
// ilk değer verir.
void ds1621_init(void)
{
I2C_Start();
I2C_Wr(DS1621_WRITE_ADDR);
I2C_Wr(DS1621_ACCESS_CONFIG_CMD);
I2C_Wr(DS1621_CONFIG_INIT_VALUE);
I2C_Stop();
}
//Isı okuma çevrimini başlatır.
void ds1621_start_conversion(void)
{
I2C_Start();
I2C_Wr(DS1621_WRITE_ADDR);
I2C_Wr(DS1621_START_CONVERSION_CMD);
I2C_Stop();
}
// Isı bilgisi DS1621'den okunur ve en değerli byte'ı fonksiyon
// dışına taşınır.
char ds1621_read_temperature(void)
{
char data_low, data_high;
I2C_Start(); // I2C iletişimi başlat
I2C_Wr(DS1621_WRITE_ADDR);
I2C_Wr(DS1621_READ_TEMPERATURE_CMD);
I2C_Repeated_Start();
I2C_Wr(DS1621_READ_ADDR);
// Isının en değerli byte'ı okunur ve ACK gönderilir
data_high = I2C_Rd(1);
// I2C hattı meşgul olduğu sürece bekle
while(I2C_Is_Idle() == 0);
// Isının en değersiz byte'ı okunur ve NOT ACK gönderilir
data_low = I2C_Rd(0);
// I2C hattı meşgul olduğu sürece bekle
while(I2C_Is_Idle() == 0);
I2C_Stop();
// Isı Kontrol kaydedicisinin 0. biti set ise bir hata olduğu
// anlaşılır.
if(data_low == 0xFF)
if(data_high == 0xFF) {IsiKontrol.ERROR = 1; return(0);}
else IsiKontrol.ERROR = 0;
// Eğer ısı 0 derecenin altında ise data_high byte'ın en değerli
// biti set olur. Bu durumda data_high değerinin 2.tamlayanı
// alınarak ısı değeri elde edilir ve bu ısının negatif olduğunu
// belirtmek için IsiKontrol kaydedicisinin NEGATIF bayrağı set
// edilir.
if(data_high & 0x80)
{
// Isının negatif olduğu kontrol kaydedicisine yazılır
IsiKontrol.NEG = 1;
// Isının en değerli byte'ının 2. tamlayanı alınır
data_high = ~data_high + 1;
if(data_low) data_high--; // 1/2 C kısmı var ise bir eksilt
} else IsiKontrol.NEG = 0; // ısı pozitif
// data_low büyük 0 ise 1/2 C değeri var, o halde IsiKontrol
// kaydedicisinin ilgili bitini set et data_low = 0 ise 1/2 C değeri
// yoktur. Bu durumda IsiKontrol kaydedicisinin ilgili biti silinir.
if(data_low) IsiKontrol.ONDABES = 1; else IsiKontrol.ONDABES = 0;
// Isı değeri 99'dan büyükse 99 olarak kabul et
if(data_high > 99) return 99;
return data_high;
}
// Eğim değerini fonksiyon dışına taşır.
char ds1621_read_slope(void)
{
char slope;
I2C_Start();
I2C_Wr(DS1621_WRITE_ADDR);
I2C_Wr(DS1621_READ_SLOPE_CMD);
I2C_Repeated_Start();
I2C_Wr(DS1621_READ_ADDR);
slope = I2C_Rd(0);
I2C_Stop();
return slope;
}
// Sayac değerini fonksiyon dışına taşır.
char ds1621_read_counter(void)
{
char counter;
I2C_Start();
I2C_Wr(DS1621_WRITE_ADDR);
I2C_Wr(DS1621_READ_COUNTER_CMD);
I2C_Repeated_Start();
I2C_Wr(DS1621_READ_ADDR);
counter = I2C_Rd(0);
I2C_Stop();
return counter;
}
// Bir byte'lık hexadesimal sayıyı 2 basamaklı desimal sayıya
// dönüştürür.
char Hex2Dec(char ch) // 2 digit dönüşüm
{
char tmp = 0; // Geçici değişkeni sıfırla
// sayının onlar basamağını bulur
while(ch>=10) {tmp++; ch -= 10;}
// Birler basamağını sayıya ekler
tmp = (tmp<<4) + ch;
return tmp; // Sonucu fonksiyon dışına taşı
}
// Bir byte'lık sayıyı text'e dönüştürür.
void BintoStr(char data)
{
data = Hex2Dec(data); // Desimale dönüştür
// Text'e dönüştürür (ilk karakter)
str[0] = 48 + ((data & 0xF0) >> 4);
// sayının 10'lar basamağı sıfır ise boşluk yazar
if (str[0] == 48) str[0] = 32;
// Text'e dönüştürür (ikinci karakter)
str[1]= 48 + (data & 0x0F);
}
// İlk işlemler alt programı LCD, I2C ve DS1621'i kullanıma hazırlar
// ve ısı dönüşümünü başlatır.
void init()
{
LCD_Config(&PORTB,4,5,7,3,2,1,0); // LCD bağlantısını tanımla
LCD_Cmd(LCD_CURSOR_OFF); // imleci gizle
I2C_Init(100000); // I2C iletişimi hazırla, full master mode
IsiKontrol = 0; // Isı kontrol kaydedicisinin ilk değeri sıfır.
ds1621_init(); // Isı sensörünü başlat
ds1621_start_conversion(); // Isı dönüşümünü başlat
}
// Ana program, ısı bilgisini DS1621'den okuyarak LCD üzerinde
// görüntüler.
void main(void)
{
char isi;
init(); // ilk işlemleri gerçekleştir
while(1) // Bu blok içerisindeki işlemler sistem kapatılana
{ // ya da resetlenene kadar tekrarlar.
isi = ds1621_read_temperature(); // Isıyı ölç
if(IsiKontrol.ERROR) continue; // Hata var yeniden ölç
LCD_Out(1,1,"Isi = ");
// Negatif ısı ise - işareti yaz, değilse boşluk koy
if(IsiKontrol.NEG) LCD_Out_Cp("-"); else LCD_Out_Cp(" ");
BintoStr(isi); // Isıyı text'e dönüştür (2 dijit)
LCD_Out_Cp(str); // Isıyı yazdır
if(IsiKontrol.ONDABES) LCD_Out_Cp(".5"); else LCD_Out_Cp(".0"); // ondalıklı kısmı yazdır
Lcd_Chr_Cp(0xDF); // derece işareti
LCD_Out_Cp("C"); // C yazdır
Delay_ms(1000); // yeni ölçüm için 1 saniye bekle
}
}
// Dosya Adı : 13_3.c // Açıklama : L297 ve L298 ile step motor kontrolü // Notlar : Proteus programı simülasyonu // : XT ==> 4 MHz // Step motor bağlantı tanımlamaları. #define stepMotor PORTB // Step motor kontrol uçlarının // bağlandığı port. #define stepMotorTris TRISB // Step motorun bağlı olduğu // portun yönlendirme kaydedicisi #define enable F0 // L297 step motor sürücüsünü // etkinleştiren pin tanımı. #define reset F1 // L297'nin reset ucunun bağlı // olduğu pin tanımı. #define halffull F2 // Bu pin 1 ise half modda, // 0 ise full modda. #define direction F3 // Yön kontrol pini, 1 ise saat // yönünde (ileri), 0 ise geri. #define clock F4 // L297 için saat darbesi üreten // pin tanımı. #define home F5 // Bu pin step motorun her tam // dönüşünde işlemciye saat // darbesi üretir. #define control F6 // Kontrol pini tanımı. // Step motoru half moda alır (45 derecelik açılar ile dönüş modu). void half_mode() { stepMotor.halffull = 1; //L297'yi yarım adım moduna alır. } // Step motoru full moda alır (90 derecelik açılar ile dönüş modu). void full_mode() { stepMotor.halffull = 0; // L297'yi tam adım moduna alır. } // Step motoru istenilen adım kadar saat ibresi yönünde döndürür. void ileri(unsigned int adim) { stepMotor.reset = 1; // L297'yi resetle. stepMotor.enable = 1; // L297'yi etkinleştir. stepMotor.direction = 1; // Yön saat ibrelerinin yönünde do // do - while döngüsü açılıyor. { stepMotor.clock = 1; // Yükselen darbe kenarı. asm nop stepMotor.clock = 0; // İnen darbe kenarı ile L297 // tetikleniyor. delay_ms(50); // 50ms bekle. }while(--adim); } // Step motoru istenilen adım kadar saat ibresinin tersi yönünde // döndürür. void geri(unsigned int adim) { stepMotor.reset = 1; // L297'yi resetle. stepMotor.enable = 1; // L297'yi etkinleştir. stepMotor.direction = 0; // saat ibresinin tersi yönünde do // do - while döngüsü açılıyor. { stepMotor.clock = 1; // Yükselen darbe kenarı. asm nop stepMotor.clock = 0; // İnen darbe kenarı ile L297 // tetikleniyor. delay_ms(50); // Step motor yeni konumu alması // için kısa bir süre bekle. // Bu süre step motorun tepki // süresinden büyük olmalıdır. // Örneğimizde 50 ms seçilmiştir. }while(--adim); } // L297'yi resetler. void resetle() { stepMotor.reset = 0; // L297 resetlendi. stepMotor.enable = 0; // L297 pasif yapıldı. delay_ms(1000); } // Ana program ilk işlemler alt programı port yönlendirir. void init() { stepMotor = 0; // ilk çıkışlar sıfır. stepMotorTris.enable = 0; // enable pini çıkış yapıldı. stepMotorTris.reset = 0; // enable pini çıkış yapıldı. stepMotorTris.halffull = 0; // half/full pini çıkış yapıldı. stepMotorTris.direction = 0; // direction pini çıkış yapıldı. stepMotorTris.clock = 0; // clock pini çıkış yapıldı. stepMotorTris.home = 1; // home pini giriş yapıldı. stepMotorTris.control = 0; // control pini çıkış yapıldı. resetle(); // L297'yi resetle } // Ana program: Step motoru half ve full modlarda ileri ve geri // yönlerde aralarında 1 sn bekleyerek döndürür ve aynı işlemleri // sistem resetlenene ya da kapatılana kadar devam ettirir. void main() { init(); // İlk işlemler yapılıyor. while(1) // Sonsuz döngü açılıyor. { // while bloğu başlangıcı. half_mode(); // Half modda çalıştırılacak. ileri(50); // 50 adım saat ibresi yönünde. delay_ms(1000); // 1 sn bekle. geri(100); // 100 adım saat ibresinin tersi // yönünde dön. delay_ms(1000); full_mode(); // Full modda çalıştırılacak. ileri(100); // 100 adım saat ibresi yönünde. delay_ms(1000); geri(50); // 50 adım saat ibresinin tersi. delay_ms(1000); } // while bloğu sonu. }
YAZININ DİĞER SAYFALARI: 1 2
Yazar: gevv
Yazarımızın 320volt.com Blog üzerinde şu an okuduğunuz yazı dahil 1941 yazısı bulunmaktadır. Yazarımız hakkında bilgileri ve diğer yazılarını görmek için bakınız; gevv












Paylaşımda büyük emek var teşekkürler ;)
Allah razı olsun emegine sağlık
işte bizim hocalarımız ellerinize sağlık…
emeğine sağlık usta.Benim bir projem var , 16f877 ile ilgili. içinde dac-adc konvertorler ve lcd ekran olacak. hangi butona basarsak lcd ekranda “su butona bastınız ” ve yanında da ” x v ” yazacak.yani hem hangi butona basıldığını hem de o butonun üzerındeki gerilimi ekrana yazdıracak. yardımcı olursanız sevinirim. herkese iyi günler