| 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
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 */
161 static I2C_XFER_T seep_xfer;
162 static I2C_XFER_T iox_xfer;
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 */
178 static void i2c_state_handling(I2C_ID_T id)
179 {
180 if (Chip_I2C_IsMasterActive(id)) {
181 Chip_I2C_MasterStateHandler(id);
182 } else {
183 Chip_I2C_SlaveStateHandler(id);
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)) {
213 Chip_I2C_SlaveStateHandler(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);
288 Chip_I2C_SetMasterEventHandler(id, Chip_I2C_EventHandler);
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);
293 Chip_I2C_SetMasterEventHandler(id, Chip_I2C_EventHandlerPolling);
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 */
311 static void i2c_probe_slaves(I2C_ID_T i2c)
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 */
348 static void i2c_eeprom_events(I2C_ID_T id, I2C_EVENT_T event)
349 {
350 static int is_addr = 1;
351 switch(event) {
352 case I2C_EVENT_DONE:
353 is_addr = 1;
354 i2c_eeprom_update_state(&seep_xfer, seep_data, I2C_SLAVE_EEPROM_SIZE);
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 */
363 i2c_eeprom_update_state(&seep_xfer, seep_data, I2C_SLAVE_EEPROM_SIZE);
364 break;
365 }
366
367 seep_data[0] ++;
368 seep_data[0] &= (I2C_SLAVE_EEPROM_SIZE - 1);
369 if (seep_xfer.rxSz == 1)
370 i2c_eeprom_update_state(&seep_xfer, seep_data, I2C_SLAVE_EEPROM_SIZE);
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)
377 i2c_eeprom_update_state(&seep_xfer, seep_data, I2C_SLAVE_EEPROM_SIZE);
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);
390 Chip_I2C_SlaveSetup(id, I2C_SLAVE_0, &seep_xfer, i2c_eeprom_events, 0);
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 */
409 static void i2c_iox_events(I2C_ID_T id, I2C_EVENT_T event)
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);
422 i2c_iox_update_regs(1);
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 {
437 Board_Buttons_Init();
438 iox_xfer.slaveAddr = (I2C_SLAVE_IOX_ADDR << 1);
439 i2c_iox_events(id, I2C_EVENT_DONE);
440 Chip_I2C_SlaveSetup(id, I2C_SLAVE_1, &iox_xfer, i2c_iox_events, 0);
441 i2c_iox_update_regs(3);
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 {
458 i2c_iox_update_regs(2);
459 }
460
465 void I2C1_IRQHandler(void)
466 {
467 i2c_state_handling(I2C1);
468 }
469
474 void I2C0_IRQHandler(void)
475 {
476 i2c_state_handling(I2C0);
477 }
478
483 int main(void)
484 {
485 int tmp;
486 int xflag = 0;
487 static I2C_XFER_T xfer;
488
489 Board_Init();
490 i2c_app_init(I2C0, SPEED_100KHZ);
491 i2c_app_init(I2C1, SPEED_100KHZ);
492
493 /* Simulate an EEPROM slave in I2C0 */
494 i2c_eeprom_init(I2C_EEPROM_BUS);
495
496 /* Simuldate an IO Expansion slave in I2C0 */
497 i2c_iox_init(I2C_IOX_BUS);
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:
528 i2c_probe_slaves(i2cDev);
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;
549 Chip_I2C_MasterTransfer(i2cDev, &xfer);
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 }
560 Chip_I2C_DeInit(I2C0);
561 Chip_I2C_DeInit(I2C1);
562
563 return 0;
564 }
565