sorry forgot but ive already withen this code, is this any good?
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "samd21.h"
#include "hal_gpio.h"
#include "component/sercom.h"
#define I2C_ADDRESS 0x00
#define RAM_ADDRESS 0x07
#define I2C_SERCOM SERCOM2
#define I2C_SERCOM_PMUX PORT_PMUX_PMUXE_D_Val
#define I2C_SERCOM_GCLK_ID SERCOM2_GCLK_ID_CORE
#define I2C_SERCOM_CLK_GEN 0
#define I2C_SERCOM_APBCMASK PM_APBCMASK_SERCOM2
#define T_RISE 215e-9 // Depends on the board, actually
enum
{
I2C_TRANSFER_WRITE = 0,
I2C_TRANSFER_READ = 1,
};
enum
{
I2C_PINS_SDA = (1 << 0),
I2C_PINS_SCL = (1 << 1),
};
//-----------------------------------------------------------------------------
static void sys_init(void) // enable 8Mhz OSC, no prescaler
{
SYSCTRL->OSC8M.bit.PRESC = 0;
}
//-----------------------------------------------------------------------------
int i2c_init(int freq)
{
int baud = ((float)F_CPU / freq - (float)F_CPU * T_RISE - 10.0) / 2.0;
if (baud < 0)
baud = 0;
else if (baud > 255)
baud = 255;
freq = (float)F_CPU / (2.0 * (5.0 + baud) + (float)F_CPU * T_RISE);
PM->APBCMASK.reg |= I2C_SERCOM_APBCMASK;
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(I2C_SERCOM_GCLK_ID) |
GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(I2C_SERCOM_CLK_GEN);
I2C_SERCOM->I2CM.CTRLA.reg = SERCOM_I2CM_CTRLA_SWRST;
while (I2C_SERCOM->I2CM.CTRLA.reg & SERCOM_I2CM_CTRLA_SWRST);
I2C_SERCOM->I2CM.CTRLB.reg = SERCOM_I2CM_CTRLB_SMEN;
while (I2C_SERCOM->I2CM.SYNCBUSY.reg);
I2C_SERCOM->I2CM.BAUD.reg = SERCOM_I2CM_BAUD_BAUD(baud);
while (I2C_SERCOM->I2CM.SYNCBUSY.reg);
I2C_SERCOM->I2CM.CTRLA.reg = SERCOM_I2CM_CTRLA_ENABLE |
SERCOM_I2CM_CTRLA_MODE_I2C_MASTER |
SERCOM_I2CM_CTRLA_SDAHOLD(3);
while (I2C_SERCOM->I2CM.SYNCBUSY.reg);
I2C_SERCOM->I2CM.STATUS.reg |= SERCOM_I2CM_STATUS_BUSSTATE(1);
return freq;
}
//-----------------------------------------------------------------------------
bool i2c_read(uint8_t *data, int size)
{
// Start + Slave_adress + write (ten ack from slave)
// master send RAM adress to read from ( ten ack from slave)
// repeted start +read bit (ack slave)
// read slave lowebit from slave (ack master)
// read save upperbit slave (ack master)
// read pec form slave (ack master)
// stop
I2C_SERCOM->I2CM.ADDR.reg = I2C_ADDRESS | I2C_TRANSFER_WRITE; // I2C adress = 0x00 eni2c wirte = 0x07
while (0 == (I2C_SERCOM->I2CM.INTFLAG.reg & SERCOM_I2CM_INTFLAG_MB));
if (I2C_SERCOM->I2CM.STATUS.reg & SERCOM_I2CM_STATUS_RXNACK)
{
I2C_SERCOM->I2CM.CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(3);
//dbg_log("I2C: RXNACK during write (address)\r\n");
return false;
}
I2C_SERCOM->I2CM.DATA.reg = RAM_ADDRESS; // send ram adrees byte
while (0 == (I2C_SERCOM->I2CM.INTFLAG.reg & SERCOM_I2CM_INTFLAG_MB));
if (I2C_SERCOM->I2CM.STATUS.reg & SERCOM_I2CM_STATUS_RXNACK)
{
I2C_SERCOM->I2CM.CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(3);
//dbg_log("I2C: RXNACK during write (data)\r\n");
return false;
}
I2C_SERCOM->I2CM.ADDR.reg = I2C_ADDRESS | I2C_TRANSFER_READ;
while (0 == (I2C_SERCOM->I2CM.INTFLAG.reg & SERCOM_I2CM_INTFLAG_SB));
if (I2C_SERCOM->I2CM.STATUS.reg & SERCOM_I2CM_STATUS_RXNACK)
{
I2C_SERCOM->I2CM.CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(3);
return false;
}
I2C_SERCOM->I2CM.CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT;
for (int i = 0; i < size-1; i++) // read lower bite, upper bite and pec
{
data[i] = I2C_SERCOM->I2CM.DATA.reg;
while (0 == (I2C_SERCOM->I2CM.INTFLAG.reg & SERCOM_I2CM_INTFLAG_SB));
}
if (size)
{
I2C_SERCOM->I2CM.CTRLB.reg |= SERCOM_I2CM_CTRLB_ACKACT;
I2C_SERCOM->I2CM.CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(3);
data[size-1] = I2C_SERCOM->I2CM.DATA.reg;
}
if ((I2C_SERCOM->I2CM.INTFLAG.reg & SERCOM_I2CM_INTFLAG_MB) ||
(I2C_SERCOM->I2CM.INTFLAG.reg & SERCOM_I2CM_INTFLAG_SB))
{
I2C_SERCOM->I2CM.CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(3); // stop bit
}
return true;
}
/*Assigning pin to the alternate peripheral function*/
static inline void pin_set_peripheral_function(uint32_t pinmux)
{
uint8_t port = (uint8_t)((pinmux >> 16)/32);
PORT->Group[port].PINCFG[((pinmux >> 16) - (port*32))].bit.PMUXEN = 1;
PORT->Group[port].PMUX[((pinmux >> 16) - (port*32))/2].reg &= ~(0xF << (4 * ((pinmux >> 16) & 0x01u)));
PORT->Group[port].PMUX[((pinmux >> 16) - (port*32))/2].reg |= (uint8_t)((pinmux & 0x0000FFFF) << (4 * ((pinmux >> 16) & 0x01u)));
}
/* I2C pin initialization */
void i2c_pin_init()
{
/* PA08 and PA09 set into peripheral function D*/
pin_set_peripheral_function(PINMUX_PA08D_SERCOM2_PAD0); // SDA
pin_set_peripheral_function(PINMUX_PA09D_SERCOM2_PAD1); // SCL
}
int main(void)
{
uint16_t value;
uint8_t buf[3];
float temp;
sys_init();
i2c_init(8000000);
i2c_read(buf, 4);
value = ((uint16_t)buf[0] << 8) | buf[1]; // combining the upper and lower byte value into a 16bit value
// convert to temp hex to decimal, devide bij 50 and subsitute 273 (Kelvin to C)
temp = ( (float)value/ (float)50) - (float)273;
while (1)
{
}
return 0;
}