使用IIC驱动框架来读取LM75的信号

发表在 I2C2019-1-28 20:44 [复制链接] 29 1132

本帖最后由 whj467467222 于 2019-4-11 08:32 编辑
6 U2 ?+ @2 P, C0 y$ y8 L; \/ q6 w5 J+ J' ~
该测试是在RT_Thread下测试,硬件正常情况下的测试。自己写的一个测试使用IIC来读取LM75的测试程序,顺便总结一下自己对IIC驱动框架的理解。0 g( _3 c( _/ K: R2 c; G) v: I: \( G
该测试基于STM32F107 μC/Eval 开发板,使用模拟IIC,使用引脚为PB6 PB7。/ A5 a: ]- m: U, L  j
所有内容参考I2C总线设备) _) c7 d1 K' R/ k  z
使用道具 举报 显示全部楼层 回复
最新评论 | 正序浏览
显示全部楼层 |楼层直达:
发表于 2019-1-28 20:59:28 | 显示全部楼层
1,在ENV开启IIC驱动框架
% t- U. R; P+ H" Z7 v  O  R9 L      RT_THREAD Components--Device Drivers. h. B- Z4 Y5 y+ [9 H  G) G& m, [
      这里要记得选择模拟IIC
; G& @5 b, i  F; y9 a8 `/ J' F4 K
TIM截图20190128205828.png
使用道具 举报 回复
发表于 2019-1-28 21:06:55 | 显示全部楼层
2,在rtconfig.h里面就有了如下的宏定义- O2 `, g  {/ P# O: n9 g  F
  1. #define RT_USING_I2C; @) J  Q/ z* G# Q* u
  2. #define RT_USING_I2C_BITOPS
复制代码
这里就表示开启了IIC,并且使用的是模拟IIC
" d5 h* q5 @% |4 i, c$ p. z
& c0 M% c# J0 k2 W' J; s6 K% n) F8 X2 M: W3 s2 x- s/ e, i( r
3,因为本BSP包目前还没有添加支持IIC,目前无法通过ENV来进行设置,所以这里的模拟IIC的 SDA SCL定义到哪个引脚还需要自己设置4 e& N' q) p0 ^  R
      我在这里设置为% N( h5 A9 |7 x  |$ ]
  1. #define BSP_I2C1_SCL_PIN 22  Y% Y; ^! Z% E- Z# t
  2. #define BSP_I2C1_SDA_PIN 23
复制代码
上面的22 23是在drv_gpio.c里面查表所得,这里有一点需要值得注意的是,早先的RTT是使用的STM32的引脚编码来进行编号,但是现在这个地方做了更改。7 u& u* p' w2 `0 w0 A
早前的版本使用引脚编码来进行编号,方便查找,但是不同引脚的MCU就需要定义不同的顺序,代码量很大,而且要使用很多判断语句,显得很臃肿。' X9 _2 J+ R/ E& i: W: \1 z
新版采用的方法是查表法,每个端口的几号引脚可以通过drv_gpio.c来进行查找方便了很多,而且代码很精简。6 _  U% r& b8 X  H/ X
使用道具 举报 回复
发表于 2019-1-28 21:21:17 | 显示全部楼层
4,上面配置好了,接下来就是IIC总线的初始化。' g3 `: p) P* J; ^1 \
  1. int rt_hw_i2c_init(void)
    / z! G; s& T. C  Y, F# G
  2. {
    - f8 x- D3 X0 W' s8 @
  3.     rt_size_t obj_num = sizeof(i2c_obj) / sizeof(struct stm32_i2c);
    / z0 v& U6 v8 M% |/ x0 O' m
  4.     rt_err_t result;7 C6 ]. W9 a* D# [4 V  k5 f

  5. # W) D1 ^) q. H$ }' b/ c; K+ I+ r
  6.     for (int i = 0; i < obj_num; i++)
    8 l+ b# ]" A- @; K/ K9 t
  7.     {
    - Y- X6 Q9 \  d/ I
  8.         i2c_obj[i].ops = stm32_bit_ops_default;
    4 c, i1 ~" }9 x+ G" T4 v
  9.         i2c_obj[i].ops.data = (void*)&soft_i2c_config[i];' m* C2 l& N5 w2 x7 H: \
  10.         i2c_obj[i].i2c2_bus.priv = &i2c_obj[i].ops;
    ' o0 E" n* v! Q: Y0 E, `
  11.         stm32_i2c_gpio_init(&i2c_obj[i]);) S: x, A5 \! q( _" K; k( T: O6 w
  12.         result = rt_i2c_bit_add_bus(&i2c_obj[i].i2c2_bus, soft_i2c_config[i].bus_name);$ e- J9 g& H% w1 @- ~: H2 Z
  13.         RT_ASSERT(result == RT_EOK);
    : u+ h5 t# b6 V' A
  14.         stm32_i2c_bus_unlock(&soft_i2c_config[i]);- J! s5 P& g3 I4 M, H
  15.     }
      ?* p: [  s7 ]# h
  16. 3 {5 K1 y1 D/ r1 N2 k
  17.     return RT_EOK;' n% O- g4 H# ]; p) D% W- _( y) ]
  18. }: v/ o0 T) b/ `% {% ]3 N( w: N; Z
  19. INIT_BOARD_EXPORT(rt_hw_i2c_init);
复制代码
这个函数完成了IIC的初始化。
# h; M( V/ J' aINIT_BOARD_EXPORT(rt_hw_i2c_init)完成了板级自动初始化。
8 C/ W  ^( ]1 J# ~
) \$ I2 h5 _8 _8 M' Z! D8 p+ a- M5 g

# ?5 F0 `/ a2 ~1 lobj_num = sizeof(i2c_obj) / sizeof(struct stm32_i2c);计算定义了几个IIC总线1 C7 }& V% x6 q% O$ M. k
soft_i2c_config这个结构体通过宏定义来获取定义了几个IIC总线的名字:目前支持I2C1 I2C2 I2C3% \# w  Y* V! p3 L. Q% E, p$ M, u
i2c_obj.ops = stm32_bit_ops_default;默认的参数,这里不需要自己修改4 {* T  @/ S" r+ G# k- m. j
  1. static const struct rt_i2c_bit_ops stm32_bit_ops_default =& v9 J" H9 f% V# A1 K8 W
  2. {
      ^, K; z$ `  _; Y' I# q
  3.     .data     = RT_NULL,. G. y1 j  U; g- a5 k9 m9 c
  4.     .set_sda  = stm32_set_sda,
    ) H- ]$ u$ W0 S; P+ R
  5.     .set_scl  = stm32_set_scl,5 b! u0 \2 g; q8 P2 Q  d( Q2 I
  6.     .get_sda  = stm32_get_sda,
    8 V! N/ h9 n! l* Y. i! k
  7.     .get_scl  = stm32_get_scl,
    ! Q% Z0 D3 O% y% x+ W4 k
  8.     .udelay   = stm32_udelay,
    6 [4 O$ a! D" Z0 @- x' A$ \
  9.     .delay_us = 1,
    1 O2 x; v! e# c: o" v* ^! y  ]
  10.     .timeout  = 1002 C3 c  h2 b! n' G
  11. };
复制代码
stm32_i2c_gpio_init(&i2c_obj);完成对模拟IIC SDA SCL引脚的初始化,这里初始化的模式是PIN_MODE_OUTPUT_OD
+ O3 O4 m% O2 W1 z5 e/ T2 C4 y) k3 I/ U
% q. Y% e+ _% q6 O! j2 Y, \rt_i2c_bit_add_bus(&i2c_obj.i2c2_bus, soft_i2c_config.bus_name);完成对IIC总线的注册
6 z7 h5 z' J& r( x: d. ]. X: m& k7 T/ s$ e# t- E5 @
stm32_i2c_bus_unlock(&soft_i2c_config);刚刚完成对IIC总线的注册,这个时候还不需要发送数据,这个时候把互斥锁打开。" S% C0 Q( o2 d2 ?& @
+ y! {8 `5 E$ K- e( o1 v- a
6 y1 _% g+ h5 U
使用道具 举报 回复
发表于 2019-1-28 21:25:01 | 显示全部楼层
5,IIC总线注册到系统中之后可以通过list_device来进行查看
, S. Q" Y( m9 d* W+ [  |
$ n1 Q- S3 Y$ J9 x1 O
TIM截图20190128212443.png
使用道具 举报 回复
发表于 2019-1-28 21:30:06 | 显示全部楼层
6,总线注册成功之后就是对设备的操作
7 e! ?: m! \: q7 w
  1. static void i2c_stlm75_sample(int argc, char *argv[])8 c3 q$ C2 U5 B- G
  2. {! I5 t% h6 s+ \0 p7 f. l9 {% ]# I
  3.     float temperature;. T. z$ g, x( d9 f* @
  4.     temperature = 0.0;9 t9 E" r* Q# V, S4 I: R
  5.     if (!initialized)' U1 x' x" U9 i2 G4 a" u
  6.     {
    2 I: q8 ]2 T( m) b
  7.         stlm75_init(name);, n9 P5 L0 V1 W& V$ v
  8.     }
    9 E* `) [6 t) Z- N$ W
  9.     while(1)
    7 O$ N) o  ?& D, ~
  10.     {
    $ |3 Y" F, S$ K! R
  11.         if (initialized)
      y9 ~1 w7 o3 j- |
  12.         {           & `3 m: G. k+ v
  13.            read_temp(&temperature);$ d+ |1 W6 @: Z

  14. # W  b) C; l/ r2 Y% s. _
  15.             rt_kprintf("read stlm10 sensor temperature: %d.%d \n", (int)temperature, (int)(temperature * 10) % 10);+ b0 A4 T* ^: J% _  a  V
  16.         }
    2 q1 T" V( P+ E4 f4 t; d
  17.         else
    9 y, @" s# U( y  W2 k6 J
  18.         {" D! W( }3 R2 S* K+ ^& ^
  19.             rt_kprintf("initialize sensor failed!\n");
    3 ?5 c( V9 A, t0 j1 I: v  E
  20.         }6 m. o% `/ Q3 g
  21.         rt_thread_delay(1000);
    - w+ h* n) Z: ^3 [8 ~
  22.     }" [6 @) E# P7 G/ Z. ~$ f
  23. }
    ! F& |. B7 r+ V4 R
  24. 6 g: t5 [; n& n! I1 F
  25. MSH_CMD_EXPORT(i2c_stlm75_sample, i2c stlm75 sample);
复制代码
首先导出命令行6 n% a& _: x, d
上面的初始化函数完成了传感器的初始化,然后1S的循环来定时读取温度传感器的数据
, [9 `* r1 I5 |5 f( H$ _
使用道具 举报 回复
发表于 2019-1-28 21:32:05 | 显示全部楼层
7,传感器初始化函数
9 A0 M: _( P- `+ x, cstatic void stlm75_init(const char *name)/ i" K, A: q3 }. R
{9 w+ C) j1 H3 v8 R9 y
    i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(name);
! ~8 L* u  p3 N0 o    if (i2c_bus == RT_NULL)
& w  O3 ]5 R: K8 R    {) Y* i! j9 b5 n# ^( @1 G
        rt_kprintf("can't find %s device!\n", name);
/ r  j* V, t3 V    }
$ F# a* M5 H2 O% m+ q6 ]    else# M7 d  ^! J% {" R1 U! p9 b# Q
    {
& W1 t% i6 O( h9 U; l$ M1 q* h& E        initialized = RT_TRUE;
. q* h0 t% v; ~+ H' ~8 u& q# D    }
! a7 p2 o- I( V4 A, r9 v, A8 F( S3 I}
# }1 Y1 Y( U5 u  s% W0 R& F
; a" O0 N" X. ]( s9 j3 D4 u% C! w/ d& J使用rt_device_find来查找在前面注册的IIC总线
4 t# G3 `6 \. H2 `4 p) f0 h
使用道具 举报 回复
发表于 2019-1-28 21:48:45 | 显示全部楼层
本帖最后由 whj467467222 于 2019-1-28 21:49 编辑
0 m3 v( z5 }/ g' J3 h" h' a, t2 d4 q2 W. M
8,读取温度传感器信号函数
5 J9 R, O1 f4 }0 d, R
  1. static void read_temp(float *cur_temp)1 g9 f$ p: [, G7 x% v5 l5 ]
  2. {
    8 U' N, \: b* E4 R$ Y7 n) W
  3.     rt_uint8_t temp[2];
    $ p+ x8 }2 B; j+ }2 l
  4.     rt_uint16_t abc;/ ^2 h3 v9 [% X7 l0 O9 i' `, ], Z
  5.     rt_uint8_t write[1]= {0x00};
    1 l* D% d# @6 q4 Y
  6. ; s! W5 f+ i; X% P
  7.     write_regs(i2c_bus,1,write);0 V3 e' F$ Q# S9 G" E7 y7 r# E6 P

  8. + X3 V2 g, Z( |# x9 L
  9.     read_regs(i2c_bus,2, temp);+ |9 r/ ~2 u* x7 E! X2 |
  10. * j! W+ j: ^1 B! I2 A3 I
  11.     abc = ((rt_uint16_t)temp[0]<<8 | temp[1])>>5;
    $ J. ~6 ~1 ~: F4 T

  12. & K0 j! |# o* x  [( z
  13.     *cur_temp = abc*0.125;
    ! {+ \. u/ m( Q+ G: a. b
  14. }
复制代码
9 `- x7 c% F& n+ T0 d

( L% F7 A) ?& s- W4 Q这个地方的函数按照IC的要求进行操作就可以了。! k4 M. i9 W4 A* E! }/ m0 `
使用道具 举报 回复
发表于 2019-1-28 21:49:44 | 显示全部楼层
9,写操作命令. g+ U1 U/ B% t3 n! l
  1. static rt_err_t write_regs(struct rt_i2c_bus_device *bus, rt_uint8_t len, rt_uint8_t *buf)8 O$ s' e. f2 `& X0 L/ c
  2. {
    6 Y( _  ?7 S& P  f
  3.     struct rt_i2c_msg msgs;) ?) [9 x! k6 D6 Q  G) }: E* ?  d+ l

  4. ) B0 w6 W' ~8 c% t
  5.     msgs.addr = STLM75_ADDR;
    - G+ u! L0 c6 C3 }0 O3 B
  6.     msgs.flags = RT_I2C_WR;
    7 ~8 X3 s, E, u+ P$ D
  7.     msgs.buf = buf;
    ' M+ R- y6 i9 Z! U$ J" g6 m1 a( U
  8.     msgs.len = len;9 I2 p+ X6 N) R( v: x
  9. 0 k! V6 s5 T$ l7 P
  10.     if (rt_i2c_transfer(bus, &msgs, 1) == 1)
    9 E2 c$ J. Z) H5 w% ^
  11.     {
    5 X  h: S+ L; b+ K( C
  12.         return RT_EOK;
    6 N" j# h6 ?/ O  G
  13.     }
    & g2 ~% L% t& M% l
  14.     else( |- `0 O" i! c( {, y7 Z
  15.     {
    0 j$ f% ?5 W* h& m
  16.         return -RT_ERROR;
    5 N) N. w* t2 j% ~! J$ ]) [
  17.     }
    . f9 R1 Z: @4 W4 b3 ]
  18. }
复制代码
按照IC要求进行操作: D7 ~: @: Q" ?& v) d
使用道具 举报 回复
发表于 2019-1-28 22:10:07 | 显示全部楼层
10,IIC总线框架读写操作的函数rt_i2c_transfer: r/ R% m5 i- z  e0 T" r$ f
  1. rt_size_t rt_i2c_transfer(struct rt_i2c_bus_device *bus,
    * r" k4 U; P3 k; E9 A# P4 I
  2.                                        struct rt_i2c_msg         msgs[],% D0 m- y  {5 ^/ x
  3.                                        rt_uint32_t               num): i1 `- i5 k% X! ?9 e& O
  4. {
    ) V2 s8 n* w) h0 ^
  5.         rt_mutex_take(&bus->lock, RT_WAITING_FOREVER);
    7 @# C9 h6 |1 }/ }) l
  6.         ret = bus->ops->master_xfer(bus, msgs, num);0 a' j' c' }5 U7 J& j8 K6 u0 V
  7.         rt_mutex_release(&bus->lock);, Z5 l" \  w1 v: D- |

  8. 3 W+ ^/ v, F0 a$ J* d( b
  9.         return ret;2 w; H+ i) a6 ?0 L; }, e- k$ |
  10. }
复制代码
struct rt_i2c_bus_device *bus, 总线3 a. N' D* C7 W  _4 _; h
struct rt_i2c_msg msgs[]          消息结构体
2 F* J* x" m2 T. {- w3 |2 _# ^rt_uint32_t num                        数据数量        
0 U9 u3 ^2 ^2 T5 x9 w* }
% k3 S$ z6 a  ?& b
; ~$ H. i& f& _
然后获取互斥锁,获取到了之后执行% y9 x# D# }- e4 U
  1. ret = bus->ops->master_xfer(bus, msgs, num);
复制代码
实际执行的函数是$ f. s7 x' G- S. w  d/ @
  1. static rt_size_t i2c_bit_xfer(struct rt_i2c_bus_device *bus,
    + R$ A! b/ N- p. ^: h; h
  2.                               struct rt_i2c_msg         msgs[]," M) `* n3 v' i
  3.                               rt_uint32_t               num)  _" q. Y9 b$ p( v' A5 I/ m$ [9 h
  4. {
    2 {( w" J" N7 E* k- c9 c; c
  5.     struct rt_i2c_msg *msg;
    * Q' F7 J& S5 p: O$ Z
  6.     struct rt_i2c_bit_ops *ops = bus->priv;
    1 G# G! _7 g% p3 D1 o0 }! Z
  7.     rt_int32_t i, ret;2 ~* b6 D3 L+ I0 _, P5 l* x5 D
  8.     rt_uint16_t ignore_nack;
    + ~- k- b5 Q& {- A
  9. ; X+ Q0 j1 i9 u; t. r
  10.     bit_dbg("send start condition\n");
    - h9 B3 O$ C1 t' P& h( G0 I4 ]# s) S
  11.     i2c_start(ops);
    3 L% b4 H- L* A, I0 O+ E0 G) f
  12.     for (i = 0; i < num; i++)
    3 Y0 d1 e' i3 b. V6 ^6 d3 n  m
  13.     {6 w4 V) e5 |! \5 q/ w, c
  14.         msg = &msgs[i];  T) e7 j% X/ Q
  15.         ignore_nack = msg->flags & RT_I2C_IGNORE_NACK;
    6 _' T& C; j# y; i
  16.         if (!(msg->flags & RT_I2C_NO_START))8 d; x4 b+ k! _9 G0 E/ S
  17.         {
    3 ~9 f9 ~! Z( `+ h8 w4 @* ?
  18.             if (i)
    2 X; M. _4 `8 R7 I, z" m
  19.             {9 M# N+ ?3 A0 w* O) ]+ _
  20.                 i2c_restart(ops);! v9 n' e: P9 X
  21.             }) s1 i( q" R1 S2 _7 U
  22.             ret = i2c_bit_send_address(bus, msg);4 s; ]8 B, P- l
  23.             if ((ret != RT_EOK) && !ignore_nack). a' j& D1 Z4 q2 o: D
  24.             {
    " u0 Q2 z6 `" P8 B: {" Y
  25.                 bit_dbg("receive NACK from device addr 0x%02x msg %d\n",
    2 g' ~9 }$ e2 r) m. V. l3 u  h5 J
  26.                         msgs[i].addr, i);$ a! U1 {- p7 ~) V
  27.                 goto out;
    + M. j. L- b+ v! y8 H+ u7 w0 J
  28.             }
    ; R, q& ?- C1 T, F; n6 ~  P
  29.         }5 O$ j8 S, p8 b' D: _6 X! D' b" h& O
  30.         if (msg->flags & RT_I2C_RD)6 R; j* i7 `5 O) B' \, Z5 `  r
  31.         {' t6 f& K1 d  {% ]# I8 P
  32.             ret = i2c_recv_bytes(bus, msg);
    ; T, w& D! S* Y
  33.             if (ret >= 1)
    & l6 s& _4 q2 [4 o9 {* q
  34.                 bit_dbg("read %d byte%s\n", ret, ret == 1 ? "" : "s");
    : O9 U$ l+ a( L
  35.             if (ret < msg->len)
    5 N* Z# \% p3 i8 _; d$ W9 z, X4 V  D& L
  36.             {
    # q9 m' _2 m8 f6 o
  37.                 if (ret >= 0)
    ! O6 v( H5 l1 t1 l" `
  38.                     ret = -RT_EIO;
    : _9 n5 L6 F/ l- y
  39.                 goto out;' I; g' O4 q! h% j0 E1 D
  40.             }
    , A% H) j0 G7 x6 t/ n$ Q
  41.         }# G/ Z. |3 t- g6 n: k, T$ o5 Z
  42.         else
    9 O; Y( V- [% K- C6 C
  43.         {2 Z6 V0 x& v0 l( \
  44.             ret = i2c_send_bytes(bus, msg);
    1 {5 f3 |! }, l) M
  45.             if (ret >= 1)
    / K3 ?8 E& _% Q9 E9 a
  46.                 bit_dbg("write %d byte%s\n", ret, ret == 1 ? "" : "s");# t' q- h" ^0 L
  47.             if (ret < msg->len)6 J4 r, M! K. x5 v  M$ R$ e" b! O
  48.             {: j8 I* t; q/ d" w
  49.                 if (ret >= 0)
    / ~6 o% v1 W' j- K  E. @% B" O# V
  50.                     ret = -RT_ERROR;
    . m/ q6 E+ L, C
  51.                 goto out;/ ~/ O8 b# V4 ^! F, b
  52.             }) a7 I3 X: v( \' R
  53.         }
    0 U6 t" c. V+ l; e3 n
  54.     }' c5 f# G1 n  [3 |5 b5 ~6 y+ q( ?
  55.     ret = i;
    . `' \& r! H- E# @

  56. - I8 o3 X5 G7 ]! `  b
  57. out:7 [, L  f' [( N
  58.     bit_dbg("send stop condition\n");. Q# A: q# T1 e/ y4 f
  59.     i2c_stop(ops);9 b  F2 K: U& d& X) D
  60. 5 a! P& f, U1 f
  61.     return ret;
    ! g3 @; z! V0 d) B. s
  62. }
复制代码

- a2 b) D8 ]" l& A该函数进入之后就发送了i2c_start(ops);IIC启动信号,
  b2 \& z+ {+ B) B2 W: w然后进入了for循环,我这个就发送一个数据进行说明
: ~/ W" W: u# aignore_nack = msg->flags & RT_I2C_IGNORE_NACK; 这里需要回复ACK所以这里的ignore_nack=0+ J. G$ C+ O; m% n8 x0 Q- L
所以i2c_restart(ops);不会被执行' F& I' d! q8 d: j. g9 j( Z
接下来执行ret = i2c_bit_send_address(bus, msg);9 B  z5 d1 W$ F6 ~, J
  1. static rt_err_t i2c_bit_send_address(struct rt_i2c_bus_device *bus,4 v+ k  X" T5 [# m6 r% a4 ~
  2.                                      struct rt_i2c_msg        *msg)
    + D- }9 W& d6 H* \
  3. {
    " J/ _3 c$ k2 E! J8 v
  4.     rt_uint16_t flags = msg->flags;( w8 b* c. w4 f# q
  5.     rt_uint16_t ignore_nack = msg->flags & RT_I2C_IGNORE_NACK;
    8 O$ w2 s  Q( r
  6.     struct rt_i2c_bit_ops *ops = bus->priv;; o* F1 i! I- Z$ B
  7. + P4 P+ d" w" H# U; j. e- h: C
  8.     rt_uint8_t addr1, addr2;
    6 ?: y5 v7 f, E) ?7 K4 q' x2 z
  9.     rt_int32_t retries;. A, s- j- x" V! p2 M) S9 `
  10.     rt_err_t ret;' o' h4 Y% M6 N+ E& \2 c/ ?
  11. 8 R& A: P. Y7 v" h( P1 l
  12.     retries = ignore_nack ? 0 : bus->retries;) h6 ~" d. b7 d  B2 H- ^6 h0 u  _: J

  13. * F6 E$ p  c: b7 E4 e
  14.     if (flags & RT_I2C_ADDR_10BIT)1 c( {: H$ N; n7 J! w
  15.     {: ~; M5 s: D5 `% g8 k: ]$ |! j
  16.     }
    . f3 B, C" T: [* r4 N& L
  17.     else, R$ S' z' ~$ Z" }1 @
  18.     {6 L2 G. {: m2 o7 q" u. s
  19.         /* 7-bit addr */9 s0 s; ^  v. h2 M& v7 _4 j) P
  20.         addr1 = msg->addr << 1;+ `9 O( O" o# x
  21.         if (flags & RT_I2C_RD)
    9 C5 e1 e* F& }9 K8 k' b  L
  22.             addr1 |= 1;
    ) U2 C3 p7 w6 o9 C7 {4 F; Y/ _
  23.         ret = i2c_send_address(bus, addr1, retries);
    ' z$ M7 P) D0 x+ C( i* F2 _
  24.         if ((ret != 1) && !ignore_nack)) i% f/ K3 {+ m/ z
  25.             return -RT_EIO;
    1 Z0 k4 a$ b# O9 Z' b  `7 H4 W
  26.     }
    * E9 M  f' w; h- ~5 {' n
  27. 0 Q/ J6 R5 R9 \) E; \+ l$ C2 }
  28.     return RT_EOK;
    1 g8 x% R/ K; w$ w0 S& h- f3 G
  29. }
复制代码
这里删掉了10bit模式,因为我用的7bi't'模式,10bit还没看
& N8 W8 B1 d% @; ~& V/ jrt_uint16_t ignore_nack = msg->flags & RT_I2C_IGNORE_NACK;因为第一次是写数据,所以这里的结果是0  |& H6 J5 J" B
addr1 = msg->addr << 1;这个地方要重点注意一下,地址左移了一位
/ D7 ?: u: A; T$ Y' G8 m然后执行ret = i2c_send_address(bus, addr1, retries);% `5 W# G* e: K4 L
  1.     for (i = 0; i <= retries; i++)
    3 f6 B5 k, o) x9 l! z0 G
  2.     {% b" \" P/ |7 e
  3.         ret = i2c_writeb(bus, addr);
    6 A3 ]& a* ]$ f4 W0 ^
  4.         if (ret == 1 || i == retries)
    4 Z# \- s6 }3 W- e( p* W; y$ `: s
  5.             break;( ]7 l. b& ~0 c% e2 ?* Y: `
  6.         bit_dbg("send stop condition\n");1 R8 c& w/ M, z2 c+ B8 u+ W2 j- F# t
  7.         i2c_stop(ops);# |0 S' e  D- I4 e* J
  8.         i2c_delay2(ops);2 M4 c4 ?9 E6 R* ^9 v7 F/ ~
  9.         bit_dbg("send start condition\n");
    1 }$ U: ^$ F" ~/ |0 ^
  10.         i2c_start(ops);
    ! y# H* l! q" b
  11.     }
复制代码
前面做了这么多的准备工作,终于要执行写数据的函数了
) {) M6 W0 R0 \( U- a
  1. static rt_int32_t i2c_writeb(struct rt_i2c_bus_device *bus, rt_uint8_t data)
    + `3 [+ D, c- `: H- M- ?; i0 w
  2. {
    # f/ o$ O9 j8 G1 F
  3.     rt_int32_t i;1 H; T( R8 F; S7 _. s
  4.     rt_uint8_t bit;' j0 I4 y3 `+ m
  5. ( Y% ^8 R! m- R$ X9 a2 u
  6.     struct rt_i2c_bit_ops *ops = bus->priv;
    & h1 g9 G- K0 g1 d

  7. - A$ r; i% m- c
  8.     for (i = 7; i >= 0; i--)# ]: ^9 C7 i& j$ I# `
  9.     {
    7 V# a% E# p) C) I7 W( U
  10.         SCL_L(ops);
    & C# T* e" |2 k; f9 u
  11.         bit = (data >> i) & 1;" j& o9 D0 S3 ]& K
  12.         SET_SDA(ops, bit);
    * \+ q1 c% T% y- G4 {  q
  13.         i2c_delay(ops);0 z+ l) g8 ]9 l& Y
  14.         if (SCL_H(ops) < 0)" d8 w' V. a& J0 x0 [8 k- V/ o
  15.         {3 g8 Q4 R* z& `/ R1 x$ u
  16.             bit_dbg("i2c_writeb: 0x%02x, "
    # @  x& l0 h4 O+ N* B
  17.                     "wait scl pin high timeout at bit %d\n",
    ' g/ ^% |  T9 e! \
  18.                     data, i);1 z7 o6 Y! K4 l

  19. 4 s% l# {1 a8 o1 ]! p( }2 |/ N% o
  20.             return -RT_ETIMEOUT;9 c" @3 U! y/ ]7 O& _) @2 y
  21.         }; T. e! l5 M2 z0 e$ L& }$ ]
  22.     }0 `2 D" c  z1 {* b9 ?
  23.     SCL_L(ops);! S9 d" H! w& L3 v& B7 g$ J9 z
  24.     i2c_delay(ops);; Y" h( R" r6 ]3 r' q
  25. 9 u4 e9 d( c% c# X! H$ Z3 D8 l
  26.     return i2c_waitack(ops);
    1 v8 |5 S+ R5 i  U
  27. }
复制代码
9 b  |0 {8 K: b) \6 ^5 ?
" O5 k% Z, V- v1 o) L% v4 o0 Z3 _
使用道具 举报 回复
发表于 2019-1-28 22:12:36 | 显示全部楼层
这个是我今天在空调房间板子在电脑旁边测得温度,吐槽一下这个片子精度是有0.5℃。# y; A3 C# T& G5 {7 }

7 A6 m2 q! U/ c6 }. ~; u( g# ?
TIM截图20190128221131.png
使用道具 举报 回复
发表于 2019-1-29 09:43:34 | 显示全部楼层
本帖最后由 海阔天kongcyc 于 2019-1-29 09:49 编辑 - x! `/ ~$ E1 ~/ o

7 _( ~) C- D" ~( v2 t  O) W& f  K  j$ f谢谢楼主,有关IIC的驱动框架分析,以及LM75的驱动示例,讲解很清晰
使用道具 举报 回复
发表于 2019-1-29 14:31:19 | 显示全部楼层
目前驱动只做了温度正值,负值没做。
使用道具 举报 回复
发表于 2019-2-25 14:42:30 | 显示全部楼层
whj467467222 发表于 2019-1-28 20:59  z3 e$ }  o' R
1,在ENV开启IIC驱动框架% ]! c* O6 v) D9 h( o/ R. O
      RT_THREAD Components--Device Drivers
! W2 ~: O; f6 U. I% p5 N      这里要记得选择模拟IIC
3 s- `$ N( b7 k% m1 v2 w9 c' Z8 ?6 y0 {
不采用模拟IIC,使用硬件IIC操作。那这里也要打开模拟IIC的选项吗?
使用道具 举报 回复
发表于 2019-3-15 13:45:38 | 显示全部楼层
感谢楼主分享 帮顶 让更多人看到
使用道具 举报 回复
发表于 2019-3-29 18:27:33 | 显示全部楼层
xiexie
使用道具 举报 回复
发表于 2019-4-7 10:01:46 | 显示全部楼层
正在移植调试设备外设接口。。。
使用道具 举报 回复
发表于 2019-4-7 10:29:32 | 显示全部楼层
这个传感器驱动可以更新下做成一个软件包呢。
使用道具 举报 回复
发表于 2019-4-10 22:56:16 | 显示全部楼层
INIT_BOARD_EXPORT(rt_hw_i2c_init)完成了板级自动初始化

' i* U. }7 ?1 h9 A+ k" @; K原来是加入这个就可以被系统调用rt_hw_i2c_init()了。
使用道具 举报 回复
发表于 2019-4-19 12:43:38 | 显示全部楼层
谢谢分享`!~~~
使用道具 举报 回复
发表于 2019-4-30 22:59:37 | 显示全部楼层
戎传林 发表于 2019-2-25 14:423 a8 y8 `: [6 k1 s3 G- Q
不采用模拟IIC,使用硬件IIC操作。那这里也要打开模拟IIC的选项吗?
' q5 h0 Z0 Z$ B! {
不需要,这里的IIC仅仅是说的模拟IIC。
7 B* l6 R5 S4 m9 v' H; \+ yRTT目前还不支持硬件IIC
使用道具 举报 回复
发表于 2019-5-17 13:37:37 | 显示全部楼层
学习下
使用道具 举报 回复
发表于 2019-6-5 17:25:17 | 显示全部楼层
学习学习
使用道具 举报 回复
发表于 2019-6-26 13:35:51 | 显示全部楼层
学习一下
使用道具 举报 回复
发表于 2019-7-2 19:43:28 | 显示全部楼层
新版本在 drv_gpio.c 的 static const struct pin_index pins[] 里面对应的就是IO的编号
使用道具 举报 回复
发表于 2019-7-3 09:04:08 | 显示全部楼层
whj467467222 发表于 2019-4-30 22:59
2 ~: k/ A' x- |# p不需要,这里的IIC仅仅是说的模拟IIC。
% Z( ^3 {( O+ RRTT目前还不支持硬件IIC

4 @; h4 Z  F7 r硬件 IIC 也支持的。
使用道具 举报 回复
发表于 2019-7-17 18:10:41 | 显示全部楼层
谢谢楼主
使用道具 举报 回复
发表于 2019-7-18 00:00:18 | 显示全部楼层
感谢楼主分享,学习学习了。
使用道具 举报 回复
发表于 2019-7-24 16:34:26 | 显示全部楼层
挺全面 谢谢分享
使用道具 举报 回复
发表于 2019-8-11 22:48:44 | 显示全部楼层
谢谢分享,学习使用iic,
使用道具 举报 回复
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|RT-Thread开发者社区 ( 沪ICP备13014002号-1

有害信息举报电话:021-31165890 手机:18930558079

© 2006-2019 上海睿赛德电子科技有限公司

Powered by RT-Thread

快速回复 返回顶部 返回列表