[fpc-pascal] FPC/Lazarus on RPi4 - How to read/write I2C connected EEPROM?

Christo Crause christo.crause at gmail.com
Wed Apr 5 17:57:00 CEST 2023

On Wed, Apr 5, 2023 at 12:43 PM Bo Berglund via fpc-pascal <
fpc-pascal at lists.freepascal.org> wrote:

> On Wed, 5 Apr 2023 11:40:09 +0200, Christo Crause via fpc-pascal
> <fpc-pascal at lists.freepascal.org> wrote:
> >Looking at the datasheet for CAT24C128, Fig. 6 Byte Write Sequence, shows
> >no repeated start condition between register address and data bytes. I
> >suspect that the second i2c message should contain the I2C_M_NOSTART flag,
> >else the address and data parts of the transaction will be separated by a
> >repeated start signal. I have modified the WriteBytesToReg methods in
> >i2c.pas, please feel free to pull from Github and test this again.

I tested the i2c code with a PCA9685 IC.  It also supports multi-byte
writes, although it only has 8 bit register addresses.  I realised that my
original code used two i2c transactions and that each transaction starts
with sending the device address.  The multibyte write obviously doesn't
work like this, so I changed the WriteBytesToReg methods (in i2c.pas) to
combine the register address and data into one buffer, which is then
transmitted using the WriteBytes method.

This was tested and confirmed when writing 4 bytes to sequential registers
to a PCA9685 IC with the new WriteBytesToReg method (

Only the WriteBytesToReg for 16 bit register addresses are now untested,
although it follows a similar pattern so I have a reasonable expectation
that it should work.

If this update still doesn't work, I will need a logic analyser trace of an
i2c write transaction that is successful (say using i2ctrace) and one which
is unsuccessful using TI2cMaster.WriteBytesToReg.  Or I need to find a
similar EEPROM to test...

Thanks, I did so and used it in my code but it still does not write the
> Here is the code I use to test (in a command line program), maybe you can
> see a
> usage problem?
> var
>   i2cbus,
>   dev_addr,
>   reg_addr,
>   data_cnt: integer;
>   indata: TBytes;
> procedure main_12c_write(); //This is the main application procedure
> var
>   i: integer;
>   num: uint16;
>   i2cEeprom: TI2c_eeprom;
> begin
>   processInputs; //Read command line and write to variables
>   //Now process the data towards the EEPROM
>   i2cEeprom := TI2c_eeprom.Create; //Defaults are set for my EEPROM
>   try
>     num := i2cEeprom.WriteData(reg_addr, data_cnt, indata);
>     Writeln('Wrote ' + IntToStr(num) + ' bytes to address $' +
> IntToHex(reg_addr,4) );
>   finally
>     i2cEeprom.Free;
>   end;
> function TI2c_eeprom.WriteData(StartAddress, NumBytes: uint16; Source:
> TBytes):
> uint16;
> var
>   endpos, capacity, addr: uint16;
>   i2cMaster: TI2cMaster;
>   i2cbus: TI2CBus;
>   sourcelen, i, j: integer;
>   pSource: PByte;
> begin
>   Result := 0;
>   //Check valid indata:
>   //snip....
>   //Prepare the handler for action...
>   i2cbus := TI2CBus(FI2cBusNo);
>   i2cMaster := TI2cMaster.Create;
>   try
>     if not i2cMaster.Initialize(i2cbus) then
>     begin
>       writeln('Error opening i2c device: ', FI2cBusNo);
>       exit;
>     end;
>     //Check if data will fit into a single page start at given address:
>     if ((StartAddress and $ffc0) = (endpos and  $ffc0)) then //Fits in page
>     begin
>       //Perform a single write cycle into the buffer
>       pSource := @source[0];
>       if not i2cMaster.WriteBytesToReg(FEEPROMAddr, startaddress, pSource,
> NumBytes) then
>       begin
>         Writeln('Error: Could not write to I2C device!');
>         exit;
>       end
>       else
>         Result := NumBytes;
>     end
>     else  //We need to split data over several commands
>     begin
>       Writeln('Not yet implmented data split into several writes');
>     end;
>   finally
>     i2cMaster.Free;
>   end;

The use of WriteBytesToReg in the TI2c_eeprom.WriteData method seems fine,
perhaps retest with the updated WriteBytesToReg method.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-pascal/attachments/20230405/ff41efb2/attachment.htm>

More information about the fpc-pascal mailing list