//// 16F877A_AD_to_rs232_LCD_i2c5.c //// //// read AtoD 0,1,2 and print values by rs232 //// //// also print to LCD and send data to Slug when requested by i2c //// //--------------------------------------------------------------------------- // program PIC_i2c sends a string of data bytes - these are:- // 1 - 80 (decimal address of the PIC - Linux version) // 2 - StartPoint - save data starting at buf[StartPoint] // - - now send the data bytes - - // 3 - Master sends value of x when requesting 2 byte AtoD value // 4 - command byte - makes PIC change the display 0=main 1=admin // 5 - bytes 5 to 7 are for future use // 6 // 7 // 8 // eg ./PIC_i2c 80 0 0 0 0 0 0 0 - see admin page // ./PIC_i2c 80 0 0 1 0 0 0 0 - see temperatures as -2.5,12.5 etc //-------------------------------------------------------------------------- // these are my settings in Flex_LCD420.c // #define LCD_DB4 PIN_B4 // #define LCD_DB5 PIN_B5 // #define LCD_DB6 PIN_B6 // #define LCD_DB7 PIN_B7 // #define LCD_RS PIN_B3 // //#define LCD_RW PIN_B0 (this is earthed - no read from LCD) // #define LCD_E PIN_B2 //-------------------------------------------------------------------------- // PORTC.4 [RC4] -> I2C SDA (I2C Serial Data) // PORTC.3 [RC3] -> I2C SCL (I2C Serial Clock) // i2c address set here is 0xA0 - it becomes 0x50 (dec 80) on the Slug // - Linux puts a 0 before the PIC address and removes one at the end //-------------------------------------------------------------------------- #include <16F877A.h> #device ADC=16 #fuses HS,NOWDT,NOPROTECT,NOLVP #use delay(clock=20000000) #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7) #use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0xA0, FORCE_HW) //I2C by Hardware,i2c address (dec 80)is the first byte from the master #include //the general purpose LCD display driver BYTE incoming, state; // receive string of up to 127 bytes on the i2c line BYTE StartPoint ; // Load data from master starting at buf[StartPoint] //StartPoint is the second byte in the string from the master int8 buf[8]={0,0,0,0,0,0,0,0}; //we could make this longer in future // the string of data bytes received from the master is stored in buf[] // starting at buf[StartPoint]. // Prog PIC_i2c sends - then 5 bytes // that are stored at a location in the array buf[] starting at buf[StartPoint] // PIC_i2c could be modified to send up to 125 data bytes per run to master int16 buffer[8]; //Array of 2 byte Int16s that are copies of the buf (int8) data int8 i;//for a count int8 x;//used by master to count up the Val10Bit[] array long value[8];//AtoD values from the PIC AtoD pins (values 0-65472) long Val10Bit[8];// create a (0 to 1023) value from value[8] float Temperature[8];//use for decimal representation of temperatures int8 TempByte[8]={91,92,93,94,95,96,97,98}; // data is stored here ready for sending to the master //0 is -10 degrees, 100 is 40 degrees (byte to send to Slug) //about 2 units on the A/D (0to1023) are equivalent to 1 degree C //==============================================================i2c routine #INT_SSP void ssp_interupt () { state = i2c_isr_state(); //i2c event caused by master interrups the PIC and state says //if the master is requesting or sending data if(state < 0x80) //Master is sending data { if(state == 0) { } if(state == 1) //First received byte is StartPoint { incoming = i2c_read(); StartPoint = incoming; } for(i=0; i<=8; ++i) //(start at 2, 125 vaues maximum) { if(state == (i+2)) // state increments as each data byte comes in { incoming = i2c_read(); buf[StartPoint+i] = incoming; buffer[StartPoint+i] = (long)buf[StartPoint+i]; //int16 needed later } } } if(state == 0x80) //Master is requesting data from the PIC { x = buf[StartPoint]; //send the temperature asked for // The first byte from the master (stored at buf[StartPoint]) increments // on each of master's repeated request for data and forces the PIC to scan up // the TempByte[] array and send to master the byte stored there for(i=0; i<=6; i=i+2) //send master AtoD long values as LO byte then HI byte { if (x==i) { i2c_write (Val10Bit[i/2]); } if (x==i+1) { i2c_write (Val10Bit[i/2]>>8);//bit shift HI byte to LO byte position } } if (x>=6) { i2c_write (99);//change later } //------------------------ } } //====================================================================main void main() { int8 i; lcd_init(); enable_interrupts(INT_SSP); enable_interrupts(GLOBAL); delay_ms(200); // power up delay printf(lcd_putc, "\f"); //clear screen delay_ms(500); lcd_putc("\fWelcome! . . .\n"); // first display delay_ms(2000); setup_port_a( ALL_ANALOG ); setup_adc( ADC_CLOCK_INTERNAL ); do { for(i=0; i<=2; ++i) //read PIC AtoD lines 0,1 and 2 { set_adc_channel( i ); delay_ms(100); value[i] = Read_ADC(); //comes in as 0-65472 Val10Bit[i] = value[i]/64; // value now 0-1023 //master is sent 0 to 100 meaning -10 to +40 degrees if (Val10Bit[i]>=640) //-10 to +40 degrees is 540 to 640 approx TempByte[i] = 100; //we send this temperature byte to the Slug if (Val10Bit[i]<=540) TempByte[i] = 0; if ((Val10Bit[i] > 540) && (Val10Bit[i] < 640)) TempByte[i] = Val10Bit[i] - 540; Temperature[i] = TempByte[i]; Temperature[i] = Temperature[i] - 20; Temperature[i] = Temperature[i]/2; } //==========================================================rs232 display // un-comment next line to get a report on the rs232 port // printf("Value 0: %Lu Value 1: %Lu Value 2: %Lu\n\r",(value[0]/64), (value[1]/64), (value[2]/64)); //============================================================LCD display printf(lcd_putc, "\f");//clear screen delay_ms(5); //buf[StartPoint + 1] is the command byte from the master if(buf[StartPoint + 1] == 0) { for(i=0; i<=2; ++i) //print raw AtoD values { lcd_gotoxy((1+5*i),1); printf(lcd_putc, "%Lu ", Val10Bit[i]); } lcd_gotoxy(1,2); printf(lcd_putc, "0=%u 1=%u 2=%u ", TempByte[0],TempByte[1],TempByte[2]); lcd_gotoxy(1,3); printf(lcd_putc, "StPt %u x %u Cmd %u", StartPoint, buf[StartPoint], buf[StartPoint+1]); for(i=0; i<=3; ++i) //print raw AtoD values { lcd_gotoxy((1+4*i),4); printf(lcd_putc, "%u ", buf[StartPoint+2+i]); } delay_ms(100); } if(buf[StartPoint + 1] == 1) { lcd_gotoxy(1,2); printf(lcd_putc, "Temperature 0 %2.1g",Temperature[0]) ; lcd_gotoxy(1,3); printf(lcd_putc, "Temperature 1 %2.1g",Temperature[1]) ; lcd_gotoxy(1,4); printf(lcd_putc, "Temperature 2 %2.1g",Temperature[2] ); delay_ms(100); } if(buf[StartPoint + 1] >= 2) { lcd_gotoxy(1,2); printf(lcd_putc, "invalid command"); } } while (TRUE); }