I2C hard-coded for Raspberry Pi Rev 2

1,920 views
Skip to first unread message

Arvi

unread,
Mar 2, 2013, 10:45:33 PM3/2/13
to bcm...@googlegroups.com
I am a pretty basic RPi tinkerer - just wanted to share this with somebody who might encounter the same thing. 

I wanted to use this great library for I2C communication on my Rev 1 RPi. Took me a while to figure out that it wouldn't work because the library is written for the Rev 2 version of the RPi. I made the required modifications to the source to change the BSC controller from 1 to 0 (in all the I2C related functions) - works great after re-compilation. Here is the modified code:

void bcm2835_i2c_begin(void)
{
volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_DIV/4;

    // Set the I2C/BSC0 pins to the Alt 0 function to enable I2C access on them
    bcm2835_gpio_fsel(RPI_GPIO_P1_03, BCM2835_GPIO_FSEL_ALT0); // SDA
    bcm2835_gpio_fsel(RPI_GPIO_P1_05, BCM2835_GPIO_FSEL_ALT0); // SCL

    // Read the clock divider register
    uint16_t cdiv = bcm2835_peri_read(paddr);
    // Calculate time for transmitting one byte
    // 1000000 = micros seconds in a second
    // 9 = Clocks per byte : 8 bits + ACK
    i2c_byte_wait_us = ((float)cdiv / BCM2835_CORE_CLK_HZ) * 1000000 * 9;
}

void bcm2835_i2c_end(void)
{
    // Set all the I2C/BSC0 pins back to input
    bcm2835_gpio_fsel(RPI_GPIO_P1_03, BCM2835_GPIO_FSEL_INPT); // SDA
    bcm2835_gpio_fsel(RPI_GPIO_P1_05, BCM2835_GPIO_FSEL_INPT); // SCL
}

void bcm2835_i2c_setSlaveAddress(uint8_t addr)
{
// Set I2C Device Address
volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_A/4;
bcm2835_peri_write(paddr, addr);
}

// defaults to 0x5dc, should result in a 166.666 kHz I2C clock frequency.
// The divisor must be a power of 2. Odd numbers
// rounded down.
void bcm2835_i2c_setClockDivider(uint16_t divider)
{
    volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_DIV/4;
    bcm2835_peri_write(paddr, divider);
    // Calculate time for transmitting one byte
    // 1000000 = micros seconds in a second
    // 9 = Clocks per byte : 8 bits + ACK
    i2c_byte_wait_us = ((float)divider / BCM2835_CORE_CLK_HZ) * 1000000 * 9;
}

// Writes an number of bytes to I2C
uint8_t bcm2835_i2c_write(const char * buf, uint32_t len)
{
    volatile uint32_t* dlen    = bcm2835_bsc0 + BCM2835_BSC_DLEN/4;
    volatile uint32_t* fifo    = bcm2835_bsc0 + BCM2835_BSC_FIFO/4;
    volatile uint32_t* status  = bcm2835_bsc0 + BCM2835_BSC_S/4;
    volatile uint32_t* control = bcm2835_bsc0 + BCM2835_BSC_C/4;

    uint32_t remaining = len;
    uint32_t i = 0;
    uint8_t reason = BCM2835_I2C_REASON_OK;

    // Clear FIFO
    bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 );
    // Clear Status
bcm2835_peri_write_nb(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE);
// Set Data Length
    bcm2835_peri_write_nb(dlen, len);
    // Enable device and start transfer
    bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST);

    while (!(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE))
    {
    while ((bcm2835_peri_read(status) & BCM2835_BSC_S_TXD) && remaining)
    {
        // Write to FIFO, no barrier
        bcm2835_peri_write_nb(fifo, buf[i]);
        i++;
        remaining--;
    }
    // When remaining data is to be send, then wait for an empty FIFO
    if (remaining >= BCM2835_BSC_FIFO_SIZE)
    delayMicroseconds(i2c_byte_wait_us * BCM2835_BSC_FIFO_SIZE);
    else
    delayMicroseconds(i2c_byte_wait_us * remaining);
    }

    // Received a NACK
    if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR)
    {
reason = BCM2835_I2C_REASON_ERROR_NACK;
    }

    // Received Clock Stretch Timeout
    else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT)
    {
reason = BCM2835_I2C_REASON_ERROR_CLKT;
    }

    // Not all data is sent
    else if (remaining)
    {
reason = BCM2835_I2C_REASON_ERROR_DATA;
    }

    bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE , BCM2835_BSC_S_DONE);

    return reason;
}

// Read an number of bytes from I2C
uint8_t bcm2835_i2c_read(char* buf, uint32_t len)
{
    volatile uint32_t* dlen    = bcm2835_bsc0 + BCM2835_BSC_DLEN/4;
    volatile uint32_t* fifo    = bcm2835_bsc0 + BCM2835_BSC_FIFO/4;
    volatile uint32_t* status  = bcm2835_bsc0 + BCM2835_BSC_S/4;
    volatile uint32_t* control = bcm2835_bsc0 + BCM2835_BSC_C/4;

    uint32_t remaining = len;
    uint32_t i = 0;
    uint8_t reason = BCM2835_I2C_REASON_OK;

    // Clear FIFO
    bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 );
    // Clear Status
bcm2835_peri_write_nb(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE);
// Set Data Length
    bcm2835_peri_write_nb(dlen, len);

    // Start read
    bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ);

    while (!(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE))
    {
    while (bcm2835_peri_read(status) & BCM2835_BSC_S_RXD)
    {
    // Read from FIFO, no barrier
    buf[i] = bcm2835_peri_read_nb(fifo);
        i++;
        remaining--;
    }
    // When remaining data is to be received, then wait for a fully FIFO
    if (remaining >= BCM2835_BSC_FIFO_SIZE)
    delayMicroseconds(i2c_byte_wait_us * BCM2835_BSC_FIFO_SIZE);
    else
    delayMicroseconds(i2c_byte_wait_us * remaining);
    }

    // Received a NACK
    if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR)
    {
reason = BCM2835_I2C_REASON_ERROR_NACK;
    }

    // Received Clock Stretch Timeout
    else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT)
    {
reason = BCM2835_I2C_REASON_ERROR_CLKT;
    }

    // Not all data is received
    else if (remaining)
    {
reason = BCM2835_I2C_REASON_ERROR_DATA;
    }

    bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE , BCM2835_BSC_S_DONE);

    return reason;
}

KarlS

unread,
Mar 6, 2013, 4:43:40 PM3/6/13
to bcm...@googlegroups.com
Hi Arvi:

I'm pretty sure my tinkering with the Raspi is even more basic than your's. I made the changes you suggested in the latest v1.22, compiled the library ... and still couldn't use I2C.

I’m using the library in a project that receives data from a weather station using a RFM01 receiver with SPI. This part works. Now I have added a BMP085 pressure module that uses I2C communication. SDA is connected to pin 3 and SCL to pin 5 of my rev.1 board. This simple test program never makes it past the  bcm2835_i2c_begin();

/*****************************************************************************
* File:           bmp085test.c
* Compiled with: gcc -o bmp085test bmp085test.c -l bcm2835
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <bcm2835.h>

char eeprom[22] = { 0, 0, };

void main()
{
    bcm2835_i2c_begin();
    bcm2835_i2c_setSlaveAddress(0x78);
    uint8_t ret = bcm2835_i2c_read(eeprom, 22);
    printf("Read return code: %d\n", ret);
    bcm2835_i2c_end();
}

BTW the pressure module works perfectly well with a different bcm2835 library. I just don’t want to use two bcm2835 libraries in the same project. Any suggestions?

Arjan

unread,
Mar 6, 2013, 4:56:32 PM3/6/13
to bcm...@googlegroups.com
Hi,

You are missing bcm2835_init at the beginning of your code.

http://www.open.com.au/mikem/bcm2835/group__init.html#ga9351fa3ec8eeff4e9d998d3d5d912a4f

Op woensdag 6 maart 2013 22:43:40 UTC+1 schreef KarlS het volgende:

KarlS

unread,
Mar 6, 2013, 5:15:19 PM3/6/13
to bcm...@googlegroups.com
Stupid, stupid, stupid ... after all I already have done this for the SPI part.

But this just brings me to my (maybe stupid) next question. The base address of the module is 0x77, but I need to access the registers in the module located at 0xf4 (for write) and 0xf6 (for read). How do I access these addresses?

Michael Petersen

unread,
Mar 6, 2013, 6:48:31 PM3/6/13
to bcm...@googlegroups.com
Thanks for this post! I finally got my i2c ports to work using this library. 

Arvi

unread,
Mar 6, 2013, 11:02:55 PM3/6/13
to bcm...@googlegroups.com

I looked at the data sheet of the BMP085 - you have to send the address of the memory register to read from (including other control data) and then read the value of the register off the I2C bus. Since this is a fairly commonly used sensor - I would suggest looking at code already written for this sensor (Arduino or other places) - it should be fairly easy to replace the I2C portion of the code with the functions this library provides. Hope this helps.

KarlS

unread,
Mar 8, 2013, 5:34:02 PM3/8/13
to bcm...@googlegroups.com

Sorry, but this is WAY beyond me. I tried to read up on the I2C protocol, but this might as well have been Chinese. I have absolutely no experience in electrical engineering; I’m strictly a software guy. The BMP085 datasheet says the steps to find the temperature and pressure are:

  1. first read out the EEPROM registers starting at register address 0xAA
  2. read the uncompensated temperature value by writing 0x2E into register 0xF4 and finally read registers 0xF6 (MSB) and 0xF7 (LSB)
  3. read the uncompensated pressure value by writing 0x34+(oss<<6) into register 0xF4 and finally read registers 0xF6 (MSB), 0xF7 (LSB) and 0xF8 (XLSB)
  4.  

Here is my fist problem: how do I read 22 bytes from the module with a slave address of 0x77 starting at the register address 0xAA? The original BMP085 API has a function like:

i2c_read(0x77, 0xaa, eeprom, 22);

 The bcm2835 library doesn’t have such a function. Here is what I have done so far:

char readcmd = 0xef;
char writecmd = 0xee;
char eeprom[50];
...
if (!bcm2835_init()) exit(1);
bcm2835_i2c_begin();
bcm2835_i2c_setSlaveAddress(0x77);
bcm2835_i2c_write(&readcmd, 1);
bcm2835_i2c_read(eeprom, 50);
...

 

At this point I can find the 22 byte EEPROM data starting at eeprom[20]. OK, I don’t understand that, but good to have the data anyway.

Now comes the second step. I’m supposed to write the value 0x2E to register 0xF4. Here I’m stuck, completely … Again the original API uses a function like:

i2c_write(0x77, 0xf4, &cmd_ut, 1);

My next commands are:

...
char cmd_ut = 0x2e;
bcm2835_i2c_write(&writecmd, 1);
bcm2835_i2c_write(&cmd_ut, 1);
usleep(4500);
bcm2835_i2c_write(&readcmd, 1);
bcm2835_i2c_read(r
eg, 50);

Where do I specify the address 0xf4 to write to? Whatever I do, the write command does nothing. I found out that after the successful execution I should find the data in eeprom[7] to eeprom[9].

What am I doing wrong?? Is the bcm2835 library missing a function here? Can anybody post a working I2C program (but again, I might not be able to understand it)?

Cheers

Karl

Mike McCauley

unread,
Mar 9, 2013, 5:11:05 PM3/9/13
to bcm...@googlegroups.com
Hi,

I dont have one of those devices to test, but looking at the datasheet....


The basic strategy is to set the slave address to 0x77 (you are doing that
OK). That takes card of the read and write command bytes 0xee and 0xff (note
0xee is (0x77 << 1)

Then you need to write the register address you want to access in the next
step.
Then you read or write from the bus, and the data will go to/from the register
you wrote in the previous step.

more below......

On Friday, March 08, 2013 02:34:02 PM KarlS wrote:
> Sorry, but this is WAY beyond me. I tried to read up on the I2C protocol,
> but this might as well have been Chinese. I have absolutely no experience
> in electrical engineering; I’m strictly a software guy. The BMP085
> datasheet says the steps to find the temperature and pressure are:
>
> 1. first read out the EEPROM registers starting at register address 0xAA
> 2. read the uncompensated temperature value by writing 0x2E into
> register 0xF4 and finally read registers 0xF6 (MSB) and 0xF7 (LSB)
> 3. read the uncompensated pressure value by writing 0x34+(oss<<6) into
> register 0xF4 and finally read registers 0xF6 (MSB), 0xF7 (LSB) and 0xF8
> (XLSB)
> 4. …
>
> Here is my fist problem: how do I read 22 bytes from the module with a
> slave address of 0x77 starting at the register address 0xAA? The original
> BMP085 API has a function like:
>
> i2c_read(0x77, 0xaa, eeprom, 22);
>
> The bcm2835 library doesn’t have such a function. Here is what I have done
> so far:
> char readcmd = 0xef;
> char writecmd = 0xee;
> char eeprom[50];
> ...
> if (!bcm2835_init()) exit(1);
> bcm2835_i2c_begin();
> bcm2835_i2c_setSlaveAddress(0x77);
> bcm2835_i2c_write(&readcmd, 1);
> bcm2835_i2c_read(eeprom, 50);

To read the calibration registers, I think you want something like (untested):

char readcmd = 0xef;
char writecmd = 0xee;
char eeprom[50];
char register;

To read the calibration registers, I think you want:
if (!bcm2835_init()) exit(1);
bcm2835_i2c_begin();
bcm2835_i2c_setSlaveAddress(0x77);
register = 0xaa;
bcm2835_i2c_write(&register, 1);
bcm2835_i2c_read(eeprom, 22);


> ...
>
>
>
> At this point I can find the 22 byte EEPROM data starting at eeprom[20].
> OK, I don’t understand that, but good to have the data anyway.
>
> Now comes the second step. I’m supposed to write the value 0x2E to register
> 0xF4. Here I’m stuck, completely … Again the original API uses a function
> like:
>
> i2c_write(0x77, 0xf4, &cmd_ut, 1);
>
> My next commands are:
>
> ...
> char cmd_ut = 0x2e;
> bcm2835_i2c_write(&writecmd, 1);
> bcm2835_i2c_write(&cmd_ut, 1);
> usleep(4500);
> bcm2835_i2c_write(&readcmd, 1);
> bcm2835_i2c_read(reg, 50);

UNTESTED:

// initialised as above
...
char ut[2];
char cmd_ut = 0x2e; // read uncompensated temp
register = 0xf4; // Start temp read
bcm2835_i2c_write(&register, 1);
bcm2835_i2c_write(&cmd_ut, 1);
//wait 4.5ms
bcm2835_delay(5); // Actually only need 4.5ms
register = 0xf6; // resulting uncompensated temp
bcm2835_i2c_write(&register, 1);
bcm2835_i2c_read(ut, 2);

I think you will have to read the data sheet more carefully if you want to
work effectively with this module.



>
> Where do I specify the address 0xf4 to write to? Whatever I do, the write
> command does nothing. I found out that after the successful execution I
> should find the data in eeprom[7] to eeprom[9].
>
> What am I doing wrong?? Is the bcm2835 library missing a function here? Can
> anybody post a working I2C program (but again, I might not be able to
> understand it)?
>
> Cheers
> Karl
--
Mike McCauley mi...@open.com.au
Open System Consultants Pty. Ltd
9 Bulbul Place Currumbin Waters QLD 4223 Australia http://www.open.com.au
Phone +61 7 5598-7474 Fax +61 7 5598-7070

Radiator: the most portable, flexible and configurable RADIUS server
anywhere. SQL, proxy, DBM, files, LDAP, NIS+, password, NT, Emerald,
Platypus, Freeside, TACACS+, PAM, external, Active Directory, EAP, TLS,
TTLS, PEAP, TNC, WiMAX, RSA, Vasco, Yubikey, MOTP, HOTP, TOTP,
DIAMETER etc. Full source on Unix, Windows, MacOSX, Solaris, VMS, NetWare etc.

KarlS

unread,
Mar 9, 2013, 9:00:09 PM3/9/13
to bcm...@googlegroups.com

Hi Mike:

Thank you for your fast answer. I really appreciate you taking time to help users like me. I’ve got 40+ years of programming experience in Assembler, Fortran, Cobol, PL/1 … you name it. But not in C or any of its OO derivates! I’m also just finding my way around Linux, so I’ve got a lot to learn, all at the same time. I hope you bear with me.

The good news is: the read part work. The bcm2835_i2c_write(…); however just doesn’t seem to do what I want it to. Here is my sequence of commands:

reg = 0xf4; cmd = 0x2e;
bcm2835_i2c_write(&reg, 1);
bcm2835_i2c_write(&cmd, 1);
bcm2835_delay(5);
reg = 0xf6;
bcm2835_i2c_write(&reg, 1);
bcm2835_i2c_read(utemp, 2);

This should get me the temperature in the utemp buffer. However what I get is whatever was left by the previous program in the specified register locations. If the last successful call (by a different program) was for the pressure, that’s what I get, even though I’ve requested the temperature. The two successive write commands don’t seem work. Here is another of my stupid (or maybe not) questions: how does the BMP085 module distinguish if the first parameter of the write command is an address (to write to) or a data (to be written into some address)?

Anyway, here is an excerpt of the program that works. It’s by Kevin Sangelee and part of his weather station project. For brevity I have only copied the i2c_write and i2c_read functions

#define BSC0_C *(bsc0.addr + 0x00)
#define BSC0_S *(bsc0.addr + 0x01)
#define BSC0_DLEN *(bsc0.addr + 0x02)
#define BSC0_A *(bsc0.addr + 0x03)
#define BSC0_FIFO *(bsc0.addr + 0x04)

#define BSC_C_I2CEN (1 << 15)
#define BSC_C_ST (1 << 7)
#define BSC_C_CLEAR (1 << 4)
#define BSC_C_READ 1

#define START_READ BSC_C_I2CEN|BSC_C_ST|BSC_C_CLEAR|BSC_C_READ
#define START_WRITE BSC_C_I2CEN|BSC_C_ST

#define BSC_S_CLKT (1 << 9)
#define BSC_S_ERR (1 << 8)
#define BSC_S_DONE (1 << 1)
#define BSC_S_TA 1

#define CLEAR_STATUS BSC_S_CLKT|BSC_S_ERR|BSC_S_DONE

// Function to wait for the I2C transaction to complete
void wait_i2c_done() {
   while((!((BSC0_S) & BSC_S_DONE))) { usleep(100); }
}

// Function to write data to an I2C device via the FIFO.
void i2c_write(char dev_addr, char reg_addr, char *buf, uint16_t len) {
   uint8_t idx;

   BSC0_A = dev_addr;
   BSC0_DLEN = len + 1; // one byte for the register address, plus the buffer length

   BSC0_FIFO = reg_addr; // start register address
   for(idx=0; idx < len; idx++) BSC0_FIFO = buf[idx];

   BSC0_S = CLEAR_STATUS; // Reset status bits
   BSC0_C = START_WRITE; // Start Write

   wait_i2c_done();
}

// Function to read a number of bytes into a buffer from the FIFO
void i2c_read(char dev_addr, char reg_addr, char *buf, uint16_t len) {
   i2c_write(dev_addr, reg_addr, NULL, 0);

   uint16_t bufidx = 0;

   memset(buf, 0, len); // clear the buffer

   BSC0_DLEN = len;
   BSC0_S = CLEAR_STATUS; // Reset status bits
   BSC0_C = START_READ; // Start Read after clearing FIFO

   do {
    // Wait for some data to appear in the FIFO
    while((BSC0_S & BSC_S_TA) && !(BSC0_S & BSC_S_RXD));

    // Consume the FIFO
    while((BSC0_S & BSC_S_RXD) && (bufidx < len)) { buf[bufidx++] = BSC0_FIFO; }
  } while((!(BSC0_S & BSC_S_DONE)));
}

I tried to compare this code to your read/write functions, but I’m probably comparing apples and oranges.

Thanks again for your help and this library!

Cheers

Karl

Mike McCauley

unread,
Mar 10, 2013, 1:06:00 AM3/10/13
to bcm...@googlegroups.com
Hi,

On Saturday, March 09, 2013 06:00:09 PM KarlS wrote:
> Hi Mike:
>
> Thank you for your fast answer. I really appreciate you taking time to help
> users like me. I’ve got 40+ years of programming experience in Assembler,
> Fortran, Cobol, PL/1 … you name it. But not in C or any of its OO
> derivates! I’m also just finding my way around Linux, so I’ve got a lot to
> learn, all at the same time. I hope you bear with me.

Sure but without a device to test against, Im working in the dark.
I think Ill have to leave it to you or someone else.

Cheers.

>
> The good news is: the read part work. The bcm2835_i2c_write(…); however
> just doesn’t seem to do what I want it to. Here is my sequence of commands:
> reg = 0xf4; cmd = 0x2e;
> bcm2835_i2c_write(&reg, 1);
> bcm2835_i2c_write(&cmd, 1);
> bcm2835_delay(5);
> reg = 0xf6;
> bcm2835_i2c_write(&reg, 1);
> bcm2835_i2c_read(utemp, 2);
>
> This should get me the temperature in the utemp buffer. However what I get
> is whatever was left by the previous program in the specified register
> locations. If the last successful call (by a different program) was for the
> pressure, that’s what I get, even though I’ve requested the temperature.
> The two successive write commands don’t seem work. Here is another of my
> stupid (or maybe not) questions: how does the BMP085 module distinguish if
> the first parameter of the write command is an address (to write to) or a
> data (to be written into some address)?
>
> Anyway, here is an excerpt of the program that works. It’s by Kevin
> Sangelee and part of his weather station
> project<http://www.susa.net/wordpress/2012/08/raspberry-pi-reading-wh1081-w
> eather-sensors-using-an-rfm01-and-rfm12b/>. For brevity I have only copied

Mark Dootson

unread,
Mar 8, 2013, 6:34:52 PM3/8/13
to bcm...@googlegroups.com
Hi,

I don't have a BMP085 but I think you should be able to translate the
code from the wiring library at

http://wiring.org.co/learning/libraries/bmp085.html

At least this gives you the correct ordering, format and addresses of
reads and writes. Most devices seem to have good examples for 'wiring'
which are fairly easily translated.

Personally as I don't have any i2c devices that require the sort of
control or speed that the bcm2835 library might provide, I just use the
kernel driver and SMBus protocol which seems to work with all the
devices I have tried.

If you get your bmp085 working with raw i2c reads and writes, I'd be
interested to see the code for future reference.

Regards

Mark

Hope it helps

On 08/03/2013 22:34, KarlS wrote:
> Sorry, but this is WAY beyond me. I tried to read up on the I2C
> protocol, but this might as well have been Chinese. I have absolutely no
> experience in electrical engineering; I�m strictly a software guy. The
> BMP085 datasheet says the steps to find the temperature and pressure are:
>
> 1. first read out the EEPROM registers starting at register address 0xAA
> 2. read the uncompensated temperature value by writing 0x2E into
> register 0xF4 and finally read registers 0xF6 (MSB) and 0xF7 (LSB)
> 3. read the uncompensated pressure value by writing 0x34+(oss<<6) into
> register 0xF4 and finally read registers 0xF6 (MSB), 0xF7 (LSB) and
> 0xF8 (XLSB)
> 4. �
>
> Here is my fist problem: how do I read 22 bytes from the module with a
> slave address of 0x77 starting at the register address 0xAA? The
> original BMP085 API has a function like:
>
> i2c_read(0x77, 0xaa, eeprom, 22);
>
> The bcm2835 library doesn�t have such a function. Here is what I have
> done so far:
>
> char readcmd = 0xef;
> char writecmd = 0xee;
> char eeprom[50];
> ...
> if (!bcm2835_init()) exit(1);
> bcm2835_i2c_begin();
> bcm2835_i2c_setSlaveAddress(0x77);
> bcm2835_i2c_write(&readcmd, 1);
> bcm2835_i2c_read(eeprom, 50);
> ...
>
> At this point I can find the 22 byte EEPROM data starting at eeprom[20].
> OK, I don�t understand that, but good to have the data anyway.
>
> Now comes the second step. I�m supposed to write the value 0x2E to
> register 0xF4. Here I�m stuck, completely � Again the original API uses
> a function like:
>
> i2c_write(0x77, 0xf4, &cmd_ut, 1);
>
> My next commands are:
>
> ...
> char cmd_ut = 0x2e;
> bcm2835_i2c_write(&writecmd, 1);
> bcm2835_i2c_write(&cmd_ut, 1);
> usleep(4500);
> bcm2835_i2c_write(&readcmd, 1);
> bcm2835_i2c_read(reg, 50);
>
> Where do I specify the address 0xf4 to write to? Whatever I do, the
> write command does nothing. I found out that after the successful
> execution I should find the data in eeprom[7] to eeprom[9].
>
> What am I doing wrong?? Is the bcm2835 library missing a function here?
> Can anybody post a working I2C program (but again, I might not be able
> to understand it)?
>
> Cheers
>
> Karl
>
> --
> You received this message because you are subscribed to the Google
> Groups "bcm2835" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to bcm2835+u...@googlegroups.com.
> To post to this group, send email to bcm...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/bcm2835/-/O91y81dTtswJ.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>
Reply all
Reply to author
Forward
0 new messages