Connect with us

Software for PIC 16F876

Discussion in 'Electronic Basics' started by Frits, Nov 25, 2004.

Scroll to continue with content
  1. Frits

    Frits Guest

    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 ADC=10
    #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 ( clock=4000000 )
    #use standard_io ( A )
    #use standard_io ( B )
    #use standard_io ( C )
    #use rs232 ( baud=9600, xmit=PIN_B3 )
    #use i2c ( master, scl=EEPROM_SCL, sda=EEPROM_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 ( "\r\n\r\n Sample interval -- %lu
    seconds", 256 * read_eeprom ( SAMPLE_INTERVAL_HI ) + read_eeprom (
    SAMPLE_INTERVAL_LO ) );
    printf ( "\r\n Number of samples- %lu", iY );
    printf ( "\r\n\r\nSample\tVolts" );
    printf ( "\r\n------\t-----\r\n" );
    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 ( "%lu\tO/L\r\n", iX ); /*
    out-of-range */
    }
    else
    {
    printf ( "%lu\t%1.2f\r\n", 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 );
    }
     
  2. Craig

    Craig Guest

    < 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
     
Ask a Question
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.
Electronics Point Logo
Continue to site
Quote of the day

-