LPCOpen Platform  v1.03
LPCOpen Platform for NXP LPC Microcontrollers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
i2c.c
Go to the documentation of this file.
1 /*
2  * @brief I2C example
3  * This example show how to use the I2C interface
4  *
5  * @note
6  * Copyright(C) NXP Semiconductors, 2012
7  * All rights reserved.
8  *
9  * @par
10  * Software that is described herein is for illustrative purposes only
11  * which provides customers with programming information regarding the
12  * LPC products. This software is supplied "AS IS" without any warranties of
13  * any kind, and NXP Semiconductors and its licensor disclaim any and
14  * all warranties, express or implied, including all implied warranties of
15  * merchantability, fitness for a particular purpose and non-infringement of
16  * intellectual property rights. NXP Semiconductors assumes no responsibility
17  * or liability for the use of the software, conveys no license or rights under any
18  * patent, copyright, mask work right, or any other intellectual property rights in
19  * or to any products. NXP Semiconductors reserves the right to make changes
20  * in the software without notification. NXP Semiconductors also makes no
21  * representation or warranty that such application will be suitable for the
22  * specified use without further testing or modification.
23  *
24  * @par
25  * Permission to use, copy, modify, and distribute this software and its
26  * documentation is hereby granted, under NXP Semiconductors' and its
27  * licensor's relevant copyrights in the software, without fee, provided that it
28  * is used in conjunction with NXP Semiconductors microcontrollers. This
29  * copyright, permission, and disclaimer notice must appear in all copies of
30  * this code.
31  */
32 
33 #include <stdlib.h>
34 #include <string.h>
35 #include "board.h"
36 
129 /*****************************************************************************
130  * Private types/enumerations/variables
131  ****************************************************************************/
132 #define DEFAULT_I2C I2C0
133 
134 #define I2C_EEPROM_BUS DEFAULT_I2C
135 #define I2C_IOX_BUS DEFAULT_I2C
136 
137 #define SPEED_100KHZ 100000
138 #define SPEED_400KHZ 400000
139 
140 #ifdef DEBUG_ENABLE
141 static const char menu[] =
142 "**************** I2C Demo Menu ****************\r\n"
143 "\t0: Exit Demo\r\n"
144 "\t1: Select I2C peripheral [\033[1;32mI2C%d\033[0;37m]\r\n"
145 "\t2: Toggle mode POLLING/INTERRUPT [\033[1;32m%s\033[0;37m]\r\n"
146 "\t3: Probe for Slave devices\r\n"
147 "\t4: Read slave data\r\n"
148 "\t5: Write slave data\r\n"
149 "\t6: Write/Read slave data\r\n";
150 #endif
151 
152 static int mode_poll; /* Poll/Interrupt mode flag */
153 static I2C_ID_T i2cDev = DEFAULT_I2C; /* Currently active I2C device */
154 
155 /* EEPROM SLAVE data */
156 #define I2C_SLAVE_EEPROM_SIZE 64
157 #define I2C_SLAVE_EEPROM_ADDR 0x5A
158 #define I2C_SLAVE_IOX_ADDR 0x5B
159 
160 /* Xfer structure for slave operations */
163 
164 /* Data area for slave operations */
165 static uint8_t seep_data[I2C_SLAVE_EEPROM_SIZE + 1];
166 static uint8_t buffer[2][256];
167 static uint8_t iox_data[2]; /* PORT0 input port, PORT1 Output port */
168 
169 /*****************************************************************************
170  * Public types/enumerations/variables
171  ****************************************************************************/
172 
173 /*****************************************************************************
174  * Private functions
175  ****************************************************************************/
176 
177 /* State machine handler for I2C0 and I2C1 */
179 {
180  if (Chip_I2C_IsMasterActive(id)) {
182  } else {
184  }
185 }
186 
187 /* Print data to console */
188 static void con_print_data(const uint8_t *dat, int sz)
189 {
190  int i;
191  if (!sz) return;
192  for (i = 0; i < sz; i++) {
193  if (!(i & 0xF)) DEBUGOUT("\r\n%02X: ", i);
194  DEBUGOUT(" %02X", dat[i]);
195  }
196  DEBUGOUT("\r\n");
197 }
198 
199 /* Get an integer input from UART */
200 static int con_get_input(const char *str)
201 {
202 #ifdef DEBUG_ENABLE
203  int input_valid = 0;
204  int x;
205  char ch[16], *ptr;
206  int i = 0;
207 
208  while (!input_valid) {
209  DEBUGOUT("%s", str);
210  while(1) {
211  /* Setting poll mode for slave is a very bad idea, it works nevertheless */
212  if((mode_poll & (1 << i2cDev)) && Chip_I2C_IsStateChanged(i2cDev)) {
214  }
215 
216  x = DEBUGIN();
217  if (x == EOF) continue;
218  if (i >= sizeof(ch) - 2) break;
219  if ((x == '\r' || x == '\n') && i) {
220  DEBUGOUT("\r\n");
221  break;
222  }
223  if (x == '\b') {
224  if (i) {
225  DEBUGOUT("\033[1D \033[1D");
226  i --;
227  }
228  continue;
229  }
230  DEBUGOUT("%c", x);
231  ch[i++] = x;
232  };
233  ch[i] = 0;
234  i = strtol(ch, &ptr, 0);
235  if (*ptr) {
236  i = 0;
237  DEBUGOUT("Invalid input. Retry!\r\n");
238  continue;
239  }
240  input_valid = 1;
241  }
242  return i;
243 #else
244  static int sind = 0;
245  static uint8_t val[] = {1, 1, 5, I2C_SLAVE_IOX_ADDR, 1, 1, 0};
246  while(!val[sind]);
247 
248  return val[sind++];
249 #endif
250 }
251 
252 static void i2c_rw_input(I2C_XFER_T *xfer, int ops)
253 {
254  int tmp, i;
255 
256  tmp = con_get_input("Enter 7-Bit Slave address : ");
257  tmp &= 0xFF;
258  xfer->slaveAddr = tmp;
259  xfer->rxBuff = 0;
260  xfer->txBuff = 0;
261  xfer->txSz = 0;
262  xfer->rxSz = 0;
263 
264  if (ops & 1) {
265  tmp = con_get_input("Enter number of bytes to read : ");
266  tmp &= 0xFF;
267  xfer->rxSz = tmp;
268  xfer->rxBuff = buffer[1];
269  }
270 
271  if (ops & 2) {
272  tmp = con_get_input("Enter number of bytes to write : ");
273  tmp &= 0xFF;
274  for (i = 0; i < tmp; i++) {
275  DEBUGOUT("%d:", i + 1);
276  buffer[0][i] = con_get_input("Enter Data: ");
277  }
278  xfer->txSz = tmp;
279  xfer->txBuff = buffer[0];
280  }
281 }
282 
283 /* Set I2C mode to polling/interrupt */
284 static void i2c_set_mode(I2C_ID_T id, int polling)
285 {
286  if(!polling) {
287  mode_poll &= ~(1 << id);
289  NVIC_EnableIRQ(id == I2C0 ? I2C0_IRQn : I2C1_IRQn);
290  } else {
291  mode_poll |= 1 << id;
292  NVIC_DisableIRQ(id == I2C0 ? I2C0_IRQn : I2C1_IRQn);
294  }
295 }
296 
297 /* Initialize the I2C bus */
298 static void i2c_app_init(I2C_ID_T id, int speed)
299 {
300  Board_I2C_Init(id);
301 
302  /* Initialize I2C */
303  Chip_I2C_Init(id);
304  Chip_I2C_SetClockRate(id, speed);
305 
306  /* Set default mode to interrupt */
307  i2c_set_mode(id, 0);
308 }
309 
310 /* Function that probes all available slaves connected to an I2C bus */
312 {
313  int i;
314  uint8_t ch[2];
315 
316  DEBUGOUT("Probing available I2C devices...\r\n");
317  DEBUGOUT("\r\n 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
318  DEBUGOUT("\r\n====================================================");
319  for (i = 0; i <= 0x7F; i++) {
320  if (!(i & 0x0F)) DEBUGOUT("\r\n%02X ", i >> 4);
321  if (i <= 7 || i > 0x78) {
322  DEBUGOUT(" ");
323  continue;
324  }
325  /* Address 0x48 points to LM75AIM device which needs 2 bytes be read */
326  if(Chip_I2C_MasterRead(i2c, i, ch, 1 + (i == 0x48)) > 0)
327  DEBUGOUT(" %02X", i);
328  else
329  DEBUGOUT(" --");
330  }
331  DEBUGOUT("\r\n");
332 }
333 
334 static int i2c_menu(void)
335 {
336  DEBUGOUT(menu, i2cDev, (mode_poll & (1 << i2cDev)) ? "POLLING" : "INTERRUPT");
337  return con_get_input("\r\nSelect an option [0 - 6] :");
338 }
339 
340 /* Update the EEPROM state */
341 static void i2c_eeprom_update_state(I2C_XFER_T *xfer, uint8_t *buff, int sz)
342 {
343  xfer->txBuff = xfer->rxBuff = &buff[buff[0]+1];
344  xfer->rxSz = xfer->txSz = sz - buff[0] + 1;
345 }
346 
347 /* Slave event handler for simulated EEPROM */
349 {
350  static int is_addr = 1;
351  switch(event) {
352  case I2C_EVENT_DONE:
353  is_addr = 1;
355  seep_xfer.rxBuff = seep_data;
356  seep_xfer.rxSz ++;
357  break;
358 
359  case I2C_EVENT_SLAVE_RX:
360  if (is_addr) {
361  is_addr = 0;
362  seep_data[0] &= (I2C_SLAVE_EEPROM_SIZE - 1); /* Correct addr if required */
364  break;
365  }
366 
367  seep_data[0] ++;
368  seep_data[0] &= (I2C_SLAVE_EEPROM_SIZE - 1);
369  if (seep_xfer.rxSz == 1)
371  break;
372 
373  case I2C_EVENT_SLAVE_TX:
374  seep_data[0] ++;
375  seep_data[0] &= (I2C_SLAVE_EEPROM_SIZE - 1);
376  if (seep_xfer.txSz == 1)
378  break;
379  }
380 }
381 
382 /* Simulate an I2C EEPROM slave */
383 static void i2c_eeprom_init(I2C_ID_T id)
384 {
385  memset(&seep_data[1], 0xFF, I2C_SLAVE_EEPROM_SIZE);
386  seep_xfer.slaveAddr = (I2C_SLAVE_EEPROM_ADDR << 1);
387  seep_xfer.txBuff = &seep_data[1];
388  seep_xfer.rxBuff = seep_data;
389  seep_xfer.txSz = seep_xfer.rxSz = sizeof(seep_data);
391 }
392 /*-------- IO Expansion slave device implementation ----------*/
393 /* Update IN/OUT port states to real devices */
394 void i2c_iox_update_regs(int ops)
395 {
396  if (ops & 1) { /* update out port */
397  Board_LED_Set(0, iox_data[1] & 1);
398  Board_LED_Set(1, iox_data[1] & 2);
399  Board_LED_Set(2, iox_data[1] & 4);
400  Board_LED_Set(3, iox_data[1] & 8);
401  }
402 
403  if (ops & 2) { /* update in port */
404  iox_data[0] = (uint8_t) Buttons_GetStatus();
405  }
406 }
407 
408 /* Slave event handler for simulated EEPROM */
410 {
411  switch(event) {
412  case I2C_EVENT_DONE:
413  iox_xfer.rxBuff = &iox_data[1];
414  iox_xfer.rxSz = sizeof(iox_data);
415  iox_xfer.txBuff = (const uint8_t *)iox_data;
416  iox_xfer.txSz = sizeof(iox_data) + 1;
417  break;
418 
419  case I2C_EVENT_SLAVE_RX:
420  iox_xfer.rxBuff = &iox_data[1];
421  iox_xfer.rxSz = sizeof(iox_data);
423  break;
424 
425  case I2C_EVENT_SLAVE_TX:
426  if(iox_xfer.txSz == 1) {
427  iox_xfer.txBuff = (const uint8_t *)iox_data[0];
428  iox_xfer.txSz = sizeof(iox_data) + 1;
429  }
430  break;
431  }
432 }
433 
434 /* Simulate an IO Expansion slave device */
435 static void i2c_iox_init(I2C_ID_T id)
436 {
438  iox_xfer.slaveAddr = (I2C_SLAVE_IOX_ADDR << 1);
440  Chip_I2C_SlaveSetup(id, I2C_SLAVE_1, &iox_xfer, i2c_iox_events, 0);
442  /* Setup SysTick timer to get the button status updated at regular intervals */
443  SysTick_Config(Chip_Clock_GetSystemClockRate() / 50);
444 }
445 
446 /*-------------------- End of IO Expansion slave device ----------------------*/
447 
448 /*****************************************************************************
449  * Public functions
450  ****************************************************************************/
456 void SysTick_Handler(void)
457 {
459 }
460 
465 void I2C1_IRQHandler(void)
466 {
468 }
469 
474 void I2C0_IRQHandler(void)
475 {
477 }
478 
483 int main(void)
484 {
485  int tmp;
486  int xflag = 0;
487  static I2C_XFER_T xfer;
488 
489  Board_Init();
492 
493  /* Simulate an EEPROM slave in I2C0 */
495 
496  /* Simuldate an IO Expansion slave in I2C0 */
498 
499  while (!xflag) {
500  switch(i2c_menu()) {
501  case 0:
502  xflag = 1;
503  DEBUGOUT("End of I2C Demo! Bye!\r\n");
504  break;
505 
506  case 1:
507  tmp = con_get_input("Select I2C device [0 or 1] : ");
508  DEBUGOUT("\r\n");
509  if ((I2C_ID_T) tmp == I2C0) {
510  if (i2cDev == I2C0) break;
511  i2c_set_mode(I2C0, 0);
512  i2cDev = I2C0;
513  }
514  else if((I2C_ID_T) tmp == I2C1) {
515  if (i2cDev == I2C1) break;
516  i2c_set_mode(I2C1, 0);
517  i2cDev = I2C1;
518  }
519  else
520  DEBUGOUT("Invalid I2C Device [Must be 0 or 1]\r\n");
521  break;
522 
523  case 2:
524  i2c_set_mode(i2cDev, !(mode_poll & (1 << i2cDev)));
525  break;
526 
527  case 3:
529  break;
530 
531  case 4:
532  i2c_rw_input(&xfer, 1);
533  tmp = Chip_I2C_MasterRead(i2cDev, xfer.slaveAddr, xfer.rxBuff, xfer.rxSz);
534  DEBUGOUT("Read %d bytes of data from slave 0x%02X.\r\n", tmp, xfer.slaveAddr);
535  con_print_data(buffer[1], tmp);
536  break;
537 
538  case 5:
539  i2c_rw_input(&xfer, 2);
540  if (xfer.txSz == 0) break;
541  tmp = Chip_I2C_MasterSend(i2cDev, xfer.slaveAddr, xfer.txBuff, xfer.txSz);
542  DEBUGOUT("Written %d bytes of data to slave 0x%02X.\r\n", tmp, xfer.slaveAddr);
543  break;
544 
545  case 6:
546  i2c_rw_input(&xfer, 3);
547  tmp = xfer.rxSz;
548  if (!tmp && !xfer.txSz) break;
550  DEBUGOUT("Master transfer : %s\r\n",
551  xfer.status == I2C_STATUS_DONE ? "SUCCESS" : "FAILURE");
552  DEBUGOUT("Received %d bytes from slave 0x%02X\r\n", tmp - xfer.rxSz, xfer.slaveAddr);
553  con_print_data(buffer[1], tmp - xfer.rxSz);
554  break;
555 
556  default:
557  DEBUGOUT("Input Invalid! Try Again.\r\n");
558  }
559  }
562 
563  return 0;
564 }
565