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

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

MCU是STM32F103, I2C挂接AT24C128, RT系统调试I2C时序时的注意事项:+ J1 a! y4 ~- k6 p" |4 }6 s6 I
RT系统版本:% L* T  j5 r: o0 S' D7 n& v
. M; u& F& e8 @8 k5 N% W  ~
\ | /1 }- f6 F- Q0 Q* w+ D- ?/ v# _
- RT -     Thread Operating System
: S5 q& ~/ ?) Q2 q# N  L / | \     4.0.1 build Sep 11 2019
  G  F: _, ~/ p0 K9 z 2006 - 2019 Copyright by rt-thread team& @8 {. Y' q3 C) {, u
/ }+ r8 b" v1 ^! o9 R: S
: p2 v5 @3 E& B# y! W4 G  M
1. 地址问题, RT系统I2C驱动地址是左移了一位的, (i2c_bit_send_address函数) 如下:  u  X3 H3 j$ V, k0 I4 @% j7 Q
        /* 7-bit addr */4 q1 b1 p% m3 F
        addr1 = msg->addr << 1;" F$ [, F" z+ p
        if (flags & RT_I2C_RD)" |0 m% s4 a; w+ ~" O8 e2 j( W
            addr1 |= 1;
+ E* r5 S) i' v1 ~! _6 c        ret = i2c_send_address(bus, addr1, retries);
# m+ {0 s0 g- q. C5 E$ i7 S% o8 \" q4 v; {+ M

5 X- W# y3 P# G- L0 x6 ^但是E2PROM地址不需要左移, 所以初始化时地址要右移一位:# w! p! l+ s' }8 M

" N! T5 Y0 s1 q8 C4 q7 V0 ~        #define EP24C128_SIZE (16*1024)& D! u* Y6 a# U1 b1 G4 P+ W
        static struct ep24c128_config ep24cfg = {EP24C128_SIZE,           //24c128 16KByte2 y/ v) e1 J( q. h
                                                                                         0x50,                  //24c128 addr 0xA0, 需要右移一位
/ E% v  ?) w; o7 n                                                                                         0};
2 E: {( a$ [0 e1 T        stm32f1_i2c_init("i2cE2");
- P9 ]0 P8 w: i  q8 K6 w9 O- c# R        ep24c128_register("ep24c128", "i2cE2", &ep24cfg);' x6 w3 F; X( r- ^2 v3 {, g# w
        gParamDev_t = rt_device_find("ep24c128");
  O9 Z% ]! C7 p% S9 \+ o        rt_device_open(gParamDev_t, RT_DEVICE_OFLAG_RDWR);  T, |" f0 {9 b' q* y4 s

. d* s" P* Z! e1 ]3 K: Y2. SDA引脚问题, SDA引脚初始化为推挽输出, 在获取IO电平时要切换为输入- e; U! k1 G+ ]/ o8 Q  {; v7 o" b
static void setSDAMode(uint32_t mode)
. v, p" E) ~6 {3 |{
" c# k" U6 ~* n3 K; Z) T+ x        static GPIO_InitTypeDef GPIO_InitStruct = {SDA_Pin,
( X( L7 M3 ^9 d4 |9 S5 I                                                                              GPIO_MODE_OUTPUT_PP,
2 o3 C* ^. a  _- q: [$ s! J( z9 X                                                                              GPIO_NOPULL,
& l/ t% ^% ~* z/ ]' l  |                                                                              GPIO_SPEED_FREQ_MEDIUM};
- q' L  X. r7 |# C        GPIO_InitStruct.Mode = mode;0 p; @5 n- V" r- a) j
        HAL_GPIO_Init(SDA_Port, &GPIO_InitStruct);
9 v' G9 W- O; V1 ^}, U- X% d3 P6 ^* y1 L0 s

, X' J9 y4 B- W" Y
+ ~9 ]% X( f. @# r1 Sstatic void stm32f1_set_sda(void *data, rt_int32_t state)7 p2 x& C% b/ p! M' u# ~  p
{  ~1 W4 A! J3 L0 _' h- ~- |2 |, }
        setSDAMode(GPIO_MODE_OUTPUT_PP);$ v9 E* \5 U' V) |0 P8 Q4 f& b: t, ^+ c
        HAL_GPIO_WritePin(SDA_Port, SDA_Pin, (GPIO_PinState)state);
9 h( G9 v( t( Q/ ~+ x- R}% |& [6 y/ {6 e( Q

/ S# d# F' M% p) X# {* [static rt_int32_t  stm32f1_get_sda(void *data)
0 r+ Q5 {  r) `{$ @3 O7 \3 `+ h" H; U( L7 q
        setSDAMode(GPIO_MODE_INPUT);, ?; [& `9 t! ?7 g
        return (rt_int32_t)GetIo(SDA_Port, SDA_Pin);
7 K" B7 p# e" G; A8 a}
; T. j( K2 R6 b+ x这样做效率不是很高, RT在i2c-bit-ops.c中没有进行切换, 需要自行处理
8 f# G/ }/ F; v
: I. T' Y2 b/ F4 ]8 t. R% T/ B" U3. 调试时打开RT_I2C_BIT_DEBUG选项可以方便查找问题! {7 Q8 K. n' P$ G9 B0 @& j1 w
send start condition
; D  o# s0 i7 j+ uACK$ X( g. S0 M8 Q' m' ~; D/ {
ACK2 b. i3 L) X# M. d
ACK/ G% M1 |: n  Z9 c& B1 Z
write 2 bytes
+ G8 n: c; K) Y/ i3 J1 UACK' @/ i, Q0 p' D0 S$ m- u
recieve bytes: 0xff, NACK
% Y0 I$ b) H! O" U3 |read 1 byte
: H! I9 z' P4 A4 Csend stop condition- p& ^' o' ~0 _7 n( u
/ s' w8 ?! _# [1 t- F  F* W1 C) s
使用道具 举报 显示全部楼层 回复
最新评论 | 正序浏览
显示全部楼层 |楼层直达:
发表于 2019-9-15 20:07:38 | 显示全部楼层
关于第二点,IIC的标准中,端口应该是开漏上拉挂载在总线上,此时不存在需要更改IO口输入输出状态,可以直接读取端口电平
使用道具 举报 回复
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

Powered by RT-Thread

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