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

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

MCU是STM32F103, I2C挂接AT24C128, RT系统调试I2C时序时的注意事项:
6 G& D/ X, F, y8 X+ S% ~RT系统版本:
! a5 e0 C  A2 S9 K5 A1 O5 {! r7 G4 _7 g, c9 j* l" \
\ | /' r. V3 Z" \; t# ?* w
- RT -     Thread Operating System$ Q! Y  [: j; I* n! F
/ | \     4.0.1 build Sep 11 2019
0 y! W& a0 C+ K9 K. [0 m 2006 - 2019 Copyright by rt-thread team
! a( b0 Y2 X8 |: L* R: r& O5 h! ~6 p# ]  h8 W! h
: b* ]: r3 b1 {3 O% m' d
1. 地址问题, RT系统I2C驱动地址是左移了一位的, (i2c_bit_send_address函数) 如下:
( |  y5 f% `* \4 k% x        /* 7-bit addr */5 h" \/ L$ W8 E8 U0 T$ P
        addr1 = msg->addr << 1;
. X" z* A; h8 x& _        if (flags & RT_I2C_RD)2 _5 Q( E6 {" B, Q, O3 j; ^
            addr1 |= 1;
' W8 C. {/ o$ p3 ]; y0 j0 T* U        ret = i2c_send_address(bus, addr1, retries);
5 x% l3 D% A& g; \1 Q' d( G
2 {- w! A" K' _* B: W) p1 Q: p  T, W$ E1 s1 z; ^; ^; g: D
但是E2PROM地址不需要左移, 所以初始化时地址要右移一位:, F  _3 F- K- U; p7 i. i- @

# c" q( n. C) `  u1 y/ ~        #define EP24C128_SIZE (16*1024)
) B, d. O  n2 C! B8 O        static struct ep24c128_config ep24cfg = {EP24C128_SIZE,           //24c128 16KByte" \1 m3 S6 M5 ~$ x
                                                                                         0x50,                  //24c128 addr 0xA0, 需要右移一位
3 Q. \$ N% Y0 e/ t6 e& W6 X                                                                                         0};7 D, ?7 z4 H$ e8 g& I. U* C
        stm32f1_i2c_init("i2cE2");' a- M! {+ M$ S3 d5 q6 Z# b
        ep24c128_register("ep24c128", "i2cE2", &ep24cfg);
0 |6 Q: l  {# D5 Q% Z9 b* L% c        gParamDev_t = rt_device_find("ep24c128");$ a3 k1 \* X1 z; ~
        rt_device_open(gParamDev_t, RT_DEVICE_OFLAG_RDWR);+ S! ]$ O0 C. t3 _0 q* t8 c1 L- J$ o

- }* j& @" B3 N- O7 B2. SDA引脚问题, SDA引脚初始化为推挽输出, 在获取IO电平时要切换为输入
% a( A1 X/ e% q. y5 rstatic void setSDAMode(uint32_t mode)3 Q3 t* L; k& I
{
2 p$ n2 S' Q8 w$ s        static GPIO_InitTypeDef GPIO_InitStruct = {SDA_Pin,
4 l4 i  J9 L" m' x; ~: I1 C                                                                              GPIO_MODE_OUTPUT_PP,
( R* m( ]* D2 A2 q& z0 n                                                                              GPIO_NOPULL,
3 L9 h- m0 U: V/ I                                                                              GPIO_SPEED_FREQ_MEDIUM};9 w, g! w) ], ~3 B* H6 t; O
        GPIO_InitStruct.Mode = mode;: T6 |* q: F+ I) o# V% L
        HAL_GPIO_Init(SDA_Port, &GPIO_InitStruct);, a3 H7 t* M+ ?7 w( f
}9 m7 f3 ~2 @1 r/ z- `
8 i0 \- _& f' t! w. ~

* g! }5 e7 n9 ~7 i2 Z6 D  J* c4 J8 fstatic void stm32f1_set_sda(void *data, rt_int32_t state)$ C4 }( ~+ j3 l: n* \( L$ J
{2 @6 @1 d! x; a  q* R$ w
        setSDAMode(GPIO_MODE_OUTPUT_PP);
8 k: a  I' c" [        HAL_GPIO_WritePin(SDA_Port, SDA_Pin, (GPIO_PinState)state);6 m: p  _& ^7 H) }# M' K
}; z6 v& S: S5 V& @8 ?; |0 h3 D
. a2 N: v5 \% l) R
static rt_int32_t  stm32f1_get_sda(void *data)
* e# E1 ?5 i4 @3 J4 d8 P! ?{
; y, H$ |) ]2 S; Z+ u8 B        setSDAMode(GPIO_MODE_INPUT);
- Y* Q. ^% Z- ?        return (rt_int32_t)GetIo(SDA_Port, SDA_Pin);
: C# W; z% F' V5 ]( ?# |}: Z" K/ c% z1 y$ j) `: P& a
这样做效率不是很高, RT在i2c-bit-ops.c中没有进行切换, 需要自行处理& _' M  C- m# p7 W6 S3 W* ~9 S/ f& S6 ^

( F- c" `- k+ q0 @8 c3 y4 a3. 调试时打开RT_I2C_BIT_DEBUG选项可以方便查找问题
; H/ m- n% F8 S  wsend start condition
6 Y- \' a3 b4 dACK' `; o% D, u6 _* t4 k& @; A
ACK
$ d% O! @; }3 E+ R4 \/ p" QACK5 j- N2 d, q9 c
write 2 bytes
8 G6 O4 K' Z9 }& Z+ m8 |2 }2 |6 kACK$ b& L8 _! |' I8 ~% F, R
recieve bytes: 0xff, NACK* o( L+ B+ g, h! q4 n& V
read 1 byte: e! }2 |9 q; @: n/ O
send stop condition
% M4 W9 f3 O5 I2 V( r3 u$ ^1 K" t$ G/ r$ ]4 e; z0 _
使用道具 举报 显示全部楼层 回复
最新评论 | 正序浏览
显示全部楼层 |楼层直达:
发表于 2019-9-15 20:07:38 | 显示全部楼层
关于第二点,IIC的标准中,端口应该是开漏上拉挂载在总线上,此时不存在需要更改IO口输入输出状态,可以直接读取端口电平
使用道具 举报 回复
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

Powered by RT-Thread

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