PİC16F877 Hakkında ufak bir sorun

PORTA yı dijital kurman lazım,
Temel problemler bunlar, internette birçok forumda yazıldı defalarca,
kendiniz bulmaya alışırsanız daha kısa zamanda çözersiniz.

Kod:
acdon1=0x07   //porta ve porte dijital giriş çıkış olsun
Butona basılıyken bir durum, basılı değilken başka durumda olan ledler:
Kod:
void main(void) {
acdon1=0x07   //porta ve porte dijital giriş çıkış olsun
    TRISB=0x00;
    TRISA=0xFF;
    while(1)
    {
        if (RA0==1){
            PORTB=0x0F;
        }
        if (RA0==0){
            PORTB=0xF0;
        }
    } 
}

yerine

Butona her basıldığında durum değiştiren ve değiştiği durumda kalan ledler:
Kod:
void main(void) {
acdon1=0x07   //porta ve porte dijital giriş çıkış olsun 
    TRISB=0x00;
    TRISA=0xFF;
            PORTB=0x0F;
    while(1)
    {
        if (RA0==1){
            PORTB = PORTB ^ 0xFF;  ;portb pinlerinin durumunlarını ters çevir
50 milisaniye bekle //buton arkı, button debounce
while (RA0 == 1); buton bırakılana kadar bekle
50 milisaniye bekle
        }

    } 
}



--------------------------------------------------------------------------------------------------------

Arkadaşlar birşy sormak istiyorun
Ben asansör işi yapıyorum ve asansör kumanda kartlarını microdenetleyicilerke programlayacağız sorum şu mikrodenetleyicilere can bus seri haberleşme programaı yazmak zormudur daha önce hiç yazmadım
Yeni konu açın lütfen.
Kısaca o iş öyle olmuyor, asansör kontrol kartlarında şu an TS EN 81-20 ye uymak zorundasın ve
can taşıdığın için tecrübesiz yapılacak şeyler değil,
asansör montaj firmalarının böyle girişimleri oluyor ona benzettim.
 
Son düzenleme:
Denemeden yazıyorum ama şu kodun çalışması lazım.

Şimdi 2 tane LED ile denedim.

PIC16F877A'nın üzerinde 8 tane uç normalde analog giriş olarak görev yapıyor.

pic16f877a.png

Burada görebileceğiniz üzere RA0'ın yanında AN0 yazıyor. Bu normalde bu ucun analog giriş olduğunu gösteriyor.

Bu uçtan sayısal giriş okumak için bu ucu sayısal olarak belirtmemiz gerekiyor.

adcon1.png

Bunu da ADCON1 yazmacının PCFG1, PCFG2 ve PCFG3 numaralı bitlerini değiştirerek yapıyoruz.

adcon2.png

Resimden de görülebileceği üzere AN0'ı sayısal yapmak için tüm analog girişleri sayısal yapmak gerekiyor.

Bunun için ADCON1 yazmacının kapı ayarlama bitlerine (PCFG) 011x değerini atıyoruz. Sondaki x bu değerin önemsiz olduğunu gösteriyor.

Bu değişikliklerden sonra sadece RA0 basılı iken LED'ler yansın bırakınca sönsün istersek programımız şu şekilde olacak.
C:
#include <pic.h>

#ifndef _XTAL_FREQ
// Saat frekansı 16 Mhz
#define _XTAL_FREQ 16000000
#endif

__CONFIG (FOSC_HS & WDTE_OFF & LVP_OFF & CPD_OFF & CP_OFF);

int main()
{
    ADCON1 = 0x06;        // Normalde analog olan RA0 diğer bir ifadeyle
                          // Analog0 girişini sayısal yaptık
    TRISAbits.TRISA0 = 1; // RA0 giriş

    /*  Sadece bununla kalmadık PIC üzerinde bulunan tüm analog girişleri
        sayısal yaptık. Bu girişler :
          RA0, RA1, RA2, RA3, RA5, RE0, RE1 ve RE2

          AN0, AN1, AN2, AN3, AN4, AN5, AN6 ve AN7 şeklinde
    */

    TRISB = 0;    // PORTB çıkış

    PORTB = 0;    // PORTB üzerindeki tüm LED'ler kapalı

    while(1)
    {
        if (PORTAbits.RA0 == 1)
        {
            // Anlık olarak gecikme yapacaksak buna gerek yok
            // __delay_ms(250);
            PORTB = 0x0F; // b 0000 1111
        }
        else if (PORTAbits.RA0 == 0)
        {
            //__delay_ms(250);
            PORTB = 0xF0; // b 1111 0000
        }
    }
}

Yok eğer RA0'a bir kere basıldığı zaman ışıkların yarısı yanmaya başlasın. İkinci kez basışımızda ışıkların diğer yarısı yansın istiyorsak uygulamamız şu şekilde olacak.
C:
#include <pic.h>

#ifndef _XTAL_FREQ
// Saat frekansı 16 Mhz
#define _XTAL_FREQ 16000000
#endif

__CONFIG (FOSC_HS & WDTE_OFF & LVP_OFF & CPD_OFF & CP_OFF);

int main()
{
    static char yananlar = 0xFF;

    ADCON1 = 0x06;        // Normalde analog olan RA0 diğer bir ifadeyle
                          // Analog0 girişini sayısal yaptık
    TRISAbits.TRISA0 = 1; // RA0 giriş

    /*  Sadece bununla kalmadık PIC üzerinde bulunan tüm analog girişleri
        sayısal yaptık. Bu girişler :
          RA0, RA1, RA2, RA3, RA5, RE0, RE1 ve RE2

          AN0, AN1, AN2, AN3, AN4, AN5, AN6 ve AN7 şeklinde
    */

    TRISB = 0;    // PORTB çıkış
    PORTB = 0;

    while(1)
    {
        // Düğmeye basıldıysa tersine çevir
        if (PORTAbits.RA0 == 1)
        {
            __delay_ms(250);
            yananlar = ~yananlar;
        }
        PORTB = yananlar;
    }
}
 
Son düzenleme:
Şimdi 2 tane LED ile denedim.

PIC16F877A'nın üzerinde 8 tane uç normalde analog giriş olarak görev yapıyor.

Ekli dosyayı görüntüle 68321
Burada görebileceğiniz üzere RA0'ın yanında AN0 yazıyor. Bu normalde bu ucun analog giriş olduğunu gösteriyor.

Bu uçtan sayısal giriş okumak için bu ucu sayısal olarak belirtmemiz gerekiyor.

Ekli dosyayı görüntüle 68322
Bunu da ADCON1 yazmacının PCFG1, PCFG2 ve PCFG3 numaralı bitlerini değiştirerek yapıyoruz.

Ekli dosyayı görüntüle 68324
Resimden de görülebileceği üzere AN0'ı sayısal yapmak için tüm analog girişleri sayısal yapmak gerekiyor.

Bunun için ADCON1 yazmacının kapı ayarlama bitlerine (PCFG) 011x değerini atıyoruz. Sondaki x bu değerin önemsiz olduğunu gösteriyor.

Bu değişikliklerden sonra sadece RA0 basılı iken LED'ler yansın bırakınca sönsün istersek programımız şu şekilde olacak.
C:
#include <pic.h>

#ifndef _XTAL_FREQ
// Saat frekansı 16 Mhz
#define _XTAL_FREQ 16000000
#endif

__CONFIG (FOSC_HS & WDTE_OFF & LVP_OFF & CPD_OFF & CP_OFF);

int main()
{
    ADCON1 = 0x06;        // Normalde analog olan RA0 diğer bir ifadeyle
                          // Analog0 girişini sayısal yaptık
    TRISAbits.TRISA0 = 1; // RA0 giriş

    /*  Sadece bununla kalmadık PIC üzerinde bulunan tüm analog girişleri
        sayısal yaptık. Bu girişler :
          RA0, RA1, RA2, RA3, RA5, RE0, RE1 ve RE2

          AN0, AN1, AN2, AN3, AN4, AN5, AN6 ve AN7 şeklinde
    */

    TRISB = 0;    // PORTB çıkış

    PORTB = 0;    // PORTB üzerindeki tüm LED'ler kapalı

    while(1)
    {
        if (PORTAbits.RA0 == 1)
        {
            // Anlık olarak gecikme yapacaksak buna gerek yok
            // __delay_ms(250);
            PORTB = 0x0F; // b 0000 1111
        }
        else if (PORTAbits.RA0 == 0)
        {
            //__delay_ms(250);
            PORTB = 0xF0; // b 1111 0000
        }
    }
}

Yok eğer RA0'a bir kere basıldığı zaman ışıkların yarısı yanmaya başlasın. İkinci kez basışımızda ışıkların diğer yarısı yansın istiyorsak uygulamamız şu şekilde olacak.
C:
#include <pic.h>

#ifndef _XTAL_FREQ
// Saat frekansı 16 Mhz
#define _XTAL_FREQ 16000000
#endif

__CONFIG (FOSC_HS & WDTE_OFF & LVP_OFF & CPD_OFF & CP_OFF);

int main()
{
    static char yananlar = 0xFF;

    ADCON1 = 0x06;        // Normalde analog olan RA0 diğer bir ifadeyle
                          // Analog0 girişini sayısal yaptık
    TRISAbits.TRISA0 = 1; // RA0 giriş

    /*  Sadece bununla kalmadık PIC üzerinde bulunan tüm analog girişleri
        sayısal yaptık. Bu girişler :
          RA0, RA1, RA2, RA3, RA5, RE0, RE1 ve RE2

          AN0, AN1, AN2, AN3, AN4, AN5, AN6 ve AN7 şeklinde
    */

    TRISB = 0;    // PORTB çıkış
    PORTB = 0;

    while(1)
    {
        // Düğmeye basıldıysa tersine çevir
        if (PORTAbits.RA0 == 1)
        {
            __delay_ms(250);
            yananlar = ~yananlar;
        }
        PORTB = yananlar;
    }
}
Çok teşekkür ederim bu bilgiler için.
 
Bu dil HI-TECH C sanırım. CCS C diline çok benziyor.
Ben temel olarak CCS C dilini biliyorum.
HI-TECH C diline yabancı olduğum için detaylarını pek bilmiyorum.

Birkaç sorum olacak. En iyi kullananlar bilir. O sebeple burada soruyorum.

Derleyici ücretli mi?
Kullanımı yaygın mı?
Takıldığınız yerde çözüm bulmakta zorlanıyor musunuz?
Bu dil ile ilgili Türkçe içerik yayınlayan bir site var mı?

Bir web sitem var. Bu dil ile ilgili içerik yayınlamayı düşünebilirim.
 
Bu dil HI-TECH C sanırım. CCS C diline çok benziyor.
Ben temel olarak CCS C dilini biliyorum.

Dil C dili. HI-TECH C ya da CCS C de sadece derleyici isimleri.

Derleyici ücretli mi?

Benim kullandığım derleyici Microchip MPLAB XC8 C derleyicisi olarak geçiyor. Derleyici ücretsiz ama ücretsiz sürümde derleyici sanırım bazı en iyileştirmeleri yapmıyor. Her derlemede eğer paralı sürümü kullansaydınız %60 daha küçük ve %400 daha hızlı çalışan bir uygulama üretebilecektiniz diye bir ileti veriyor.

Takıldığınız yerde çözüm bulmakta zorlanıyor musunuz?
Örneğin arkadaşın sorduğu sorunun ikinci kısmı basit gibi görünmesine
biraz zorladı.

Çözüm bulma konusuna gelince aslında istesem ESO'da sorabilirim.

Yok eğer RA0'a bir kere basıldığı zaman ışıkların yarısı yanmaya başlasın. İkinci kez basışımızda ışıkların diğer yarısı yansın istiyorsak uygulamamız şu şekilde olacak.

Aslında benim denediğim devrede A0 ucuna takılı olan düğme toprağa bağlı değilmiş.

Neyse bu uygulamayı çalıştırdığınızda ilk önce normal çalıştığını düşünebilirsiniz.

Bu haliyle ışıkların tamamı yanıyor. A0'a tekrar bastığınızda sönüyor. Tekrar düğmeye basılana kadar bu haliyle kalıyor.

Ama arkadaşın sorusunda ışıkların yarısını yakmak istiyordu. İşte ilginçlik bu noktada başlıyor.

static char yananlar = 0x0F;

Yananlar değişkenini bu şekilde değiştirince istediğimiz gibi çalışmıyor.

Bakalım bu soruyu çözebilecek arkadaşlar çıkacak mı?
 
Son düzenleme:
Arkadaşın sorduğu sorunun ikinci kısmını da çözdüm.

Devre şu şekilde :

pic_a0.png

Çalışan uygulama da aşağıdaki gibi :

C:
#include <pic.h>

#ifndef _XTAL_FREQ
// Saat frekansı 16 Mhz
#define _XTAL_FREQ 16000000
#endif

__CONFIG (FOSC_HS & WDTE_OFF & LVP_OFF & CPD_OFF & CP_OFF);

int main()
{
    static char yananlar = 0xAA;

    ADCON1 = 0x06;        // RA0 sayısal giriş
    TRISAbits.TRISA0 = 1; // RA0 giriş

    TRISB = 0;    // PORTB çıkış
    PORTB = 0;    // PORTB'nin tüm uçlarını düşük yap

    while(1)
    {
        // Düğmeye basıldıysa LED'leri tersini çevir ve o durumda kal
        if (PORTAbits.RA0 == 1)
        {
           yananlar = ~yananlar;
            __delay_ms(250);
        }

        PORTB = yananlar ^ 0xFF;
    }
}
 
Arkadaşlar, RB1 e bağlanan led 1sn aralıklarla yanıp sönmekte. RB0 kesmesi devreye girince RA0 a bağlanmış olan ledin 2 sn boyunca yanması gerekli. aşağıdaki kodu yazdım PİC16f84 için. Fakat derleyici (MPLAB XC8) resimdeki gibi hata veriyor. Sıkıntı nedir?

Kod:
#include <xc.h>
// CONFIG
#pragma config FOSC = XT        // Oscillator Selection bits (XT oscillator)
#pragma config WDTE = OFF        // Watchdog Timer (WDT enabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (Power-up Timer is disabled)
#pragma config CP = OFF         // Code Protection bit (Code protection disabled)

#define _XTAL_FREQ 4000000



void interrupt kesme (void)
{
        if(INTF==1)
        {
            PORTA=255;
            __delay_ms(2000);
        }
        INTF=0;
        PORTA=0;
}

void main(void) {
    
    GIE=1;
    INTE=1;
    TRISB=1;
    TRISA=0;
    PORTA=0;
    while(1){
        RB1=0;
        __delay_ms(1000);
        RB1=1;
        __delay_ms(1000);
    }
}
 

Ekli dosyalar

  • hata.PNG
    hata.PNG
    43.5 KB · Görüntüleme: 10
Sizin gösterdiğiniz hata iletisinde bir yazım hatası gözüküyor. Ama kodu derlemeyi denedim derleniyor.

Şu örneği deneyebilirsiniz.

pic16f84a.jpg


C:
#include <xc.h>

#pragma config FOSC = XT        // Oscillator Selection bits (XT oscillator)
#pragma config WDTE = OFF        // Watchdog Timer (WDT enabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (Power-up Timer is disabled)
#pragma config CP = OFF         // Code Protection bit (Code protection disabled)

#define _XTAL_FREQ 4000000

void interrupt(void)
{
    if( INTCON.INTF)   // kesme oluştu mu
    {
        PORTA.B0 = ~PORTA.B0; //  RA0'ı ters çevir

        INTCON.INTF = 0; //  kesme bayrağını tekrar temizle
    }
}
void main()
{

    TRISB.B0 = 1; // RB0 giriş
    INTCON |= 0x90; // Kesmeyi etkinleştir
    OPTION_REG |= 0x40; // Kesme saat sinyalinin yükselen kenarında olacak
    TRISA.B0 = 0; // RA0 ucu giriş
    PORTA.B0 = 0; // RA0'ı düşük yap


    while(1)
    {
    }
}

Yukarıdaki örneği deneyin bakalım. Çalışacak mı ?
 
Parametre almayan fonksiyonlarda parantezler içine "void" komutu yazmak gereksizdir.
Büyük ihtimalle bu sebeple hata veriyor. Void komutunu değişken olarak algılıyor.
Şu şekilde yazın:
Kod:
void interrupt kesme()
 
Sizin gösterdiğiniz hata iletisinde bir yazım hatası gözüküyor. Ama kodu derlemeyi denedim derleniyor.

Şu örneği deneyebilirsiniz.

Ekli dosyayı görüntüle 68398

C:
#include <xc.h>

#pragma config FOSC = XT        // Oscillator Selection bits (XT oscillator)
#pragma config WDTE = OFF        // Watchdog Timer (WDT enabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (Power-up Timer is disabled)
#pragma config CP = OFF         // Code Protection bit (Code protection disabled)

#define _XTAL_FREQ 4000000

void interrupt(void)
{
    if( INTCON.INTF)   // kesme oluştu mu
    {
        PORTA.B0 = ~PORTA.B0; //  RA0'ı ters çevir

        INTCON.INTF = 0; //  kesme bayrağını tekrar temizle
    }
}
void main()
{

    TRISB.B0 = 1; // RB0 giriş
    INTCON |= 0x90; // Kesmeyi etkinleştir
    OPTION_REG |= 0x40; // Kesme saat sinyalinin yükselen kenarında olacak
    TRISA.B0 = 0; // RA0 ucu giriş
    PORTA.B0 = 0; // RA0'ı düşük yap


    while(1)
    {
    }
}

Yukarıdaki örneği deneyin bakalım. Çalışacak mı ?
interrupt fonksiyon ismi olmadığından uyarı çıkıyor isim verince yine problemli.
 

Forum istatistikleri

Konular
130,089
Mesajlar
932,980
Kullanıcılar
453,116
Son üye
bthnercan

Yeni konular

Geri
Üst