Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2194 | - | 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 16000000UL |
||
18 | #endif |
||
19 | |||
20 | /* I2C clock in Hz */ |
||
21 | #define SCL_CLOCK 400000L |
||
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 */ |