LPCOpen Platform for LPC18XX/43XX microcontrollers
18XX43XX
LPCOpen Platform for the NXP LPC18XX/43XX family of Microcontrollers
Main Page
Modules
Data Structures
Files
File List
Globals
software
lpc_core
lpc_chip
chip_18xx_43xx
i2cm_18xx_43xx.c
Go to the documentation of this file.
1
/*
2
* @brief LPC18xx/43xx I2C master driver
3
*
4
* @note
5
* Copyright(C) NXP Semiconductors, 2013
6
* All rights reserved.
7
*
8
* @par
9
* Software that is described herein is for illustrative purposes only
10
* which provides customers with programming information regarding the
11
* LPC products. This software is supplied "AS IS" without any warranties of
12
* any kind, and NXP Semiconductors and its licensor disclaim any and
13
* all warranties, express or implied, including all implied warranties of
14
* merchantability, fitness for a particular purpose and non-infringement of
15
* intellectual property rights. NXP Semiconductors assumes no responsibility
16
* or liability for the use of the software, conveys no license or rights under any
17
* patent, copyright, mask work right, or any other intellectual property rights in
18
* or to any products. NXP Semiconductors reserves the right to make changes
19
* in the software without notification. NXP Semiconductors also makes no
20
* representation or warranty that such application will be suitable for the
21
* specified use without further testing or modification.
22
*
23
* @par
24
* Permission to use, copy, modify, and distribute this software and its
25
* documentation is hereby granted, under NXP Semiconductors' and its
26
* licensor's relevant copyrights in the software, without fee, provided that it
27
* is used in conjunction with NXP Semiconductors microcontrollers. This
28
* copyright, permission, and disclaimer notice must appear in all copies of
29
* this code.
30
*/
31
32
#include "
chip.h
"
33
34
/*****************************************************************************
35
* Private types/enumerations/variables
36
****************************************************************************/
37
38
/* Control flags */
39
#define I2C_CON_FLAGS (I2C_CON_AA | I2C_CON_SI | I2C_CON_STO | I2C_CON_STA)
40
41
/*****************************************************************************
42
* Public types/enumerations/variables
43
****************************************************************************/
44
45
/*****************************************************************************
46
* Private functions
47
****************************************************************************/
48
/* Get the ADC Clock Rate */
49
static
CHIP_CCU_CLK_T
i2cm_getClkId
(
LPC_I2C_T
*pI2C)
50
{
51
return
(pI2C ==
LPC_I2C0
)?
CLK_APB1_I2C0
:
CLK_APB3_I2C1
;
52
}
53
54
/*****************************************************************************
55
* Public functions
56
****************************************************************************/
57
58
/* Initializes the LPC_I2C peripheral with specified parameter */
59
void
Chip_I2CM_Init
(
LPC_I2C_T
*pI2C)
60
{
61
/* Enable I2C clock */
62
Chip_Clock_Enable
(
i2cm_getClkId
(pI2C));
63
/* Reset I2C state machine */
64
Chip_I2CM_ResetControl
(pI2C);
65
}
66
67
/* De-initializes the I2C peripheral registers to their default reset values */
68
void
Chip_I2CM_DeInit
(
LPC_I2C_T
*pI2C)
69
{
70
/* Reset I2C state machine */
71
Chip_I2CM_ResetControl
(pI2C);
72
/* Disable I2C clock */
73
Chip_Clock_Disable
(
i2cm_getClkId
(pI2C));
74
}
75
76
/* Set up bus speed for LPC_I2C interface */
77
void
Chip_I2CM_SetBusSpeed
(
LPC_I2C_T
*pI2C, uint32_t busSpeed)
78
{
79
uint32_t clockDiv = (
Chip_Clock_GetRate
(
i2cm_getClkId
(pI2C)) / busSpeed);
80
81
Chip_I2CM_SetDutyCycle
(pI2C, (clockDiv >> 1), (clockDiv - (clockDiv >> 1)));
82
}
83
84
/* Master transfer state change handler handler */
85
uint32_t
Chip_I2CM_XferHandler
(
LPC_I2C_T
*pI2C,
I2CM_XFER_T
*xfer)
86
{
87
uint32_t cclr =
I2C_CON_FLAGS
;
88
89
switch
(
Chip_I2CM_GetCurState
(pI2C)) {
90
case
0x08:
/* Start condition on bus */
91
case
0x10:
/* Repeated start condition */
92
pI2C->
DAT
= (xfer->
slaveAddr
<< 1) | (xfer->
txSz
== 0);
93
break
;
94
95
/* Tx handling */
96
case
0x20:
/* SLA+W sent NAK received */
97
case
0x30:
/* DATA sent NAK received */
98
if
((xfer->
options
&
I2CM_XFER_OPTION_IGNORE_NACK
) == 0) {
99
xfer->
status
=
I2CM_STATUS_NAK
;
100
cclr &= ~
I2C_CON_STO
;
101
break
;
102
}
103
104
case
0x18:
/* SLA+W sent and ACK received */
105
case
0x28:
/* DATA sent and ACK received */
106
if
(!xfer->
txSz
) {
107
if
(xfer->
rxSz
) {
108
cclr &= ~
I2C_CON_STA
;
109
}
110
else
{
111
xfer->
status
=
I2CM_STATUS_OK
;
112
cclr &= ~
I2C_CON_STO
;
113
}
114
115
}
116
else
{
117
pI2C->
DAT
= *xfer->
txBuff
++;
118
xfer->
txSz
--;
119
}
120
break
;
121
122
/* Rx handling */
123
case
0x58:
/* Data Received and NACK sent */
124
case
0x50:
/* Data Received and ACK sent */
125
*xfer->
rxBuff
++ = pI2C->
DAT
;
126
xfer->
rxSz
--;
127
128
case
0x40:
/* SLA+R sent and ACK received */
129
if
((xfer->
rxSz
> 1) || (xfer->
options
&
I2CM_XFER_OPTION_LAST_RX_ACK
)) {
130
cclr &= ~
I2C_CON_AA
;
131
}
132
if
(xfer->
rxSz
== 0) {
133
xfer->
status
=
I2CM_STATUS_OK
;
134
cclr &= ~
I2C_CON_STO
;
135
}
136
break
;
137
138
/* NAK Handling */
139
case
0x48:
/* SLA+R sent NAK received */
140
xfer->
status
=
I2CM_STATUS_SLAVE_NAK
;
141
cclr &= ~
I2C_CON_STO
;
142
break
;
143
144
case
0x38:
/* Arbitration lost */
145
xfer->
status
=
I2CM_STATUS_ARBLOST
;
146
break
;
147
148
case
0x00:
/* Bus Error */
149
xfer->
status
=
I2CM_STATUS_BUS_ERROR
;
150
cclr &= ~
I2C_CON_STO
;
151
break
;
152
default
:
153
xfer->
status
=
I2CM_STATUS_ERROR
;
154
cclr &= ~
I2C_CON_STO
;
155
break
;
156
}
157
158
/* Set clear control flags */
159
pI2C->
CONSET
= cclr ^
I2C_CON_FLAGS
;
160
/* Stop flag should not be cleared as it is a reserved bit */
161
pI2C->
CONCLR
= cclr & (
I2C_CON_AA
|
I2C_CON_SI
|
I2C_CON_STA
);
162
163
return
xfer->
status
!=
I2CM_STATUS_BUSY
;
164
}
165
166
/* Transmit and Receive data in master mode */
167
void
Chip_I2CM_Xfer
(
LPC_I2C_T
*pI2C,
I2CM_XFER_T
*xfer)
168
{
169
/* set the transfer status as busy */
170
xfer->
status
=
I2CM_STATUS_BUSY
;
171
/* Clear controller state. */
172
Chip_I2CM_ResetControl
(pI2C);
173
/* Enter to Master Transmitter mode */
174
Chip_I2CM_SendStart
(pI2C);
175
}
176
177
/* Transmit and Receive data in master mode */
178
uint32_t
Chip_I2CM_XferBlocking
(
LPC_I2C_T
*pI2C,
I2CM_XFER_T
*xfer)
179
{
180
uint32_t ret = 0;
181
/* start transfer */
182
Chip_I2CM_Xfer
(pI2C, xfer);
183
184
while
(ret == 0) {
185
/* wait for status change interrupt */
186
while
(
Chip_I2CM_StateChanged
(pI2C) == 0) {}
187
/* call state change handler */
188
ret =
Chip_I2CM_XferHandler
(pI2C, xfer);
189
}
190
return
ret;
191
}
192
193
/* Master tx only */
194
uint32_t
Chip_I2CM_Write
(
LPC_I2C_T
*pI2C,
const
uint8_t *buff, uint32_t len)
195
{
196
uint32_t txLen = 0, err = 0;
197
198
/* clear state change interrupt status */
199
Chip_I2CM_ClearSI
(pI2C);
200
/* generate START condition */
201
Chip_I2CM_SendStart
(pI2C);
202
203
while
((txLen < len) && (err == 0)) {
204
/* wait for status change interrupt */
205
while
(
Chip_I2CM_StateChanged
(pI2C) == 0) {}
206
207
/* check status and send data */
208
switch
(
Chip_I2CM_GetCurState
(pI2C)) {
209
case
0x08:
/* Start condition on bus */
210
case
0x10:
/* Repeated start condition */
211
case
0x18:
/* SLA+W sent and ACK received */
212
case
0x28:
/* DATA sent and ACK received */
213
Chip_I2CM_WriteByte
(pI2C, buff[txLen++]);
214
break
;
215
216
case
0x38:
/* Arbitration lost */
217
break
;
218
219
default
:
/* we shouldn't be in any other state */
220
err = 1;
221
break
;
222
}
223
/* clear state change interrupt status */
224
Chip_I2CM_ClearSI
(pI2C);
225
}
226
227
return
txLen;
228
}
229
230
/* Sequential master read */
231
uint32_t
Chip_I2CM_Read
(
LPC_I2C_T
*pI2C, uint8_t *buff, uint32_t len)
232
{
233
uint32_t rxLen = 0, err = 0;
234
235
/* clear state change interrupt status */
236
Chip_I2CM_ClearSI
(pI2C);
237
/* generate START condition and auto-ack data received */
238
pI2C->
CONSET
=
I2C_CON_AA
|
I2C_CON_STA
;
239
240
while
((rxLen < len) && (err == 0)) {
241
/* wait for status change interrupt */
242
while
(
Chip_I2CM_StateChanged
(pI2C) == 0) {}
243
244
/* check status and send data */
245
switch
(
Chip_I2CM_GetCurState
(pI2C)) {
246
case
0x08:
/* Start condition on bus */
247
case
0x10:
/* Repeated start condition */
248
case
0x40:
/* SLA+R sent and ACK received */
249
case
0x50:
/* Data Received and ACK sent */
250
buff[rxLen++] =
Chip_I2CM_ReadByte
(pI2C);
251
break
;
252
253
case
0x38:
/* Arbitration lost */
254
break
;
255
256
default
:
/* we shouldn't be in any other state */
257
err = 1;
258
break
;
259
}
260
/* clear state change interrupt status */
261
Chip_I2CM_ClearSI
(pI2C);
262
}
263
264
return
rxLen;
265
}
Generated on Fri Feb 20 2015 21:29:43 for LPCOpen Platform for LPC18XX/43XX microcontrollers by
1.8.3.1