Browse Source

Added twi library

Thomas Buck 12 years ago
parent
commit
61527d088e
5 changed files with 384 additions and 10 deletions
  1. 1
    0
      README.md
  2. 3
    10
      cube.c
  3. 1
    0
      makefile
  4. 201
    0
      twi.c
  5. 178
    0
      twi.h

+ 1
- 0
README.md View File

@@ -9,6 +9,7 @@ You can find the schematic as png and Eagle file in this directory.
9 9
 ## Firmware
10 10
 
11 11
 The firmware of the Controller is yet to be developed...
12
+It will use [Peter Fleury's UART and TWI Library](http://homepage.hispeed.ch/peterfleury/avr-software.html).
12 13
 
13 14
 ## Cube Control
14 15
 

+ 3
- 10
cube.c View File

@@ -85,15 +85,8 @@ inline void isrCall(void) {
85 85
 	}
86 86
 }
87 87
 
88
-inline void delay_ns(uint16_t ns) {
88
+inline void delay_ns(int16_t ns) {
89 89
 	// minimum 63 nanoseconds (= 1 tick)
90
-	uint16_t i = ns;
91
-	if (ns != 0) {
92
-		if (ns < 63) {
93
-			ns = 63;
94
-		}
95
-		for (; i > 0; i -= 63) {
96
-			asm volatile("nop"::);
97
-		}
98
-	}
90
+	for (ns > 0; ns -= 63)
91
+		asm volatile("nop"::);
99 92
 }

+ 1
- 0
makefile View File

@@ -38,6 +38,7 @@ TARGET = main
38 38
 SRC = $(TARGET).c
39 39
 SRC += uart.c # Additional Source-File
40 40
 SRC += cube.c
41
+SRC += twi.c
41 42
 
42 43
 # List Assembler source files here.
43 44
 # Make them always end in a capital .S.  Files ending in a lowercase .s

+ 201
- 0
twi.c View File

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

+ 178
- 0
twi.h View File

@@ -0,0 +1,178 @@
1
+#ifndef _I2CMASTER_H
2
+#define _I2CMASTER_H   1
3
+/************************************************************************* 
4
+* Title:    C include file for the I2C master interface 
5
+*           (i2cmaster.S or twimaster.c)
6
+* Author:   Peter Fleury <pfleury@gmx.ch>  http://jump.to/fleury
7
+* File:     $Id: i2cmaster.h,v 1.10 2005/03/06 22:39:57 Peter Exp $
8
+* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3
9
+* Target:   any AVR device
10
+* Usage:    see Doxygen manual
11
+**************************************************************************/
12
+
13
+#ifdef DOXYGEN
14
+/**
15
+ @defgroup pfleury_ic2master I2C Master library
16
+ @code #include <i2cmaster.h> @endcode
17
+  
18
+ @brief I2C (TWI) Master Software Library
19
+
20
+ Basic routines for communicating with I2C slave devices. This single master 
21
+ implementation is limited to one bus master on the I2C bus. 
22
+
23
+ This I2c library is implemented as a compact assembler software implementation of the I2C protocol 
24
+ which runs on any AVR (i2cmaster.S) and as a TWI hardware interface for all AVR with built-in TWI hardware (twimaster.c).
25
+ Since the API for these two implementations is exactly the same, an application can be linked either against the
26
+ software I2C implementation or the hardware I2C implementation.
27
+
28
+ Use 4.7k pull-up resistor on the SDA and SCL pin.
29
+ 
30
+ Adapt the SCL and SDA port and pin definitions and eventually the delay routine in the module 
31
+ i2cmaster.S to your target when using the software I2C implementation ! 
32
+ 
33
+ Adjust the  CPU clock frequence F_CPU in twimaster.c or in the Makfile when using the TWI hardware implementaion.
34
+
35
+ @note 
36
+    The module i2cmaster.S is based on the Atmel Application Note AVR300, corrected and adapted 
37
+    to GNU assembler and AVR-GCC C call interface.
38
+    Replaced the incorrect quarter period delays found in AVR300 with 
39
+    half period delays. 
40
+    
41
+ @author Peter Fleury pfleury@gmx.ch  http://jump.to/fleury
42
+
43
+ @par API Usage Example
44
+  The following code shows typical usage of this library, see example test_i2cmaster.c
45
+
46
+ @code
47
+
48
+ #include <i2cmaster.h>
49
+
50
+
51
+ #define Dev24C02  0xA2      // device address of EEPROM 24C02, see datasheet
52
+
53
+ int main(void)
54
+ {
55
+     unsigned char ret;
56
+
57
+     i2c_init();                             // initialize I2C library
58
+
59
+     // write 0x75 to EEPROM address 5 (Byte Write) 
60
+     i2c_start_wait(Dev24C02+I2C_WRITE);     // set device address and write mode
61
+     i2c_write(0x05);                        // write address = 5
62
+     i2c_write(0x75);                        // write value 0x75 to EEPROM
63
+     i2c_stop();                             // set stop conditon = release bus
64
+
65
+
66
+     // read previously written value back from EEPROM address 5 
67
+     i2c_start_wait(Dev24C02+I2C_WRITE);     // set device address and write mode
68
+
69
+     i2c_write(0x05);                        // write address = 5
70
+     i2c_rep_start(Dev24C02+I2C_READ);       // set device address and read mode
71
+
72
+     ret = i2c_readNak();                    // read one byte from EEPROM
73
+     i2c_stop();
74
+
75
+     for(;;);
76
+ }
77
+ @endcode
78
+
79
+*/
80
+#endif /* DOXYGEN */
81
+
82
+/**@{*/
83
+
84
+#if (__GNUC__ * 100 + __GNUC_MINOR__) < 304
85
+#error "This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !"
86
+#endif
87
+
88
+#include <avr/io.h>
89
+
90
+/** defines the data direction (reading from I2C device) in i2c_start(),i2c_rep_start() */
91
+#define I2C_READ    1
92
+
93
+/** defines the data direction (writing to I2C device) in i2c_start(),i2c_rep_start() */
94
+#define I2C_WRITE   0
95
+
96
+
97
+/**
98
+ @brief initialize the I2C master interace. Need to be called only once 
99
+ @param  void
100
+ @return none
101
+ */
102
+extern void i2c_init(void);
103
+
104
+
105
+/** 
106
+ @brief Terminates the data transfer and releases the I2C bus 
107
+ @param void
108
+ @return none
109
+ */
110
+extern void i2c_stop(void);
111
+
112
+
113
+/** 
114
+ @brief Issues a start condition and sends address and transfer direction 
115
+  
116
+ @param    addr address and transfer direction of I2C device
117
+ @retval   0   device accessible 
118
+ @retval   1   failed to access device 
119
+ */
120
+extern unsigned char i2c_start(unsigned char addr);
121
+
122
+
123
+/**
124
+ @brief Issues a repeated start condition and sends address and transfer direction 
125
+
126
+ @param   addr address and transfer direction of I2C device
127
+ @retval  0 device accessible
128
+ @retval  1 failed to access device
129
+ */
130
+extern unsigned char i2c_rep_start(unsigned char addr);
131
+
132
+
133
+/**
134
+ @brief Issues a start condition and sends address and transfer direction 
135
+   
136
+ If device is busy, use ack polling to wait until device ready 
137
+ @param    addr address and transfer direction of I2C device
138
+ @return   none
139
+ */
140
+extern void i2c_start_wait(unsigned char addr);
141
+
142
+ 
143
+/**
144
+ @brief Send one byte to I2C device
145
+ @param    data  byte to be transfered
146
+ @retval   0 write successful
147
+ @retval   1 write failed
148
+ */
149
+extern unsigned char i2c_write(unsigned char data);
150
+
151
+
152
+/**
153
+ @brief    read one byte from the I2C device, request more data from device 
154
+ @return   byte read from I2C device
155
+ */
156
+extern unsigned char i2c_readAck(void);
157
+
158
+/**
159
+ @brief    read one byte from the I2C device, read is followed by a stop condition 
160
+ @return   byte read from I2C device
161
+ */
162
+extern unsigned char i2c_readNak(void);
163
+
164
+/** 
165
+ @brief    read one byte from the I2C device
166
+ 
167
+ Implemented as a macro, which calls either i2c_readAck or i2c_readNak
168
+ 
169
+ @param    ack 1 send ack, request more data from device<br>
170
+               0 send nak, read is followed by a stop condition 
171
+ @return   byte read from I2C device
172
+ */
173
+extern unsigned char i2c_read(unsigned char ack);
174
+#define i2c_read(ack)  (ack) ? i2c_readAck() : i2c_readNak(); 
175
+
176
+
177
+/**@}*/
178
+#endif

Loading…
Cancel
Save