-
Notifications
You must be signed in to change notification settings - Fork 0
/
twimaster.c
134 lines (98 loc) · 4.31 KB
/
twimaster.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include <inttypes.h>
#include <compat/twi.h>
#include <avr/io.h>
#include <i2cmaster.h>
/* define CPU frequency in hz here if not defined in Makefile */
#ifndef F_CPU
#define F_CPU 4000000UL
#endif
/* I2C clock in Hz */
#define SCL_CLOCK 100000L
/*************************************************************************
Initialization of the I2C bus interface. Need to be called only once
*************************************************************************/
void i2c_init(void)
{
TWI0.MCTRLA = TWI_ENABLE_bm; // Enable as master, no interrupts
TWI0.MSTATUS = TWI_BUSSTATE_IDLE_gc;
}/* i2c_init */
/*************************************************************************
Issues a start condition and sends address and transfer direction.
return 0 = device accessible, 1= failed to access device
*************************************************************************/
unsigned char i2c_start(unsigned char address)
{
TWI0.MCTRLB |= TWI_FLUSH_bm; //flush
TWI0.MADDR = address; // Send START condition and address
while (!(TWI0.MSTATUS & (TWI_WIF_bm | TWI_RIF_bm))); // Wait for write or read interrupt flag
if ((TWI0.MSTATUS & (TWI_ARBLOST_bm | TWI_BUSERR_bm)) return false; // Return false if arbitration lost or bus error
return !(TWI0.MSTATUS & TWI_RXACK_bm); // Return true if slave gave an ACK
}/* i2c_start */
/*************************************************************************
Issues a start condition and sends address and transfer direction.
If device is busy, use ack polling to wait until device is ready
Input: address and transfer direction of I2C device
*************************************************************************/
void i2c_start_wait(unsigned char address)
{
while (!i2c_start(address) )
{
while(!(TWI0.MSTATUS & TWI_BUSSTATE_IDLE_gc)); // wait for bus to be idle
}
}
}/* i2c_start_wait */
/*************************************************************************
Issues a repeated start condition and sends address and transfer direction
Input: address and transfer direction of I2C device
Return: 0 device accessible
1 failed to access device
*************************************************************************/
unsigned char i2c_rep_start(unsigned char address)
{
return i2c_start( address );
}/* i2c_rep_start */
/*************************************************************************
Terminates the data transfer and releases the I2C bus
*************************************************************************/
void i2c_stop(void)
{
TWI0.MCTRLB = TWI_MCMD_STOP_gc;
// wait until stop condition is executed and bus released
while(TWCR & (1<<TWSTO));
}/* i2c_stop */
/*************************************************************************
Send one byte to I2C device
Input: byte to be transfered
Return: 0 write successful
1 write failed
*************************************************************************/
unsigned char i2c_write( unsigned char data )
{
uint8_t twst;
// send data to the previously addressed device
TWI0.MDATA = data;
while (!(TWI0.MSTATUS & TWI_WIF_bm)); //Wait for transmission to complete
return !(TWI0.MSTATUS & TWI_RXACK_bm);
}/* i2c_write */
/*************************************************************************
Read one byte from the I2C device, request more data from device
Return: byte read from I2C device
*************************************************************************/
unsigned char i2c_readAck(void)
{
while (!(TWI0.MSTATUS & TWI_RIF_bm)); // Wait for read interrupt flag
uint8_t data = TWI0.MDATA;
TWI0.MCTRLB = TWI_MCMD_RECVTRANS_gc; //return ack
return data;
}/* i2c_readAck */
/*************************************************************************
Read one byte from the I2C device, read is followed by a stop condition
Return: byte read from I2C device
*************************************************************************/
unsigned char i2c_readNak(void)
{
while (!(TWI0.MSTATUS & TWI_RIF_bm)); // Wait for read interrupt flag
uint8_t data = TWI0.MDATA;
TWI0.MCTRLB = TWI_ACKACT_bm | TWI_MCMD_RECVTRANS_gc; // Send NAK
return data;
}/* i2c_readNak */