Project

General

Profile

Statistics
| Revision:

root / branches / autonomous_recharging / code / projects / autonomous_recharging / archs / USI_TWI_Master.c @ 956

History | View | Annotate | Download (10.3 KB)

1 80 bneuman
/*****************************************************************************
2
*
3
* Atmel Corporation
4
*
5
* File              : USI_TWI_Master.c
6
* Compiler          : IAR EWAAVR 2.28a/3.10a
7
* Revision          : $Revision: 1.11 $
8
* Date              : $Date: Tuesday, September 13, 2005 09:09:36 UTC $
9
* Updated by        : $Author: jtyssoe $
10
*
11
* Support mail      : avr@atmel.com
12
*
13
* Supported devices : All device with USI module can be used.
14
*                     The example is written for the ATmega169, ATtiny26 and ATtiny2313
15
*
16
* AppNote           : AVR310 - Using the USI module as a TWI Master
17
*
18
* Description       : This is an implementation of an TWI master using
19
*                     the USI module as basis. The implementation assumes the AVR to
20
*                     be the only TWI master in the system and can therefore not be
21
*                     used in a multi-master system.
22
* Usage             : Initialize the USI module by calling the USI_TWI_Master_Initialise()
23
*                     function. Hence messages/data are transceived on the bus using
24
*                     the USI_TWI_Transceive() function. The transceive function
25
*                     returns a status byte, which can be used to evaluate the
26
*                     success of the transmission.
27
*
28
****************************************************************************/
29
#ifndef _USI_TWI_MASTER_H
30
#define _USI_TWI_MASTER_H
31
32
#include <util/delay.h>
33
#include <avr/io.h>
34
#include <avr/interrupt.h>
35
#include "USI_TWI_Master.h"
36
37
unsigned char USI_TWI_Master_Transfer( unsigned char );
38
unsigned char USI_TWI_Master_Stop( void );
39
40
union  USI_TWI_state
41
{
42
  unsigned char errorState;         // Can reuse the TWI_state for error states due to that it will not be need if there exists an error.
43
  struct
44
  {
45
    unsigned char addressMode         : 1;
46
    unsigned char masterWriteDataMode : 1;
47
    unsigned char unused              : 6;
48
  };
49
}   USI_TWI_state;
50
51
/*---------------------------------------------------------------
52
 USI TWI single master initialization function
53
---------------------------------------------------------------*/
54
void USI_TWI_Master_Initialise( void )
55
{
56
  PORT_USI |= (1<<PIN_USI_SDA);           // Enable pullup on SDA, to set high as released state.
57
  PORT_USI |= (1<<PIN_USI_SCL);           // Enable pullup on SCL, to set high as released state.
58
59
  DDR_USI  |= (1<<PIN_USI_SCL);           // Enable SCL as output.
60
  DDR_USI  |= (1<<PIN_USI_SDA);           // Enable SDA as output.
61
62
  USIDR    =  0xFF;                       // Preload dataregister with "released level" data.
63
  USICR    =  (0<<USISIE)|(0<<USIOIE)|                            // Disable Interrupts.
64
              (1<<USIWM1)|(0<<USIWM0)|                            // Set USI in Two-wire mode.
65
              (1<<USICS1)|(0<<USICS0)|(1<<USICLK)|                // Software stobe as counter clock source
66
              (0<<USITC);
67
  USISR   =   (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)|      // Clear flags,
68
              (0x0<<USICNT0);                                     // and reset counter.
69
}
70
71
/*---------------------------------------------------------------
72
Use this function to get hold of the error message from the last transmission
73
---------------------------------------------------------------*/
74
unsigned char USI_TWI_Get_State_Info( void )
75
{
76
  return ( USI_TWI_state.errorState );                            // Return error state.
77
}
78
79
/*---------------------------------------------------------------
80
 USI Transmit and receive function. LSB of first byte in data
81
 indicates if a read or write cycles is performed. If set a read
82
 operation is performed.
83

84
 Function generates (Repeated) Start Condition, sends address and
85
 R/W, Reads/Writes Data, and verifies/sends ACK.
86

87
 Success or error code is returned. Error codes are defined in
88
 USI_TWI_Master.h
89
---------------------------------------------------------------*/
90
unsigned char USI_TWI_Start_Transceiver_With_Data( unsigned char *msg, unsigned char msgSize)
91
{
92
  unsigned char tempUSISR_8bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)|      // Prepare register value to: Clear flags, and
93
                                 (0x0<<USICNT0);                                     // set USI to shift 8 bits i.e. count 16 clock edges.
94
  unsigned char tempUSISR_1bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)|      // Prepare register value to: Clear flags, and
95
                                 (0xE<<USICNT0);                                     // set USI to shift 1 bit i.e. count 2 clock edges.
96
97
  USI_TWI_state.errorState = 0;
98
  USI_TWI_state.addressMode = TRUE;
99
100
101
102
  if ( !(*msg & (1<<TWI_READ_BIT)) )                // The LSB in the address byte determines if is a masterRead or masterWrite operation.
103
  {
104
    USI_TWI_state.masterWriteDataMode = TRUE;
105
  }
106
107
/* Release SCL to ensure that (repeated) Start can be performed */
108
  PORT_USI |= (1<<PIN_USI_SCL);                     // Release SCL.
109
  while( !(PORT_USI & (1<<PIN_USI_SCL)) );          // Verify that SCL becomes high.
110
111
  _delay_loop_1(T2_TWI);
112
  //_delay_us(T4_TWI);
113
  //__delay_cycles( T2_TWI );                         // Delay for T2TWI if TWI_STANDARD_MODE
114
115
116
/* Generate Start Condition */
117
  PORT_USI &= ~(1<<PIN_USI_SDA);                    // Force SDA LOW.
118
  _delay_loop_1(T4_TWI);
119
  //_delay_us(T4_TWI);
120
  //__delay_cycles( T4_TWI );
121
  PORT_USI &= ~(1<<PIN_USI_SCL);                    // Pull SCL LOW.
122
  PORT_USI |= (1<<PIN_USI_SDA);                     // Release SDA.
123
124
//Start
125
PORTA |= _BV(PA3);
126
127
128
/*Write address and Read/Write data */
129
  do
130
  {
131
    /* If masterWrite cycle (or inital address tranmission)*/
132
    if (USI_TWI_state.addressMode || USI_TWI_state.masterWriteDataMode)
133
    {
134
       PORTA |= _BV(PA4);
135
      /* Write a byte */
136
      PORT_USI &= ~(1<<PIN_USI_SCL);                // Pull SCL LOW.
137
      USIDR     = *(msg++);                        // Setup data.
138
      USI_TWI_Master_Transfer( tempUSISR_8bit );    // Send 8 bits on bus.
139
140
      /* Clock and verify (N)ACK from slave */
141
      DDR_USI  &= ~(1<<PIN_USI_SDA);                // Enable SDA as input.
142
143
      PORTA |= _BV(PA5);
144
145
      if( USI_TWI_Master_Transfer( tempUSISR_1bit ) & (1<<TWI_NACK_BIT) )
146
      {
147
        //Shit
148
        PORTA |= _BV(PA3) | _BV(PA4) | _BV(PA5) | _BV(PA6) | _BV(PA7);
149
150
        if ( USI_TWI_state.addressMode )
151
          USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_ADDRESS;
152
        else
153
          USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_DATA;
154
        return (FALSE);
155
      }
156
      USI_TWI_state.addressMode = FALSE;            // Only perform address transmission once.
157
158
159
      PORTA &= (~_BV(PA4) | ~_BV(PA5));
160
    }
161
    /* Else masterRead cycle*/
162
    else
163
    {
164
      /* Read a data byte */
165
      DDR_USI   &= ~(1<<PIN_USI_SDA);               // Enable SDA as input.
166
      *(msg++)  = USI_TWI_Master_Transfer( tempUSISR_8bit );
167
168
      /* Prepare to generate ACK (or NACK in case of End Of Transmission) */
169
      if( msgSize == 1)                            // If transmission of last byte was performed.
170
      {
171
        USIDR = 0xFF;                              // Load NACK to confirm End Of Transmission.
172
      }
173
      else
174
      {
175
        USIDR = 0x00;                              // Load ACK. Set data register bit 7 (output for SDA) low.
176
      }
177
      USI_TWI_Master_Transfer( tempUSISR_1bit );   // Generate ACK/NACK.
178
    }
179
  }while( --msgSize) ;                             // Until all data sent/received.
180
181
182
  PORTA |= _BV(PA6);
183
184
  USI_TWI_Master_Stop();                           // Send a STOP condition on the TWI bus.
185
186
/* Transmission successfully completed*/
187
  return (TRUE);
188
}
189
190
/*---------------------------------------------------------------
191
 Core function for shifting data in and out from the USI.
192
 Data to be sent has to be placed into the USIDR prior to calling
193
 this function. Data read, will be return'ed from the function.
194
---------------------------------------------------------------*/
195
unsigned char USI_TWI_Master_Transfer( unsigned char temp )
196
{
197
  USISR = temp;                                     // Set USISR according to temp.
198
                                                    // Prepare clocking.
199
  temp  =  (0<<USISIE)|(0<<USIOIE)|                 // Interrupts disabled
200
           (1<<USIWM1)|(0<<USIWM0)|                 // Set USI in Two-wire mode.
201
           (1<<USICS1)|(0<<USICS0)|(1<<USICLK)|     // Software clock strobe as source.
202
           (1<<USITC);                              // Toggle Clock Port.
203
  do
204
  {
205
    //__delay_cycles( T2_TWI );
206
    _delay_loop_1(T2_TWI);
207
    //_delay_us(T2_TWI);
208
    USICR = temp;                          // Generate positve SCL edge.
209
    while( !(PIN_USI & (1<<PIN_USI_SCL)) );// Wait for SCL to go high.
210
    _delay_loop_1(T4_TWI);
211
    //__delay_cycles( T4_TWI );
212
   // _delay_us(T4_TWI);
213
    USICR = temp;                          // Generate negative SCL edge.
214
  }while( !(USISR & (1<<USIOIF)) );        // Check for transfer complete.
215
  _delay_loop_1(T2_TWI);
216
  //_delay_us(T2_TWI);
217
  //__delay_cycles( T2_TWI );
218
  temp  = USIDR;                           // Read out data.
219
  USIDR = 0xFF;                            // Release SDA.
220
  DDR_USI |= (1<<PIN_USI_SDA);             // Enable SDA as output.
221
222
  return temp;                             // Return the data from the USIDR
223
}
224
225
/*---------------------------------------------------------------
226
 Function for generating a TWI Stop Condition. Used to release
227
 the TWI bus.
228
---------------------------------------------------------------*/
229
unsigned char USI_TWI_Master_Stop( void )
230
{
231
  PORT_USI &= ~(1<<PIN_USI_SDA);           // Pull SDA low.
232
  PORT_USI |= (1<<PIN_USI_SCL);            // Release SCL.
233
  while( !(PIN_USI & (1<<PIN_USI_SCL)) );  // Wait for SCL to go high.
234
  _delay_loop_1(T4_TWI);
235
  //_delay_us(T4_TWI);
236
  //__delay_cycles( T4_TWI );
237
  PORT_USI |= (1<<PIN_USI_SDA);            // Release SDA.
238
  _delay_loop_1(T2_TWI);
239
  //_delay_us(T2_TWI);
240
  //__delay_cycles( T2_TWI );
241
242
#ifdef SIGNAL_VERIFY
243
  if( !(USISR & (1<<USIPF)) )
244
  {
245
    USI_TWI_state.errorState = USI_TWI_MISSING_STOP_CON;
246
    return (FALSE);
247
  }
248
#endif
249
250
  return (TRUE);
251
}
252
253
#endif