# programa en ccs para 16f887 (instruccion fuses?)



## ecazcarra (Mar 11, 2008)

Hola tengo un pograma en ccs que viene con el pickit2 de microchip, y la verdad no lo entiendo, primeramente no entiendo lo de #fuses y un monton de palabras que no son registros, en un principio fuses pone a set los registros indicados pero no aqui no hay registros. A continuación declara una estructura que tampoco entiendo. Si alguien me lo puede explicar lo agradeceria mucho. cuelgo todo el programa por si a alguien más le puede servir para aprender (también sirve para los 16F87X).

Un saludo,



#include <16F887.h>             // header file for the PIC16F887
                                // includes built-in functions and constants
                                // for arguments/returns.

#use fast_io(A)                 // all other ports default to 'standard_io'
#use fast_io(B)                 // fast_io means the tris bits only change
                                // when we explicitly set them.

// FUSES sets the PIC16F887 Configuration Words.  See top of the header file
// 16F887.h for fuse option constants.
#FUSES INTRC,NOWDT,NOPUT,NOMCLR,NOPROTECT,NOCPD,NOBROWNOUT,NOIESO,NOFCMEN,NOLVP

struct adc_result
    {
    int8 value;         // ADC built-in functions default to 8 bit result.
    int1 new_flag;      // 1-bit falg to indicate a new (fresh) value
    } adc_conversion;

void init_io()
{
    // set up PORTA so RA0 is an input for the ADC, RA1-RA7 are outputs
    SET_TRIS_A(0x01);   // bit 0 = output, 1 = input

    // set up PORTB so RB0 is an input for the switch SW1, RB1-RB7 are outputs
    SET_TRIS_B(0x01);   // bit 0 = output, 1 = input

    // set up remaining ports to be all outputs
    OUTPUT_C(0x00);
    OUTPUT_D(0x00);
    OUTPUT_E(0x00);
}

void init_adc()
{
    // Set up RA0 as the only analog input, using VDD and VSS 
    // as the references
    SETUP_ADC_PORTS(sAN0 | VSS_VDD);

    // Turn on ADC and use Fosc/8 as the conversion clock
    // (Fosc = 4MHz)
    SETUP_ADC(ADC_CLOCK_DIV_8);   

    // Set channel for conversion to AN0 (on RA0)
    SET_ADC_CHANNEL(0);

    // start the first conversion
    READ_ADC(ADC_START_ONLY);
}

#INT_RTCC   // This function will be called on a Timer0 interrupt
void timer0_interrupt_service()
{
    // channel is always set to AN0.  Otherwise we might change
    // it here

    // Get last conversion result.
    adc_conversion.value = READ_ADC(ADC_READ_ONLY);
    adc_conversion.new_flag = 1;    // new value

    // start next conversion
    READ_ADC(ADC_START_ONLY);
}


void main()
{
    int1 led_bar_right = 0; // default is led bar graph starting on the left (DS0)   
    int switch_count = 0;   // used for debouncing the switch
    int bars = 0;           // used to compute the number of LED "bars" to display
    int temp1 = 0;          // temporary working variable
    int led_display = 0;    // led display value

    // initialize global variables
    adc_conversion.value = 0;
    adc_conversion.new_flag = 0;

    // Set up MCU
    init_io();
    init_adc();
        // Timer 0 runs off internal clock with 1:256 prescaler
        // This means it should run over every ((256*256)/(4MHz/4)) = 65.5ms
        // It will be used to start an ADC conversion.
    SETUP_TIMER_0(RTCC_INTERNAL | RTCC_DIV_256);
    ENABLE_INTERRUPTS(GLOBAL);          // enable interrupts in general to be active
    ENABLE_INTERRUPTS(INT_RTCC);        // enable the interrupt for Timer 0

    while(1)
    {
        // look for a new conversion result
        if (adc_conversion.new_flag == 1)
        { 
            bars = adc_conversion.value;
            adc_conversion.new_flag = 0;        // reset flag
            // We'll use the 3 most significant bits of the conversion result
            // to determine whether to display 1 to 8 "bars" on the LED display
            bars = (bars >> 5) + 1; // add one to make it 1 to 8 (vs 0 to 7)
            led_display = 0; // clear display variable
            for (temp1 = 0; temp1 < bars; temp1++)
            {
                // shift in a '1' for each bar
                led_display = (led_display << 1) + 1; 
            }
        }

        // check for a switch press & debounce
        if (INPUT_STATE(PIN_B0) == 0)
        { // switch is low when pressed
            if (switch_count < 8)
            { // increment the count on all consecutive checks where switch is pressed
              // to a max of 8
                switch_count ++;
                // if we've seen 8 consecutive checks where the switch is pressed
                // it's considered a valid switch press.  Reverse the bar graph
                if (switch_count == 8)
                {
                    led_bar_right = ~led_bar_right;
                }
            }
        }
        else
        { // anytime switch is detected as not pressed, reset the count
            switch_count = 0;
        }


        // update display
        if (led_bar_right == 0)
        {  // from left
            OUTPUT_D(led_display);
        }
        else
        { // from right
            // we have to shift it so it displays 1-8 bars.  Just complementing
            // would display 0-7.
            OUTPUT_D(~(led_display >> 1));
        }

    }

}


----------



## Power (Mar 12, 2008)

hola, #FUSE es una directiva para el precompilador al igual que todas aquellas que empiezan con el simbolo numeral(#),el precompilador es una parte del compilador que se ejecuta cuando compilas un programa y que automaticamente reemplaza a #XXXX por lo que corresponda para que pueda ser interpretado por el compilador,en este caso le dice como configurar los fusibles del microntrolador, dependiendo del pic con que trabajes hay distintos fusibles validos los cuales puedes ver entrando en el CCS a VIEW -> VALID FUSES y luego seleccionar el pic que utilizas, te aparece una lista de los fusibles validos y que significa cada uno, por ejemplo uno de los mas comunes es WDT que habilita al Watch Dog Timer (en caso de que no lo quieras habilitar es NOWDT) o el fusible XT que indica que vas a usar un oscilador a cristal a una frecuencia menor o igual a 4MHz

Las estructuras son un conjunto de variables, en este caso 2 value new_flag,que estan definidas bajo el mismo nombre, en realidad es como crear un tipo de variable nueva como puede ser byte o boolean, en este caso el tipo de estructura es adc_result  y el nombre es adc_conversion  , en general se utilizan en programacion avanzada y te recomiendo que si estas empezando no le des mucha importancia a las estructuras si bien en algoritmos complejos puede ser util emplearlas no son indispensables y ya tendras tiempo de utilizarlas.

Espero que te sirva 
Saludos


----------



## ecazcarra (Mar 12, 2008)

muchisimas gracias, si que me ha servido, lo de fuses confundia con los registros y por eso no me cuadraba.
Un saludo


----------



## facuenta (Mar 18, 2010)

Tengo el pickit2, pero como hago el debuger para ir midiendo el tiempo de los procesos con un programa hecho en CCS? incircuit? Me compré hace unos días una placa entrenadora que viene con el PIC16F887 pero el problema que tengo que el LCD tiene su bus de datos conectado al PORTD, pero los terminales de control están en otro lado... el E está conectado a RE2, el RS está conectado al RE1 y el R/W directamente a masa... qué tengo que cambiar en la biblioteca LCD.C?
Saludos,
Facundo


----------

