A while back I was trying to help someone with a 24FC1025 and I was having problems with PBP I2C so I decided to work with the part the "old fashioned" way using SHIFTIN and SHIFTOUT. Turns out my problem was using an analog pin on the PIC without setting it to digital. Yes, a typical mistake, not always made by newbies.
Many devices are interfaced via I2C, they can also be interfaced via SHIFTIN/SHIFTOUT. Either way an understanding of the part is needed. That is where the data sheet comes in.
First, compare the two figures below. The fisrt one is from the PBP manual showing a time line of the SHIFT sequence. The second is from the EEPROM data sheet showing the data transfer sequence. Similar ???
From the data sheet look at figure 6.1. This shows the sequence of events to write a BYTE of data to the EEPROM.
The first thing we do is put the EEPROM in a START condition. This is done by holding the EEPROM clock pin HIGH and toggleing the data pin High to LOW. The I2C command does this for us.
HIGH CPIN:HIGH DPIN:LOW DPIN
Bits 7-4 are the control code for this EEPROM. "1010"
Bit 3 is is for selecting the memory block, this EEPROM is divided into to parts. This example is using the lower half. "0"
Bits 2-1 are for addressing. Up to four EEPROM can be used on the same bus. In this example both pins A1 and A2 are pulled LOW. "00"
Bit 0 selects Read or Write mode. "0" for Write, "1" for Read. PBP's I2C command will set this bit for us, leave as "0"
When the EEPROM receives the control byte it will then send an ACKnowledge bit to the MCU. Then the High byte of the EEPROM address can be sent, this will be followed by another ACK from the EEPROM. The LOW byte of the address is sent next, with the EEPROM sending an ACK again.
In the below code the above is all in the "INT_ROM:" routine. PBP I2C will take care of the ACKs.
Now a BYTE of data can be sent to the EEPROM, when the data is received by the EEPROM it will send an ACK to the MCU. The MCU will then send a STOP condition to the EEPROM letting it know to start writing the data. Again, the I2C command does this for us.
HIGH CPIN:LOW DPIN:HIGH DPIN
Part #2 will talk about WORD and page writes to the EEPROM.
' 18F6680 24FC1025 '912 BYTES DEFINE OSC 20 @ __CONFIG _CONFIG1H, _OSC_HS_1H @ __CONFIG _CONFIG2H, _WDT_OFF_2H & _WDTPS_128_2H @ __CONFIG _CONFIG4L, _LVP_OFF_4L DEFINE LCD_DREG PORTG define LCD_DBIT 0 DEFINE LCD_RSREG PORTE DEFINE LCD_RSBIT 0 DEFINE LCD_EREG PORTE DEFINE LCD_EBIT 1 DEFINE LCD_BITS 4 DEFINE LCD_LINES 4 DEFINE LCD_COMMANDUS 3000 DEFINE LCD_DATAUS 150 DPIN VAR PORTB.2 'I2C DATA PIN CPIN VAR PORTB.1 'I2C CLOCK PIN ADDR VAR WORD DATI VAR BYTE DATO VAR BYTE START2: ADDR = 0 : DATO = 0 For ADDR = 0 To 15 DATO = DATO + 2 I2CWRITE DPIN,CPIN,$A0,ADDR,[DATO] Pause 10 Next ADDR Pause 100 ADDR = 0 For ADDR = 0 To 15 I2CREAD DPIN,CPIN,$A0,ADDR,[DATI] lcdout $FE,1,"DATI ",DEC DATI lcdout $FE,$C0,"ADDR ",DEC ADDR PAUSE 250 Next ADDR GOTO START2
' 18F6680 24FC1025 '1216 BYTES DEFINE OSC 20 @ __CONFIG _CONFIG1H, _OSC_HS_1H @ __CONFIG _CONFIG2H, _WDT_OFF_2H & _WDTPS_128_2H @ __CONFIG _CONFIG4L, _LVP_OFF_4L DEFINE LCD_DREG PORTG define LCD_DBIT 0 DEFINE LCD_RSREG PORTE DEFINE LCD_RSBIT 0 DEFINE LCD_EREG PORTE DEFINE LCD_EBIT 1 DEFINE LCD_BITS 4 DEFINE LCD_LINES 4 DEFINE LCD_COMMANDUS 3000 DEFINE LCD_DATAUS 150 DPIN VAR PORTB.2 'I2C DATA PIN CPIN VAR PORTB.1 'I2C CLOCK PIN ADDR_HB VAR BYTE ADDR_LB VAR BYTE ADDR_HB = 0 ADDR_LB = 0 CONT1 CON %10100001 'READ CONTROL CONT0 CON %10100000 'WRITE CONTROL ACK VAR BIT DATI VAR BYTE DATO VAR BYTE START: DATO = 0 WRITE_DATA: For ADDR_LB = 1 To 15 DATO = DATO + 2 GOSUB INT_ROM SHIFTOUT DPIN,CPIN,1,[DATO\8,%1\1] GOSUB STOP_ROM PAUSE 10 NEXT ADDR_LB READ_DATA: For ADDR_LB = 0 To 15 GOSUB INT_ROM GOSUB START_ROM SHIFTOUT DPIN,CPIN,1,[CONT1] SHIFTIN DPIN,CPIN,0,[ACK\1,DATI\8] SHIFTOUT DPIN,CPIN,1,[%1\1] GOSUB STOP_ROM lcdout $FE,1,"DATI ",DEC DATI lcdout $FE,$C0,"ADDR ",DEC ADDR_LB PAUSE 250 NEXT ADDR_LB GOTO START INT_ROM: GOSUB START_ROM SHIFTOUT DPIN,CPIN,1,[CONT0] SHIFTIN DPIN,CPIN,0,[ACK\1] SHIFTOUT DPIN,CPIN,1,[ADDR_HB] SHIFTIN DPIN,CPIN,0,[ACK\1] SHIFTOUT DPIN,CPIN,1,[ADDR_LB] SHIFTIN DPIN,CPIN,0,[ACK\1] RETURN START_ROM: HIGH CPIN:HIGH DPIN:LOW DPIN:RETURN STOP_ROM: HIGH CPIN:LOW DPIN:HIGH DPIN:RETURN
Re: K42 and Timer Interrupts
Thanks for the explanation.
Ioannis - 28th April 2025, 19:28I misinterpreted these paragraphs. My understanding was to have ASYNC cleared and use Fosc/4.
Ioannis