Software for PIC 16F876

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From English to

Threaded View
Hello,
I want to built a simple datalogger with a PIC 16F876, and found a
nice schema
on the net.
My problem: te software (source) is written in "C", but i need a hex
files to program the PIC processor. I have playing with JAL, but i
have not a "C" knowledge. Can someone help me, and "translate" the C
to hex ?

Thanks

*/

#include <16F876.H>
#device ADC10%
#include
#fuses XT, NOPROTECT, NOPUT, NOWDT, NOBROWNOUT, NOLVP, NOCPD, NOWRT

/* INTERNAL EEPROM ASSIGNMENTS */
#define SAMPLE_INTERVAL_HI 0
#define SAMPLE_INTERVAL_LO 1
#define SAMPLE_COUNT_HI    2
#define SAMPLE_COUNT_LO    3
#define LOGGING_STATE      4
#define RANGE              5

/* EXTERNAL EEPROM ASSIGNMENTS */
#define EEPROM_ADDRESS     long int
#define EEPROM_BYTE_SIZE   8192
#define EEPROM_SCL         PIN_B0
#define EEPROM_SDA         PIN_B1

/* LCD STUFF */
#define LCD_D0  PIN_C3
#define LCD_D1  PIN_C4
#define LCD_D2  PIN_C5
#define LCD_D3  PIN_C6
#define LCD_EN  PIN_B5
#define LCD_RS  PIN_B6
#define LINE_1  0x00
#define LINE_2  0x40
#define CLEAR_DISP  0x01

#define MENU_DEC_SWITCH        PIN_C0
#define SELECT_INC_SWITCH      PIN_C1
#define RANGE_SHUNT            PIN_C2
#define SEL0                   PIN_B2
#define SEL1                   PIN_B4

#define MINIMUM_INTERVAL   1
#define STATE_START        0
#define STATE_STOP         1
#define STATE_STATUS       2
#define STATE_RESET        3
#define STATE_RANGE        4
#define STATE_INTERVAL     5
#define STATE_VIEW         6
#define STATE_DUMP         7
#define MAX_MENU_STATE     7

#define hi(x)  (*(&x+1))

#use delay ( clock40%00000 )
#use standard_io ( A )
#use standard_io ( B )
#use standard_io ( C )
#use rs232 ( baud96%00, xmit=PIN_B3 )
#use i2c ( master, sclEE%PROM_SCL, sdaEE%PROM_SDA )

void PrintMenu ( void );       /* protos */
void init_ext_eeprom ( void );
void write_ext_eeprom ( long int lngAddress, BYTE intData );
BYTE read_ext_eeprom ( long int lngAddress );
void SetTime ( void );
void CheckSample ( void );
void CheckSwitches ( void );
char GetEchoNumChar ( void );
void LCD_Init ( void );
void LCD_SetPosition ( unsigned int cX );
void LCD_PutChar ( unsigned int cX );
void LCD_PutCmd ( unsigned int cX );
void LCD_PulseEnable ( void );
void LCD_SetData ( unsigned int cX );
void DisplayVolts ( long iAdcValue, char cLoc );
float ScaleAdc ( long iValue );
void SetRange ( BYTE cDisplay );

static long iIntervalCount, iIntervalTrigger, iSampleCount;
static char cLogging, cSampleFlag, cLedCount;
static char cLoggingIndicatorFlag, cAdcFlag, cToggleFlag;
static char cInterruptCount, cViewing;
static char cMenuState, cSelectFlag, cRange, cSel;
static char cMenuDecSwitchOn, cMenuSwitchCount;
static char cSelIncSwitchOn, cSelectSwitchCount;

void main ( void )
    {
    init_ext_eeprom();                  /* set SDA and SCL to float */
    setup_counters ( RTCC_INTERNAL, RTCC_DIV_128 );       /* 31mS roll
*/

    LCD_Init();
    LCD_PutCmd ( CLEAR_DISP );
    LCD_SetPosition ( LINE_1 + 2 );
    printf ( LCD_PutChar, "DATA LOGGER" );
    LCD_SetPosition ( LINE_2 + 2 );
    printf ( LCD_PutChar, "%4lu samples", EEPROM_BYTE_SIZE / 2 );
    delay_ms ( 2000 );
    LCD_PutCmd ( CLEAR_DISP );    LCD_Init();
    LCD_SetPosition ( LINE_1 + 4 );
    printf ( LCD_PutChar, "Jon Fick" );
    LCD_SetPosition ( LINE_2 + 4 );
    printf ( LCD_PutChar, "03/01/04" );
    delay_ms ( 2000 );
    LCD_PutCmd ( CLEAR_DISP );

    /* RESTORE PREVIOUS STATE */
    cRange =  read_eeprom ( RANGE );
    SetRange ( NO );         /* set range, don't display */
    iSampleCount = ( 256 * read_eeprom ( SAMPLE_COUNT_HI ) ) +
read_eeprom ( SAMPLE_COUNT_LO );
    cLogging = read_eeprom ( LOGGING_STATE );   /* get existing state
*/
    iIntervalTrigger = ( 256 * read_eeprom ( SAMPLE_INTERVAL_HI ) ) +
read_eeprom ( SAMPLE_INTERVAL_LO );
    if ( iIntervalTrigger == 0 )
        {
        iIntervalTrigger = 1;     /* preset to at least 1 second
sample interval */
        }

    setup_adc_ports ( RA0_ANALOG );     /* these three statements set
up the ADC */
    setup_adc ( ADC_CLOCK_INTERNAL );   /* clock source */
    set_adc_channel ( 0 );              /* select channel */
    enable_interrupts ( INT_RTCC );     /* turn on timer interrupt */
    enable_interrupts ( GLOBAL );       /* enable interrupts */

    cSelectFlag = OFF;
    cToggleFlag = 0;
    cMenuDecSwitchOn = OFF;
    cSelIncSwitchOn = OFF;
    cMenuSwitchCount = 0;
    cSelectSwitchCount = 0;
    cMenuState = ( cLogging == YES ) ? STATE_STOP : STATE_START;  /*
set first menu */

    while ( TRUE )              /* do forever */
        {
        PrintMenu();            /* display screen */
        CheckSwitches();        /* check and do any switch activity */
        CheckSample();          /* check if it's time to sample ADC */
        }
    }

/******************************************************************************/

#int_rtcc
void TimerInterrupt ( void )      /* 32.768mS tic, ~30 interrupts per
second */
    {
    if ( cInterruptCount++ == 30 )      /* if one second yet */
        {
        cAdcFlag = ON;              /* allow write to display */
        cInterruptCount = 0;
        if ( cLogging == YES )
            {
            cLoggingIndicatorFlag = ON;    /* time to toggle "running"
indicator on display */
            }
        if ( ( iIntervalCount++ == iIntervalTrigger - 1 ) && (
cLogging == YES ) )  /* if sample time yet */
                {
                cSampleFlag = ON;                       /* signal time
to sample */
                iIntervalCount = 0;                     /* start count
over */
                }
           }
    if ( input ( MENU_DEC_SWITCH ) == LOW )
        {
        if ( cMenuSwitchCount++ == 0 )     /* debounce for 30mS, (was
2) */
            {
            cMenuDecSwitchOn = YES;        /* signal that switch was
pressed */
            cMenuSwitchCount = cViewing ? 252 : 240;       /* set up
for auto repeat (faster if viewing) */
            }
        }
    else
        {
        cMenuSwitchCount = 0;             /* switch up, restart */
        }
    if ( input ( SELECT_INC_SWITCH ) == LOW )
        {
        if ( cSelectSwitchCount++ == 0 )  /* debounce for 30mS (was 2)
*/
            {
            cSelIncSwitchOn = YES;        /* signal that switch was
pressed */
            cSelectSwitchCount = cViewing ? 252 : 240;       /* set up
for auto repeat (faster if viewing) */
            }
        }
    else
        {
        cSelectSwitchCount = 0;             /* switch is up, restart
count */
        }
    set_rtcc ( 4 );     /* restart at adjusted value for 1-second
accuracy */
    }

/******************************************************************************/

void CheckSwitches ( void )
    {
    char cX, cDigit, cDigitPointer, cDone;
    long iX, iY, iVal, iPlace;

    if ( cMenuDecSwitchOn == YES )      /* if interrupt caught the
switch press */
        {
        if ( cMenuState++ >= MAX_MENU_STATE )      /* if at maximum */
            {
            cMenuState = 0;            /* roll */
            }
        cMenuDecSwitchOn = NO;     /* turn back off */
        }
    if ( cSelIncSwitchOn == YES )      /* if interrupt caught the
switch press */
        {
        cSelectFlag = ON;
        cSelIncSwitchOn = NO;     /* turn back off */
        }

    if ( cLogging == NO )
        {
        cSel = 2 * input ( SEL0 ) + input ( SEL1 );    /* determine
state of SEL inputs, (unused at present) */
        }

    switch ( cMenuState )
        {
        case ( STATE_START ):
            {
            if ( cSelectFlag == ON )    /* if switch is pressed */
                {
                cSelectFlag = OFF;         /* turn flag off */
                if ( iSampleCount >= ( EEPROM_BYTE_SIZE / 2 ) )  /*
already at end of memory */
                    {
                    LCD_PutCmd ( CLEAR_DISP );
                    LCD_SetPosition ( LINE_1 + 2);
                    printf ( LCD_PutChar, "MEMORY FULL" );
                    LCD_SetPosition ( LINE_2 + 2 );
                    printf ( LCD_PutChar, "%4lu samples", iSampleCount
);
                    delay_ms ( 1000 );
                    LCD_PutCmd ( CLEAR_DISP );
                    cMenuDecSwitchOn = NO;
                    cSelIncSwitchOn = NO;
                    cMenuState = STATE_START;    /* menu displays
"START" */
                    }
                else                        /* if OK to start */
                    {
                    cLogging = YES;
                    write_eeprom ( LOGGING_STATE, YES );
                    write_eeprom ( RANGE, cRange );
                    cSampleFlag = ON;                       /*
immediate sample */
                    cInterruptCount = 0;    /* synchronize interrupt
timing from here */
                    iIntervalCount = 0;         /* synchronize */
                    cMenuState = STATE_STOP;    /* menu displays
"STOP" */
                    break;
                    }
                }
            }
        case ( STATE_STOP ):
            {
            if ( cSelectFlag == ON )    /* if switch is pressed */
                {
                cSelectFlag = OFF;         /* turn flag off */
                cLogging = NO;
                write_eeprom ( LOGGING_STATE, NO );
                cMenuState = STATE_START;    /* menu displays "START"
*/
                break;
                }
            }
         case ( STATE_RESET ):
            {
            if ( cSelectFlag == ON )    /* if switch is pressed */
                {
                cSelectFlag = OFF;         /* turn flag off */
                write_eeprom ( SAMPLE_COUNT_HI, 0 );
                write_eeprom ( SAMPLE_COUNT_LO, 0 );
                iSampleCount = 0;
                cLogging = NO;
                LCD_PutCmd ( CLEAR_DISP );
                LCD_SetPosition ( LINE_1 + 0 );
                printf ( LCD_PutChar, "Reset..." );
                delay_ms ( 1000 );
                LCD_SetPosition ( LINE_1 + 8 );
                printf ( LCD_PutChar, "complete" );
                delay_ms ( 1000 );
                LCD_PutCmd ( CLEAR_DISP );
                cMenuDecSwitchOn = NO;
                cSelIncSwitchOn = NO;
                cMenuState = STATE_START;    /* menu displays "START"
*/
                break;
                }
            }
         case ( STATE_STATUS ):
            {
            if ( cSelectFlag == ON )    /* if switch is pressed */
                {
                cSelectFlag = OFF;         /* turn flag off */
                LCD_PutCmd ( CLEAR_DISP );
                LCD_SetPosition ( LINE_1 );
                printf ( LCD_PutChar, "Interval: %lus", 256 *
read_eeprom ( SAMPLE_INTERVAL_HI ) + read_eeprom ( SAMPLE_INTERVAL_LO
) );
                LCD_SetPosition ( LINE_2 );
                printf ( LCD_PutChar, "Samples:  %lu", 256 *
read_eeprom ( SAMPLE_COUNT_HI ) + read_eeprom ( SAMPLE_COUNT_LO ) );
                delay_ms ( 2000 );
                LCD_PutCmd ( CLEAR_DISP );
                cMenuDecSwitchOn = NO;
                cSelIncSwitchOn = NO;
                cMenuState = STATE_START;    /* menu displays "LOG" */
                break;
                }
            }
        case ( STATE_RANGE ):
            {
            if ( cSelectFlag == ON )    /* if switch is pressed */
                {
                cSelectFlag = OFF;         /* turn flag off */
                LCD_PutCmd ( CLEAR_DISP );
                LCD_SetPosition ( LINE_2 + 0 );
                printf ( LCD_PutChar, "CHANGE    Return" );
                LCD_SetPosition ( LINE_1 + 7 );
                SetRange ( YES );         /* set range, display */
                while ( TRUE )
                    {
                    if ( cSelIncSwitchOn == YES )
                        {
                        cSelIncSwitchOn = NO;
                    break;
                        }
                    if ( cMenuDecSwitchOn == YES )
                        {
                        cMenuDecSwitchOn = NO;
                        if ( ++cRange >= 2 )       /* increment and
wrap */
                            {
                            cRange = 0;
                            }
                        LCD_SetPosition ( LINE_1 + 7 );
                        SetRange ( YES );         /* set range,
display */
                        }
                    }
                write_eeprom ( RANGE, cRange );    /* save range */
                cMenuState = STATE_START;          /* menu displays
"START" */
                break;
                }
            }
        case ( STATE_INTERVAL ):
            {
            if ( cSelectFlag == ON )    /* if switch is pressed */
                {
                cSelectFlag = OFF;         /* turn flag off */
                LCD_PutCmd ( CLEAR_DISP );
                LCD_SetPosition ( LINE_1 );
                printf ( LCD_PutChar, "Presently %05lus",
iIntervalTrigger );
                LCD_SetPosition ( LINE_2 + 0 );
                printf ( LCD_PutChar, "DIGIT 00000s INC" );
                cX = LINE_2 + 6;        /* point to beginning of zeros
*/
                LCD_SetPosition ( cX );
                LCD_PutCmd ( 0x0E );    /* display ON, cursor on, no
blink */
                cDigit = 0;
                cDigitPointer = 0;
                iX = 0;
                iPlace = 10000;
                while ( TRUE )
                    {
                    if ( cSelIncSwitchOn == YES )
                        {
                        if ( ++cDigit > 9 )       /* increment digit
*/
                            {
                            cDigit = 0;     /* roll */
                            }
                        cSelIncSwitchOn = NO;
                        cSelIncSwitchOn = NO;
                        LCD_SetPosition ( cX + cDigitPointer );   /*
set cursor to this digit */
                        printf ( LCD_PutChar, "%u", cDigit );     /*
display the digit */
                        LCD_SetPosition ( cX + cDigitPointer );   /*
set cursor back to this digit */
                        }
                    if ( cMenuDecSwitchOn == YES )
                        {
                        cMenuDecSwitchOn = NO;
                        iX += cDigit * iPlace;   /* add in to total */
                        iPlace /= 10;         /* point to next place
value down */
                        cDigit = 0;      /* zero digit again */
                        if ( ++cDigitPointer == 5 ) /* point to next
digit */
                            {
                            break;
                            }
                        LCD_SetPosition ( cX + cDigitPointer );
                        }
                    }
                if ( iX != 0 )         /* if number was updated */
                   {
                   write_eeprom ( SAMPLE_INTERVAL_HI, iX / 256 );  /*
store high byte */
                   write_eeprom ( SAMPLE_INTERVAL_LO, iX % 256 );  /*
store low byte */
                   iIntervalTrigger = iX;       /* update interval */
                   }
                LCD_PutCmd ( 0x0E );    /* display ON, cursor off, no
blink */
                LCD_PutCmd ( CLEAR_DISP );
                cMenuState = STATE_START;    /* menu displays "LOG" */
                break;
                }
            }
        case ( STATE_VIEW ):
            {
            if ( cSelectFlag == ON )    /* if switch is pressed */
                {
                cSelectFlag = OFF;         /* turn flag off */
                iX = 0;        /* zero sample number */
                iY = ( read_eeprom ( SAMPLE_COUNT_HI ) * 256 ) +
read_eeprom ( SAMPLE_COUNT_LO );
                cRange =  read_eeprom ( RANGE );    /* used stored
range */
                LCD_PutCmd ( CLEAR_DISP );
                cDone = NO;
                if ( iY != 0 )           /* if any samples at all */
                    {
                    LCD_SetPosition ( LINE_1 );
                    printf ( LCD_PutChar, "#" );
                    LCD_SetPosition ( LINE_2 );
                    printf ( LCD_PutChar, "DEC BothDone INC" );
                    while ( cDone == NO )
                        {
                        LCD_SetPosition ( LINE_1 + 1 );
                        printf ( LCD_PutChar, "%04lu", iX );   /*
display sample number */
                        iPlace = ( read_ext_eeprom ( iX * 2 ) * 256 )
+ read_ext_eeprom ( ( iX * 2 ) + 1 );    /* retrieve data from EEPROM
*/
                        DisplayVolts ( iPlace, 10 );      /* display
data at position 7 */
                        while ( TRUE )
                            {
                            cViewing = ON;
                            if ( ( input ( MENU_DEC_SWITCH ) == LOW )
&& ( input ( SELECT_INC_SWITCH ) == LOW ) )
                                {
                                cDone = YES;
                                break;
                                }
                            if ( cMenuDecSwitchOn == YES )
                                {
                                cMenuDecSwitchOn = NO;
                                if ( iX-- == 0 )
                                    {
                                    iX = iY - 1;     /* roll negative
*/
                                    }
                                    break;
                                }
                            if ( cSelIncSwitchOn == YES )
                                {
                                cSelIncSwitchOn = NO;
                                if ( iX++ >= ( iY - 1 ) )
                                    {
                                    iX = 0;        /* roll positive */
                                    }
                                break;
                                }
                            }
                        cViewing = OFF;
                        }
                    }
                else
                    {
                    LCD_SetPosition ( LINE_1 );
                    printf ( LCD_PutChar, "No samples yet!" );
                    delay_ms ( 1000 );
                    }
                LCD_PutCmd ( CLEAR_DISP );
                cMenuState = STATE_START;    /* menu displays "LOG" */
                break;
                }
            }
        case ( STATE_DUMP ):
            {
            if ( cSelectFlag == ON )    /* if switch is pressed */
                {
                cSelectFlag = OFF;         /* turn flag off */
                iY = ( read_eeprom ( SAMPLE_COUNT_HI ) * 256 ) +
read_eeprom ( SAMPLE_COUNT_LO );     /* get number of samples */
                cRange =  read_eeprom ( RANGE );    /* used stored
range */
                LCD_PutCmd ( CLEAR_DISP );
                cDone = NO;
                if ( iY != 0 )           /* if any samples at all */
                    {
                    LCD_SetPosition ( LINE_1 + 0 );
                    printf ( LCD_PutChar, "Dump 9600-8-N-1 " );
                    LCD_SetPosition ( LINE_2 );
                    printf ( LCD_PutChar, "   Both=Stop    " );
                    disable_interrupts ( GLOBAL );  /* turn off during
async */
                    printf ( "rnrn   Sample interval -- %lu
seconds", 256 * read_eeprom ( SAMPLE_INTERVAL_HI ) + read_eeprom (
SAMPLE_INTERVAL_LO ) );
                    printf ( "rn   Number of samples- %lu", iY );
                    printf ( "rnrnSampletVolts" );
                    printf ( "rn------t-----rn" );
                    for ( iX = 0; iX < iY; iX++ )
                        {
                        if ( ( input ( MENU_DEC_SWITCH ) == LOW ) && (
input ( SELECT_INC_SWITCH ) == LOW ) )
                            {
                            cDone = YES;
                            break;
                            }
                        iVal = ( read_ext_eeprom ( iX * 2 ) * 256 ) +
read_ext_eeprom ( ( iX * 2 ) + 1 );  /* get sample data */
                        if ( iVal == 0x3FF )
                            {
                            printf ( "%lutO/Lrn", iX ); /*
out-of-range */
                            }
                        else
                            {
                            printf ( "%lut%1.2frn", iX, ScaleAdc (
iVal ) ); /* send data sample */
                            }
                        delay_ms ( 1 );     /* avoids text glitches in
output stream */
                        }
                    enable_interrupts ( GLOBAL );  /* turn on again */
                    }
                else
                    {
                    LCD_SetPosition ( LINE_1 );
                    printf ( LCD_PutChar, "No samples yet!" );
                    delay_ms ( 1000 );
                    }
                delay_ms ( 1000 );      /* allow time to view 9600
baud msg, etc. */
                LCD_PutCmd ( CLEAR_DISP );
                cMenuState = STATE_START;    /* menu displays "LOG" */
                break;
                }
            }
        }
    }

void PrintMenu ( void )
    {
    LCD_SetPosition ( LINE_1 + 15 );
    if ( cLogging == NO )       /* if not logging at this time */
        {
        printf ( LCD_PutChar, " " );    /* blank symbol */
        }
    else                    /* if presently logging */
        {
        if ( cLoggingIndicatorFlag == ON )  /* turned on once per
second by interrupt */
            {
            cToggleFlag ^= 1;              /* toggle the symbol */
            if ( cToggleFlag == 1 )
                {
                printf ( LCD_PutChar, "%c", 255 );  /* symbol */
                }
            else
                {
                printf ( LCD_PutChar, " " );    /* blank */
                }
            cLoggingIndicatorFlag = OFF;
            }
        }
    LCD_SetPosition ( LINE_2 + 0 );
    switch ( cMenuState )
        {
        case STATE_START:
            {
            if ( cLogging == YES )      /* don't display while logging
*/
                {
                cMenuState++;   /* point to next menu */
                break;
                }
            printf ( LCD_PutChar, "Next       START" );
            break;
            }
        case STATE_STOP:
            {
            if ( cLogging == NO )      /* don't display if not logging
*/
                {
                cMenuState++;   /* point to next menu */
                break;
                }
            printf ( LCD_PutChar, "#%04lu", iSampleCount );
            LCD_SetPosition ( LINE_2 + 11 );
            printf ( LCD_PutChar, " STOP" );
            break;
            }
        case STATE_INTERVAL:
            {
            if ( cLogging == YES )      /* prevent changing while
logging */
                {
                cMenuState++;   /* point to next menu */
                break;
                }
            printf ( LCD_PutChar, "Next    INTERVAL" );
            break;
            }
        case STATE_STATUS:
            {
            printf ( LCD_PutChar, "Next      STATUS" );
            break;
            }
        case STATE_VIEW:
            {
            printf ( LCD_PutChar, "Next        VIEW" );
            break;
            }
        case STATE_DUMP:
            {
            printf ( LCD_PutChar, "Next      UPLOAD" );
            break;
            }
        case STATE_RESET:
            {
            if ( cLogging == YES )      /* prevent changing while
logging */
                {
                cMenuState++;   /* point to next menu */
                break;
                }
            printf ( LCD_PutChar, "Next       RESET" );
            break;
            }
        case STATE_RANGE:
            {
            if ( cLogging == YES )      /* prevent changing while
logging */
                {
                cMenuState++;   /* point to next menu */
                break;
                }
            printf ( LCD_PutChar, "Next       RANGE" );
            break;
            }
        }
    if ( cAdcFlag == ON )                    /* if interrupt signalled
an ADC reading */
        {
        DisplayVolts ( read_adc(), 5 );      /* read ADC, send raw
data to display routine at position 3 */
        cAdcFlag = OFF;
        }
    }

void SetRange ( BYTE cDisplay )
    {
    switch ( cRange )
        {
    case ( 0 ):         /* if 5V range */
            {
            output_float ( RANGE_SHUNT );      /* open shunt pulldown
*/
            if ( cDisplay == YES )
                {
            printf ( LCD_PutChar, "5V " );     /* 5V scale */
            }
            break;
        }
    case ( 1 ):         /* if 14V range */
            {
            output_low ( RANGE_SHUNT );        /* pull shunt resistor
down */
            if ( cDisplay == YES )
                {
            printf ( LCD_PutChar, "14V" );     /* 14V scale */
            }
            break;
        }
    default:            /* anything else is 5V range */
            {
            output_float ( RANGE_SHUNT );      /* open shunt pulldown
*/
            if ( cDisplay == YES )
                {
            printf ( LCD_PutChar, "5V " );     /* 5V scale */
            }
            break;
            }
        }
    }

void CheckSample ( void )
    {
    long iVal;

    if ( cSampleFlag == ON )     /* if time to sample */
        {
        if ( iSampleCount >= ( EEPROM_BYTE_SIZE / 2 ) )  /* at end of
memory */
            {
            cLogging = NO;       /* stop any further logging */
            write_eeprom ( LOGGING_STATE, NO );
            cMenuState = STATE_STATUS;     /* display status menu next
*/
            }
        else
            {
            iVal = read_adc();
        /*    iVal = iSampleCount;   only for testing */
            write_ext_eeprom ( iSampleCount * 2, iVal / 256 );   /*
write high data to external EEPROM */
            write_ext_eeprom ( ( iSampleCount * 2 ) + 1, iVal % 256 );
  /* write low data */
            iSampleCount++;             /* point to next memory
location */
            write_eeprom ( SAMPLE_COUNT_HI, ( char ) ( iSampleCount /
256 ) );    /* save sample count to internal EEPROM */
            write_eeprom ( SAMPLE_COUNT_LO, ( char ) ( iSampleCount %
256 ) );
            }
        cSampleFlag = OFF;       /* reset flag, interrupt turns on
again later */
        }
    }

void init_ext_eeprom ( void )
    {
    output_float ( EEPROM_SCL );
    output_float ( EEPROM_SDA );
    }

void write_ext_eeprom ( long int lngAddress, BYTE intData )
    {
    i2c_start();
    i2c_write ( 0xa0 );  /* set up for writing address and data, chip
address 000 */
    i2c_write ( hi ( lngAddress ) );      /* write high address */
    i2c_write ( lngAddress );      /* write low address */
    i2c_write ( intData );                        /* write data */
    i2c_stop();
    delay_ms ( 11 );
    }

BYTE read_ext_eeprom ( long int lngAddress )
    {
    BYTE intData;

    i2c_start();
    i2c_write ( 0xa0 );   /* set up for writing address, chip address
000 */
    i2c_write ( hi ( lngAddress ) );      /* write high address */
    i2c_write ( lngAddress );      /* write low address */
    i2c_start();
    i2c_write ( 0xa1 );   /* set up for reading data, chip address 000
*/
    intData = i2c_read ( 0 );                     /* read data */
    i2c_stop();
    return ( intData );
    }

char GetEchoNumChar ( void )
    {
    char cX;

    while ( TRUE )
        {
       // cX = getc();                    /* wait for character */
       cX = GETC();
        if ( ( cX >= '0' ) && ( cX <= '9' ) )   /* check bounds */
            {
            break;
            }
        }
    PUTC ( cX );                                /* echo to screen */
    return ( cX - 0x30 );                       /* adjust to numeric
*/
    }

void DisplayVolts ( long iAdcValue, char cLoc )
    {
    LCD_SetPosition ( LINE_1 + cLoc );
    if ( iAdcValue == 0x3FF )
        {
        printf ( LCD_PutChar, " O/L     " );    /* out of range */
        }
    else
        {
        printf ( LCD_PutChar, "%2.2fV ", ScaleAdc ( iAdcValue ) ); /*
display data sample */
        }
    }

float ScaleAdc ( long iValue )
    {
    float fScale;

    switch ( cRange )
        {
        case ( 0 ):
            {
            fScale = 5;     /* 5V scale */
            break;
            }
        case ( 1 ):
            {
            fScale = 14;     /* 14V scale */
            break;
            }
        case ( 2 ):
            {
            fScale = 5;     /* 5V scale */
            break;
            }
        case ( 3 ):
            {
            fScale = 5;     /* 5V scale */
            break;
            }
        }
    return ( ( float ) iValue / 1023 * fScale );   /* scale to proper
range, 1023 leaves room for out-of-range */
    }

void LCD_Init ( void )
    {
    LCD_SetData ( 0x00 );
    delay_ms ( 200 );       /* wait enough time after Vdd rise */
    output_low ( LCD_RS );
    LCD_SetData ( 0x03 );   /* init with specific nibbles to start
4-bit mode */
    LCD_PulseEnable();
    LCD_PulseEnable();
    LCD_PulseEnable();
    LCD_SetData ( 0x02 );   /* set 4-bit interface */
    LCD_PulseEnable();      /* send dual nibbles hereafter, MSN first
*/
    LCD_PutCmd ( 0x2C );    /* function set (all lines, 5x7
characters) */
    LCD_PutCmd ( 0x0C );    /* display ON, cursor off, no blink */
    LCD_PutCmd ( 0x01 );    /* clear display */
    LCD_PutCmd ( 0x06 );    /* entry mode set, increment */
    }

void LCD_SetPosition ( unsigned int cX )
    {
    /* this subroutine works specifically for 4-bit Port A */
    LCD_SetData ( swap ( cX ) | 0x08 );
    LCD_PulseEnable();
    LCD_SetData ( swap ( cX ) );
    LCD_PulseEnable();
    }

void LCD_PutChar ( unsigned int cX )
    {
    /* this subroutine works specifically for 4-bit Port A */
    output_high ( LCD_RS );
    LCD_SetData ( swap ( cX ) );     /* send high nibble */
    LCD_PulseEnable();
    LCD_SetData ( swap ( cX ) );     /* send low nibble */
    LCD_PulseEnable();
    output_low ( LCD_RS );
    }

void LCD_PutCmd ( unsigned int cX )
    {
    /* this subroutine works specifically for 4-bit Port A */
    LCD_SetData ( swap ( cX ) );     /* send high nibble */
    LCD_PulseEnable();
    LCD_SetData ( swap ( cX ) );     /* send low nibble */
    LCD_PulseEnable();
    }

void LCD_PulseEnable ( void )
    {
    output_high ( LCD_EN );
    delay_us ( 10 );
    output_low ( LCD_EN );
    delay_ms ( 5 );
    }

void LCD_SetData ( unsigned int cX )
    {
    output_bit ( LCD_D0, cX & 0x01 );
    output_bit ( LCD_D1, cX & 0x02 );
    output_bit ( LCD_D2, cX & 0x04 );
    output_bit ( LCD_D3, cX & 0x08 );
    }


Software for PIC 16F876
Hello,
I want to built a simple datalogger with a PIC 16F876, and found a
nice schema
on the net.
My problem: te software (source) is written in "C", but i need a hex
files to program the PIC processor. I have playing with JAL, but i
have not a "C" knowledge. Can someone help me, and "translate" the C
to hex ?

Thanks

*/

#include <16F876.H>
#device ADC10%
#include
#fuses XT, NOPROTECT, NOPUT, NOWDT, NOBROWNOUT, NOLVP, NOCPD, NOWRT

/* INTERNAL EEPROM ASSIGNMENTS */
#define SAMPLE_INTERVAL_HI 0
#define SAMPLE_INTERVAL_LO 1
#define SAMPLE_COUNT_HI    2
#define SAMPLE_COUNT_LO    3
#define LOGGING_STATE      4
#define RANGE              5

/* EXTERNAL EEPROM ASSIGNMENTS */
#define EEPROM_ADDRESS     long int
#define EEPROM_BYTE_SIZE   8192
#define EEPROM_SCL         PIN_B0
#define EEPROM_SDA         PIN_B1

/* LCD STUFF */
#define LCD_D0  PIN_C3
#define LCD_D1  PIN_C4
#define LCD_D2  PIN_C5
#define LCD_D3  PIN_C6
#define LCD_EN  PIN_B5
#define LCD_RS  PIN_B6
#define LINE_1  0x00
#define LINE_2  0x40
#define CLEAR_DISP  0x01

#define MENU_DEC_SWITCH        PIN_C0
#define SELECT_INC_SWITCH      PIN_C1
#define RANGE_SHUNT            PIN_C2
#define SEL0                   PIN_B2
#define SEL1                   PIN_B4

#define MINIMUM_INTERVAL   1
#define STATE_START        0
#define STATE_STOP         1
#define STATE_STATUS       2
#define STATE_RESET        3
#define STATE_RANGE        4
#define STATE_INTERVAL     5
#define STATE_VIEW         6
#define STATE_DUMP         7
#define MAX_MENU_STATE     7

#define hi(x)  (*(&x+1))

#use delay ( clock40%00000 )
#use standard_io ( A )
#use standard_io ( B )
#use standard_io ( C )
#use rs232 ( baud96%00, xmit=PIN_B3 )
#use i2c ( master, sclEE%PROM_SCL, sdaEE%PROM_SDA )

void PrintMenu ( void );       /* protos */
void init_ext_eeprom ( void );
void write_ext_eeprom ( long int lngAddress, BYTE intData );
BYTE read_ext_eeprom ( long int lngAddress );
void SetTime ( void );
void CheckSample ( void );
void CheckSwitches ( void );
char GetEchoNumChar ( void );
void LCD_Init ( void );
void LCD_SetPosition ( unsigned int cX );
void LCD_PutChar ( unsigned int cX );
void LCD_PutCmd ( unsigned int cX );
void LCD_PulseEnable ( void );
void LCD_SetData ( unsigned int cX );
void DisplayVolts ( long iAdcValue, char cLoc );
float ScaleAdc ( long iValue );
void SetRange ( BYTE cDisplay );

static long iIntervalCount, iIntervalTrigger, iSampleCount;
static char cLogging, cSampleFlag, cLedCount;
static char cLoggingIndicatorFlag, cAdcFlag, cToggleFlag;
static char cInterruptCount, cViewing;
static char cMenuState, cSelectFlag, cRange, cSel;
static char cMenuDecSwitchOn, cMenuSwitchCount;
static char cSelIncSwitchOn, cSelectSwitchCount;

void main ( void )
    {
    init_ext_eeprom();                  /* set SDA and SCL to float */
    setup_counters ( RTCC_INTERNAL, RTCC_DIV_128 );       /* 31mS roll
*/

    LCD_Init();
    LCD_PutCmd ( CLEAR_DISP );
    LCD_SetPosition ( LINE_1 + 2 );
    printf ( LCD_PutChar, "DATA LOGGER" );
    LCD_SetPosition ( LINE_2 + 2 );
    printf ( LCD_PutChar, "%4lu samples", EEPROM_BYTE_SIZE / 2 );
    delay_ms ( 2000 );
    LCD_PutCmd ( CLEAR_DISP );    LCD_Init();
    LCD_SetPosition ( LINE_1 + 4 );
    printf ( LCD_PutChar, "Jon Fick" );
    LCD_SetPosition ( LINE_2 + 4 );
    printf ( LCD_PutChar, "03/01/04" );
    delay_ms ( 2000 );
    LCD_PutCmd ( CLEAR_DISP );

    /* RESTORE PREVIOUS STATE */
    cRange =  read_eeprom ( RANGE );
    SetRange ( NO );         /* set range, don't display */
    iSampleCount = ( 256 * read_eeprom ( SAMPLE_COUNT_HI ) ) +
read_eeprom ( SAMPLE_COUNT_LO );
    cLogging = read_eeprom ( LOGGING_STATE );   /* get existing state
*/
    iIntervalTrigger = ( 256 * read_eeprom ( SAMPLE_INTERVAL_HI ) ) +
read_eeprom ( SAMPLE_INTERVAL_LO );
    if ( iIntervalTrigger == 0 )
        {
        iIntervalTrigger = 1;     /* preset to at least 1 second
sample interval */
        }

    setup_adc_ports ( RA0_ANALOG );     /* these three statements set
up the ADC */
    setup_adc ( ADC_CLOCK_INTERNAL );   /* clock source */
    set_adc_channel ( 0 );              /* select channel */
    enable_interrupts ( INT_RTCC );     /* turn on timer interrupt */
    enable_interrupts ( GLOBAL );       /* enable interrupts */

    cSelectFlag = OFF;
    cToggleFlag = 0;
    cMenuDecSwitchOn = OFF;
    cSelIncSwitchOn = OFF;
    cMenuSwitchCount = 0;
    cSelectSwitchCount = 0;
    cMenuState = ( cLogging == YES ) ? STATE_STOP : STATE_START;  /*
set first menu */

    while ( TRUE )              /* do forever */
        {
        PrintMenu();            /* display screen */
        CheckSwitches();        /* check and do any switch activity */
        CheckSample();          /* check if it's time to sample ADC */
        }
    }

/******************************************************************************/

#int_rtcc
void TimerInterrupt ( void )      /* 32.768mS tic, ~30 interrupts per
second */
    {
    if ( cInterruptCount++ == 30 )      /* if one second yet */
        {
        cAdcFlag = ON;              /* allow write to display */
        cInterruptCount = 0;
        if ( cLogging == YES )
            {
            cLoggingIndicatorFlag = ON;    /* time to toggle "running"
indicator on display */
            }
        if ( ( iIntervalCount++ == iIntervalTrigger - 1 ) && (
cLogging == YES ) )  /* if sample time yet */
                {
                cSampleFlag = ON;                       /* signal time
to sample */
                iIntervalCount = 0;                     /* start count
over */
                }
           }
    if ( input ( MENU_DEC_SWITCH ) == LOW )
        {
        if ( cMenuSwitchCount++ == 0 )     /* debounce for 30mS, (was
2) */
            {
            cMenuDecSwitchOn = YES;        /* signal that switch was
pressed */
            cMenuSwitchCount = cViewing ? 252 : 240;       /* set up
for auto repeat (faster if viewing) */
            }
        }
    else
        {
        cMenuSwitchCount = 0;             /* switch up, restart */
        }
    if ( input ( SELECT_INC_SWITCH ) == LOW )
        {
        if ( cSelectSwitchCount++ == 0 )  /* debounce for 30mS (was 2)
*/
            {
            cSelIncSwitchOn = YES;        /* signal that switch was
pressed */
            cSelectSwitchCount = cViewing ? 252 : 240;       /* set up
for auto repeat (faster if viewing) */
            }
        }
    else
        {
        cSelectSwitchCount = 0;             /* switch is up, restart
count */
        }
    set_rtcc ( 4 );     /* restart at adjusted value for 1-second
accuracy */
    }

/******************************************************************************/

void CheckSwitches ( void )
    {
    char cX, cDigit, cDigitPointer, cDone;
    long iX, iY, iVal, iPlace;

    if ( cMenuDecSwitchOn == YES )      /* if interrupt caught the
switch press */
        {
        if ( cMenuState++ >= MAX_MENU_STATE )      /* if at maximum */
            {
            cMenuState = 0;            /* roll */
            }
        cMenuDecSwitchOn = NO;     /* turn back off */
        }
    if ( cSelIncSwitchOn == YES )      /* if interrupt caught the
switch press */
        {
        cSelectFlag = ON;
        cSelIncSwitchOn = NO;     /* turn back off */
        }

    if ( cLogging == NO )
        {
        cSel = 2 * input ( SEL0 ) + input ( SEL1 );    /* determine
state of SEL inputs, (unused at present) */
        }

    switch ( cMenuState )
        {
        case ( STATE_START ):
            {
            if ( cSelectFlag == ON )    /* if switch is pressed */
                {
                cSelectFlag = OFF;         /* turn flag off */
                if ( iSampleCount >= ( EEPROM_BYTE_SIZE / 2 ) )  /*
already at end of memory */
                    {
                    LCD_PutCmd ( CLEAR_DISP );
                    LCD_SetPosition ( LINE_1 + 2);
                    printf ( LCD_PutChar, "MEMORY FULL" );
                    LCD_SetPosition ( LINE_2 + 2 );
                    printf ( LCD_PutChar, "%4lu samples", iSampleCount
);
                    delay_ms ( 1000 );
                    LCD_PutCmd ( CLEAR_DISP );
                    cMenuDecSwitchOn = NO;
                    cSelIncSwitchOn = NO;
                    cMenuState = STATE_START;    /* menu displays
"START" */
                    }
                else                        /* if OK to start */
                    {
                    cLogging = YES;
                    write_eeprom ( LOGGING_STATE, YES );
                    write_eeprom ( RANGE, cRange );
                    cSampleFlag = ON;                       /*
immediate sample */
                    cInterruptCount = 0;    /* synchronize interrupt
timing from here */
                    iIntervalCount = 0;         /* synchronize */
                    cMenuState = STATE_STOP;    /* menu displays
"STOP" */
                    break;
                    }
                }
            }
        case ( STATE_STOP ):
            {
            if ( cSelectFlag == ON )    /* if switch is pressed */
                {
                cSelectFlag = OFF;         /* turn flag off */
                cLogging = NO;
                write_eeprom ( LOGGING_STATE, NO );
                cMenuState = STATE_START;    /* menu displays "START"
*/
                break;
                }
            }
         case ( STATE_RESET ):
            {
            if ( cSelectFlag == ON )    /* if switch is pressed */
                {
                cSelectFlag = OFF;         /* turn flag off */
                write_eeprom ( SAMPLE_COUNT_HI, 0 );
                write_eeprom ( SAMPLE_COUNT_LO, 0 );
                iSampleCount = 0;
                cLogging = NO;
                LCD_PutCmd ( CLEAR_DISP );
                LCD_SetPosition ( LINE_1 + 0 );
                printf ( LCD_PutChar, "Reset..." );
                delay_ms ( 1000 );
                LCD_SetPosition ( LINE_1 + 8 );
                printf ( LCD_PutChar, "complete" );
                delay_ms ( 1000 );
                LCD_PutCmd ( CLEAR_DISP );
                cMenuDecSwitchOn = NO;
                cSelIncSwitchOn = NO;
                cMenuState = STATE_START;    /* menu displays "START"
*/
                break;
                }
            }
         case ( STATE_STATUS ):
            {
            if ( cSelectFlag == ON )    /* if switch is pressed */
                {
                cSelectFlag = OFF;         /* turn flag off */
                LCD_PutCmd ( CLEAR_DISP );
                LCD_SetPosition ( LINE_1 );
                printf ( LCD_PutChar, "Interval: %lus", 256 *
read_eeprom ( SAMPLE_INTERVAL_HI ) + read_eeprom ( SAMPLE_INTERVAL_LO
) );
                LCD_SetPosition ( LINE_2 );
                printf ( LCD_PutChar, "Samples:  %lu", 256 *
read_eeprom ( SAMPLE_COUNT_HI ) + read_eeprom ( SAMPLE_COUNT_LO ) );
                delay_ms ( 2000 );
                LCD_PutCmd ( CLEAR_DISP );
                cMenuDecSwitchOn = NO;
                cSelIncSwitchOn = NO;
                cMenuState = STATE_START;    /* menu displays "LOG" */
                break;
                }
            }
        case ( STATE_RANGE ):
            {
            if ( cSelectFlag == ON )    /* if switch is pressed */
                {
                cSelectFlag = OFF;         /* turn flag off */
                LCD_PutCmd ( CLEAR_DISP );
                LCD_SetPosition ( LINE_2 + 0 );
                printf ( LCD_PutChar, "CHANGE    Return" );
                LCD_SetPosition ( LINE_1 + 7 );
                SetRange ( YES );         /* set range, display */
                while ( TRUE )
                    {
                    if ( cSelIncSwitchOn == YES )
                        {
                        cSelIncSwitchOn = NO;
                    break;
                        }
                    if ( cMenuDecSwitchOn == YES )
                        {
                        cMenuDecSwitchOn = NO;
                        if ( ++cRange >= 2 )       /* increment and
wrap */
                            {
                            cRange = 0;
                            }
                        LCD_SetPosition ( LINE_1 + 7 );
                        SetRange ( YES );         /* set range,
display */
                        }
                    }
                write_eeprom ( RANGE, cRange );    /* save range */
                cMenuState = STATE_START;          /* menu displays
"START" */
                break;
                }
            }
        case ( STATE_INTERVAL ):
            {
            if ( cSelectFlag == ON )    /* if switch is pressed */
                {
                cSelectFlag = OFF;         /* turn flag off */
                LCD_PutCmd ( CLEAR_DISP );
                LCD_SetPosition ( LINE_1 );
                printf ( LCD_PutChar, "Presently %05lus",
iIntervalTrigger );
                LCD_SetPosition ( LINE_2 + 0 );
                printf ( LCD_PutChar, "DIGIT 00000s INC" );
                cX = LINE_2 + 6;        /* point to beginning of zeros
*/
                LCD_SetPosition ( cX );
                LCD_PutCmd ( 0x0E );    /* display ON, cursor on, no
blink */
                cDigit = 0;
                cDigitPointer = 0;
                iX = 0;
                iPlace = 10000;
                while ( TRUE )
                    {
                    if ( cSelIncSwitchOn == YES )
                        {
                        if ( ++cDigit > 9 )       /* increment digit
*/
                            {
                            cDigit = 0;     /* roll */
                            }
                        cSelIncSwitchOn = NO;
                        cSelIncSwitchOn = NO;
                        LCD_SetPosition ( cX + cDigitPointer );   /*
set cursor to this digit */
                        printf ( LCD_PutChar, "%u", cDigit );     /*
display the digit */
                        LCD_SetPosition ( cX + cDigitPointer );   /*
set cursor back to this digit */
                        }
                    if ( cMenuDecSwitchOn == YES )
                        {
                        cMenuDecSwitchOn = NO;
                        iX += cDigit * iPlace;   /* add in to total */
                        iPlace /= 10;         /* point to next place
value down */
                        cDigit = 0;      /* zero digit again */
                        if ( ++cDigitPointer == 5 ) /* point to next
digit */
                            {
                            break;
                            }
                        LCD_SetPosition ( cX + cDigitPointer );
                        }
                    }
                if ( iX != 0 )         /* if number was updated */
                   {
                   write_eeprom ( SAMPLE_INTERVAL_HI, iX / 256 );  /*
store high byte */
                   write_eeprom ( SAMPLE_INTERVAL_LO, iX % 256 );  /*
store low byte */
                   iIntervalTrigger = iX;       /* update interval */
                   }
                LCD_PutCmd ( 0x0E );    /* display ON, cursor off, no
blink */
                LCD_PutCmd ( CLEAR_DISP );
                cMenuState = STATE_START;    /* menu displays "LOG" */
                break;
                }
            }
        case ( STATE_VIEW ):
            {
            if ( cSelectFlag == ON )    /* if switch is pressed */
                {
                cSelectFlag = OFF;         /* turn flag off */
                iX = 0;        /* zero sample number */
                iY = ( read_eeprom ( SAMPLE_COUNT_HI ) * 256 ) +
read_eeprom ( SAMPLE_COUNT_LO );
                cRange =  read_eeprom ( RANGE );    /* used stored
range */
                LCD_PutCmd ( CLEAR_DISP );
                cDone = NO;
                if ( iY != 0 )           /* if any samples at all */
                    {
                    LCD_SetPosition ( LINE_1 );
                    printf ( LCD_PutChar, "#" );
                    LCD_SetPosition ( LINE_2 );
                    printf ( LCD_PutChar, "DEC BothDone INC" );
                    while ( cDone == NO )
                        {
                        LCD_SetPosition ( LINE_1 + 1 );
                        printf ( LCD_PutChar, "%04lu", iX );   /*
display sample number */
                        iPlace = ( read_ext_eeprom ( iX * 2 ) * 256 )
+ read_ext_eeprom ( ( iX * 2 ) + 1 );    /* retrieve data from EEPROM
*/
                        DisplayVolts ( iPlace, 10 );      /* display
data at position 7 */
                        while ( TRUE )
                            {
                            cViewing = ON;
                            if ( ( input ( MENU_DEC_SWITCH ) == LOW )
&& ( input ( SELECT_INC_SWITCH ) == LOW ) )
                                {
                                cDone = YES;
                                break;
                                }
                            if ( cMenuDecSwitchOn == YES )
                                {
                                cMenuDecSwitchOn = NO;
                                if ( iX-- == 0 )
                                    {
                                    iX = iY - 1;     /* roll negative
*/
                                    }
                                    break;
                                }
                            if ( cSelIncSwitchOn == YES )
                                {
                                cSelIncSwitchOn = NO;
                                if ( iX++ >= ( iY - 1 ) )
                                    {
                                    iX = 0;        /* roll positive */
                                    }
                                break;
                                }
                            }
                        cViewing = OFF;
                        }
                    }
                else
                    {
                    LCD_SetPosition ( LINE_1 );
                    printf ( LCD_PutChar, "No samples yet!" );
                    delay_ms ( 1000 );
                    }
                LCD_PutCmd ( CLEAR_DISP );
                cMenuState = STATE_START;    /* menu displays "LOG" */
                break;
                }
            }
        case ( STATE_DUMP ):
            {
            if ( cSelectFlag == ON )    /* if switch is pressed */
                {
                cSelectFlag = OFF;         /* turn flag off */
                iY = ( read_eeprom ( SAMPLE_COUNT_HI ) * 256 ) +
read_eeprom ( SAMPLE_COUNT_LO );     /* get number of samples */
                cRange =  read_eeprom ( RANGE );    /* used stored
range */
                LCD_PutCmd ( CLEAR_DISP );
                cDone = NO;
                if ( iY != 0 )           /* if any samples at all */
                    {
                    LCD_SetPosition ( LINE_1 + 0 );
                    printf ( LCD_PutChar, "Dump 9600-8-N-1 " );
                    LCD_SetPosition ( LINE_2 );
                    printf ( LCD_PutChar, "   Both=Stop    " );
                    disable_interrupts ( GLOBAL );  /* turn off during
async */
                    printf ( "rnrn   Sample interval -- %lu
seconds", 256 * read_eeprom ( SAMPLE_INTERVAL_HI ) + read_eeprom (
SAMPLE_INTERVAL_LO ) );
                    printf ( "rn   Number of samples- %lu", iY );
                    printf ( "rnrnSampletVolts" );
                    printf ( "rn------t-----rn" );
                    for ( iX = 0; iX < iY; iX++ )
                        {
                        if ( ( input ( MENU_DEC_SWITCH ) == LOW ) && (
input ( SELECT_INC_SWITCH ) == LOW ) )
                            {
                            cDone = YES;
                            break;
                            }
                        iVal = ( read_ext_eeprom ( iX * 2 ) * 256 ) +
read_ext_eeprom ( ( iX * 2 ) + 1 );  /* get sample data */
                        if ( iVal == 0x3FF )
                            {
                            printf ( "%lutO/Lrn", iX ); /*
out-of-range */
                            }
                        else
                            {
                            printf ( "%lut%1.2frn", iX, ScaleAdc (
iVal ) ); /* send data sample */
                            }
                        delay_ms ( 1 );     /* avoids text glitches in
output stream */
                        }
                    enable_interrupts ( GLOBAL );  /* turn on again */
                    }
                else
                    {
                    LCD_SetPosition ( LINE_1 );
                    printf ( LCD_PutChar, "No samples yet!" );
                    delay_ms ( 1000 );
                    }
                delay_ms ( 1000 );      /* allow time to view 9600
baud msg, etc. */
                LCD_PutCmd ( CLEAR_DISP );
                cMenuState = STATE_START;    /* menu displays "LOG" */
                break;
                }
            }
        }
    }

void PrintMenu ( void )
    {
    LCD_SetPosition ( LINE_1 + 15 );
    if ( cLogging == NO )       /* if not logging at this time */
        {
        printf ( LCD_PutChar, " " );    /* blank symbol */
        }
    else                    /* if presently logging */
        {
        if ( cLoggingIndicatorFlag == ON )  /* turned on once per
second by interrupt */
            {
            cToggleFlag ^= 1;              /* toggle the symbol */
            if ( cToggleFlag == 1 )
                {
                printf ( LCD_PutChar, "%c", 255 );  /* symbol */
                }
            else
                {
                printf ( LCD_PutChar, " " );    /* blank */
                }
            cLoggingIndicatorFlag = OFF;
            }
        }
    LCD_SetPosition ( LINE_2 + 0 );
    switch ( cMenuState )
        {
        case STATE_START:
            {
            if ( cLogging == YES )      /* don't display while logging
*/
                {
                cMenuState++;   /* point to next menu */
                break;
                }
            printf ( LCD_PutChar, "Next       START" );
            break;
            }
        case STATE_STOP:
            {
            if ( cLogging == NO )      /* don't display if not logging
*/
                {
                cMenuState++;   /* point to next menu */
                break;
                }
            printf ( LCD_PutChar, "#%04lu", iSampleCount );
            LCD_SetPosition ( LINE_2 + 11 );
            printf ( LCD_PutChar, " STOP" );
            break;
            }
        case STATE_INTERVAL:
            {
            if ( cLogging == YES )      /* prevent changing while
logging */
                {
                cMenuState++;   /* point to next menu */
                break;
                }
            printf ( LCD_PutChar, "Next    INTERVAL" );
            break;
            }
        case STATE_STATUS:
            {
            printf ( LCD_PutChar, "Next      STATUS" );
            break;
            }
        case STATE_VIEW:
            {
            printf ( LCD_PutChar, "Next        VIEW" );
            break;
            }
        case STATE_DUMP:
            {
            printf ( LCD_PutChar, "Next      UPLOAD" );
            break;
            }
        case STATE_RESET:
            {
            if ( cLogging == YES )      /* prevent changing while
logging */
                {
                cMenuState++;   /* point to next menu */
                break;
                }
            printf ( LCD_PutChar, "Next       RESET" );
            break;
            }
        case STATE_RANGE:
            {
            if ( cLogging == YES )      /* prevent changing while
logging */
                {
                cMenuState++;   /* point to next menu */
                break;
                }
            printf ( LCD_PutChar, "Next       RANGE" );
            break;
            }
        }
    if ( cAdcFlag == ON )                    /* if interrupt signalled
an ADC reading */
        {
        DisplayVolts ( read_adc(), 5 );      /* read ADC, send raw
data to display routine at position 3 */
        cAdcFlag = OFF;
        }
    }

void SetRange ( BYTE cDisplay )
    {
    switch ( cRange )
        {
    case ( 0 ):         /* if 5V range */
            {
            output_float ( RANGE_SHUNT );      /* open shunt pulldown
*/
            if ( cDisplay == YES )
                {
            printf ( LCD_PutChar, "5V " );     /* 5V scale */
            }
            break;
        }
    case ( 1 ):         /* if 14V range */
            {
            output_low ( RANGE_SHUNT );        /* pull shunt resistor
down */
            if ( cDisplay == YES )
                {
            printf ( LCD_PutChar, "14V" );     /* 14V scale */
            }
            break;
        }
    default:            /* anything else is 5V range */
            {
            output_float ( RANGE_SHUNT );      /* open shunt pulldown
*/
            if ( cDisplay == YES )
                {
            printf ( LCD_PutChar, "5V " );     /* 5V scale */
            }
            break;
            }
        }
    }

void CheckSample ( void )
    {
    long iVal;

    if ( cSampleFlag == ON )     /* if time to sample */
        {
        if ( iSampleCount >= ( EEPROM_BYTE_SIZE / 2 ) )  /* at end of
memory */
            {
            cLogging = NO;       /* stop any further logging */
            write_eeprom ( LOGGING_STATE, NO );
            cMenuState = STATE_STATUS;     /* display status menu next
*/
            }
        else
            {
            iVal = read_adc();
        /*    iVal = iSampleCount;   only for testing */
            write_ext_eeprom ( iSampleCount * 2, iVal / 256 );   /*
write high data to external EEPROM */
            write_ext_eeprom ( ( iSampleCount * 2 ) + 1, iVal % 256 );
  /* write low data */
            iSampleCount++;             /* point to next memory
location */
            write_eeprom ( SAMPLE_COUNT_HI, ( char ) ( iSampleCount /
256 ) );    /* save sample count to internal EEPROM */
            write_eeprom ( SAMPLE_COUNT_LO, ( char ) ( iSampleCount %
256 ) );
            }
        cSampleFlag = OFF;       /* reset flag, interrupt turns on
again later */
        }
    }

void init_ext_eeprom ( void )
    {
    output_float ( EEPROM_SCL );
    output_float ( EEPROM_SDA );
    }

void write_ext_eeprom ( long int lngAddress, BYTE intData )
    {
    i2c_start();
    i2c_write ( 0xa0 );  /* set up for writing address and data, chip
address 000 */
    i2c_write ( hi ( lngAddress ) );      /* write high address */
    i2c_write ( lngAddress );      /* write low address */
    i2c_write ( intData );                        /* write data */
    i2c_stop();
    delay_ms ( 11 );
    }

BYTE read_ext_eeprom ( long int lngAddress )
    {
    BYTE intData;

    i2c_start();
    i2c_write ( 0xa0 );   /* set up for writing address, chip address
000 */
    i2c_write ( hi ( lngAddress ) );      /* write high address */
    i2c_write ( lngAddress );      /* write low address */
    i2c_start();
    i2c_write ( 0xa1 );   /* set up for reading data, chip address 000
*/
    intData = i2c_read ( 0 );                     /* read data */
    i2c_stop();
    return ( intData );
    }

char GetEchoNumChar ( void )
    {
    char cX;

    while ( TRUE )
        {
       // cX = getc();                    /* wait for character */
       cX = GETC();
        if ( ( cX >= '0' ) && ( cX <= '9' ) )   /* check bounds */
            {
            break;
            }
        }
    PUTC ( cX );                                /* echo to screen */
    return ( cX - 0x30 );                       /* adjust to numeric
*/
    }

void DisplayVolts ( long iAdcValue, char cLoc )
    {
    LCD_SetPosition ( LINE_1 + cLoc );
    if ( iAdcValue == 0x3FF )
        {
        printf ( LCD_PutChar, " O/L     " );    /* out of range */
        }
    else
        {
        printf ( LCD_PutChar, "%2.2fV ", ScaleAdc ( iAdcValue ) ); /*
display data sample */
        }
    }

float ScaleAdc ( long iValue )
    {
    float fScale;

    switch ( cRange )
        {
        case ( 0 ):
            {
            fScale = 5;     /* 5V scale */
            break;
            }
        case ( 1 ):
            {
            fScale = 14;     /* 14V scale */
            break;
            }
        case ( 2 ):
            {
            fScale = 5;     /* 5V scale */
            break;
            }
        case ( 3 ):
            {
            fScale = 5;     /* 5V scale */
            break;
            }
        }
    return ( ( float ) iValue / 1023 * fScale );   /* scale to proper
range, 1023 leaves room for out-of-range */
    }

void LCD_Init ( void )
    {
    LCD_SetData ( 0x00 );
    delay_ms ( 200 );       /* wait enough time after Vdd rise */
    output_low ( LCD_RS );
    LCD_SetData ( 0x03 );   /* init with specific nibbles to start
4-bit mode */
    LCD_PulseEnable();
    LCD_PulseEnable();
    LCD_PulseEnable();
    LCD_SetData ( 0x02 );   /* set 4-bit interface */
    LCD_PulseEnable();      /* send dual nibbles hereafter, MSN first
*/
    LCD_PutCmd ( 0x2C );    /* function set (all lines, 5x7
characters) */
    LCD_PutCmd ( 0x0C );    /* display ON, cursor off, no blink */
    LCD_PutCmd ( 0x01 );    /* clear display */
    LCD_PutCmd ( 0x06 );    /* entry mode set, increment */
    }

void LCD_SetPosition ( unsigned int cX )
    {
    /* this subroutine works specifically for 4-bit Port A */
    LCD_SetData ( swap ( cX ) | 0x08 );
    LCD_PulseEnable();
    LCD_SetData ( swap ( cX ) );
    LCD_PulseEnable();
    }

void LCD_PutChar ( unsigned int cX )
    {
    /* this subroutine works specifically for 4-bit Port A */
    output_high ( LCD_RS );
    LCD_SetData ( swap ( cX ) );     /* send high nibble */
    LCD_PulseEnable();
    LCD_SetData ( swap ( cX ) );     /* send low nibble */
    LCD_PulseEnable();
    output_low ( LCD_RS );
    }

void LCD_PutCmd ( unsigned int cX )
    {
    /* this subroutine works specifically for 4-bit Port A */
    LCD_SetData ( swap ( cX ) );     /* send high nibble */
    LCD_PulseEnable();
    LCD_SetData ( swap ( cX ) );     /* send low nibble */
    LCD_PulseEnable();
    }

void LCD_PulseEnable ( void )
    {
    output_high ( LCD_EN );
    delay_us ( 10 );
    output_low ( LCD_EN );
    delay_ms ( 5 );
    }

void LCD_SetData ( unsigned int cX )
    {
    output_bit ( LCD_D0, cX & 0x01 );
    output_bit ( LCD_D1, cX & 0x02 );
    output_bit ( LCD_D2, cX & 0x04 );
    output_bit ( LCD_D3, cX & 0x08 );
    }


Re: Software for PIC 16F876

> Hello,
> I want to built a simple datalogger with a PIC 16F876, and found a
> nice schema
> on the net.
> My problem: te software (source) is written in "C", but i need a hex
> files to program the PIC processor. I have playing with JAL, but i
> have not a "C" knowledge. Can someone help me, and "translate" the C
> to hex ?
>
> Thanks
>
< SNIP SOURCE CODE >

Hello,

You can download a free PIC C compiler from here:

http://www.htsoft.com/products/PICClite.php

It does have some restrictions, but it's okay for most projects.  I'm not
sure if it supports the PIC16F876 though.  If it doesn't, then you will need
to consider a different PIC.  The PIC16F877 is supported and should be
capable of doing whatever the PIC16F876 is doing.  Although the pin numbers
of the 2 pics is different.  The PIC16F877 has 40 pins and has more I/O
ports than the PIC16F876.  You'll have to check the data sheets, but the pin
names should be the same for both devices.

The C compiler should have some tutorials with it, which will tell you how
to produce the hex file.  You can also find plenty of online tutorials.
It's pretty straightforward to produce the hex file once you have the source
code.

Good luck,

Craig
Homepage: http://www.craigsarea.com





Site Timeline