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 #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
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