1 | /*************************************************************************
|
2 | * Title: I2C master library using hardware TWI interface
|
3 | * Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury
|
4 | * File: $Id: twimaster.c,v 1.3 2005/07/02 11:14:21 Peter Exp $
|
5 | * Software: AVR-GCC 3.4.3 / avr-libc 1.2.3
|
6 | * Target: any AVR device with hardware TWI
|
7 | * Usage: API compatible with I2C Software Library i2cmaster.h
|
8 | **************************************************************************/
|
9 | #include <inttypes.h>
|
10 | #include <compat/twi.h>
|
11 |
|
12 | #include "i2cmaster.h"
|
13 |
|
14 |
|
15 | /* define CPU frequency in Mhz here if not defined in Makefile */
|
16 | #ifndef F_CPU
|
17 | #define F_CPU 4000000UL
|
18 | #endif
|
19 |
|
20 | /* I2C clock in Hz */
|
21 | #define SCL_CLOCK 10000L
|
22 |
|
23 |
|
24 | /*************************************************************************
|
25 | Initialization of the I2C bus interface. Need to be called only once
|
26 | *************************************************************************/
|
27 | void i2c_init(void)
|
28 | {
|
29 | /* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */
|
30 |
|
31 | TWSR = 0; /* no prescaler */
|
32 | TWBR = ((F_CPU/SCL_CLOCK)-16)/2; /* must be > 10 for stable operation */
|
33 |
|
34 | }/* i2c_init */
|
35 |
|
36 |
|
37 | /*************************************************************************
|
38 | Issues a start condition and sends address and transfer direction.
|
39 | return 0 = device accessible, 1= failed to access device
|
40 | *************************************************************************/
|
41 | unsigned char i2c_start(unsigned char address)
|
42 | {
|
43 | uint8_t twst;
|
44 |
|
45 | // send START condition
|
46 | TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
|
47 |
|
48 | // wait until transmission completed
|
49 | while(!(TWCR & (1<<TWINT)));
|
50 |
|
51 | // check value of TWI Status Register. Mask prescaler bits.
|
52 | twst = TW_STATUS & 0xF8;
|
53 | if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;
|
54 |
|
55 | // send device address
|
56 | TWDR = address;
|
57 | TWCR = (1<<TWINT) | (1<<TWEN);
|
58 |
|
59 | // wail until transmission completed and ACK/NACK has been received
|
60 | while(!(TWCR & (1<<TWINT)));
|
61 |
|
62 | // check value of TWI Status Register. Mask prescaler bits.
|
63 | twst = TW_STATUS & 0xF8;
|
64 | if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;
|
65 |
|
66 | return 0;
|
67 |
|
68 | }/* i2c_start */
|
69 |
|
70 |
|
71 | /*************************************************************************
|
72 | Issues a start condition and sends address and transfer direction.
|
73 | If device is busy, use ack polling to wait until device is ready
|
74 |
|
75 | Input: address and transfer direction of I2C device
|
76 | *************************************************************************/
|
77 | void i2c_start_wait(unsigned char address)
|
78 | {
|
79 | uint8_t twst;
|
80 |
|
81 |
|
82 | while ( 1 )
|
83 | {
|
84 | // send START condition
|
85 | TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
|
86 |
|
87 | // wait until transmission completed
|
88 | while(!(TWCR & (1<<TWINT)));
|
89 |
|
90 | // check value of TWI Status Register. Mask prescaler bits.
|
91 | twst = TW_STATUS & 0xF8;
|
92 | if ( (twst != TW_START) && (twst != TW_REP_START)) continue;
|
93 |
|
94 | // send device address
|
95 | TWDR = address;
|
96 | TWCR = (1<<TWINT) | (1<<TWEN);
|
97 |
|
98 | // wail until transmission completed
|
99 | while(!(TWCR & (1<<TWINT)));
|
100 |
|
101 | // check value of TWI Status Register. Mask prescaler bits.
|
102 | twst = TW_STATUS & 0xF8;
|
103 | if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) )
|
104 | {
|
105 | /* device busy, send stop condition to terminate write operation */
|
106 | TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
|
107 |
|
108 | // wait until stop condition is executed and bus released
|
109 | while(TWCR & (1<<TWSTO));
|
110 |
|
111 | continue;
|
112 | }
|
113 | //if( twst != TW_MT_SLA_ACK) return 1;
|
114 | break;
|
115 | }
|
116 |
|
117 | }/* i2c_start_wait */
|
118 |
|
119 |
|
120 | /*************************************************************************
|
121 | Issues a repeated start condition and sends address and transfer direction
|
122 |
|
123 | Input: address and transfer direction of I2C device
|
124 |
|
125 | Return: 0 device accessible
|
126 | 1 failed to access device
|
127 | *************************************************************************/
|
128 | unsigned char i2c_rep_start(unsigned char address)
|
129 | {
|
130 | return i2c_start( address );
|
131 |
|
132 | }/* i2c_rep_start */
|
133 |
|
134 |
|
135 | /*************************************************************************
|
136 | Terminates the data transfer and releases the I2C bus
|
137 | *************************************************************************/
|
138 | void i2c_stop(void)
|
139 | {
|
140 | /* send stop condition */
|
141 | TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
|
142 |
|
143 | // wait until stop condition is executed and bus released
|
144 | while(TWCR & (1<<TWSTO));
|
145 |
|
146 | }/* i2c_stop */
|
147 |
|
148 |
|
149 | /*************************************************************************
|
150 | Send one byte to I2C device
|
151 |
|
152 | Input: byte to be transfered
|
153 | Return: 0 write successful
|
154 | 1 write failed
|
155 | *************************************************************************/
|
156 | unsigned char i2c_write( unsigned char data )
|
157 | {
|
158 | uint8_t twst;
|
159 |
|
160 | // send data to the previously addressed device
|
161 | TWDR = data;
|
162 | TWCR = (1<<TWINT) | (1<<TWEN);
|
163 |
|
164 | // wait until transmission completed
|
165 | while(!(TWCR & (1<<TWINT)));
|
166 |
|
167 | // check value of TWI Status Register. Mask prescaler bits
|
168 | twst = TW_STATUS & 0xF8;
|
169 | if( twst != TW_MT_DATA_ACK) return 1;
|
170 | return 0;
|
171 |
|
172 | }/* i2c_write */
|
173 |
|
174 |
|
175 | /*************************************************************************
|
176 | Read one byte from the I2C device, request more data from device
|
177 |
|
178 | Return: byte read from I2C device
|
179 | *************************************************************************/
|
180 | unsigned char i2c_readAck(void)
|
181 | {
|
182 | TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
|
183 | while(!(TWCR & (1<<TWINT)));
|
184 |
|
185 | return TWDR;
|
186 |
|
187 | }/* i2c_readAck */
|
188 |
|
189 |
|
190 | /*************************************************************************
|
191 | Read one byte from the I2C device, read is followed by a stop condition
|
192 |
|
193 | Return: byte read from I2C device
|
194 | *************************************************************************/
|
195 | unsigned char i2c_readNak(void)
|
196 | {
|
197 | TWCR = (1<<TWINT) | (1<<TWEN);
|
198 | while(!(TWCR & (1<<TWINT)));
|
199 |
|
200 | return TWDR;
|
201 |
|
202 | }/* i2c_readNak */
|