PIC16F877A ile 16 Buton, 16 Led

Daha önceden hazırladığım test kodlarını paylaşıyorum.

18F877A ile yapılan bu çalışmada 16 giriş ve 16 çıkış kullanılmıştır. Her buton ilgili ledini diğer butonlardan bağımsız şekilde yakıp/söndürebilmektedir.

Kodların içerisinde elimden geldiğince açıklama yapmaya çalıştım. Timer0 ile yaptığım kesme ile çıkışlar saniyede 1000 kez tazelenmektedir. Butonlar da ana döngü içerisinden okunmaktadır.

Doğal olarak farklı şekillerde yapmak mümkündür.
 

/*
* File:   main.c
* Author: mbmb
*
* Created on 11 Temmuz 2015 Cumartesi, 20:15
* 16 giriş ve 16 çıkış ile ayrı ayrı kontrol
* her giriş ve her çıkış bağımsız olarak çalışmaktadır.
*
*/

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

// PIC16F877A Configuration Bit Settings
// 'C' source line config statements

#include <xc.h>

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

// CONFIG
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
#pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = ON          // Flash Program Memory Code Protection bit (All program memory code-protected)

#define _XTAL_FREQ              4000000L //4MHz harici kristal

#define BASILI_BUTON_MAX        16
uint8_t basiliButon[BASILI_BUTON_MAX] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
uint8_t basiliButonSon[BASILI_BUTON_MAX] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

//Butonlar ve ledlerin portları
#define LED0                PORTCbits.RC0
#define LED1                PORTCbits.RC1
#define LED2                PORTCbits.RC2
#define LED3                PORTCbits.RC3
#define LED4                PORTCbits.RC4
#define LED5                PORTCbits.RC5
#define LED6                PORTCbits.RC6
#define LED7                PORTCbits.RC7
#define LED8                PORTAbits.RA0
#define LED9                PORTAbits.RA1
#define LED10               PORTAbits.RA2
#define LED11               PORTAbits.RA3
#define LED12               PORTAbits.RA4
#define LED13               PORTAbits.RA5
#define LED14               PORTEbits.RE0
#define LED15               PORTEbits.RE1

#define BUTON0              PORTBbits.RB0
#define BUTON1              PORTBbits.RB1
#define BUTON2              PORTBbits.RB2
#define BUTON3              PORTBbits.RB3
#define BUTON4              PORTBbits.RB4
#define BUTON5              PORTBbits.RB5
#define BUTON6              PORTBbits.RB6
#define BUTON7              PORTBbits.RB7
#define BUTON8              PORTDbits.RD0
#define BUTON9              PORTDbits.RD1
#define BUTON10             PORTDbits.RD2
#define BUTON11             PORTDbits.RD3
#define BUTON12             PORTDbits.RD4
#define BUTON13             PORTDbits.RD5
#define BUTON14             PORTDbits.RD6
#define BUTON15             PORTDbits.RD7

int8_t val;
int8_t val2;
int8_t buttonState;
int8_t lightMode = 0; 

/*
* Mcu başlangıç ayarları
*/
static void mcuInit(void)
{
    PORTA = 0x00;
    TRISA = 0x00;

    PORTB = 0x00;
    TRISB = 0xFF;

    PORTC = 0x00;
    TRISC = 0x00;

    PORTD = 0x00;
    TRISD = 0xFF;

    PORTE = 0x00;
    TRISE = 0x00;

    ADCON1bits.PCFG = 0b0110;
    CMCONbits.CM = 0b111;

}

/*
*  Timer0 için ön hazırlık.
*  http://eng-serve.com/pic/pic_timer.html
*  Bu sitede oluşturulan kodlar ile küçük düzenlemeler yapılmaktadır...
*/
void timerInit(void)
{
    //Timer0 Registers Prescaler= 4 - TMR0 Preset = 6 - Freq = 1000.00 Hz - Period = 0.001000 seconds
    OPTION_REGbits.T0CS = 0; // bit 5  TMR0 Clock Source Select bit...0 = Internal Clock (CLKO) 1 = Transition on T0CKI pin
    OPTION_REGbits.T0SE = 0; // bit 4 TMR0 Source Edge Select bit 0 = low/high 1 = high/low
    OPTION_REGbits.PSA = 0; // bit 3  Prescaler Assignment bit...0 = Prescaler is assigned to the Timer0
    OPTION_REGbits.PS2 = 0; // bits 2-0  PS2:PS0: Prescaler Rate Select bits
    OPTION_REGbits.PS1 = 0;
    OPTION_REGbits.PS0 = 1;
    TMR0 = 6; // preset for timer register

    // Interrupt Registers
    INTCON = 0; // clear the interrpt control register
    INTCONbits.TMR0IE = 1; // bit5 TMR0 Overflow Interrupt Enable bit...1 = Enables the TMR0 interrupt
    INTCONbits.TMR0IF = 0; // bit2 clear timer 0 interrupt flag
    INTCONbits.GIE = 1; // bit7 global interrupt enable
}

/*
* Çıkış olarak tanımlanan portlara gereken değerler veriliyor...
*/
void ledYak(void)
{
    LED0 = basiliButon[0];
    LED1 = basiliButon[1];
    LED2 = basiliButon[2];
    LED3 = basiliButon[3];
    LED4 = basiliButon[4];
    LED5 = basiliButon[5];
    LED6 = basiliButon[6];
    LED7 = basiliButon[7];

    LED8 = basiliButon[8];
    LED9 = basiliButon[9];
    LED10 = basiliButon[10];
    LED11 = basiliButon[11];
    LED12 = basiliButon[12];
    LED13 = basiliButon[13];
    LED14 = basiliButon[14];
    LED15 = basiliButon[15];
}

/*
* Basılan buton var mı?
*/
void butonOku(uint8_t sonButon)
{
    lightMode   = basiliButon[sonButon];
    buttonState = basiliButonSon[sonButon];

    switch (sonButon)
    {
    case 0:
        val = BUTON0;
        break;
    case 1:
        val = BUTON1;
        break;
    case 2:
        val = BUTON2;
        break;
    case 3:
        val = BUTON3;
        break;
    case 4:
        val = BUTON4;
        break;
    case 5:
        val = BUTON5;
        break;
    case 6:
        val = BUTON6;
        break;
    case 7:
        val = BUTON7;
        break;
    case 8:
        val = BUTON8;
        break;
    case 9:
        val = BUTON9;
        break;
    case 10:
        val = BUTON10;
        break;
    case 11:
        val = BUTON11;
        break;
    case 12:
        val = BUTON12;
        break;
    case 13:
        val = BUTON13;
        break;
    case 14:
        val = BUTON14;
        break;
    case 15:
        val = BUTON15;
        break;
    }

    __delay_ms(10); 

    switch (sonButon)
    {
    case 0:
        val2 = BUTON0;
        break;
    case 1:
        val2 = BUTON1;
        break;
    case 2:
        val2 = BUTON2;
        break;
    case 3:
        val2 = BUTON3;
        break;
    case 4:
        val2 = BUTON4;
        break;
    case 5:
        val2 = BUTON5;
        break;
    case 6:
        val2 = BUTON6;
        break;
    case 7:
        val2 = BUTON7;
        break;
    case 8:
        val2 = BUTON8;
        break;
    case 9:
        val2 = BUTON9;
        break;
    case 10:
        val2 = BUTON10;
        break;
    case 11:
        val2 = BUTON11;
        break;
    case 12:
        val2 = BUTON12;
        break;
    case 13:
        val2 = BUTON13;
        break;
    case 14:
        val2 = BUTON14;
        break;
    case 15:
        val2 = BUTON15;
        break;
    }

    if (val == val2)
    {
        if (val != buttonState)
        {
            if (val == 0)
            {
                if (lightMode == 0)
                {
                    lightMode = 1;
                }
                else
                {
                    lightMode = 0;
                }
            }
        }
        buttonState = val;
        basiliButon[sonButon] = lightMode;
        basiliButonSon[sonButon] = buttonState;
    }
}

/*
* Interrupt Handler
* Timer0 kesme oluşturduğunca çalışacak kodlar..
*/
void interrupt ISR(void)
{
    // Timer0 Interrupt - Freq = 1000.00 Hz - Period = 0.001000 seconds
    if (INTCONbits.TMR0IF == 1) // timer 0 interrupt flag
    {
        ledYak();

        INTCONbits.TMR0IF = 0; // clear the flag
        INTCONbits.TMR0IE = 1; // reenable the interrupt
        TMR0 = 6; // reset the timer preset count
    }

}

/*
* Ana Fonksiyon...
*/
void main(void)
{
    mcuInit();
    timerInit();

    while (1)
    {
        butonOku(0);
        butonOku(1);
        butonOku(2);
        butonOku(3);
        butonOku(4);
        butonOku(5);
        butonOku(6);
        butonOku(7);

        butonOku(8);
        butonOku(9);
        butonOku(10);
        butonOku(11);
        butonOku(12);
        butonOku(13);
        butonOku(14);
        butonOku(15);
    }
}