//// 16F877A_AD_to_rs232_LCD_i2c5b.c //// //// read AtoD 0-7 and print values by rs232 //// //// switch lines D0,1,2,3 read line states D4,5,6,7 //// //// print to text 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 - x value - used to choose which data to read from Val10Bit[0 -15] // x = 0,2,4 to read from DtoA 0,1,2 // - - now send the data bytes - - // 3 - command byte - makes PIC change the display 0=main 1=admi // 4 - switch line D0 - 0 off, 1 on // 5 - switch line D1 // 6 - switch line D2 // 7 - switch line D3 // eg ./PIC_i2c 80 0 0 0 0 0 0 0 - read AD0 - see admin page // ./PIC_i2c 80 4 0 1 0 0 0 0 - read AD2 - 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 #define GP0 PIN_D0 //set port D to GPIO 0-3 used as outputs #define GP1 PIN_D1 #define GP2 PIN_D2 #define GP3 PIN_D3 #define GP4 PIN_D4 //4-7 used as inputs #define GP5 PIN_D5 #define GP6 PIN_D6 #define GP7 PIN_D7 BYTE incoming, state; // receive string of up to 127 bytes on the i2c line 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[0]. ] // PIC_i2c_one_value_a could be modified to send up to 125 data bytes int8 i;//for a count int8 x;//used by master to count up the Val10Bit[] array // x gets lo byte, x+1 gets hi byte - so x counts up in twos long value[8];//AtoD values from the PIC AtoD pins (comes in as values 0-65472) long Val10Bit[16];// create a (0 to 1023) value from value[8] // top end of array stores PORT D pin states float Temperature[8];//use for decimal representation of temperatures int8 TempByte[8]={91,92,93,94,95,96,97,98}; //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 i2c master interrups the PIC //"state" sets if the master is requesting or sending data if(state < 0x80) //Master is sending data { if(state == 0) { } } for(i=0; i<=8; ++i) { if(state == (i+1)) // state increments from 1 as each data byte comes in { incoming = i2c_read(); buf[i] = incoming; } } if(state == 0x80) //Master is requesting data from the PIC { x = buf[0]; //used to chose data site in array - 2 x values per double byte element //master send x then x+1 - not sure how to read a data stream???? for(i=0; i<=32; 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 } } } } //eg x=4 gets Val10Bit[2)lo byte, x=5 gets Val10Bit[2)hi byte //====================================================================main void main() { int8 i; lcd_init(); enable_interrupts(INT_SSP); enable_interrupts(GLOBAL); { for(i=0; i<=16; ++i) { Val10Bit[i] = i; } } 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<=7; ++i) //read PIC AtoD lines 0 to 7 { 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[1] is the command byte from the master if(buf[1] == 0) { for(i=0; i<=2; ++i) //print raw AtoD values to LCD { 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, "%Lu %Lu %Lu", Val10Bit[0],Val10Bit[1],Val10Bit[2]); lcd_gotoxy(1,4); printf(lcd_putc, "%u %u %u %u %u %u", buf[0],buf[1],buf[2],buf[3],buf[4],buf[5]); delay_ms(100); } if(buf[1] == 1) //show temperatures { 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); } // Switch PIC lines D0/1/2/3 depending on Slug i2c command bytes 3/4/5/6 { if (buf[2] == 1) output_high (GP0); else output_low (GP0); } { if (buf[3] == 1) output_high (GP1); else output_low (GP1); } { if (buf[4] == 1) output_high (GP2); else output_low (GP2); } { if (buf[5] == 1) output_high (GP3); else output_low (GP3); } // port D 4,5,6,7 are inputs - store 0 or 1 in Val10Bit[8,9,10,11] - ignore hi byte on read { if (!input (GP4)) Val10Bit[8] = 1; else Val10Bit[8] = 0; } { if (!input (GP5)) Val10Bit[9] = 1; else Val10Bit[9] = 0; } { if (!input (GP6)) Val10Bit[10] = 1; else Val10Bit[10] = 0; } { if (!input (GP7)) Val10Bit[11] = 1; else Val10Bit[11] = 0; } } while (TRUE); }