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

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

本帖最后由 whj467467222 于 2019-4-11 08:32 编辑 * O- V+ n+ f7 E% @1 N) l

5 f* M# ]( o( [  J, y$ b, d9 f9 D0 A该测试是在RT_Thread下测试,硬件正常情况下的测试。自己写的一个测试使用IIC来读取LM75的测试程序,顺便总结一下自己对IIC驱动框架的理解。& P3 `, f: X+ G2 ]
该测试基于STM32F107 μC/Eval 开发板,使用模拟IIC,使用引脚为PB6 PB7。& n* |% I; W1 j* h  y, I  T
所有内容参考I2C总线设备5 j5 w" J' h4 F# V
使用道具 举报 显示全部楼层 回复
最新评论 | 正序浏览
显示全部楼层 |楼层直达:
发表于 2019-1-28 20:59:28 | 显示全部楼层
1,在ENV开启IIC驱动框架
, H0 I. Q3 K/ c# ^8 o      RT_THREAD Components--Device Drivers5 ^, r7 _! A+ d6 B, L: `* Q
      这里要记得选择模拟IIC
& G- v5 X5 \5 h
TIM截图20190128205828.png
使用道具 举报 回复
发表于 2019-1-28 21:06:55 | 显示全部楼层
2,在rtconfig.h里面就有了如下的宏定义5 Q, r; W. N: E; K
  1. #define RT_USING_I2C# Y4 t2 D2 i9 u: @6 o7 k3 ~
  2. #define RT_USING_I2C_BITOPS
复制代码
这里就表示开启了IIC,并且使用的是模拟IIC
. g9 r. W% X- `2 H1 o* m. T7 K! S2 n9 e& @2 m4 d1 q' l
  {" w4 \' A" z: g
3,因为本BSP包目前还没有添加支持IIC,目前无法通过ENV来进行设置,所以这里的模拟IIC的 SDA SCL定义到哪个引脚还需要自己设置% W- \- Y9 z; _
      我在这里设置为
0 C% E  _3 X5 q8 w
  1. #define BSP_I2C1_SCL_PIN 223 {. @' E" {, a0 i' P
  2. #define BSP_I2C1_SDA_PIN 23
复制代码
上面的22 23是在drv_gpio.c里面查表所得,这里有一点需要值得注意的是,早先的RTT是使用的STM32的引脚编码来进行编号,但是现在这个地方做了更改。
. [; ^+ l# e" f1 M, F* @) Z( y# e4 o早前的版本使用引脚编码来进行编号,方便查找,但是不同引脚的MCU就需要定义不同的顺序,代码量很大,而且要使用很多判断语句,显得很臃肿。0 _, ?9 I; ]2 z' r8 ]
新版采用的方法是查表法,每个端口的几号引脚可以通过drv_gpio.c来进行查找方便了很多,而且代码很精简。) M, G; |0 g0 i
使用道具 举报 回复
发表于 2019-1-28 21:21:17 | 显示全部楼层
4,上面配置好了,接下来就是IIC总线的初始化。3 {6 V- q/ w8 e+ J; W
  1. int rt_hw_i2c_init(void), p6 F& Q( z9 m/ ~8 ]4 b
  2. {
    / k6 h. ^& L' }- F
  3.     rt_size_t obj_num = sizeof(i2c_obj) / sizeof(struct stm32_i2c);4 S1 i# s8 g, n/ D7 {: M
  4.     rt_err_t result;
    2 V$ ?: k8 u( K6 S
  5.   a! ^* w9 l( J9 H
  6.     for (int i = 0; i < obj_num; i++)
    6 C( f) d8 R0 R" X' v
  7.     {
    6 M6 x) h- g8 t6 s5 e; [
  8.         i2c_obj[i].ops = stm32_bit_ops_default;7 f+ X2 A: E. Q+ M6 l0 {
  9.         i2c_obj[i].ops.data = (void*)&soft_i2c_config[i];
    0 L& Y3 l$ ^3 g. A( v' Q6 |
  10.         i2c_obj[i].i2c2_bus.priv = &i2c_obj[i].ops;
    ) |$ o( Q( d+ J5 k; P/ v# z8 S% v
  11.         stm32_i2c_gpio_init(&i2c_obj[i]);
    % C% `  \/ B+ f! m" ]8 |- d
  12.         result = rt_i2c_bit_add_bus(&i2c_obj[i].i2c2_bus, soft_i2c_config[i].bus_name);
    0 @5 \% a4 I) k- f
  13.         RT_ASSERT(result == RT_EOK);/ x. Q1 s3 F. ~3 Q" C7 y, r6 |3 i0 J
  14.         stm32_i2c_bus_unlock(&soft_i2c_config[i]);
    6 P1 H. K+ c( n6 k8 z0 }
  15.     }
    , ^- J* y# M: w& b

  16. ) b/ s8 r+ d7 F2 l
  17.     return RT_EOK;( y# i0 o5 s8 X; ?& V$ X& Y0 z
  18. }9 X1 A& Z# ?5 \; S# \; B
  19. INIT_BOARD_EXPORT(rt_hw_i2c_init);
复制代码
这个函数完成了IIC的初始化。
5 S0 X5 @( }% mINIT_BOARD_EXPORT(rt_hw_i2c_init)完成了板级自动初始化。
- T: D8 f& F, K$ E' F3 S( k, s
7 R3 b6 d5 l1 Q* P
  [1 q5 |' ^6 G3 W
obj_num = sizeof(i2c_obj) / sizeof(struct stm32_i2c);计算定义了几个IIC总线$ [7 S4 f; n  |/ e5 O/ ?# H( R
soft_i2c_config这个结构体通过宏定义来获取定义了几个IIC总线的名字:目前支持I2C1 I2C2 I2C3- H# U$ M9 J$ N+ M7 t) Z. H9 _- f4 k
i2c_obj.ops = stm32_bit_ops_default;默认的参数,这里不需要自己修改4 z* M! i  ]1 m2 ?4 d: W
  1. static const struct rt_i2c_bit_ops stm32_bit_ops_default =  n$ G7 w8 r- k) q0 s3 I
  2. {4 r) o9 l1 [3 g$ r, o& Q7 M4 q
  3.     .data     = RT_NULL,+ d3 K6 w/ z# `1 `& t6 T3 ~- R! g
  4.     .set_sda  = stm32_set_sda,
    " {, q6 e/ h" I1 Q; ?' F
  5.     .set_scl  = stm32_set_scl,! H/ d; ]8 u2 p; [0 {# J8 Z
  6.     .get_sda  = stm32_get_sda,  M6 ~! }" ~. z- d
  7.     .get_scl  = stm32_get_scl,7 b" h* J1 c/ k4 s! p3 _
  8.     .udelay   = stm32_udelay,
    0 e7 \. e0 ^5 g" ^" F2 E- v* v
  9.     .delay_us = 1,
    . t$ D. q$ u0 k# i$ c
  10.     .timeout  = 100& F  p/ X1 e0 k; P6 B
  11. };
复制代码
stm32_i2c_gpio_init(&i2c_obj);完成对模拟IIC SDA SCL引脚的初始化,这里初始化的模式是PIN_MODE_OUTPUT_OD
* ]8 P! K& L6 |4 W' m# y5 x! y7 O* F3 z  d; |  u# _
rt_i2c_bit_add_bus(&i2c_obj.i2c2_bus, soft_i2c_config.bus_name);完成对IIC总线的注册; v  C+ T) s" k' Z1 Z+ u. O
# h/ V* `# g# n; |) m' A0 z/ ]
stm32_i2c_bus_unlock(&soft_i2c_config);刚刚完成对IIC总线的注册,这个时候还不需要发送数据,这个时候把互斥锁打开。
9 b0 d5 s' b" ^- D) F) `7 O; O; j! ^/ w% S0 m9 ]' {  U
: X" @' z7 v9 Z# T4 A
使用道具 举报 回复
发表于 2019-1-28 21:25:01 | 显示全部楼层
5,IIC总线注册到系统中之后可以通过list_device来进行查看
4 d% M9 W' e/ d! m- J
% V( b$ u3 ]: x) {* D  s
TIM截图20190128212443.png
使用道具 举报 回复
发表于 2019-1-28 21:30:06 | 显示全部楼层
6,总线注册成功之后就是对设备的操作
0 b# M) d0 f- f7 j
  1. static void i2c_stlm75_sample(int argc, char *argv[])
    & _! N( @" P" r3 k( h7 f
  2. {
    & W( S+ m# w/ [
  3.     float temperature;
    - ?( d' q- n1 X; ]; M% X
  4.     temperature = 0.0;, T, n0 ?. B/ `6 ]* r- L
  5.     if (!initialized)6 q  e  U: F9 V( g; z% Y
  6.     {
    7 C# }4 K- ~' G$ d
  7.         stlm75_init(name);
    0 Y% N) Z) v% l( n
  8.     }
    ( f3 @8 r# ]$ ]5 {7 T
  9.     while(1)
    3 m' x  Z8 y% l7 I3 ?2 ]8 Z1 l: }
  10.     {- X3 d& k  m6 v. ^0 ^5 a' _9 y
  11.         if (initialized)7 Y% x' T9 x" G1 L, _; j% o! G
  12.         {           7 h+ q/ i) d3 ?! x6 Z
  13.            read_temp(&temperature);
    8 {' ?/ C+ \9 s: W$ n

  14. & u9 z, l2 n/ D5 D2 L  D
  15.             rt_kprintf("read stlm10 sensor temperature: %d.%d \n", (int)temperature, (int)(temperature * 10) % 10);
    * r; r3 d$ x' R7 b2 y- t* q- ^
  16.         }6 R7 \8 P: a4 {: ^: X! ]) C
  17.         else7 E' n* _; ~+ R( |; _" \
  18.         {, c( W2 S; |$ D- |1 u
  19.             rt_kprintf("initialize sensor failed!\n");. L9 ]* R% L4 P# n/ ^8 }" ]
  20.         }2 N( E$ I& E% ~' x2 A9 E
  21.         rt_thread_delay(1000);  M5 X2 X. @4 X& D# w' A; v6 J& X1 ]
  22.     }
    ' C( K6 L0 F" E! ^7 Y2 }/ A
  23. }1 ]9 t5 x# |1 o' `

  24. 7 M3 O8 r/ {5 C5 b  O  J+ ^, L3 {0 K
  25. MSH_CMD_EXPORT(i2c_stlm75_sample, i2c stlm75 sample);
复制代码
首先导出命令行
/ n* B5 f6 b. M  I; n& O0 @$ b' K上面的初始化函数完成了传感器的初始化,然后1S的循环来定时读取温度传感器的数据
- a6 d+ D% C6 }* {9 M3 v
使用道具 举报 回复
发表于 2019-1-28 21:32:05 | 显示全部楼层
7,传感器初始化函数
0 R( l: O: a7 i. s( istatic void stlm75_init(const char *name)2 c$ }* Y# L; D. S
{7 a0 Z# U: T9 {" I7 b' j7 s
    i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(name);; V# `# u. |0 N" \
    if (i2c_bus == RT_NULL)9 I. S% X: N" o: n+ D
    {
- N) A5 z; ^' z) N% v        rt_kprintf("can't find %s device!\n", name);* Y$ W6 _7 d" {( N1 s
    }
& U% h' J/ C! T# Y+ [; W6 ?: `& M    else2 p$ Y! B1 ?" M! M- I7 q
    {, `) Q9 y2 \3 X) q" g
        initialized = RT_TRUE;
$ v: Q/ e" j& m1 Q% @2 J    }
9 Z$ t! A; x4 b# S/ O) W}
- u2 Z) ~. e( \' w3 f0 I/ e7 w& d2 U7 }4 L  H. i! B- v
使用rt_device_find来查找在前面注册的IIC总线
% a& T! }# u9 c8 }
使用道具 举报 回复
发表于 2019-1-28 21:48:45 | 显示全部楼层
本帖最后由 whj467467222 于 2019-1-28 21:49 编辑 : ]* g# e; X( ^, j6 Q5 U

+ w/ r# }2 O& R) Y5 a9 y8,读取温度传感器信号函数* e' S8 K/ a" p3 D4 i2 X5 N
  1. static void read_temp(float *cur_temp)
    ! S5 ~7 w: E; H6 P8 \, z/ }
  2. {
    # u+ d- w9 W2 A) L
  3.     rt_uint8_t temp[2];
    7 v$ r) ]/ c( L/ `. M
  4.     rt_uint16_t abc;
    6 }" S  |+ l6 y2 k- O9 F
  5.     rt_uint8_t write[1]= {0x00};/ I, T0 W: \5 g9 b
  6. * Z2 v7 `6 ~! d' v/ c! d1 `/ b0 M
  7.     write_regs(i2c_bus,1,write);5 a( ^8 X+ o7 n& Y* c: Y; d

  8. 0 X/ [( q% z6 J9 B/ L
  9.     read_regs(i2c_bus,2, temp);
    $ }: }1 S0 N  ]/ h7 j
  10. 4 d. [; I. `4 v0 g# o0 H; ?! _
  11.     abc = ((rt_uint16_t)temp[0]<<8 | temp[1])>>5;
    / |- B$ k# I, b: I
  12. : ~2 v! r. l8 I% t
  13.     *cur_temp = abc*0.125;( |4 a! ^# X$ A. M/ B
  14. }
复制代码

. j: e: s* k; Q' X( Q$ y% g; x2 g5 Z8 V3 x  Y8 J7 Y, _- G! A
这个地方的函数按照IC的要求进行操作就可以了。' H' V5 b" }6 Q0 o
使用道具 举报 回复
发表于 2019-1-28 21:49:44 | 显示全部楼层
9,写操作命令# z* M* K. o5 c' x0 L9 s2 O
  1. static rt_err_t write_regs(struct rt_i2c_bus_device *bus, rt_uint8_t len, rt_uint8_t *buf)+ q  _- i" }# [5 d& f, k& N
  2. {3 L: R; w1 i" J! \5 O4 L  p
  3.     struct rt_i2c_msg msgs;: N4 k) \: A2 S: z. d$ ^. }) }; }

  4. 6 `/ [  [; Z4 J* @" d9 ]4 v
  5.     msgs.addr = STLM75_ADDR;1 \# B$ T8 k7 E; ?; \1 u
  6.     msgs.flags = RT_I2C_WR;
    * T# f1 W' P9 T0 i+ d( C
  7.     msgs.buf = buf;* w% _2 e, C* ^9 L
  8.     msgs.len = len;1 H" T0 o8 K) @0 Q- Y: u+ e' _
  9. ; |& ~- l6 h! N" x5 O5 K
  10.     if (rt_i2c_transfer(bus, &msgs, 1) == 1); A1 Q; q. \: m: L' F: q: U) O
  11.     {
    0 _7 Q5 _" Q/ t
  12.         return RT_EOK;. H9 X+ F7 v/ y5 D* z( t6 y
  13.     }
    7 W1 ?& @: t! P5 t9 L4 l
  14.     else: C7 |- Z! v5 |5 o
  15.     {
    ! N4 ^& K  s( n
  16.         return -RT_ERROR;; ?# a" F4 s$ R0 E5 R0 A$ I
  17.     }
    * f1 P: V/ g( u% Q# o) k  ^
  18. }
复制代码
按照IC要求进行操作7 o5 B2 I2 R5 M/ c) {
使用道具 举报 回复
发表于 2019-1-28 22:10:07 | 显示全部楼层
10,IIC总线框架读写操作的函数rt_i2c_transfer
, y  S. T0 a+ E/ U! J' g
  1. rt_size_t rt_i2c_transfer(struct rt_i2c_bus_device *bus,4 L5 N- V9 c) F1 \3 i6 o- Z
  2.                                        struct rt_i2c_msg         msgs[],
    2 i: }: Y  s" ~0 }( g$ k) \
  3.                                        rt_uint32_t               num)
    ( Y( d7 i  D- J. R
  4. {3 [5 {) R4 a3 g
  5.         rt_mutex_take(&bus->lock, RT_WAITING_FOREVER);2 l6 ?7 b, `6 Z1 D
  6.         ret = bus->ops->master_xfer(bus, msgs, num);
    * ~( p$ w' x! a# e% V+ r7 d
  7.         rt_mutex_release(&bus->lock);
    ! g) S. l% p& i& {  {
  8. 4 u' z9 R; l( k( L6 ~
  9.         return ret;
    5 k4 n. U9 s+ B# Q& T
  10. }
复制代码
struct rt_i2c_bus_device *bus, 总线
& A2 W/ r, }/ J. W6 Dstruct rt_i2c_msg msgs[]          消息结构体& b1 W- x+ @" ~/ O7 K
rt_uint32_t num                        数据数量        , t9 Y/ p1 D* A5 v

( ?, j# |$ J! O! Z5 H. [5 U/ g

# I- S9 |9 j  w1 N4 F然后获取互斥锁,获取到了之后执行
% y5 A; b8 ~% @
  1. ret = bus->ops->master_xfer(bus, msgs, num);
复制代码
实际执行的函数是, s7 B( e5 [9 S( Y# i7 {
  1. static rt_size_t i2c_bit_xfer(struct rt_i2c_bus_device *bus,( a7 Y  Z) ~% ?
  2.                               struct rt_i2c_msg         msgs[],7 q7 Q; d% A5 C1 ~
  3.                               rt_uint32_t               num)9 B! O" p' F7 t, W' E# S
  4. {
    / E* h; M& u0 v& N: v& n
  5.     struct rt_i2c_msg *msg;
    0 l7 _& l% F) \2 r
  6.     struct rt_i2c_bit_ops *ops = bus->priv;
    : d+ o$ b2 d. k' p4 o$ `  n
  7.     rt_int32_t i, ret;
    & g- e9 C+ ]0 A- q5 w, V' n
  8.     rt_uint16_t ignore_nack;
    7 C/ _9 ^! _3 w) x4 ?4 Z7 C5 M/ c

  9. . t2 O4 ?: r9 m3 O, z7 B% I- H
  10.     bit_dbg("send start condition\n");+ T$ m. q" }6 x
  11.     i2c_start(ops);
    3 j2 j# D3 z- T3 _! U8 ~5 m* @6 t
  12.     for (i = 0; i < num; i++)
    % v- E7 t* D0 x$ ~
  13.     {) [3 S' H- O* Q/ Q1 D' c
  14.         msg = &msgs[i];. |; t8 S& N! l  |
  15.         ignore_nack = msg->flags & RT_I2C_IGNORE_NACK;
    , x* i0 m! q( y1 l
  16.         if (!(msg->flags & RT_I2C_NO_START))& j7 U( K' O4 z0 G* v( N
  17.         {
    ; N0 s9 [! l% Z7 A  o# k5 R
  18.             if (i)
    0 J8 a" i7 S) z3 e) @+ b
  19.             {: U; y. L/ Q+ {. E4 E" M2 y
  20.                 i2c_restart(ops);
    + ?9 `1 c/ [' S8 x" U2 T
  21.             }
    7 Y5 h! @2 w$ g" C! _% T. d
  22.             ret = i2c_bit_send_address(bus, msg);
    + h3 \3 _% c) _: \) y; k
  23.             if ((ret != RT_EOK) && !ignore_nack)
    3 X) ^2 {0 F% o+ W+ Z. e9 J
  24.             {
    # n  @; D* E0 F8 T2 }
  25.                 bit_dbg("receive NACK from device addr 0x%02x msg %d\n",
    0 M6 v7 \# [+ h! h
  26.                         msgs[i].addr, i);7 W( G* w1 t/ z
  27.                 goto out;
    ' u1 B2 H7 x& y) X
  28.             }8 g7 F( E5 e7 }! q: @: ^2 n6 S
  29.         }" i' A; I' P( ~! l0 _
  30.         if (msg->flags & RT_I2C_RD)
    9 _1 K) z, {) V2 u+ X$ d
  31.         {# d2 Y6 P- W. t
  32.             ret = i2c_recv_bytes(bus, msg);
    . B# @- O6 T; W- M6 G
  33.             if (ret >= 1)
    * e+ k# ~+ e% y
  34.                 bit_dbg("read %d byte%s\n", ret, ret == 1 ? "" : "s");
    ! e; K: S; q9 |( A
  35.             if (ret < msg->len)7 Q6 K! Q) S) t3 E
  36.             {* t+ u, H4 ~  d1 |1 \
  37.                 if (ret >= 0)* U; O8 l! C4 F) I$ P, \
  38.                     ret = -RT_EIO;
    6 s% i. R( ~. A2 Q0 R
  39.                 goto out;4 d) u5 l3 \3 @1 x; F' ^
  40.             }( w) E9 c. @) z0 N% D, i
  41.         }# T, Y( ]( m, {, C, k! ]
  42.         else# y# P: X+ q8 Q% |
  43.         {
    ) B& r) m, U& a, C$ K7 T7 i1 ?
  44.             ret = i2c_send_bytes(bus, msg);3 S+ R4 m: g  U4 i1 O/ _: ~) N
  45.             if (ret >= 1)
    . `2 u% h+ w( H+ H' x- e
  46.                 bit_dbg("write %d byte%s\n", ret, ret == 1 ? "" : "s");: F& m0 A$ e, u
  47.             if (ret < msg->len)+ v6 x" T& R% \: N" H3 [5 M, {: `
  48.             {
    " p. g$ l8 ^( S6 H
  49.                 if (ret >= 0)$ L  ^) H$ y1 c. n
  50.                     ret = -RT_ERROR;. _. f4 @9 A8 r9 w& O7 q4 A, H2 K7 p
  51.                 goto out;+ G: ?) m) C! z2 R! V) B
  52.             }
    , [( {5 c& M' W5 ?8 M
  53.         }) n# Q- m0 x* j8 k3 w0 w7 _1 S9 e, R/ S( S
  54.     }; S7 i6 z& Z5 q, ?7 G4 e
  55.     ret = i;% Z4 y% C$ P9 N' q' O

  56. ( |9 B+ [( i& S1 R5 Z9 x
  57. out:
    " L6 s) c5 m& t  ?
  58.     bit_dbg("send stop condition\n");* P8 U- T- |7 d& ]- W% o3 d
  59.     i2c_stop(ops);
    ! B: M* D# Z+ P* n4 U

  60. & w$ S; `1 _9 K/ ]. r
  61.     return ret;
    6 m" H8 }! n/ U3 }" d1 [$ b
  62. }
复制代码

  U9 `7 ]9 O% l8 I6 _该函数进入之后就发送了i2c_start(ops);IIC启动信号,' W7 R4 w2 D1 W5 a$ C$ ]
然后进入了for循环,我这个就发送一个数据进行说明
' |2 x9 A# I6 h. A. ~8 dignore_nack = msg->flags & RT_I2C_IGNORE_NACK; 这里需要回复ACK所以这里的ignore_nack=0( p+ `3 Y% I0 Q
所以i2c_restart(ops);不会被执行  w3 w$ ?8 G+ d* S! S' V/ q0 d
接下来执行ret = i2c_bit_send_address(bus, msg);% C+ w- ~0 x+ i; L& f
  1. static rt_err_t i2c_bit_send_address(struct rt_i2c_bus_device *bus,
    0 C) Y9 j* |6 ~; {5 p& x; j5 {2 a# h
  2.                                      struct rt_i2c_msg        *msg)5 V9 f& L, O2 |& i( D
  3. {
    ( E* T0 H! y/ j: W6 V' L
  4.     rt_uint16_t flags = msg->flags;
    0 O( U8 e( c/ o6 s
  5.     rt_uint16_t ignore_nack = msg->flags & RT_I2C_IGNORE_NACK;8 Q* h& C* X. T: K& G9 g2 h
  6.     struct rt_i2c_bit_ops *ops = bus->priv;
    / n& H! J. X7 a3 r8 {
  7. * O1 h" O$ |  m; [* J, s
  8.     rt_uint8_t addr1, addr2;, Q+ Z  h1 m) p7 i% j
  9.     rt_int32_t retries;4 `, i# w9 E' j7 T3 |: }
  10.     rt_err_t ret;( c" W0 |/ a7 F

  11. . k8 v5 F# b' {4 a' k+ Q+ a4 l
  12.     retries = ignore_nack ? 0 : bus->retries;
    & Z: E  C6 o6 j+ m; H
  13. 5 T5 Z' f) W0 i) m+ |5 J1 [2 E9 B
  14.     if (flags & RT_I2C_ADDR_10BIT)+ P2 O2 T6 p8 u" K* D% k7 m6 h  ^4 b
  15.     {
    2 @) i) ?" g) p0 t/ U
  16.     }
    2 U, y- a4 h. Z0 G! d7 d8 n; V; _
  17.     else% t* Z. K7 G+ i+ t; t& a1 z
  18.     {* L' Y) O% V; o; @: T
  19.         /* 7-bit addr */
    8 _# `" z6 O6 g! l" T
  20.         addr1 = msg->addr << 1;$ D/ E1 D' U1 `+ a' Z" D
  21.         if (flags & RT_I2C_RD)$ g& d. ^* E9 ?! v- @
  22.             addr1 |= 1;
    . S1 ^3 n; j: w9 u# A/ j8 N
  23.         ret = i2c_send_address(bus, addr1, retries);9 t; q( q6 r6 y* G% ^
  24.         if ((ret != 1) && !ignore_nack)0 @( `8 ~6 ~7 u# s+ H
  25.             return -RT_EIO;
    , O7 `- {- q  ~4 j- A% o5 A
  26.     }
    ( ~( O. f2 ~& F( I2 E2 M
  27. 1 O1 k8 u2 J" Z' r% j
  28.     return RT_EOK;  K+ U% L3 o6 M( P1 V4 P
  29. }
复制代码
这里删掉了10bit模式,因为我用的7bi't'模式,10bit还没看
  E7 z1 ?$ L1 Y' A6 l" A+ crt_uint16_t ignore_nack = msg->flags & RT_I2C_IGNORE_NACK;因为第一次是写数据,所以这里的结果是0
. K2 w; o: O9 q9 Q3 Yaddr1 = msg->addr << 1;这个地方要重点注意一下,地址左移了一位5 V" J9 C# p( \& O
然后执行ret = i2c_send_address(bus, addr1, retries);
/ _% o. }/ s1 O6 n- G: j9 R% p
  1.     for (i = 0; i <= retries; i++)
    & H' w* ?- T# N; ^/ Z
  2.     {4 u, E2 H, X7 M5 w" i
  3.         ret = i2c_writeb(bus, addr);2 H7 J/ l; u6 k: N, |
  4.         if (ret == 1 || i == retries)
    $ r6 T" ]) N1 D
  5.             break;& g. `- b' E. p8 u' ?
  6.         bit_dbg("send stop condition\n");: G) B  k6 u! i% l# g. f7 E/ e/ z  w
  7.         i2c_stop(ops);
    4 x! B; I0 J" Y& [
  8.         i2c_delay2(ops);9 s8 T- A' h' ~
  9.         bit_dbg("send start condition\n");( E" n# O; t6 ^
  10.         i2c_start(ops);$ R9 }8 z; U! E; f
  11.     }
复制代码
前面做了这么多的准备工作,终于要执行写数据的函数了' V+ R% Z% Y  X, m4 ~3 l( g
  1. static rt_int32_t i2c_writeb(struct rt_i2c_bus_device *bus, rt_uint8_t data)7 e6 T' T1 @6 j/ X
  2. {
    6 Q7 y* f. S$ J
  3.     rt_int32_t i;
    1 k4 Q5 Y! S7 ~) E6 f: \2 P# i
  4.     rt_uint8_t bit;
    $ K0 f' m6 M( Z. I. L% V" C

  5. , h; s3 g' ^& \6 ~0 ~
  6.     struct rt_i2c_bit_ops *ops = bus->priv;5 q+ E0 n% O7 _2 e9 c  N! t

  7. ( L' E* W5 ]' ?- J0 v
  8.     for (i = 7; i >= 0; i--)5 Z6 C. n; k. `9 v# e2 g. j# B
  9.     {
    3 I" c5 F: r: K5 r
  10.         SCL_L(ops);1 K1 i4 k  O: G0 Y
  11.         bit = (data >> i) & 1;
    + d/ S: P$ L! {% K
  12.         SET_SDA(ops, bit);5 ~! k; S+ c- Y/ V9 q; v
  13.         i2c_delay(ops);
    ! }+ G$ f; T6 B8 r! S" W
  14.         if (SCL_H(ops) < 0)5 p! A5 L# k/ |" Q& F
  15.         {' E% \0 |+ {# a: D; ^
  16.             bit_dbg("i2c_writeb: 0x%02x, "
    / h7 y4 U# D* z
  17.                     "wait scl pin high timeout at bit %d\n",: t. m% D+ h0 m( V( m2 K
  18.                     data, i);% E, q. M# \  u2 R# ^+ o

  19. " ?6 p3 @: F+ {# z7 @, f
  20.             return -RT_ETIMEOUT;$ P/ _4 M8 ~. p0 c# Y
  21.         }' Z3 d! Q# N- O; l  [3 v
  22.     }
    ! W- \1 R  S  c, F% v) |( Q" N; \
  23.     SCL_L(ops);
    & ?# p6 c+ `2 X
  24.     i2c_delay(ops);
    ) d# b# Y" A8 W) R
  25. - o/ C8 v+ G( q0 ]& @  @6 D+ w
  26.     return i2c_waitack(ops);
      N- d* t4 _: ]) a- B
  27. }
复制代码

8 J& }+ N9 R  B! F. G3 Y- S2 l$ U% T5 w  v1 b1 k2 ?6 g
使用道具 举报 回复
发表于 2019-1-28 22:12:36 | 显示全部楼层
这个是我今天在空调房间板子在电脑旁边测得温度,吐槽一下这个片子精度是有0.5℃。  @& c( P6 }1 H

2 {" c9 s+ l* n) i! m
TIM截图20190128221131.png
使用道具 举报 回复
发表于 2019-1-29 09:43:34 | 显示全部楼层
本帖最后由 海阔天kongcyc 于 2019-1-29 09:49 编辑
' q) U3 I; _& [2 q$ I! a# |% n" h6 m! I( g
谢谢楼主,有关IIC的驱动框架分析,以及LM75的驱动示例,讲解很清晰
使用道具 举报 回复
发表于 2019-1-29 14:31:19 | 显示全部楼层
目前驱动只做了温度正值,负值没做。
使用道具 举报 回复
发表于 2019-2-25 14:42:30 | 显示全部楼层
whj467467222 发表于 2019-1-28 20:598 X% Z6 M; i$ @, s# b
1,在ENV开启IIC驱动框架
  B& M, [& G) K7 M+ n      RT_THREAD Components--Device Drivers' F0 \0 x2 c5 w; H% `, G2 z
      这里要记得选择模拟IIC
; A" z" g( m3 H
不采用模拟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)完成了板级自动初始化
# \0 T0 J; O% q0 i- l' g+ r
原来是加入这个就可以被系统调用rt_hw_i2c_init()了。
使用道具 举报 回复
发表于 2019-4-19 12:43:38 | 显示全部楼层
谢谢分享`!~~~
使用道具 举报 回复
发表于 2019-4-30 22:59:37 | 显示全部楼层
戎传林 发表于 2019-2-25 14:42
1 u' a6 m: H" J& k* l不采用模拟IIC,使用硬件IIC操作。那这里也要打开模拟IIC的选项吗?
$ F/ T( u: |( j: D
不需要,这里的IIC仅仅是说的模拟IIC。
$ {% t7 M3 r4 \; @; X! {) J$ [RTT目前还不支持硬件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
4 ~  r; q2 J  X8 [# `1 u6 |  W& i不需要,这里的IIC仅仅是说的模拟IIC。, A) Q1 p8 {! N3 V$ o% k" T1 ^& S
RTT目前还不支持硬件IIC
9 Q2 V" v, a  a
硬件 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,
使用道具 举报 回复
发表于 2019-9-1 10:26:15 | 显示全部楼层
正在学习rt thread下IIC的使用,解决了几天的困扰,非常感谢
使用道具 举报 回复
发表于 2019-9-1 23:15:54 | 显示全部楼层
whj467467222 发表于 2019-1-28 21:06
+ V" V  x* S" H# y; A3 h2,在rtconfig.h里面就有了如下的宏定义( Q, ^9 R  Q  A+ L9 \! v& K
这里就表示开启了IIC,并且使用的是模拟IIC
' x' |1 R* s  f, D2 X
楼主,这两个宏定义在哪个文件中定义呢?
使用道具 举报 回复
发表于 2019-9-2 21:08:38 | 显示全部楼层
pkokoc 发表于 2019-9-1 23:15* N4 R- _( s! j! J& ]6 d
楼主,这两个宏定义在哪个文件中定义呢?

( W* B; w* Y$ o9 ?9 @) m# I请使用ENV工具
使用道具 举报 回复
发表于 2019-9-3 17:50:06 | 显示全部楼层
whj467467222 发表于 2019-9-2 21:08' H1 d8 E8 E2 I. k
请使用ENV工具
/ r9 p+ r+ s* U* Q# J1 R5 [+ g
楼主这个文章启发很大,经过几天摸索,将使用I2C的经验总结如下:  h4 B( I1 P' t2 S0 ]1 N' q$ b
https://www.rt-thread.org/qa/for ... ypeid%26typeid%3D26
使用道具 举报 回复
发表于 2019-11-7 17:28:33 | 显示全部楼层
使用道具 举报 回复
发表于 2019-11-16 19:13:21 | 显示全部楼层
可以!!!!!!!
) o# L# ]$ r: E3 U* F2 b
使用道具 举报 回复
发表于 2019-11-29 10:19:29 | 显示全部楼层
学习ing
使用道具 举报 回复
发表于 2019-12-23 16:20:32 | 显示全部楼层
正好在看这部分模拟i2c,学习下
使用道具 举报 回复
发表于 2020-1-8 11:39:39 | 显示全部楼层
谢谢楼主,学习学习
使用道具 举报 回复
发表于 2020-1-21 15:37:10 | 显示全部楼层
看看,
使用道具 举报 回复
发表于 2020-3-9 14:27:27 | 显示全部楼层
顶,感谢分享,很有帮助
使用道具 举报 回复
发表于 2020-3-9 14:41:38 | 显示全部楼层
感谢分享~
使用道具 举报 回复
发表于 2020-3-26 16:40:15 | 显示全部楼层
多谢老兄,卡死在这里原来是没选择模拟IIC
使用道具 举报 回复
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

  1. 25 主题
  2. 3049 帖子
  3. 3049 积分

Ta的主页 发消息

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

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

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

Powered by RT-Thread

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