RT-AICHIP-sample
i2c.c
[詳解]
1 /*****************************************************************************
2  * i2c.c: I2C C file for NXP LPC13xx Family Microprocessors
3  *
4  * Copyright(C) 2008, NXP Semiconductor
5  * All rights reserved.
6  *
7  * History
8  * 2008.07.19 ver 1.00 Preliminary version, first Release
9  *
10 *****************************************************************************/
11 #include "LPC13xx.h" /* LPC134x Peripheral Registers */
12 #include "type.h"
13 #include "i2c.h"
14 
17 
18 volatile uint32_t I2CMode;
19 
22 volatile uint32_t I2CCount = 0;
25 
26 volatile uint32_t RdIndex = 0;
27 volatile uint32_t WrIndex = 0;
28 
29 /*
30 From device to device, the I2C communication protocol may vary,
31 in the example below, the protocol uses repeated start to read data from or
32 write to the device:
33 For master read: the sequence is: STA,Addr(W),offset,RE-STA,Addr(r),data...STO
34 for master write: the sequence is: STA,Addr(W),offset,RE-STA,Addr(w),data...STO
35 Thus, in state 8, the address is always WRITE. in state 10, the address could
36 be READ or WRITE depending on the I2C command.
37 */
38 
39 /*****************************************************************************
40 ** Function name: I2C_IRQHandler
41 **
42 ** Descriptions: I2C interrupt handler, deal with master mode only.
43 **
44 ** parameters: None
45 ** Returned value: None
46 **
47 *****************************************************************************/
48 void I2C_IRQHandler(void)
49 {
50  uint8_t StatValue;
51 
52  /* this handler deals with master read and master write only */
53  StatValue = LPC_I2C->STAT;
54  switch ( StatValue )
55  {
56  case 0x08: /* A Start condition is issued. */
57  WrIndex = 0;
58  LPC_I2C->DAT = I2CMasterBuffer[WrIndex++];
59  LPC_I2C->CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
61  break;
62 
63  case 0x10: /* A repeated started is issued */
64  RdIndex = 0;
65  /* Send SLA with R bit set, */
66  LPC_I2C->DAT = I2CMasterBuffer[WrIndex++];
67  LPC_I2C->CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
69  break;
70 
71  case 0x18: /* Regardless, it's a ACK */
72  if ( I2CMasterState == I2C_STARTED )
73  {
74  LPC_I2C->DAT = I2CMasterBuffer[WrIndex++];
76  }
77  LPC_I2C->CONCLR = I2CONCLR_SIC;
78  break;
79 
80  case 0x28: /* Data byte has been transmitted, regardless ACK or NACK */
81  case 0x30:
82  if ( WrIndex < I2CWriteLength )
83  {
84  LPC_I2C->DAT = I2CMasterBuffer[WrIndex++]; /* this should be the last one */
86  }
87  else
88  {
89  if ( I2CReadLength != 0 )
90  {
91  LPC_I2C->CONSET = I2CONSET_STA; /* Set Repeated-start flag */
93  }
94  else
95  {
97  LPC_I2C->CONSET = I2CONSET_STO; /* Set Stop flag */
98  }
99  }
100  LPC_I2C->CONCLR = I2CONCLR_SIC;
101  break;
102 
103  case 0x40: /* Master Receive, SLA_R has been sent */
104  if ( I2CReadLength == 1 )
105  {
106  /* Will go to State 0x58 */
107  LPC_I2C->CONCLR = I2CONCLR_AAC; /* assert NACK after data is received */
108  }
109  else
110  {
111  /* Will go to State 0x50 */
112  LPC_I2C->CONSET = I2CONSET_AA; /* assert ACK after data is received */
113  }
114  LPC_I2C->CONCLR = I2CONCLR_SIC;
115  break;
116 
117  case 0x50: /* Data byte has been received, regardless following ACK or NACK */
118  I2CSlaveBuffer[RdIndex++] = LPC_I2C->DAT;
119  if ( RdIndex < I2CReadLength )
120  {
122  LPC_I2C->CONSET = I2CONSET_AA; /* assert ACK after data is received */
123  }
124  else
125  {
127  LPC_I2C->CONCLR = I2CONCLR_AAC; /* assert NACK on last byte */
128  }
129  LPC_I2C->CONCLR = I2CONCLR_SIC;
130  break;
131 
132  case 0x58:
133  I2CSlaveBuffer[RdIndex++] = LPC_I2C->DAT;
135  LPC_I2C->CONSET = I2CONSET_STO; /* Set Stop flag */
136  LPC_I2C->CONCLR = I2CONCLR_SIC; /* Clear SI flag */
137  break;
138 
139  case 0x20: /* regardless, it's a NACK */
140  case 0x48:
141  LPC_I2C->CONCLR = I2CONCLR_SIC;
143  break;
144 
145  case 0x38: /* Arbitration lost, in this example, we don't
146  deal with multiple master situation */
147  default:
148  LPC_I2C->CONCLR = I2CONCLR_SIC;
149  break;
150  }
151  return;
152 }
153 
154 /*****************************************************************************
155 ** Function name: I2CStart
156 **
157 ** Descriptions: Create I2C start condition, a timeout
158 ** value is set if the I2C never gets started,
159 ** and timed out. It's a fatal error.
160 **
161 ** parameters: None
162 ** Returned value: true or false, return false if timed out
163 **
164 *****************************************************************************/
166 {
167  uint32_t timeout = 0;
168  uint32_t retVal = FALSE;
169 
170  /*--- Issue a start condition ---*/
171  LPC_I2C->CONSET = I2CONSET_STA; /* Set Start flag */
172 
173  /*--- Wait until START transmitted ---*/
174  while( 1 )
175  {
176  if ( I2CMasterState == I2C_STARTED )
177  {
178  retVal = TRUE;
179  break;
180  }
181  if ( timeout >= MAX_TIMEOUT )
182  {
183  retVal = FALSE;
184  break;
185  }
186  timeout++;
187  }
188  return( retVal );
189 }
190 
191 /*****************************************************************************
192 ** Function name: I2CStop
193 **
194 ** Descriptions: Set the I2C stop condition, if the routine
195 ** never exit, it's a fatal bus error.
196 **
197 ** parameters: None
198 ** Returned value: true or never return
199 **
200 *****************************************************************************/
202 {
203  LPC_I2C->CONSET = I2CONSET_STO; /* Set Stop flag */
204  LPC_I2C->CONCLR = I2CONCLR_SIC; /* Clear SI flag */
205 
206  /*--- Wait for STOP detected ---*/
207  while( LPC_I2C->CONSET & I2CONSET_STO );
208  return TRUE;
209 }
210 
211 /*****************************************************************************
212 ** Function name: I2CInit
213 **
214 ** Descriptions: Initialize I2C controller
215 **
216 ** parameters: I2c mode is either MASTER or SLAVE
217 ** Returned value: true or false, return false if the I2C
218 ** interrupt handler was not installed correctly
219 **
220 *****************************************************************************/
222 {
223  /* It seems to be bit0 is for I2C, different from
224  UM. To be retested along with SSP reset. SSP and I2C
225  reset are overlapped, a known bug, for now, both SSP
226  and I2C use bit 0 for reset enable. Once the problem
227  is fixed, change to "#if 1". */
228 #if 1
229  LPC_SYSCON->PRESETCTRL |= (0x1<<1); //De-asset I2C reset
230 #else
231  LPC_SYSCON->PRESETCTRL |= (0x1<<0);
232 #endif
233  LPC_SYSCON->SYSAHBCLKCTRL |= (1<<5); //Enable for I2C clock
234  LPC_IOCON->PIO0_4 &= ~0x3F; /* I2C I/O config */
235  LPC_IOCON->PIO0_4 |= 0x01; /* I2C SCL */
236  LPC_IOCON->PIO0_5 &= ~0x3F;
237  LPC_IOCON->PIO0_5 |= 0x01; /* I2C SDA */
238 
239  /*--- Clear flags ---*/
240  LPC_I2C->CONCLR = I2CONCLR_AAC | I2CONCLR_SIC | I2CONCLR_STAC | I2CONCLR_I2ENC;
241 
242  /*--- Reset registers ---*/
243 #if FAST_MODE_PLUS
244  LPC_IOCON->PIO0_4 |= (0x1<<9);
245  LPC_IOCON->PIO0_5 |= (0x1<<9);
246  LPC_I2C->SCLL = I2SCLL_HS_SCLL;
247  LPC_I2C->SCLH = I2SCLH_HS_SCLH;
248 #else
249  LPC_I2C->SCLL = I2SCLL_SCLL;
250  LPC_I2C->SCLH = I2SCLH_SCLH;
251 #endif
252 
253  if ( I2cMode == I2CSLAVE )
254  {
255  LPC_I2C->ADR0 = PCF8594_ADDR;
256  }
257 
258  /* Enable the I2C Interrupt */
259  NVIC_EnableIRQ(I2C_IRQn);
260 
261  LPC_I2C->CONSET = I2CONSET_I2EN;
262  return( TRUE );
263 }
264 
265 /*****************************************************************************
266 ** Function name: I2CEngine
267 **
268 ** Descriptions: The routine to complete a I2C transaction
269 ** from start to stop. All the intermitten
270 ** steps are handled in the interrupt handler.
271 ** Before this routine is called, the read
272 ** length, write length, I2C master buffer,
273 ** and I2C command fields need to be filled.
274 ** see i2cmst.c for more details.
275 **
276 ** parameters: None
277 ** Returned value: true or false, return false only if the
278 ** start condition can never be generated and
279 ** timed out.
280 **
281 *****************************************************************************/
283 {
285  RdIndex = 0;
286  WrIndex = 0;
287  if ( I2CStart() != TRUE )
288  {
289  I2CStop();
290  return ( FALSE );
291  }
292 
293  while ( 1 )
294  {
295  if ( I2CMasterState == DATA_NACK )
296  {
297  // I2CStop();
298  break;
299  }
300  }
301 
302  return ( TRUE );
303 }
304 
305 /******************************************************************************
306 ** End Of File
307 ******************************************************************************/
308 
volatile uint32_t WrIndex
Definition: i2c.c:27
uint32_t I2CInit(uint32_t I2cMode)
Definition: i2c.c:221
#define I2CONCLR_AAC
Definition: i2c.h:45
#define MAX_TIMEOUT
Definition: i2c.h:17
volatile uint8_t I2CMasterBuffer[BUFSIZE]
Definition: i2c.c:20
#define I2C_STARTED
Definition: i2c.h:33
#define FALSE
Definition: type.h:39
#define I2CONSET_STO
Definition: i2c.h:42
#define I2CONCLR_I2ENC
Definition: i2c.h:48
uint32_t I2CStart(void)
Definition: i2c.c:165
#define TRUE
Definition: type.h:43
unsigned char uint8_t
Definition: type.h:27
#define I2CONCLR_SIC
Definition: i2c.h:46
volatile uint32_t I2CWriteLength
Definition: i2c.c:24
uint32_t I2CEngine(void)
Definition: i2c.c:282
#define DATA_ACK
Definition: i2c.h:36
volatile uint32_t I2CMasterState
Definition: i2c.c:15
#define DATA_NACK
Definition: i2c.h:37
#define I2C_REPEATED_START
Definition: i2c.h:35
#define I2CONCLR_STAC
Definition: i2c.h:47
uint32_t I2CStop(void)
Definition: i2c.c:201
volatile uint32_t I2CCount
Definition: i2c.c:22
volatile uint32_t RdIndex
Definition: i2c.c:26
#define I2CONSET_I2EN
Definition: i2c.h:39
#define PCF8594_ADDR
Definition: i2c.h:26
#define I2SCLH_HS_SCLH
Definition: i2c.h:54
volatile uint8_t I2CSlaveBuffer[BUFSIZE]
Definition: i2c.c:21
#define I2CONSET_STA
Definition: i2c.h:43
#define I2C_IDLE
Definition: i2c.h:32
#define I2SCLL_HS_SCLL
Definition: i2c.h:55
volatile uint32_t I2CReadLength
Definition: i2c.c:23
#define BUFSIZE
Definition: i2c.h:16
void I2C_IRQHandler(void)
Definition: i2c.c:48
#define I2C_RESTARTED
Definition: i2c.h:34
#define I2CONSET_AA
Definition: i2c.h:40
volatile uint32_t I2CMode
Definition: i2c.c:18
volatile uint32_t I2CSlaveState
Definition: i2c.c:16
#define I2CSLAVE
Definition: i2c.h:20
#define I2SCLL_SCLL
Definition: i2c.h:53
unsigned int uint32_t
Definition: type.h:29
#define I2SCLH_SCLH
Definition: i2c.h:52