1 /* Library made by: g4lvanix
2 * Github repository: https://github.com/g4lvanix/I2C-master-lib
8 #include "i2c_master.h"
11 #define F_SCL 400000UL // SCL frequency
13 #define TWBR_val ((((F_CPU / F_SCL) / Prescaler) - 16 ) / 2)
17 TWSR = 0; /* no prescaler */
18 TWBR = (uint8_t)TWBR_val;
22 i2c_status_t i2c_start(uint8_t address, uint16_t timeout)
24 // reset TWI control register
26 // transmit START condition
27 TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
29 uint16_t timeout_timer = timer_read();
30 while( !(TWCR & (1<<TWINT)) ) {
31 if (timeout && ((timer_read() - timeout_timer) > timeout)) {
32 return I2C_STATUS_TIMEOUT;
36 // check if the start condition was successfully transmitted
37 if(((TW_STATUS & 0xF8) != TW_START) && ((TW_STATUS & 0xF8) != TW_REP_START)){ return I2C_STATUS_ERROR; }
39 // load slave address into data register
41 // start transmission of address
42 TWCR = (1<<TWINT) | (1<<TWEN);
44 timeout_timer = timer_read();
45 while( !(TWCR & (1<<TWINT)) ) {
46 if (timeout && ((timer_read() - timeout_timer) > timeout)) {
47 return I2C_STATUS_TIMEOUT;
51 // check if the device has acknowledged the READ / WRITE mode
52 uint8_t twst = TW_STATUS & 0xF8;
53 if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return I2C_STATUS_ERROR;
55 return I2C_STATUS_SUCCESS;
58 i2c_status_t i2c_write(uint8_t data, uint16_t timeout)
60 // load data into data register
62 // start transmission of data
63 TWCR = (1<<TWINT) | (1<<TWEN);
65 uint16_t timeout_timer = timer_read();
66 while( !(TWCR & (1<<TWINT)) ) {
67 if (timeout && ((timer_read() - timeout_timer) > timeout)) {
68 return I2C_STATUS_TIMEOUT;
72 if( (TW_STATUS & 0xF8) != TW_MT_DATA_ACK ){ return I2C_STATUS_ERROR; }
74 return I2C_STATUS_SUCCESS;
77 int16_t i2c_read_ack(uint16_t timeout)
80 // start TWI module and acknowledge data after reception
81 TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
83 uint16_t timeout_timer = timer_read();
84 while( !(TWCR & (1<<TWINT)) ) {
85 if (timeout && ((timer_read() - timeout_timer) > timeout)) {
86 return I2C_STATUS_TIMEOUT;
90 // return received data from TWDR
94 int16_t i2c_read_nack(uint16_t timeout)
97 // start receiving without acknowledging reception
98 TWCR = (1<<TWINT) | (1<<TWEN);
100 uint16_t timeout_timer = timer_read();
101 while( !(TWCR & (1<<TWINT)) ) {
102 if (timeout && ((timer_read() - timeout_timer) > timeout)) {
103 return I2C_STATUS_TIMEOUT;
107 // return received data from TWDR
111 i2c_status_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout)
113 i2c_status_t status = i2c_start(address | I2C_WRITE, timeout);
114 if (status) return status;
116 for (uint16_t i = 0; i < length; i++) {
117 status = i2c_write(data[i], timeout);
118 if (status) return status;
121 status = i2c_stop(timeout);
122 if (status) return status;
124 return I2C_STATUS_SUCCESS;
127 i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout)
129 i2c_status_t status = i2c_start(address | I2C_READ, timeout);
130 if (status) return status;
132 for (uint16_t i = 0; i < (length-1); i++) {
133 status = i2c_read_ack(timeout);
141 status = i2c_read_nack(timeout);
143 data[(length-1)] = status;
148 status = i2c_stop(timeout);
149 if (status) return status;
151 return I2C_STATUS_SUCCESS;
154 i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)
156 i2c_status_t status = i2c_start(devaddr | 0x00, timeout);
157 if (status) return status;
159 status = i2c_write(regaddr, timeout);
160 if (status) return status;
162 for (uint16_t i = 0; i < length; i++) {
163 status = i2c_write(data[i], timeout);
164 if (status) return status;
167 status = i2c_stop(timeout);
168 if (status) return status;
170 return I2C_STATUS_SUCCESS;
173 i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)
175 i2c_status_t status = i2c_start(devaddr, timeout);
176 if (status) return status;
178 status = i2c_write(regaddr, timeout);
179 if (status) return status;
181 status = i2c_start(devaddr | 0x01, timeout);
182 if (status) return status;
184 for (uint16_t i = 0; i < (length-1); i++) {
185 status = i2c_read_ack(timeout);
193 status = i2c_read_nack(timeout);
195 data[(length-1)] = status;
200 status = i2c_stop(timeout);
201 if (status) return status;
203 return I2C_STATUS_SUCCESS;
206 i2c_status_t i2c_stop(uint16_t timeout)
208 // transmit STOP condition
209 TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
211 uint16_t timeout_timer = timer_read();
212 while(TWCR & (1<<TWSTO)) {
213 if (timeout && ((timer_read() - timeout_timer) > timeout)) {
214 return I2C_STATUS_TIMEOUT;
218 return I2C_STATUS_SUCCESS;