-
linux gpio
模拟
i2c
的使用用
GPIO
模拟
I2
C
总线
这个结
构专门用于数据传输相关的
addr
为
I2C
设备地
址,
flags
为一些标志位,
len
为数据的长度,
buf
为数据。
这里宏定义的一些标志还是需要
了解一下。
I2C_M_TEN
表示
10
位设备地址
I2C_M_RD
读标志
I2C_M_NOSTART
无起始信号标志
<
/p>
I2C_M_IGNORE_NAK
忽略应答信号标志
回到
for
,这里的<
/p>
num
代表有几个
struct
i2c_msg
,
进入
for
语句,
接下来是个
if
语句,
判断这个设备
是否定义了
I2C_M_NOSTART
标志,这个标志主要用于写
操作时,不必重新发送起始信号和设备地址,但是对于读操
作就不同了,要调用
p>
i2c_repstart
这个函数去重新发送起始
信号,调用
bit_doAddress
函数去重新构
造设备地址字节,
来看这个函数。
static int bit_doAddress(struct
i2c_adapter *i2c_adap,
struct i2c_msg
*msg)
{
unsigned short flags =
msg->flags;
unsigned short nak_ok =
msg->flags & I2C_M_IGNORE_NAK;
struct
i2c_algo_bit_data *adap =
i2c_adap->algo_data;
unsigned char addr;
int ret, retries;
retries =
nak_ok ? 0 :
i2c_adap->retries;
if (flags &
I2C_M_TEN) {
/*
a ten bit address */
addr = 0xf0 | ((msg->addr >>
7) & 0x03);
bit_dbg(2, &i2c_adap->dev,
/* try extended address
code...*/
ret =
try_address(i2c_adap, addr, retries);
if ((ret != 1)
&& !nak_ok)
{
dev_err(&i2c_adap->dev,
return
-EREMOTEIO;
}
/*
the remaining 8
bit address */
ret = i2c_outb(i2c_adap,
msg->addr & 0x7f);
if ((ret != 1)
&&
!nak_ok) {
/* the chip did
not
ack / xmission error occurred */
dev_err(&i2c_adap->dev,
coden
return -EREMOTEIO;
}
if (flags &
I2C_M_RD) {
bit_dbg(3,
&i2c_adap->dev,
i2c_repstart(adap);
/* okay, now switch into reading mode
*/
addr |= 0x01;
ret = try_address(i2c_adap,
addr, retries);
if
((ret != 1)
&& !nak_ok)
{
dev_err(&i2c_adap->dev,
return
-EREMOTEIO;
}
}
}
else {
/* normal 7bit address
*/
addr =
msg->addr <<
1;
if (flags &
I2C_M_RD)
addr |= 1;
if
(flags
& I2C_M_REV_DIR_ADDR)
addr ^= 1;
ret = try_address(i2c_adap, addr,
retries);
if
((ret != 1) && !nak_ok)
return
-ENXIO;
}
return 0;
}
<
/p>
这里先做了一个判断,
10
位设备地址和
7
位设备地址分别做
不同的处理,通常
一条
I2C
总线上不会挂那么多
I2C
设备,
所以
10
位地址不常用,直接看对
7
位地址的处理。
< br>struct
i2c_msg
中
addr
中是真正的设备地址,而这里发送的
addr
高
7
位才是设备地址,最低位为读写位,如果
为读,最低位
为
1
,如果为写,最低位
为
0
。所以要将
struct
i2c_msg
中
addr
< br>向左移
1
位,
如果定义了
I2C_M_RD
标志,
就将
addr
或上
1
,前面就说过
,这个标志就代表读,
如果是
写,这里就不用处理,因为最低位
本身就是
0
。最后调用
try_add
ress
函数将这个地址字节发送出去。
[html]
view
plaincopyprint? 1. static int
try_address(struct i2c_adapter
*i2c_adap,
2.
unsigned char addr, int retries)
3. {
4.
struct i2c_algo_bit_data
*adap =
i2c_adap->algo_data;
5.
int i, ret = 0;
6.
7.
for (i = 0; i <=
retries; i++) {
8.
ret = i2c_outb(i2c_adap, addr);
9.
if (ret == 1 ||
i == retries)
10.
break;
11.
bit_dbg(3,
&i2c_adap->dev,
stop
conditionn
12.
i2c_stop(adap);
13.
udelay(adap->udelay);
14.
yield();
15.
bit_dbg(3, &i2c_adap->dev,
start conditionn
16.
i2c_start(adap);
17.
}
18.
if (i
&& ret)
19.
bit_dbg(1, &i2c_adap->dev,
20.
21.
addr & 1 ?
addr >>
1,
22.
ret == 1 ?
23.
return ret;
24. }
最主要
的就是调用
i2c_outb
发送一个字节,
< br>retries
为重复次数,看前面
adap->
retries=
3;
如果发送失败,也就是设备没有给出
应答信号,那就发送停
止信号,
发送起始信号,
再发送这个地址字节,
这就叫
retries
。
来看这个具体的
i2c_outb
函数
[html] view
plaincopyprint? 1. static int
i2c_outb(struct i2c_adapter
*i2c_adap,
unsigned char c)
2.
{
3.
int i;
4.
int sb;
5.
int ack;
6.
struct
i2c_algo_bit_data *adap =
i2c_adap->algo_data;
7.
8.
/* assert: scl is low */
9.
for (i = 7; i >= 0; i--)
{
10.
sb = (c >> i) &
1;
11.
setsda(adap, sb);
12.
udelay((adap->udelay +
1) / 2);
13.
if (sclhi(adap)
< 0) { /* timed out */
14.
bit_dbg(1, &i2c_adap->dev,
15.
16.
return -ETIMEDOUT;
17.
}
18.
/* FIXME do
arbitration here:
19.
*
if (sb && !getsda(adap)) ->
ouch! Get out of here.
20.
*
21.
* Report a
unique code, so higher level code
can
retry
22.
* the whole
(combined) message and *NOT*
issue
STOP.
23.
*/
24.
scllo(adap);
25.
}
26.
sdahi(adap);
27.
if (sclhi(adap) < 0) { /* timeout */
28.
bit_dbg(1,
&i2c_adap->dev,
0x%02x,
29.
30.
return -ETIMEDOUT;
31.
}
32.
33.
/* read ack: SDA should be pulled down
by slave,
or it may
34.
* NAK (usually to report problems with
the data
we wrote).
35.
*/
36.
ack =
!getsda(adap);
/* ack: sda is pulled low
-> success */
37.
bit_dbg(2, &i2c_adap->dev,
0x%02x %sn
38.
ack
?
39.
40.
scllo(adap);
41.
return ack;
42.
/*
assert: scl is low (sda undef) */
43.
}
这个函数有两个参数,
一个是
structi2c_adapter
代表
I
2C
主
机,一个是发送的字节数据。那么
I2C
是怎样将一个字节数
据发送出去的呢,那再来看看协议
。首先是发送字节数据的
最高位,在时钟为高电平期间将一位数据发送出去,最后是
p>
发送字节数据的最低位。
发送完成之后,
我
们需要一个
ACK
信号,
要不然我怎么
知道发送成功没有,
ACK
信号就是在第
九个时钟周期时数据线为低,所以在一个字节数据传送完成
后,还要将数据线拉高,我
们看程序中就是这一句
sdahi(adap);
等待这个
p>
ACK
信号的到来,
这样一个字节数据
p>
就发送完成。
回到
bit_xfer
函数中,
前面只是将设备地址字节发送出去
了,
那么接下来就是该发送数据了。
注意:这里的数据包括操作设备的基地址
如果是读则调用
readbytes
函数去读,如果是写则
调用
sendbytes
去写,先看
r
eadbytes
函数
[html] view
plaincopyprint? 1. static int
readbytes(struct i2c_adapter
*i2c_adap,
struct i2c_msg *msg)
2.
{
3.
int inval;
4.
int rdcount =
0;
/* counts bytes read */
5.
unsigned char *temp =
msg->buf;
6.
int
count = msg->len;
7.
const unsigned flags = msg->flags;
8.
9.
while (count > 0) {
10.
inval = i2c_inb(i2c_adap);
11.
if (inval >= 0) {
12.
*temp = inval;
13.
rdcount++;
14.
}
else {
/* read
timed out */
15.
break;
16.
}
17.
18.
temp++;
19.
count--;
20.
21.
/* Some SMBus transactions
require that we
receive the
22.
transaction
length as the first read byte. */
23.
if (rdcount == 1 && (flags
&
I2C_M_RECV_LEN)) {
24.
if (inval <= 0 || inval >
I2C_SMBUS_BLOCK_MAX) {
25.
if (!(flags &
I2C_M_NO_RD_ACK))
26.
acknak(i2c_adap, 0);
27.
dev_err(&i2c_adap->dev,
28.
29.
return -EREMOTEIO;
30.
}
31.
/* The original
count value accounts for
the extra
32.
bytes, that is, either 1 for a regular
transaction,
33.
or 2 for a PEC transaction.
*/
34.
count += inval;
35.
msg->len += inval;
36.
}
37.
38.
bit_dbg(2, &i2c_adap->dev,
39.
inval,
40.
(flags &
I2C_M_NO_RD_ACK)
41.
?
42.
: (count ?
43.
44.
if (!(flags
& I2C_M_NO_RD_ACK)) {
45.
inval = acknak(i2c_adap, count);
46.
if (inval < 0)
47.
return inval;
48.
}
49.
}
50.
return rdcount;
51. }
其中一个大的
while
循环,
调用
i2c_inb
去读一个字节,
count
为数据的长度,单位为多少个字节
,
那就来看
i2c_inb
函数。
static int i2c_inb(struct i2c_adapter
*i2c_adap)
{
/*
read byte via i2c port,
without start/stop sequence
*/
/* acknowledge
is sent in i2c_read.
*/
int i;
unsigned char indata = 0;
struct i2c_algo_bit_data
*adap = i2c_adap->algo_data;
/*
assert: scl is
low */
sdahi(adap);
for
(i = 0; i < 8; i++)
{
if (sclhi(adap) < 0) { /* timeout */
bit_dbg(1,
&i2c_adap->dev,
return
-ETIMEDOUT;
}
indata *= 2;
if (getsda(adap))
indata |= 0x01;
setscl(adap, 0);
udelay(i == 7 ? adap->udelay
/ 2 : adap->udelay);
}
/* assert: scl
is low */
return indata;
}
再来看
sendbytes
函数
[html] view
plaincopyprint? 1. static int
sendbytes(struct i2c_adapter
*i2c_adap,
struct i2c_msg *msg)
2.
{
3.
const unsigned
char *temp = msg->buf;
4.
int count = msg->len;
5.
unsigned short nak_ok =
msg->flags &
I2C_M_IGNORE_NAK;
6.
int retval;
7.
int wrcount =
0;
8.
9.
while (count > 0) {
10.
retval = i2c_outb(i2c_adap,
*temp);
11.
12.
/* OK/ACK; or ignored NAK */
13.
if ((retval > 0) ||
(nak_ok &&
(retval == 0))) {
14.
count--;
15.
temp++;
16.
wrcount++;
17.
18.
/* A slave NAKing the
master means the
slave didn't like
19.
* something about the data
it saw.
For
example, maybe
20.
*
the SMBus PEC was wrong.
21.
*/
22.
} else if (retval == 0) {
23.
dev_err(&i2c_adap->dev,
24.
return -EIO;
25.
26.
/*
Timeout; or (someday) lost arbitration
27.
*
28.
* FIXME Lost
ARB implies retrying the
transaction
from
29.
* the first
message, after the
master issues
30.
* its STOP.
As a rule, upper layer code has
no reason
31.
*
to know or care about this ... it is *NOT* an
error.
32.
*/
33.
} else {
34.
dev_err(&i2c_adap->dev,
35.
retval);
36.
return retval;
37.
}
38.
}
39.
return wrcount;
40. }
也是一个大的
while
循环,同发送地址字节一样,也是调用
i2c_outb
< br>去发送一个字节,
count
也是数据长度,由于
i2c_outb
函数在前面发送设备地址那里已经介绍了,这里也<
/p>
-
-
-
-
-
-
-
-
-
上一篇:DIktat 德语听力训练1 原文
下一篇:证券行业英语词汇