1 | #include <avr/io.h>
|
2 | #include <avr/interrupt.h>
|
3 | #include "TWI_Master.h"
|
4 |
|
5 | static unsigned char TWI_buf[ TWI_BUFFER_SIZE ]; // Transceiver buffer
|
6 | static unsigned char TWI_msgSize; // Number of bytes to be transmitted.
|
7 | static unsigned char TWI_state = TWI_NO_STATE; // State byte. Default set to TWI_NO_STATE.
|
8 |
|
9 | union TWI_statusReg TWI_statusReg = {0}; // TWI_statusReg is defined in TWI_Master.h
|
10 |
|
11 | /****************************************************************************
|
12 | Call this function to set up the TWI master to its initial standby state.
|
13 | Remember to enable interrupts from the main application after initializing the TWI.
|
14 | ****************************************************************************/
|
15 | void TWI_Master_Initialise(void)
|
16 | {
|
17 | TWBR = TWI_TWBR; // Set bit rate register (Baud rate). Defined in header file.Driver presumes prescaler to be 00.
|
18 | TWDR = 0xFF; // Default content = SDA released.
|
19 | TWCR = (1<<TWEN)| // Enable TWI-interface and release TWI pins.
|
20 | (0<<TWIE)|(0<<TWINT)| // Disable Interrupt.
|
21 | (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // No Signal requests.
|
22 | (0<<TWWC); //
|
23 | }
|
24 |
|
25 | /****************************************************************************
|
26 | Call this function to test if the TWI_ISR is busy transmitting.
|
27 | ****************************************************************************/
|
28 | unsigned char TWI_Transceiver_Busy( void )
|
29 | {
|
30 | return ( TWCR & (1<<TWIE) ); // IF TWI Interrupt is enabled then the Transceiver is busy
|
31 | }
|
32 |
|
33 | /****************************************************************************
|
34 | Call this function to fetch the state information of the previous operation. The function will hold execution (loop)
|
35 | until the TWI_ISR has completed with the previous operation. If there was an error, then the function
|
36 | will return the TWI State code.
|
37 | ****************************************************************************/
|
38 | unsigned char TWI_Get_State_Info( void )
|
39 | {
|
40 | while ( TWI_Transceiver_Busy() ); // Wait until TWI has completed the transmission.
|
41 | return ( TWI_state ); // Return error state.
|
42 | }
|
43 |
|
44 | /****************************************************************************
|
45 | Call this function to send a prepared message. The first byte must contain the slave address and the
|
46 | read/write bit. Consecutive bytes contain the data to be sent, or empty locations for data to be read
|
47 | from the slave. Also include how many bytes that should be sent/read including the address byte.
|
48 | The function will hold execution (loop) until the TWI_ISR has completed with the previous operation,
|
49 | then initialize the next operation and return.
|
50 | ****************************************************************************/
|
51 | void TWI_Start_Transceiver_With_Data( unsigned char *msg, unsigned char msgSize )
|
52 | {
|
53 | unsigned char temp;
|
54 |
|
55 | while ( TWI_Transceiver_Busy() ); // Wait until TWI is ready for next transmission.
|
56 |
|
57 | TWI_msgSize = msgSize; // Number of data to transmit.
|
58 | TWI_buf[0] = msg[0]; // Store slave address with R/W setting.
|
59 | if (!( msg[0] & (TRUE<<TWI_READ_BIT) )) // If it is a write operation, then also copy data.
|
60 | {
|
61 | for ( temp = 1; temp < msgSize; temp++ )
|
62 | TWI_buf[ temp ] = msg[ temp ];
|
63 | }
|
64 | TWI_statusReg.all = 0;
|
65 | TWI_state = TWI_NO_STATE ;
|
66 | TWCR = (1<<TWEN)| // TWI Interface enabled.
|
67 | (1<<TWIE)|(1<<TWINT)| // Enable TWI Interrupt and clear the flag.
|
68 | (0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)| // Initiate a START condition.
|
69 | (0<<TWWC); //
|
70 | }
|
71 |
|
72 | /****************************************************************************
|
73 | Call this function to resend the last message. The driver will reuse the data previously put in the transceiver buffers.
|
74 | The function will hold execution (loop) until the TWI_ISR has completed with the previous operation,
|
75 | then initialize the next operation and return.
|
76 | ****************************************************************************/
|
77 | void TWI_Start_Transceiver( void )
|
78 | {
|
79 | while ( TWI_Transceiver_Busy() ); // Wait until TWI is ready for next transmission.
|
80 | TWI_statusReg.all = 0;
|
81 | TWI_state = TWI_NO_STATE ;
|
82 | TWCR = (1<<TWEN)| // TWI Interface enabled.
|
83 | (1<<TWIE)|(1<<TWINT)| // Enable TWI Interrupt and clear the flag.
|
84 | (0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)| // Initiate a START condition.
|
85 | (0<<TWWC); //
|
86 | }
|
87 |
|
88 | /****************************************************************************
|
89 | Call this function to read out the requested data from the TWI transceiver buffer. I.e. first call
|
90 | TWI_Start_Transceiver to send a request for data to the slave. Then Run this function to collect the
|
91 | data when they have arrived. Include a pointer to where to place the data and the number of bytes
|
92 | requested (including the address field) in the function call. The function will hold execution (loop)
|
93 | until the TWI_ISR has completed with the previous operation, before reading out the data and returning.
|
94 | If there was an error in the previous transmission the function will return the TWI error code.
|
95 | ****************************************************************************/
|
96 | unsigned char TWI_Get_Data_From_Transceiver( unsigned char *msg, unsigned char msgSize )
|
97 | {
|
98 | unsigned char i;
|
99 |
|
100 | while ( TWI_Transceiver_Busy() ); // Wait until TWI is ready for next transmission.
|
101 |
|
102 | if( TWI_statusReg.lastTransOK ) // Last transmission competed successfully.
|
103 | {
|
104 | for ( i=0; i<msgSize; i++ ) // Copy data from Transceiver buffer.
|
105 | {
|
106 | msg[ i ] = TWI_buf[ i ];
|
107 | }
|
108 | }
|
109 | return( TWI_statusReg.lastTransOK );
|
110 | }
|
111 |
|
112 | // ********** Interrupt Handlers ********** //
|
113 | /****************************************************************************
|
114 | This function is the Interrupt Service Routine (ISR), and called when the TWI interrupt is triggered;
|
115 | that is whenever a TWI event has occurred. This function should not be called directly from the main
|
116 | application.
|
117 | ****************************************************************************/
|
118 | ISR(TWI_vect)
|
119 | {
|
120 | static unsigned char TWI_bufPtr;
|
121 |
|
122 | switch (TWSR)
|
123 | {
|
124 | case TWI_START: // START has been transmitted
|
125 | case TWI_REP_START: // Repeated START has been transmitted
|
126 | TWI_bufPtr = 0; // Set buffer pointer to the TWI Address location
|
127 | case TWI_MTX_ADR_ACK: // SLA+W has been transmitted and ACK received
|
128 | case TWI_MTX_DATA_ACK: // Data byte has been transmitted and ACK received
|
129 | if (TWI_bufPtr < TWI_msgSize)
|
130 | {
|
131 | TWDR = TWI_buf[TWI_bufPtr++];
|
132 | TWCR = (1<<TWEN)| // TWI Interface enabled
|
133 | (1<<TWIE)|(1<<TWINT)| // Enable TWI Interrupt and clear the flag to send byte
|
134 | (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| //
|
135 | (0<<TWWC); //
|
136 | }else // Send STOP after last byte
|
137 | {
|
138 | TWI_statusReg.lastTransOK = TRUE; // Set status bits to completed successfully.
|
139 | TWCR = (1<<TWEN)| // TWI Interface enabled
|
140 | (0<<TWIE)|(1<<TWINT)| // Disable TWI Interrupt and clear the flag
|
141 | (0<<TWEA)|(0<<TWSTA)|(1<<TWSTO)| // Initiate a STOP condition.
|
142 | (0<<TWWC); //
|
143 | }
|
144 | break;
|
145 | case TWI_MRX_DATA_ACK: // Data byte has been received and ACK transmitted
|
146 | TWI_buf[TWI_bufPtr++] = TWDR;
|
147 | case TWI_MRX_ADR_ACK: // SLA+R has been transmitted and ACK received
|
148 | if (TWI_bufPtr < (TWI_msgSize-1) ) // Detect the last byte to NACK it.
|
149 | {
|
150 | TWCR = (1<<TWEN)| // TWI Interface enabled
|
151 | (1<<TWIE)|(1<<TWINT)| // Enable TWI Interrupt and clear the flag to read next byte
|
152 | (1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // Send ACK after reception
|
153 | (0<<TWWC); //
|
154 | }else // Send NACK after next reception
|
155 | {
|
156 | TWCR = (1<<TWEN)| // TWI Interface enabled
|
157 | (1<<TWIE)|(1<<TWINT)| // Enable TWI Interrupt and clear the flag to read next byte
|
158 | (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // Send NACK after reception
|
159 | (0<<TWWC); //
|
160 | }
|
161 | break;
|
162 | case TWI_MRX_DATA_NACK: // Data byte has been received and NACK transmitted
|
163 | TWI_buf[TWI_bufPtr] = TWDR;
|
164 | TWI_statusReg.lastTransOK = TRUE; // Set status bits to completed successfully.
|
165 | TWCR = (1<<TWEN)| // TWI Interface enabled
|
166 | (0<<TWIE)|(1<<TWINT)| // Disable TWI Interrupt and clear the flag
|
167 | (0<<TWEA)|(0<<TWSTA)|(1<<TWSTO)| // Initiate a STOP condition.
|
168 | (0<<TWWC); //
|
169 | break;
|
170 | case TWI_ARB_LOST: // Arbitration lost
|
171 | TWCR = (1<<TWEN)| // TWI Interface enabled
|
172 | (1<<TWIE)|(1<<TWINT)| // Enable TWI Interrupt and clear the flag
|
173 | (0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)| // Initiate a (RE)START condition.
|
174 | (0<<TWWC); //
|
175 | break;
|
176 | case TWI_MTX_ADR_NACK: // SLA+W has been transmitted and NACK received
|
177 | case TWI_MRX_ADR_NACK: // SLA+R has been transmitted and NACK received
|
178 | case TWI_MTX_DATA_NACK: // Data byte has been transmitted and NACK received
|
179 | case TWI_BUS_ERROR: // Bus error due to an illegal START or STOP condition
|
180 | default:
|
181 | TWI_state = TWSR; // Store TWSR and automatically sets clears noErrors bit.
|
182 | // Reset TWI Interface
|
183 | TWCR = (1<<TWEN)| // Enable TWI-interface and release TWI pins
|
184 | (0<<TWIE)|(0<<TWINT)| // Disable Interrupt
|
185 | (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // No Signal requests
|
186 | (0<<TWWC); //
|
187 | }
|
188 | }
|