| LPCOpen Platform v1.03 LPCOpen Platform for NXP LPC Microcontrollers

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

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
136 /*****************************************************************************
137 * Private types/enumerations/variables
138 ****************************************************************************/
139 #ifdef DEBUG_ENABLE
140 #define DEFAULT_I2C I2C0
141 #else
142 #define DEFAULT_I2C I2C1
143 #endif
144
145 #define I2C_EEPROM_BUS DEFAULT_I2C
146 #define I2C_IOX_BUS DEFAULT_I2C
147
148 #define SPEED_100KHZ 100000
149 #define SPEED_400KHZ 400000
150
151 #ifdef DEBUG_ENABLE
152 static const char menu[] =
153 "**************** I2C Demo Menu ****************\r\n"
154 "\t0: Exit Demo\r\n"
155 "\t1: Select I2C peripheral [\033[1;32mI2C%d\033[0;37m]\r\n"
156 "\t2: Toggle mode POLLING/INTERRUPT [\033[1;32m%s\033[0;37m]\r\n"
157 "\t3: Probe for Slave devices\r\n"
158 "\t4: Read slave data\r\n"
159 "\t5: Write slave data\r\n"
160 "\t6: Write/Read slave data\r\n";
161 #endif
162
163 static int mode_poll; /* Poll/Interrupt mode flag */
164 static I2C_ID_T i2cDev = DEFAULT_I2C; /* Currently active I2C device */
165
166 /* EEPROM SLAVE data */
167 #define I2C_SLAVE_EEPROM_SIZE 64
168 #define I2C_SLAVE_EEPROM_ADDR 0x5A
169 #define I2C_SLAVE_IOX_ADDR 0x5B
170
171 /* Xfer structure for slave operations */
172 static I2C_XFER_T seep_xfer;
173 static I2C_XFER_T iox_xfer;
174
175 /* Data area for slave operations */
176 static uint8_t seep_data[I2C_SLAVE_EEPROM_SIZE + 1];
177 static uint8_t buffer[2][256];
178 static uint8_t iox_data[2]; /* PORT0 input port, PORT1 Output port */
179
180 /*****************************************************************************
181 * Public types/enumerations/variables
182 ****************************************************************************/
183
184 /*****************************************************************************
185 * Private functions
186 ****************************************************************************/
187
188 /* State machine handler for I2C0 and I2C1 */
189 static void i2c_state_handling(I2C_ID_T id)
190 {
191 if (Chip_I2C_IsMasterActive(id)) {
192 Chip_I2C_MasterStateHandler(id);
193 }
194 else {
195 Chip_I2C_SlaveStateHandler(id);
196 }
197 }
198
199 /* Print data to console */
200 static void con_print_data(const uint8_t *dat, int sz)
201 {
202 int i;
203 if (!sz) {
204 return;
205 }
206 for (i = 0; i < sz; i++) {
207 if (!(i & 0xF)) {
208 DEBUGOUT("\r\n%02X: ", i);
209 }
210 DEBUGOUT(" %02X", dat[i]);
211 }
212 DEBUGOUT("\r\n");
213 }
214
215 /* Get an integer input from UART */
216 static int con_get_input(const char *str)
217 {
218 #ifdef DEBUG_ENABLE
219 int input_valid = 0;
220 int x;
221 char ch[16], *ptr;
222 int i = 0;
223
224 while (!input_valid) {
225 DEBUGOUT("%s", str);
226 while (1) {
227 /* Setting poll mode for slave is a very bad idea, it works nevertheless */
228 if ((mode_poll & (1 << i2cDev)) && Chip_I2C_IsStateChanged(i2cDev)) {
229 Chip_I2C_SlaveStateHandler(i2cDev);
230 }
231
232 x = DEBUGIN();
233 if (x == EOF) {
234 continue;
235 }
236 if (i >= sizeof(ch) - 2) {
237 break;
238 }
239 if (((x == '\r') || (x == '\n')) && i) {
240 DEBUGOUT("\r\n");
241 break;
242 }
243 if (x == '\b') {
244 if (i) {
245 DEBUGOUT("\033[1D \033[1D");
246 i--;
247 }
248 continue;
249 }
250 DEBUGOUT("%c", x);
251 ch[i++] = x;
252 }
253 ch[i] = 0;
254 i = strtol(ch, &ptr, 0);
255 if (*ptr) {
256 i = 0;
257 DEBUGOUT("Invalid input. Retry!\r\n");
258 continue;
259 }
260 input_valid = 1;
261 }
262 return i;
263 #else
264 int pressed = 0;
265 volatile uint8_t *pkey = &iox_data[0];
266 static int sind = -1;
267 static uint8_t val[] = {5, I2C_SLAVE_IOX_ADDR, 1, 0};
268 if (sind >= sizeof(val)) {
269 sind = -1;
270 }
271
272 while (sind < 0) {
273 if (*pkey) {
274 pressed = 1;
275 }
276 if (*pkey && pressed) {
277 continue;
278 }
279 if (!*pkey && !pressed) {
280 continue;
281 }
282 pressed = 0;
283 sind = 0;
284 val[3]++; val[3] &= 0x3;
285 }
286 return val[sind++];
287 #endif
288 }
289
290 static void i2c_rw_input(I2C_XFER_T *xfer, int ops)
291 {
292 int tmp, i;
293
294 tmp = con_get_input("Enter 7-Bit Slave address : ");
295 tmp &= 0xFF;
296 xfer->slaveAddr = tmp;
297 xfer->rxBuff = 0;
298 xfer->txBuff = 0;
299 xfer->txSz = 0;
300 xfer->rxSz = 0;
301
302 if (ops & 1) {
303 tmp = con_get_input("Enter number of bytes to read : ");
304 tmp &= 0xFF;
305 xfer->rxSz = tmp;
306 xfer->rxBuff = buffer[1];
307 }
308
309 if (ops & 2) {
310 tmp = con_get_input("Enter number of bytes to write : ");
311 tmp &= 0xFF;
312 for (i = 0; i < tmp; i++) {
313 DEBUGOUT("%d:", i + 1);
314 buffer[0][i] = con_get_input("Enter Data: ");
315 }
316 xfer->txSz = tmp;
317 xfer->txBuff = buffer[0];
318 }
319 }
320
321 /* Set I2C mode to polling/interrupt */
322 static void i2c_set_mode(I2C_ID_T id, int polling)
323 {
324 if (!polling) {
325 mode_poll &= ~(1 << id);
326 Chip_I2C_SetMasterEventHandler(id, Chip_I2C_EventHandler);
327 NVIC_EnableIRQ(id == I2C0 ? I2C0_IRQn : I2C1_IRQn);
328 }
329 else {
330 mode_poll |= 1 << id;
331 NVIC_DisableIRQ(id == I2C0 ? I2C0_IRQn : I2C1_IRQn);
332 Chip_I2C_SetMasterEventHandler(id, Chip_I2C_EventHandlerPolling);
333 }
334 }
335
336 /* Initialize the I2C bus */
337 static void i2c_app_init(I2C_ID_T id, int speed)
338 {
339 Board_I2C_Init(id);
340
341 /* Initialize I2C */
342 Chip_I2C_Init(id);
343 Chip_I2C_SetClockRate(id, speed);
344
345 /* Set default mode to interrupt */
346 i2c_set_mode(id, 0);
347 }
348
349 /* Function that probes all available slaves connected to an I2C bus */
350 static void i2c_probe_slaves(I2C_ID_T i2c)
351 {
352 int i;
353 uint8_t ch[2];
354
355 DEBUGOUT("Probing available I2C devices...\r\n");
356 DEBUGOUT("\r\n 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
357 DEBUGOUT("\r\n====================================================");
358 for (i = 0; i <= 0x7F; i++) {
359 if (!(i & 0x0F)) {
360 DEBUGOUT("\r\n%02X ", i >> 4);
361 }
362 if ((i <= 7) || (i > 0x78)) {
363 DEBUGOUT(" ");
364 continue;
365 }
366 /* Address 0x48 points to LM75AIM device which needs 2 bytes be read */
367 if (Chip_I2C_MasterRead(i2c, i, ch, 1 + (i == 0x48)) > 0) {
368 DEBUGOUT(" %02X", i);
369 }
370 else {
371 DEBUGOUT(" --");
372 }
373 }
374 DEBUGOUT("\r\n");
375 }
376
377 static int i2c_menu(void)
378 {
379 DEBUGOUT(menu, i2cDev, (mode_poll & (1 << i2cDev)) ? "POLLING" : "INTERRUPT");
380 return con_get_input("\r\nSelect an option [0 - 6] :");
381 }
382
383 /* Update the EEPROM state */
384 static void i2c_eeprom_update_state(I2C_XFER_T *xfer, uint8_t *buff, int sz)
385 {
386 xfer->txBuff = xfer->rxBuff = &buff[buff[0] + 1];
387 xfer->rxSz = xfer->txSz = sz - buff[0] + 1; /* one byte more to avoid last byte problem */
388 }
389
390 /* Slave event handler for simulated EEPROM */
391 static void i2c_eeprom_events(I2C_ID_T id, I2C_EVENT_T event)
392 {
393 static int is_addr = 1;
394 switch (event) {
395 case I2C_EVENT_DONE:
396 is_addr = 1;
397 i2c_eeprom_update_state(&seep_xfer, seep_data, I2C_SLAVE_EEPROM_SIZE);
398 seep_xfer.rxBuff = seep_data;
399 seep_xfer.rxSz++;
400 break;
401
402 case I2C_EVENT_SLAVE_RX:
403 if (is_addr) {
404 is_addr = 0;
405 seep_data[0] &= (I2C_SLAVE_EEPROM_SIZE - 1); /* Correct addr if required */
406 i2c_eeprom_update_state(&seep_xfer, seep_data, I2C_SLAVE_EEPROM_SIZE);
407 break;
408 }
409
410 seep_data[0]++;
411 seep_data[0] &= (I2C_SLAVE_EEPROM_SIZE - 1);
412 if (seep_xfer.rxSz == 1) {
413 i2c_eeprom_update_state(&seep_xfer, seep_data, I2C_SLAVE_EEPROM_SIZE);
414 }
415 break;
416
417 case I2C_EVENT_SLAVE_TX:
418 seep_data[0]++;
419 seep_data[0] &= (I2C_SLAVE_EEPROM_SIZE - 1);
420 if (seep_xfer.txSz == 1) {
421 i2c_eeprom_update_state(&seep_xfer, seep_data, I2C_SLAVE_EEPROM_SIZE);
422 }
423 break;
424 }
425 }
426
427 /* Simulate an I2C EEPROM slave */
428 static void i2c_eeprom_init(I2C_ID_T id)
429 {
430 memset(&seep_data[1], 0xFF, I2C_SLAVE_EEPROM_SIZE);
431 seep_xfer.slaveAddr = (I2C_SLAVE_EEPROM_ADDR << 1);
432 seep_xfer.txBuff = &seep_data[1];
433 seep_xfer.rxBuff = seep_data;
434 seep_xfer.txSz = seep_xfer.rxSz = sizeof(seep_data);
435 Chip_I2C_SlaveSetup(id, I2C_SLAVE_0, &seep_xfer, i2c_eeprom_events, 0);
436 }
437
438 /*-------- IO Expansion slave device implementation ----------*/
439 /* Update IN/OUT port states to real devices */
440 void i2c_iox_update_regs(int ops)
441 {
442 if (ops & 1) { /* update out port */
443 Board_LED_Set(0, iox_data[1] & 1);
444 Board_LED_Set(1, iox_data[1] & 2);
445 Board_LED_Set(2, iox_data[1] & 4);
446 Board_LED_Set(3, iox_data[1] & 8);
447 }
448
449 if (ops & 2) { /* update in port */
450 iox_data[0] = (uint8_t) Buttons_GetStatus();
451 }
452 }
453
454 /* Slave event handler for simulated EEPROM */
455 static void i2c_iox_events(I2C_ID_T id, I2C_EVENT_T event)
456 {
457 switch (event) {
458 case I2C_EVENT_DONE:
459 iox_xfer.rxBuff = &iox_data[1];
460 iox_xfer.rxSz = sizeof(iox_data); /* one byte more to avoid last byte problem */
461 iox_xfer.txBuff = (const uint8_t *) iox_data;
462 iox_xfer.txSz = sizeof(iox_data) + 1; /* one byte more to avoid last byte problem */
463 break;
464
465 case I2C_EVENT_SLAVE_RX:
466 iox_xfer.rxBuff = &iox_data[1];
467 iox_xfer.rxSz = sizeof(iox_data); /* one byte more to avoid last byte problem */
468 i2c_iox_update_regs(1);
469 break;
470
471 case I2C_EVENT_SLAVE_TX:
472 if (iox_xfer.txSz == 1) {
473 iox_xfer.txBuff = (const uint8_t *) iox_data[0];
474 iox_xfer.txSz = sizeof(iox_data) + 1; /* one byte more to avoid last byte problem */
475 }
476 break;
477 }
478 }
479
480 /* Simulate an IO Expansion slave device */
481 static void i2c_iox_init(I2C_ID_T id)
482 {
483 Board_Buttons_Init();
484 iox_xfer.slaveAddr = (I2C_SLAVE_IOX_ADDR << 1);
485 i2c_iox_events(id, I2C_EVENT_DONE);
486 Chip_I2C_SlaveSetup(id, I2C_SLAVE_1, &iox_xfer, i2c_iox_events, 0);
487 i2c_iox_update_regs(3);
488 /* Setup SysTick timer to get the button status updated at regular intervals */
489 SysTick_Config(Chip_Clock_GetRate(CLK_MX_MXCORE) / 50);
490 }
491
492 /*-------------------- End of IO Expansion slave device ----------------------*/
493
494 /*****************************************************************************
495 * Public functions
496 ****************************************************************************/
502 void SysTick_Handler(void)
503 {
504 i2c_iox_update_regs(2);
505 }
506
511 void I2C1_IRQHandler(void)
512 {
513 i2c_state_handling(I2C1);
514 }
515
520 void I2C0_IRQHandler(void)
521 {
522 i2c_state_handling(I2C0);
523 }
524
529 int main(void)
530 {
531 int tmp;
532 int xflag = 0;
533 static I2C_XFER_T xfer;
534
535 Board_Init();
536 i2c_app_init(I2C0, SPEED_100KHZ);
537 i2c_app_init(I2C1, SPEED_100KHZ);
538
539 /* Simulate an EEPROM slave in I2C0 */
540 i2c_eeprom_init(I2C_EEPROM_BUS);
541
542 /* Simuldate an IO Expansion slave in I2C0 */
543 i2c_iox_init(I2C_IOX_BUS);
544
545 while (!xflag) {
546 switch (i2c_menu()) {
547 case 0:
548 xflag = 1;
549 DEBUGOUT("End of I2C Demo! Bye!\r\n");
550 break;
551
552 case 1:
553 tmp = con_get_input("Select I2C device [0 or 1] : ");
554 DEBUGOUT("\r\n");
555 if ((I2C_ID_T) tmp == I2C0) {
556 if (i2cDev == I2C0) {
557 break;
558 }
559 i2c_set_mode(I2C0, 0);
560 i2cDev = I2C0;
561 }
562 else if ((I2C_ID_T) tmp == I2C1) {
563 if (i2cDev == I2C1) {
564 break;
565 }
566 i2c_set_mode(I2C1, 0);
567 i2cDev = I2C1;
568 }
569 else {
570 DEBUGOUT("Invalid I2C Device [Must be 0 or 1]\r\n");
571 }
572 break;
573
574 case 2:
575 i2c_set_mode(i2cDev, !(mode_poll & (1 << i2cDev)));
576 break;
577
578 case 3:
579 i2c_probe_slaves(i2cDev);
580 break;
581
582 case 4:
583 i2c_rw_input(&xfer, 1);
584 tmp = Chip_I2C_MasterRead(i2cDev, xfer.slaveAddr, xfer.rxBuff, xfer.rxSz);
585 DEBUGOUT("Read %d bytes of data from slave 0x%02X.\r\n", tmp, xfer.slaveAddr);
586 con_print_data(buffer[1], tmp);
587 break;
588
589 case 5:
590 i2c_rw_input(&xfer, 2);
591 if (xfer.txSz == 0) {
592 break;
593 }
594 tmp = Chip_I2C_MasterSend(i2cDev, xfer.slaveAddr, xfer.txBuff, xfer.txSz);
595 DEBUGOUT("Written %d bytes of data to slave 0x%02X.\r\n", tmp, xfer.slaveAddr);
596 break;
597
598 case 6:
599 i2c_rw_input(&xfer, 3);
600 tmp = xfer.rxSz;
601 if (!tmp && !xfer.txSz) {
602 break;
603 }
604 Chip_I2C_MasterTransfer(i2cDev, &xfer);
605 DEBUGOUT("Master transfer : %s\r\n",
606 xfer.status == I2C_STATUS_DONE ? "SUCCESS" : "FAILURE");
607 DEBUGOUT("Received %d bytes from slave 0x%02X\r\n", tmp - xfer.rxSz, xfer.slaveAddr);
608 con_print_data(buffer[1], tmp - xfer.rxSz);
609 break;
610
611 default:
612 DEBUGOUT("Input Invalid! Try Again.\r\n");
613 }
614 }
615 Chip_I2C_DeInit(I2C0);
616 Chip_I2C_DeInit(I2C1);
617
618 return 0;
619 }
620