Using TWI or Wire Library?

Hello everyone.

I have a code written in C language. I want to write a code that can get temperature and pressure data with the BMP280 sensor into this code. However, I saw that the person who originally wrote the code made his own definitions using twi.c instead of the Wire.h library.

For this reason, I tried to use the BMP280 using datasheet, but I could not succeed. Is there anyone who can help?

This is the fully code https://github.com/kghunt/NWatch

I found that the Adafruit_BMP280_Library worked OK

Yes, i know but it contains "wire.h". I don't want to use that

look up details of the I2C interface on the datasheet of the microcontroller you are using it will give details of the registers, bit settings, etc so you can write your own code to drive the interface directly alternativily you could use almost any GPIO pin by bit bashing

I tried very hard but could not. Because the ready code was written in C language, creating its own i2c.h library and using twi.h made it quite difficult.

what is the problem with using i2c_write(), i2c_read() etc from the i2c.c and i2c.h from the NWatch code?

I found this code today, but I couldn’t adapt it.

#include<Wire.h>

// BMP280 I2C address is 0x76(108)
#define Addr 0x76

void setup()
{
  // Initialise I2C communication as MASTER
  Wire.begin();
  // Initialise Serial communication, set baud rate = 9600
  Serial.begin(9600);
}

void loop()
{
  unsigned int b1[24];
  unsigned int data[8];
  for (int i = 0; i < 24; i++)
  {
    // Start I2C Transmission
    Wire.beginTransmission(Addr);
    // Select data register
    Wire.write((136 + i));
    // Stop I2C Transmission
    Wire.endTransmission();

    // Request 1 byte of data
    Wire.requestFrom(Addr, 1);

    // Read 1 byte of data
    if (Wire.available() == 1)
    {
      b1[i] = Wire.read();
    }
  }
  // Convert the data
  // temp coefficients
  unsigned int dig_T1 = (b1[0] & 0xFF) + ((b1[1] & 0xFF) * 256);
  int dig_T2 = b1[2] + (b1[3] * 256);
  int dig_T3 = b1[4] + (b1[5] * 256);

  // pressure coefficients
  unsigned int dig_P1 = (b1[6] & 0xFF) + ((b1[7] & 0xFF) * 256);
  int dig_P2 = b1[8] + (b1[9] * 256);
  int dig_P3 = b1[10] + (b1[11] * 256);
  int dig_P4 = b1[12] + (b1[13] * 256);
  int dig_P5 = b1[14] + (b1[15] * 256);
  int dig_P6 = b1[16] + (b1[17] * 256);
  int dig_P7 = b1[18] + (b1[19] * 256);
  int dig_P8 = b1[20] + (b1[21] * 256);
  int dig_P9 = b1[22] + (b1[23] * 256);

  // Start I2C Transmission
  Wire.beginTransmission(Addr);
  // Select control measurement register
  Wire.write(0xF4);
  // Normal mode, temp and pressure over sampling rate = 1
  Wire.write(0x27);
  // Stop I2C Transmission
  Wire.endTransmission();

  // Start I2C Transmission
  Wire.beginTransmission(Addr);
  // Select config register
  Wire.write(0xF5);
  // Stand_by time = 1000ms
  Wire.write(0xA0);
  // Stop I2C Transmission
  Wire.endTransmission();

  for (int i = 0; i < 8; i++)
  {
    // Start I2C Transmission
    Wire.beginTransmission(Addr);
    // Select data register
    Wire.write((247 + i));
    // Stop I2C Transmission
    Wire.endTransmission();

    // Request 1 byte of data
    Wire.requestFrom(Addr, 1);

    // Read 1 byte of data
    if (Wire.available() == 1)
    {
      data[i] = Wire.read();
    }
  }

  // Convert pressure and temperature data to 19-bits
  long adc_p = (((long)(data[0] & 0xFF) * 65536) + ((long)(data[1] & 0xFF) * 256) + (long)(data[2] & 0xF0)) / 16;
  long adc_t = (((long)(data[3] & 0xFF) * 65536) + ((long)(data[4] & 0xFF) * 256) + (long)(data[5] & 0xF0)) / 16;

  // Temperature offset calculations
  double var1 = (((double)adc_t) / 16384.0 - ((double)dig_T1) / 1024.0) * ((double)dig_T2);
  double var2 = ((((double)adc_t) / 131072.0 - ((double)dig_T1) / 8192.0) *
                 (((double)adc_t) / 131072.0 - ((double)dig_T1) / 8192.0)) * ((double)dig_T3);
  double t_fine = (long)(var1 + var2);
  double cTemp = (var1 + var2) / 5120.0;
  double fTemp = cTemp * 1.8 + 32;

  // Pressure offset calculations
  var1 = ((double)t_fine / 2.0) - 64000.0;
  var2 = var1 * var1 * ((double)dig_P6) / 32768.0;
  var2 = var2 + var1 * ((double)dig_P5) * 2.0;
  var2 = (var2 / 4.0) + (((double)dig_P4) * 65536.0);
  var1 = (((double) dig_P3) * var1 * var1 / 524288.0 + ((double) dig_P2) * var1) / 524288.0;
  var1 = (1.0 + var1 / 32768.0) * ((double)dig_P1);
  double p = 1048576.0 - (double)adc_p;
  p = (p - (var2 / 4096.0)) * 6250.0 / var1;
  var1 = ((double) dig_P9) * p * p / 2147483648.0;
  var2 = p * ((double) dig_P8) / 32768.0;
  double pressure = (p + (var1 + var2 + ((double)dig_P7)) / 16.0) / 100;

  // Output data to serial monitor
  Serial.print("Pressure : ");
  Serial.print(pressure);
  Serial.println(" hPa");
  Serial.print("Temperature in Celsius : ");
  Serial.print(cTemp);
  Serial.println(" C");
  Serial.print("Temperature in Fahrenheit : ");
  Serial.print(fTemp);
  Serial.println(" F");
  delay(1000);
}

when you say you could not adapt it? what is your target processor?

if I run the code from post #6 on a UNO I get

Pressure : 1020.65 hPa
Temperature in Celsius : 23.36 C
Temperature in Fahrenheit : 74.04 F
Pressure : 1020.70 hPa
Temperature in Celsius : 23.39 C
Temperature in Fahrenheit : 74.10 F
Pressure : 1020.68 hPa
Temperature in Celsius : 23.39 C
Temperature in Fahrenheit : 74.10 F

which are similar results to that from the i2c_BMP280.h library from https://github.com/orgua/iLib

This guy also use "wire.h" library. I don't want to use wire.h library. Because my code is C , wire.h library is C++.

When you use the Arduino IDE to make a sketch, then you already use a lot C++. You can use "C" or "C++", both are okay, you don't have to choose. You can even combine it with assembly. Almost every library uses a class.

For example:

void setup()
{
  Serial.begin( 9600);
  Serial.println( "Hello");
}

void loop()
{
}

The "Serial" functions use a class, which is C++, just like the Wire library.

Why don't you want to use C++ ? If you are not using the Arduino environment, is your question about programming a microcontroller without Arduino ?

Using a Arduino board with I2C without the Wire library is almost impossible. There is no reliable alternative for the Wire library.

Koepel: When you use the Arduino IDE to make a sketch, then you already use a lot C++. You can use "C" or "C++", both are okay, you don't have to choose. You can even combine it with assembly. Almost every library uses a class.

For example:

void setup()
{
  Serial.begin( 9600);
  Serial.println( "Hello");
}

void loop() { }




The "Serial" functions use a class, which is C++, just like the Wire library.

Why don't you want to use C++ ?
If you are not using the Arduino environment, is your question about programming a microcontroller without Arduino ?

Using a Arduino board with I2C without the Wire library is almost impossible. There is no reliable alternative for the Wire library.

i want to see the code in C language

I haven’t fully tested this yet but this should cover the lowest level I2C read and writes for an Arduino using Atmega328P. It’s not complete since I haven’t implemented some error handling required for I2C

void i2c_write(uint8_t address, uint8_t length, uint8_t * data)
{
	uint8_t tmp = 0;
	
	// send START condition
	TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
	while((TWSR & (0x08)) == 0);
	
	// set MASTER WRITE ADDRESS
	TWDR = address;
	TWCR = (1<<TWINT) | (1<<TWEN);
	while((TWCR & 0x80) == 0);
	
	tmp = TWSR;
	
	if(tmp == 0x18)
	{
		// proceed to write bytes to SLAVE
		for(uint8_t count=0; count<length; count++)
		{
			TWDR = data[count];
			TWCR = (1<<TWINT) | (1<<TWEN);
			while((TWCR & 0x80) == 0);
			tmp = TWSR;
			if(tmp == 0x28) {
				// ACKed, do nothing
			}
			else if(tmp == 0x30) {
				// NOT ACKed, error condition
			}
		}
		// send STOP
		TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
	}
	else if(tmp == 0x20)
	{
		// no slave responded
		TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
	}
	
	return;
}

void i2c_read(uint8_t address, uint8_t length, uint8_t * data)
{
	uint8_t tmp = 0;
	
	// send START condition
	TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
	while((TWSR & (0x08)) == 0);
	
	// set MASTER READ ADDRESS
	TWDR = address;
	TWCR = (1<<TWINT) | (1<<TWEN);
	while((TWCR & 0x80) == 0);
	
	tmp = TWSR;
	
	if(tmp == 0x40)
	{
		// proceed to read bytes from SLAVE
		for(uint8_t count=0; count<(length - 1); count++)
		{
			TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
			while((TWCR & 0x80) == 0);
			data[count] = TWDR;
		}
		// last byte
		TWCR = (1<<TWINT) | (1<<TWEN);
		while((TWCR & 0x80) == 0);
		data[length - 1] = TWDR;

		// send STOP
		TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
	}
	else if(tmp == 0x48)
	{
		// no slave responded
		TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
	}

	return;
}

ahmetkcavusoglu: i want to see the code in C language

Why ?

For use on which Arduino ?

srnet: Why ?

For use on which Arduino ?

Leonardo. I have a watch code with C language. I want to design wire library with C language

@ahmetkcavusoglu, you still have not told us why you want a Wire library with the C language.

The only thing that we can do now is guessing what the problem could be.

Please tell us what the problem is: 1. Do you think that once you choose the 'C' language that you no longer can use 'C++' ? 2. Does your code use the I2C bus ? and is it hard to convert it for the Wire library ? Please show us your code and we can help. 3. Does your code not go along with the Arduino setup() and loop() and attachInterrupt() ? Then there are probably easy ways to transform the code. 4. Is your project not Arduino code, but you still want to use the Arduino Wire library, and your compiler is not setup properly for C++ ? Tell us which compiler you use. There is no Wire library in 'C', because there is no need for it.

I wrote before that you don't have to choose. You can combine 'C' and 'C++' and assembly in any way you want. The Arduino IDE and the compiler and linker all support that, in every combination.

Open up the wire library that the Uno uses and convert it to C; because, obviously, the the Ardunio library is not the library you are looking for.