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

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

本帖最后由 whj467467222 于 2019-4-11 08:32 编辑   j4 p- @8 V/ w! T2 q
# s3 I" N& O6 n, G1 z* q0 F0 r* ~$ c6 U
该测试是在RT_Thread下测试,硬件正常情况下的测试。自己写的一个测试使用IIC来读取LM75的测试程序,顺便总结一下自己对IIC驱动框架的理解。
( \" `; l/ ^: L0 R该测试基于STM32F107 μC/Eval 开发板,使用模拟IIC,使用引脚为PB6 PB7。+ u* R& H4 q+ M* a( `* W
所有内容参考I2C总线设备
: r3 g# u& k9 D8 l% z7 {$ C5 B
使用道具 举报 显示全部楼层 回复
最新评论 | 正序浏览
显示全部楼层 |楼层直达:
发表于 2019-1-28 20:59:28 | 显示全部楼层
1,在ENV开启IIC驱动框架
9 K+ d. D- I5 c: w: {6 T      RT_THREAD Components--Device Drivers
1 a  q" Y7 w3 ^+ n) x0 Y, \7 d      这里要记得选择模拟IIC# J! j+ x- R# w
TIM截图20190128205828.png
使用道具 举报 回复
发表于 2019-1-28 21:06:55 | 显示全部楼层
2,在rtconfig.h里面就有了如下的宏定义
0 M( b; x! P" q( u# h/ k# b
  1. #define RT_USING_I2C' u4 o- c7 b0 e: V4 S
  2. #define RT_USING_I2C_BITOPS
复制代码
这里就表示开启了IIC,并且使用的是模拟IIC- Q3 L* ]' Z1 y* U5 O
& j/ l( k# p0 X  S% g1 q

! G5 v5 P$ A# H& s8 P9 ?0 Q. \+ [8 |2 U3,因为本BSP包目前还没有添加支持IIC,目前无法通过ENV来进行设置,所以这里的模拟IIC的 SDA SCL定义到哪个引脚还需要自己设置
% D0 i; a4 A( ?; @5 _9 z      我在这里设置为9 G6 X0 f, U0 c4 Y' W
  1. #define BSP_I2C1_SCL_PIN 22
    + Z# @0 T$ e7 ?7 U! l# N3 K
  2. #define BSP_I2C1_SDA_PIN 23
复制代码
上面的22 23是在drv_gpio.c里面查表所得,这里有一点需要值得注意的是,早先的RTT是使用的STM32的引脚编码来进行编号,但是现在这个地方做了更改。0 ^, ?/ [. t7 e- H% M, O: ]
早前的版本使用引脚编码来进行编号,方便查找,但是不同引脚的MCU就需要定义不同的顺序,代码量很大,而且要使用很多判断语句,显得很臃肿。3 ?% |. H" [7 w3 j, F2 T: \
新版采用的方法是查表法,每个端口的几号引脚可以通过drv_gpio.c来进行查找方便了很多,而且代码很精简。1 t/ s' D  V$ j1 L# x
使用道具 举报 回复
发表于 2019-1-28 21:21:17 | 显示全部楼层
4,上面配置好了,接下来就是IIC总线的初始化。( Q; B  o' ~! T+ K0 ?: [
  1. int rt_hw_i2c_init(void)
    # P, g  s; S+ A, j. b0 @" ~" W
  2. {
    ; i# B3 X3 T8 {: D  H* c
  3.     rt_size_t obj_num = sizeof(i2c_obj) / sizeof(struct stm32_i2c);4 d. o1 e1 |: w( i5 L" B
  4.     rt_err_t result;
    - S( R3 S/ P3 R9 m% x

  5. 6 D7 m# |" T8 ]) X8 A/ U2 U6 e% ^
  6.     for (int i = 0; i < obj_num; i++)
    ) w2 n, O3 l2 q  L! @
  7.     {
    * k& k+ t! H2 L  A' f& L
  8.         i2c_obj[i].ops = stm32_bit_ops_default;' ^% ~$ _( y* ~8 q% I1 L
  9.         i2c_obj[i].ops.data = (void*)&soft_i2c_config[i];" [! t( |# j- a, _% K
  10.         i2c_obj[i].i2c2_bus.priv = &i2c_obj[i].ops;+ b  e6 b5 M! c
  11.         stm32_i2c_gpio_init(&i2c_obj[i]);/ r4 I3 @6 j& g, u. ^
  12.         result = rt_i2c_bit_add_bus(&i2c_obj[i].i2c2_bus, soft_i2c_config[i].bus_name);
    8 X6 ]) h" P+ R, H5 a, O  v
  13.         RT_ASSERT(result == RT_EOK);1 \* N7 `: ^+ o$ I: J' G
  14.         stm32_i2c_bus_unlock(&soft_i2c_config[i]);7 V- o% E" R4 s5 E7 w3 [
  15.     }$ u5 a* i; S' \- w+ h4 Z: O, Q

  16. / }" l) j" [" h% O2 p4 C
  17.     return RT_EOK;$ M1 R  x6 F! H6 S: s" H
  18. }
    9 t1 [: o& r- `7 Q4 r- z& \" \
  19. INIT_BOARD_EXPORT(rt_hw_i2c_init);
复制代码
这个函数完成了IIC的初始化。0 R7 v" N4 @" H6 s
INIT_BOARD_EXPORT(rt_hw_i2c_init)完成了板级自动初始化。+ P% Q9 O: D3 P# k& j* [6 y

  w! i* v& b7 _! [
4 ?. s( J* P6 J% m; P! f) k
obj_num = sizeof(i2c_obj) / sizeof(struct stm32_i2c);计算定义了几个IIC总线0 D* \0 a( }% f- ?
soft_i2c_config这个结构体通过宏定义来获取定义了几个IIC总线的名字:目前支持I2C1 I2C2 I2C32 b" p4 r6 C2 p0 y4 r; V
i2c_obj.ops = stm32_bit_ops_default;默认的参数,这里不需要自己修改5 C/ _( y$ m" ]
  1. static const struct rt_i2c_bit_ops stm32_bit_ops_default =" b9 X. h, D$ X& A0 C
  2. {
    ! `) z1 |. v* O1 y$ E- M
  3.     .data     = RT_NULL,- Y" F3 w, L2 f) J
  4.     .set_sda  = stm32_set_sda,; o9 N; v2 e4 {6 T) P2 ^; [
  5.     .set_scl  = stm32_set_scl,9 J8 ^) ]0 |9 ~( V: F* D8 g! ~
  6.     .get_sda  = stm32_get_sda,
    ! I6 p4 H! e+ Y
  7.     .get_scl  = stm32_get_scl,
    1 }9 C! P5 @* Q
  8.     .udelay   = stm32_udelay,* k! Q* |, A, z) \: `
  9.     .delay_us = 1,
      \2 |5 b6 m" P% {
  10.     .timeout  = 100
    , J4 E) h2 ]' [: S7 H& y" n- B
  11. };
复制代码
stm32_i2c_gpio_init(&i2c_obj);完成对模拟IIC SDA SCL引脚的初始化,这里初始化的模式是PIN_MODE_OUTPUT_OD
4 b) t" s; c% A2 c) c8 d5 k4 @1 u) X; N' s7 `, V
rt_i2c_bit_add_bus(&i2c_obj.i2c2_bus, soft_i2c_config.bus_name);完成对IIC总线的注册  a8 i2 V- U8 P/ q  M% b" T

1 b$ W8 W- Y6 A( [, H# w! ?stm32_i2c_bus_unlock(&soft_i2c_config);刚刚完成对IIC总线的注册,这个时候还不需要发送数据,这个时候把互斥锁打开。
4 H3 |" t8 x6 c" H: R
1 b1 S' R2 }3 t. f# z1 u
9 J( [( K- h( Q( [: w) i$ ?
使用道具 举报 回复
发表于 2019-1-28 21:25:01 | 显示全部楼层
5,IIC总线注册到系统中之后可以通过list_device来进行查看& F$ m2 E8 d5 F
. B3 l' c: Q8 p' \" i
TIM截图20190128212443.png
使用道具 举报 回复
发表于 2019-1-28 21:30:06 | 显示全部楼层
6,总线注册成功之后就是对设备的操作4 \% I, y% T1 o4 \$ R" C; f2 B0 L& P
  1. static void i2c_stlm75_sample(int argc, char *argv[])
    5 ]! l/ z% y$ r' X/ I% r; l
  2. {' C' K6 A4 k8 I  ^0 g
  3.     float temperature;
    / R2 I* A2 ~. F2 d$ `9 E  K
  4.     temperature = 0.0;
    ) O  c+ q4 H0 m: Q: H! z- m7 Q* E
  5.     if (!initialized)4 L8 Y' \* B% Y4 }! s& }
  6.     {
      x5 a5 V; i3 o5 A
  7.         stlm75_init(name);% t* |( @1 }( h. F0 \
  8.     }
    0 H% ?! C# J& _
  9.     while(1)4 D9 r8 N. n) ^8 s. T
  10.     {0 p) A8 l( E8 `: ]: W
  11.         if (initialized)
    0 d$ B% |6 [4 q- E7 D3 u3 A
  12.         {           
    6 e0 b* o" r2 I# L
  13.            read_temp(&temperature);- h* p; O6 u8 \7 Q  S* N

  14. * t" J. T- A, U" c3 n* l% K
  15.             rt_kprintf("read stlm10 sensor temperature: %d.%d \n", (int)temperature, (int)(temperature * 10) % 10);
    : N0 \) V, l# h* m. s9 Q
  16.         }
    4 m' O+ y$ a# r2 |
  17.         else
    & A# X6 I) c$ E* ?  V
  18.         {
    ' r( c+ S) B( t1 ^1 A$ v+ |
  19.             rt_kprintf("initialize sensor failed!\n");& @" i' N/ Z7 f! F) i
  20.         }
    1 j. X; u- K. ~- C! g) R
  21.         rt_thread_delay(1000);) s9 t9 |- B7 f- C1 V2 o" P/ e
  22.     }
    ' {: }' _; z2 |: J3 W
  23. }+ m2 z1 {' F2 k& C+ H
  24. 4 O$ ?0 ]# `+ I1 X/ |
  25. MSH_CMD_EXPORT(i2c_stlm75_sample, i2c stlm75 sample);
复制代码
首先导出命令行
& C1 L5 r' C  u) M; V0 |! u上面的初始化函数完成了传感器的初始化,然后1S的循环来定时读取温度传感器的数据8 L0 [" p7 r6 m/ j0 _
使用道具 举报 回复
发表于 2019-1-28 21:32:05 | 显示全部楼层
7,传感器初始化函数
9 \' P1 w2 B$ E: l7 L2 M5 O# r& Bstatic void stlm75_init(const char *name)
9 g! U- E- x- n+ @9 X5 c& I{
- z  A7 [1 y) t/ k5 \    i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(name);
* q0 @/ a+ h  m% ]    if (i2c_bus == RT_NULL): H7 \) i/ G/ C1 Y  |6 x
    {) z7 `4 @, h8 X2 ^
        rt_kprintf("can't find %s device!\n", name);% S, Q1 e/ ]  ~! y
    }
: Q% P( l  r. o    else
/ ^4 [% G* g! D( u2 W9 \4 f    {! ^/ {6 A* |5 @5 J" s" _
        initialized = RT_TRUE;
% X" o3 U; @- A, c9 h" R4 z6 ~    }
7 l% j( v, y( X  X- Y. |! W; e2 U}
+ S; [% W: e$ B' g4 e2 I4 i
+ J' h. o, Z- h( |* l- a- H1 E  @/ _使用rt_device_find来查找在前面注册的IIC总线! ?2 U9 q* V4 ^& n
使用道具 举报 回复
发表于 2019-1-28 21:48:45 | 显示全部楼层
本帖最后由 whj467467222 于 2019-1-28 21:49 编辑 ; b2 W  G9 V0 i6 e7 \4 n: {

/ v. J; g$ Z* K: t5 D8,读取温度传感器信号函数
' H4 g) {) w! u" m, [% i5 @
  1. static void read_temp(float *cur_temp)6 @  }6 n( Z0 Z2 g
  2. {
    8 Z, p; x- P3 H3 y- w' O$ T
  3.     rt_uint8_t temp[2];
    6 V' S, k' M- o+ }
  4.     rt_uint16_t abc;
    + A+ N$ n& h$ l6 a1 E! L) l- y
  5.     rt_uint8_t write[1]= {0x00};
    . l5 V: Q$ P- L4 f9 G! d

  6. ; u1 C% s5 M! v; s. ~# C1 m. q- q
  7.     write_regs(i2c_bus,1,write);
    1 ~; Y. q/ |* T0 s& \3 Y0 ^
  8. 4 X4 u3 y. R) O3 o/ v7 r& V. b
  9.     read_regs(i2c_bus,2, temp);5 n% ~) {' i$ O' i- {* z7 n7 z

  10. 2 K  I; j5 [' s# A
  11.     abc = ((rt_uint16_t)temp[0]<<8 | temp[1])>>5;
    # L- D% G7 I" Q6 s4 X
  12. ! d7 ]3 J! \" J2 L8 M/ W) I4 Q
  13.     *cur_temp = abc*0.125;5 F2 H2 }4 Z  `& ^* |/ b0 D- U
  14. }
复制代码

5 }9 ~" T" N3 R" G- R2 e& X' |& Q7 `. h5 x4 o
这个地方的函数按照IC的要求进行操作就可以了。
  ]' g1 E/ o0 k6 d3 c  c
使用道具 举报 回复
发表于 2019-1-28 21:49:44 | 显示全部楼层
9,写操作命令
5 |& R4 V8 ?4 j, `+ x; y. `7 {$ c
  1. static rt_err_t write_regs(struct rt_i2c_bus_device *bus, rt_uint8_t len, rt_uint8_t *buf)- G* B( S/ s/ d# L# `
  2. {1 p: ?9 Y$ ~5 q/ E. J& x2 m
  3.     struct rt_i2c_msg msgs;
    & t. K. d! t* w6 G4 p& g% G
  4. : e3 s7 y( {% x6 e+ S
  5.     msgs.addr = STLM75_ADDR;7 |7 `0 h) H/ t) L: m0 r# U* L
  6.     msgs.flags = RT_I2C_WR;+ q( p. v! E' ~( R! J
  7.     msgs.buf = buf;& J* a% ^7 r' l) z* j, [
  8.     msgs.len = len;
    ( J2 Y3 \5 E  C

  9. , a! d& s& B3 P. ?+ O, N- ~  {8 g$ |
  10.     if (rt_i2c_transfer(bus, &msgs, 1) == 1)9 A: g$ A) f+ b+ I
  11.     {5 \% d) _! }- i' h4 ?
  12.         return RT_EOK;
    $ L0 e- P$ d3 u; Z
  13.     }5 r% T. B2 v3 y( ^1 ~
  14.     else
    ( F/ q9 Y2 c7 A  d
  15.     {" f- Q. d& a/ n
  16.         return -RT_ERROR;
    9 R# \8 u- U9 A+ T9 ^, G$ _
  17.     }/ n$ w6 F  T+ F  m& z) K
  18. }
复制代码
按照IC要求进行操作
2 C% E/ j6 f! s
使用道具 举报 回复
发表于 2019-1-28 22:10:07 | 显示全部楼层
10,IIC总线框架读写操作的函数rt_i2c_transfer* o3 B9 R# P: V' V
  1. rt_size_t rt_i2c_transfer(struct rt_i2c_bus_device *bus,: m; l9 N7 o% y! E: H! X4 v
  2.                                        struct rt_i2c_msg         msgs[],
    8 o( s/ U  l3 ?0 {, z: [
  3.                                        rt_uint32_t               num)- J/ p! {/ {5 u4 `& b
  4. {; P# N# z  H; B2 e# ]9 c* ?; N
  5.         rt_mutex_take(&bus->lock, RT_WAITING_FOREVER);. w/ [6 A( Y8 t: b2 w
  6.         ret = bus->ops->master_xfer(bus, msgs, num);
    ) R1 Q# f' |0 }  p/ g1 v* p
  7.         rt_mutex_release(&bus->lock);
    7 S( x* Y# @) x
  8. / R6 D2 w% v2 d& n) S3 V9 K' g
  9.         return ret;
    5 _! n0 z) g: A+ `5 z* i1 W) V3 w
  10. }
复制代码
struct rt_i2c_bus_device *bus, 总线) x+ d, b/ V4 E) ^
struct rt_i2c_msg msgs[]          消息结构体
% A" m& Z6 v/ t% {2 }% J# Yrt_uint32_t num                        数据数量        # }* x/ k& X- h: t- z; N6 G
; M* s0 i2 h, o, p' W7 Q0 M! D# l
% `- f* [( k* z' P7 q+ `+ Z
然后获取互斥锁,获取到了之后执行' O! R8 {# H8 {9 B. J) }
  1. ret = bus->ops->master_xfer(bus, msgs, num);
复制代码
实际执行的函数是2 a* k/ S" e1 v$ L8 d/ ^( ]1 w( S
  1. static rt_size_t i2c_bit_xfer(struct rt_i2c_bus_device *bus,
      z6 K* e5 m5 M6 X, W
  2.                               struct rt_i2c_msg         msgs[],- ]+ u7 @! H. q8 J( d2 ]6 F
  3.                               rt_uint32_t               num)! F7 m( m6 p! W) ?" v2 P$ |
  4. {
    & ]: s* t7 f' z- g5 |
  5.     struct rt_i2c_msg *msg;
    3 ^# i0 Z  L) n) ^
  6.     struct rt_i2c_bit_ops *ops = bus->priv;
    2 G% A% ^4 f+ j3 G0 v
  7.     rt_int32_t i, ret;
    3 K$ {9 o: X) V( G/ K
  8.     rt_uint16_t ignore_nack;& a! E3 t/ S  S- i- @9 L/ Z/ y
  9. 1 B$ A" e  x& q" y
  10.     bit_dbg("send start condition\n");7 a+ m2 U- Z  H! F9 a
  11.     i2c_start(ops);
    & k7 t! t# \6 b3 l
  12.     for (i = 0; i < num; i++)) P* \# ?9 R" v; j
  13.     {& @3 B+ ?/ d* i
  14.         msg = &msgs[i];
    " {6 B. p% p4 [3 Y
  15.         ignore_nack = msg->flags & RT_I2C_IGNORE_NACK;+ a* f* k. `4 J- R; a( v! v
  16.         if (!(msg->flags & RT_I2C_NO_START))
    ! w& W9 o3 L0 ]- \9 J. Y! V2 M8 D
  17.         {! `1 c& c% t. D
  18.             if (i), h0 n  r: ?, n5 w  S5 }
  19.             {$ o) k7 ~; Z# O9 M
  20.                 i2c_restart(ops);3 K$ Y5 H: @4 @" B  N& F! C
  21.             }& `( u2 @( U" p$ r9 q
  22.             ret = i2c_bit_send_address(bus, msg);
    ' y* ?3 ]' G4 A& ^9 h3 S
  23.             if ((ret != RT_EOK) && !ignore_nack)
      {# p% T; r# U7 X! n
  24.             {) N- o- Y# q& }
  25.                 bit_dbg("receive NACK from device addr 0x%02x msg %d\n",
    ) P" `; r9 _# v1 c7 m
  26.                         msgs[i].addr, i);4 J  W5 t! i4 s4 Q
  27.                 goto out;% A' _) \$ y( ^* L
  28.             }
    3 I. a( b! i% Q& x% y$ [- F
  29.         }8 Q& s5 @& J* {- K$ \2 N: h3 b
  30.         if (msg->flags & RT_I2C_RD)
    ( K' k. E2 I( w) Z% @
  31.         {- V* ?% c+ U* P' S- F
  32.             ret = i2c_recv_bytes(bus, msg);& o: p) M8 h6 K: q* g
  33.             if (ret >= 1), N% w- n5 H# V
  34.                 bit_dbg("read %d byte%s\n", ret, ret == 1 ? "" : "s");
    + `* d- }; o3 Y
  35.             if (ret < msg->len)+ ?0 @" f" x2 r2 l- x: _6 e7 q
  36.             {
    . `0 z5 w0 v( M& e5 K1 B% n* ^
  37.                 if (ret >= 0)
    1 V6 J( M+ N  q$ L! R9 V
  38.                     ret = -RT_EIO;
    ( M+ Q4 ]' W6 e; t) C
  39.                 goto out;6 n$ J1 ~, @+ ?6 y+ _
  40.             }
    . B. M2 |& n3 Q" M% [% y
  41.         }: b4 p" i5 w' m! z7 r
  42.         else. r0 Y* W* y& h% R
  43.         {
    ! f: C4 w6 ?) N* L6 r
  44.             ret = i2c_send_bytes(bus, msg);
    0 y4 I& |& @, e. r: C, o
  45.             if (ret >= 1)* A! D  Q+ u* s8 S& w) d
  46.                 bit_dbg("write %d byte%s\n", ret, ret == 1 ? "" : "s");: o7 r# D' n* B: h
  47.             if (ret < msg->len)7 `4 p( f( {  j* B( O
  48.             {
    0 m- Z+ b7 |5 ^3 Y; \7 O
  49.                 if (ret >= 0): C3 ~- r" P: D& e
  50.                     ret = -RT_ERROR;
    0 L4 T. K9 e% W; g' y7 S4 d# Y
  51.                 goto out;
    , e4 _9 e9 L) R6 P
  52.             }
    ) A0 R1 |4 S: ?
  53.         }" \, L$ G2 A& ~8 D1 ~" [4 V. ]
  54.     }  _# z$ Q* B- G
  55.     ret = i;3 x/ T/ b' A3 b

  56. " f* O) C% ~2 W. Q& a; }' P
  57. out:
    $ n; [& Q! R0 v7 b3 _  }
  58.     bit_dbg("send stop condition\n");9 ]1 a8 O/ O% X. W# ]' b2 n4 q
  59.     i2c_stop(ops);, W: n3 j! ]8 c$ h
  60. " T* @1 ~6 J$ L+ O5 @- t
  61.     return ret;9 u4 Q# F! ^0 a6 E# l, x( g
  62. }
复制代码
! U: {# h7 f3 S0 {
该函数进入之后就发送了i2c_start(ops);IIC启动信号,4 L$ P3 R# V. J/ Y5 v. ^$ P4 p4 s
然后进入了for循环,我这个就发送一个数据进行说明
( g5 ^* w* c  G  G  _( k2 T- F4 wignore_nack = msg->flags & RT_I2C_IGNORE_NACK; 这里需要回复ACK所以这里的ignore_nack=0
" c6 [$ U3 Z! q5 |* Y  n/ v' e所以i2c_restart(ops);不会被执行6 [2 ?; X- b( Y& U9 q7 i, V
接下来执行ret = i2c_bit_send_address(bus, msg);
3 |& [8 B* A6 O0 g
  1. static rt_err_t i2c_bit_send_address(struct rt_i2c_bus_device *bus,
    4 n  ^& n  q2 l6 O: n
  2.                                      struct rt_i2c_msg        *msg)/ C( d2 E! y4 K
  3. {/ P- S5 V- y  p
  4.     rt_uint16_t flags = msg->flags;4 p4 @3 s: `# [/ N9 g" M
  5.     rt_uint16_t ignore_nack = msg->flags & RT_I2C_IGNORE_NACK;
    " Q* s$ V; h% r) `9 }
  6.     struct rt_i2c_bit_ops *ops = bus->priv;! ]2 M# p2 I( A$ K2 x$ d3 q
  7. 2 w: R) f, q" Z! A) B
  8.     rt_uint8_t addr1, addr2;
    2 Z2 i& w0 ^& ?
  9.     rt_int32_t retries;7 [0 g1 B9 @" ~
  10.     rt_err_t ret;* V+ _) F, W- _( x9 m
  11. 9 V- F: L# R4 h
  12.     retries = ignore_nack ? 0 : bus->retries;
    ( M8 f0 V/ i9 x! H: u
  13. * u3 z1 I- Z* n
  14.     if (flags & RT_I2C_ADDR_10BIT)
    2 Z$ y9 z, a2 _
  15.     {7 c& J- e% ?6 `7 |$ q
  16.     }
    # b8 L2 A0 B- s( [7 t
  17.     else
    : @3 D! T! ]0 l: y8 g8 O
  18.     {2 N5 B& z! q( {0 t3 \, S
  19.         /* 7-bit addr */
    4 q1 e/ x2 t9 Y3 g1 N! y5 V+ Q
  20.         addr1 = msg->addr << 1;& Z# |4 e/ ]1 J. q4 L+ g2 X
  21.         if (flags & RT_I2C_RD)) u( `1 c2 a( S0 Q) u
  22.             addr1 |= 1;" H; P. v* {7 N3 z# b. u; b
  23.         ret = i2c_send_address(bus, addr1, retries);/ d2 T% t7 x0 }! `7 n9 I
  24.         if ((ret != 1) && !ignore_nack)
    & _/ J2 s8 g6 X& b& S
  25.             return -RT_EIO;' l0 S" K/ `7 R  }* x
  26.     }
    % B3 o) @  A- l
  27. 2 c: i- w7 z6 z, l. X% s# F
  28.     return RT_EOK;  W1 E& R  K5 M( m( U; i
  29. }
复制代码
这里删掉了10bit模式,因为我用的7bi't'模式,10bit还没看4 U! R3 z* r9 \: [! X  p
rt_uint16_t ignore_nack = msg->flags & RT_I2C_IGNORE_NACK;因为第一次是写数据,所以这里的结果是0$ \9 ~' W! a2 d2 N
addr1 = msg->addr << 1;这个地方要重点注意一下,地址左移了一位9 Z; H* @- Y0 c. G
然后执行ret = i2c_send_address(bus, addr1, retries);
5 |  K# Z& Z5 q6 M0 B0 {
  1.     for (i = 0; i <= retries; i++)& D, ]5 a+ e/ A% K) G
  2.     {" m; ]3 V, @$ z* a' R& U6 \3 Y
  3.         ret = i2c_writeb(bus, addr);8 Q# e) f/ E9 n* w& q5 [- d9 }
  4.         if (ret == 1 || i == retries)
    ) O# {; e0 B: C: a4 G
  5.             break;
    8 a4 y2 c1 G+ p: L! V
  6.         bit_dbg("send stop condition\n");: n) a4 {& ?* A6 H2 W. C1 K1 @
  7.         i2c_stop(ops);
    # i* d( [7 d6 ~) A4 c; R. K
  8.         i2c_delay2(ops);; ]# P+ j; K# @7 H4 L+ A
  9.         bit_dbg("send start condition\n");
    9 v. A0 T. v$ M2 N. [6 ?
  10.         i2c_start(ops);
    % N8 c+ z5 P& D% I$ o% [6 ]/ z) Q
  11.     }
复制代码
前面做了这么多的准备工作,终于要执行写数据的函数了5 L9 D7 G8 T) @* G
  1. static rt_int32_t i2c_writeb(struct rt_i2c_bus_device *bus, rt_uint8_t data)% n4 Q) m( e; L- k9 K  `! u2 m
  2. {
    0 z/ B, i4 C& e/ Y
  3.     rt_int32_t i;
    0 N5 q7 |, e% m1 W
  4.     rt_uint8_t bit;
    5 L9 Y3 q( \8 P$ Q2 O

  5. 0 |# ?. M: t8 D
  6.     struct rt_i2c_bit_ops *ops = bus->priv;
    0 S% r8 @3 {* M+ g
  7. 8 k% A4 o3 `" G7 N
  8.     for (i = 7; i >= 0; i--)( Q8 q7 R" O9 G0 ~3 F- H. Q
  9.     {
    * p3 Y0 P/ B7 D/ ]5 F2 [5 C6 t
  10.         SCL_L(ops);
    % q5 P: p% S# [: n" ~, i
  11.         bit = (data >> i) & 1;0 F% ~, x( k; T, k
  12.         SET_SDA(ops, bit);
    ! h9 n% H$ F  t2 O' f+ I& [/ k
  13.         i2c_delay(ops);, p, E& d7 S) \. |4 u1 a+ C0 D
  14.         if (SCL_H(ops) < 0)
    ( o2 z& g) J# ], @% t) d6 [. Q
  15.         {" H) j% l/ \. Z
  16.             bit_dbg("i2c_writeb: 0x%02x, "4 Z+ C2 N3 l, w' ^
  17.                     "wait scl pin high timeout at bit %d\n",
    0 Z8 K7 N/ R. j
  18.                     data, i);
    # q0 C! a+ D6 ]7 y$ c$ `# D

  19.   S" ]' s# w. U
  20.             return -RT_ETIMEOUT;$ O% S  p( d1 @
  21.         }
    7 V6 t; r) H& a, r
  22.     }
    8 ^7 i2 }+ w$ o
  23.     SCL_L(ops);
    ) h4 l6 v' R, l) T; t
  24.     i2c_delay(ops);* @3 J$ R3 l1 Z( l

  25. . j* P% r. L0 M+ E3 _1 W) A
  26.     return i2c_waitack(ops);0 ~" b2 q; ]" M  R4 c. C  G
  27. }
复制代码

2 q; X; p0 }# ?% v
% r+ \- v2 z! U1 E
使用道具 举报 回复
发表于 2019-1-28 22:12:36 | 显示全部楼层
这个是我今天在空调房间板子在电脑旁边测得温度,吐槽一下这个片子精度是有0.5℃。. ?" s6 U( W, \* d

- u3 d( T4 t9 N8 _! {% s
TIM截图20190128221131.png
使用道具 举报 回复
发表于 2019-1-29 09:43:34 | 显示全部楼层
本帖最后由 海阔天kongcyc 于 2019-1-29 09:49 编辑 : k" L, K. d/ e. e. s  B: K% |

" n; g( E  [1 m# ?, _谢谢楼主,有关IIC的驱动框架分析,以及LM75的驱动示例,讲解很清晰
使用道具 举报 回复
发表于 2019-1-29 14:31:19 | 显示全部楼层
目前驱动只做了温度正值,负值没做。
使用道具 举报 回复
发表于 2019-2-25 14:42:30 | 显示全部楼层
whj467467222 发表于 2019-1-28 20:59. \7 k( w  U8 X8 A
1,在ENV开启IIC驱动框架9 ^0 q9 e/ J1 @. f+ y8 P
      RT_THREAD Components--Device Drivers
1 I! d& S: I4 V9 T  {      这里要记得选择模拟IIC

1 u" @: z* `: k6 `) K不采用模拟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)完成了板级自动初始化
# l, i0 R4 _1 n& z8 m0 D9 t
原来是加入这个就可以被系统调用rt_hw_i2c_init()了。
使用道具 举报 回复
发表于 2019-4-19 12:43:38 | 显示全部楼层
谢谢分享`!~~~
使用道具 举报 回复
发表于 2019-4-30 22:59:37 | 显示全部楼层
戎传林 发表于 2019-2-25 14:427 \5 x' T7 `. U4 v  c6 a
不采用模拟IIC,使用硬件IIC操作。那这里也要打开模拟IIC的选项吗?
+ l6 Z  _8 h4 l8 x+ }4 T( A& n
不需要,这里的IIC仅仅是说的模拟IIC。
. q9 U% X) R  W8 E- y/ y3 V2 rRTT目前还不支持硬件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:591 a# G# u; c, V" ]
不需要,这里的IIC仅仅是说的模拟IIC。. g, t0 H, A' g1 z, e
RTT目前还不支持硬件IIC

, M" `5 d# D& Y硬件 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:063 ~5 x# }2 }) ^7 d2 h
2,在rtconfig.h里面就有了如下的宏定义# W) A3 S  W# l$ H7 Z  P! C
这里就表示开启了IIC,并且使用的是模拟IIC

6 w9 v% c+ L6 L7 D/ `楼主,这两个宏定义在哪个文件中定义呢?
使用道具 举报 回复
发表于 2019-9-2 21:08:38 | 显示全部楼层
pkokoc 发表于 2019-9-1 23:15; f8 [; o1 f& A& X, {
楼主,这两个宏定义在哪个文件中定义呢?
% N; @- \0 }6 `7 |4 j- I
请使用ENV工具
使用道具 举报 回复
发表于 2019-9-3 17:50:06 | 显示全部楼层
whj467467222 发表于 2019-9-2 21:08) n. d7 M3 R: l( Y1 E2 L( A
请使用ENV工具

: p/ r( b/ _) l7 E9 i* V8 u8 G楼主这个文章启发很大,经过几天摸索,将使用I2C的经验总结如下:3 B6 ^  B9 R0 ~% C/ t  A
https://www.rt-thread.org/qa/for ... ypeid%26typeid%3D26
使用道具 举报 回复
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

Powered by RT-Thread

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