RT4.0.1版本I2C挂接E2PROM注意事项

2019-9-12 12:11 [复制链接] 1 290

MCU是STM32F103, I2C挂接AT24C128, RT系统调试I2C时序时的注意事项:( c' @, D$ b) N6 X3 [
RT系统版本:1 J/ w" n, l" b' g

3 |8 U5 f1 S: \3 p" H \ | /
  `  c- {) n4 T$ U- RT -     Thread Operating System
/ V7 ~$ \0 ?5 W / | \     4.0.1 build Sep 11 20196 j+ B6 S# J9 H& r
2006 - 2019 Copyright by rt-thread team3 h, ]# H& N) S7 E: S+ @* t& L
* o  k9 E! ]7 E: v% ]  E3 t% L" J' G
, ^  a- }8 K& t) u
1. 地址问题, RT系统I2C驱动地址是左移了一位的, (i2c_bit_send_address函数) 如下:
4 h; v& V5 z4 V- ^- c        /* 7-bit addr */7 g5 _7 t3 u4 T, l/ [; O
        addr1 = msg->addr << 1;  n+ K8 |$ n3 [0 X
        if (flags & RT_I2C_RD)
! n/ F2 P$ L# v            addr1 |= 1;
- y4 z* B3 z! {  v! D        ret = i2c_send_address(bus, addr1, retries);
9 p4 n: R! Y; @9 u) d0 Z1 b* \& C; |) }- _3 y! |  S
& }  N  i+ @. a
但是E2PROM地址不需要左移, 所以初始化时地址要右移一位:
' L, j2 y$ S- W# e3 z9 s  L; k  M$ E- M3 S, E5 W' ~4 x/ t' J9 y
        #define EP24C128_SIZE (16*1024)) D; f1 e. r+ x
        static struct ep24c128_config ep24cfg = {EP24C128_SIZE,           //24c128 16KByte9 d9 a8 O8 K/ E+ `
                                                                                         0x50,                  //24c128 addr 0xA0, 需要右移一位3 n6 d; b  T- I
                                                                                         0};
% c+ F1 v9 Y# w0 _, k* c0 D        stm32f1_i2c_init("i2cE2");
- J1 {; Q) I3 _, ^( d4 U        ep24c128_register("ep24c128", "i2cE2", &ep24cfg);% o, J1 ^- {/ Y: Z
        gParamDev_t = rt_device_find("ep24c128");
: l6 Z' f6 x# X5 z6 R+ t' ^& M        rt_device_open(gParamDev_t, RT_DEVICE_OFLAG_RDWR);
; h( \! g1 T: B7 e
: `& l# P1 H) p( [0 S& w2. SDA引脚问题, SDA引脚初始化为推挽输出, 在获取IO电平时要切换为输入
' d! e* O8 |- h, {) @% Cstatic void setSDAMode(uint32_t mode)
: V: I. X# t& X! M9 B" Y0 b{4 _  E7 k2 J0 Y" b. L" d; {
        static GPIO_InitTypeDef GPIO_InitStruct = {SDA_Pin,
2 o4 R, u( x, ^+ f0 {5 e; h6 w" K  P                                                                              GPIO_MODE_OUTPUT_PP,/ a* a  K  K% }( o' [
                                                                              GPIO_NOPULL,
2 W+ ^' w' I# J$ T' }* @, D                                                                              GPIO_SPEED_FREQ_MEDIUM};# g4 T5 W0 J$ b7 E$ C0 {) Q
        GPIO_InitStruct.Mode = mode;2 o9 }, n: Z& F6 F" p- u
        HAL_GPIO_Init(SDA_Port, &GPIO_InitStruct);
' p7 f5 o5 Y& S  f. l; `}
% ?  C2 f" c- j. M# z- M2 ?0 Q" T) p8 @  @: W, u

- L; Y3 ^7 o7 P1 r; E. @+ istatic void stm32f1_set_sda(void *data, rt_int32_t state)5 e# i- M9 ^5 i
{
0 j+ G; Z0 h5 j# q/ g! Q        setSDAMode(GPIO_MODE_OUTPUT_PP);
7 h8 e' \, V# a        HAL_GPIO_WritePin(SDA_Port, SDA_Pin, (GPIO_PinState)state);& o1 k! }) G# O* p
}/ R3 w: G8 H  F: u* _; o5 d

/ g, v3 T% u, mstatic rt_int32_t  stm32f1_get_sda(void *data)" I8 D" S+ o' ^+ {1 g
{
$ }& B5 n/ ?* R& a2 N) L        setSDAMode(GPIO_MODE_INPUT);) d3 W5 v  _' o* B" e
        return (rt_int32_t)GetIo(SDA_Port, SDA_Pin);
& u  V- g$ }' U1 a/ C! U}6 I' ^0 b- l2 s" v6 T
这样做效率不是很高, RT在i2c-bit-ops.c中没有进行切换, 需要自行处理+ P: O3 A) u: I0 d+ H/ b3 B& B8 Z

+ d% C! ?2 i( ?7 d, `3. 调试时打开RT_I2C_BIT_DEBUG选项可以方便查找问题
& k/ |2 f+ w$ a# X2 a2 ?send start condition/ G2 w5 y* ^4 W3 M! P
ACK
8 j: Y  q1 y, y2 L3 G8 DACK* s" n8 X0 p+ |, e/ ~
ACK7 s6 j" r+ e- ^& _0 ^& E2 j
write 2 bytes
( _; y) G- ]8 B/ _' @7 Y3 iACK
- s: ^/ D3 o! l2 ?recieve bytes: 0xff, NACK" p0 j" y& F% M% q6 n9 t: u
read 1 byte0 p# l: p% m% F  G9 V
send stop condition
( ?! _& C& n+ s, P5 ?( C1 F4 \2 D: B: V
使用道具 举报 显示全部楼层 回复
最新评论 | 正序浏览
显示全部楼层 |楼层直达:
发表于 2019-9-15 20:07:38 | 显示全部楼层
关于第二点,IIC的标准中,端口应该是开漏上拉挂载在总线上,此时不存在需要更改IO口输入输出状态,可以直接读取端口电平
使用道具 举报 回复
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

  1. 1 主题
  2. 7 帖子
  3. 7 积分

Ta的主页 发消息

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

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

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

Powered by RT-Thread

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