你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32F103ZE 用寄存器方式 I2C2读AT24C02失败,求解

[复制链接]
wdshuang09 提问时间:2016-11-16 23:16 /
用STM32F103ZE I2C2读取AT24C02一直没有调通,有谁用寄存器写的发一个程序出来看看,或帮忙分析分析程序,
/**************************************************
I2C2初始化函数   PB10---SCL    PB11---SDA
***************************************************/
void iic2_init(void)
{
        RCC->APB1RSTR|=(1<<22);//I2C2复位
        RCC->APB1RSTR&=~(1<<22);
        RCC->APB1ENR|=(1<<22);//I2C2时钟开启
        RCC->APB2ENR|=(1<<3);//IO端口B时钟开启
        GPIOB->CRH&=0XFFFF00FF;
        GPIOB->CRH|=0X0000DD00;//复用开漏输出
       
        I2C2->CR1&=~(1<<0);//关闭I2C模块
        I2C2->CR1&=~(1<<1);//0-->I2C模式 1-->SMBus模式
       
        I2C2->CR2|=(2<<0);//I2C模块时钟频率100k FREQ[5:0]=2为2M
        I2C2->CCR&=~(1<<15);//标准模式的I2C
        I2C2->CCR|=(10<<0);        //分频系数CCR  Thigh= CCR ×TPCLK1  Tlow= CCR ×TPCLK1
                                                //1/100K=Thigh+Tlow=2 X CCR ×TPCLK1
                           //CCR=10
        I2C2->TRISE=0X03;//标准100K   TPCLK1=1000ns/FREQ[5:0]=1000/2=500ns   
                         //I2C2->TRISE=(1000ns/TPCLK1)+1=3
        I2C2->OAR1=0;//自身地址寄存器
        I2C2->OAR2=0;
       
        I2C2->CR1|=(1<<10);//应答使能ACK
        I2C2->CR1|=(1<<0);//启用I2C模块
}


/**************************************************
功能:24C02读一个数据
入口:无  
出口:无
***************************************************/
u8 at24c02_read_data(u8 Reg_addr)
{
        u8 rdata=0;
        while((I2C2->SR2)&0x02);//总线忙检测  0-->空闲   1-->忙
        I2C2->CR1|=1<<8;//起始条件产生
        while(((I2C2->SR1)&0x01)!=0x01);//起始条件已发送  0-->未发送   1-->已发送
        I2C2->DR=I2C_addr;//24C02地址
        while((I2C2->SR1)&0X82);//TxE 0-->数据寄存器非空 1-->数据寄存器空 ADDR 0-->地址发送没有结束 1-->地址发送结束
        I2C2->SR1;
        I2C2->SR2;//读SR1然后读SR2将清除ADDR=1事件
        I2C2->DR=Reg_addr;//24C02地址
        while((I2C2->SR1)&0X80);
       
        I2C2->CR1|=1<<8;//起始条件产生
        while(((I2C2->SR1)&0x01)!=0x01);//起始条件已发送  0-->未发送   1-->已发送
        I2C2->DR=I2C_addr|0x01;//24C02地址
        while((I2C2->SR1)&0X82);
        I2C2->SR1;
        I2C2->SR2;//读SR1然后读SR2将清除ADDR=1事件
       
        while(((I2C2->SR1)&0X40)!=0X40);//数据寄存器非空(接收时)
        rdata=I2C2->DR;
        I2C2->CR1&=~(1<<10);//不应答ACK
       
        I2C2->CR1|=1<<9;//停止条件产生
        return rdata;
}

1.jpg
2.jpg
收藏 1 评论8 发布时间:2016-11-16 23:16

举报

8个回答
xhzheng 回答时间:2016-11-17 08:28:01
没有用过寄存器方式,Cube MX还是方便的;
wdshuang09 回答时间:2016-11-20 11:23:57
周末花了一个多小时,终于把I2C2调通了,
zero99 回答时间:2016-12-13 14:17:50
wdshuang09 发表于 2016-11-20 11:23
周末花了一个多小时,终于把I2C2调通了,

楼主可以分享下怎么解决的
hxh820-36096 回答时间:2017-2-26 22:51:50
我用I2c2也出问题了,发送STAR后就死在读事件上,最后发现是PB10,PB11置为上拉后,就变成低电平了,不知是什么原因,现在还没解决
hxh820-36096 回答时间:2017-2-27 11:01:19
楼主能说下问题原因与解决方法吗?
wdshuang09 回答时间:2017-2-28 08:03:45
hxh820-36096 发表于 2017-2-26 22:51
我用I2c2也出问题了,发送STAR后就死在读事件上,最后发现是PB10,PB11置为上拉后,就变成低电平了,不知是 ...

先确认一下你的IIC地址,其次是IIC初始化是否正确,下面是我写的初始化和启动函数

/**************************************************
功能:iic初始化函数 iic2   PB10---SCL    PB11---SDA
入口:无
出口:无
***************************************************/
void iic2_init(void)
{
        RCC->APB1RSTR|=(1<<22);//I2C2复位
        RCC->APB1RSTR&=~(1<<22);
        RCC->APB1ENR|=(1<<22);//I2C2时钟开启
        RCC->APB2ENR|=(1<<3);//IO端口B时钟开启
        GPIOB->CRH&=0XFFFF00FF;
        GPIOB->CRH|=0X0000FF00;//复用开漏输出
       
        I2C2->CR1&=~(1<<0);//关闭I2C模块
        I2C2->CR1&=~(1<<1);//0-->I2C模式 1-->SMBus模式
       
        I2C2->CR2|=(2<<0);//I2C模块时钟频率100k FREQ[5:0]=2为2M
        I2C2->CCR&=~(1<<15);//标准模式的I2C
        I2C2->CCR|=(10<<0);        //分频系数CCR  Thigh= CCR ×TPCLK1  Tlow= CCR ×TPCLK1
                                                //1/100K=Thigh+Tlow=2 X CCR ×TPCLK1
                           //CCR=10
        I2C2->TRISE=0X03;//标准100K   TPCLK1=1000ns/FREQ[5:0]=1000/2=500ns   
                         //I2C2->TRISE=(1000ns/TPCLK1)+1=3
        I2C2->OAR1=0;//从模式的自身地址寄存器
        I2C2->OAR2=0;
       
        I2C2->CR1|=(1<<10);//应答使能ACK
        I2C2->CR1|=(1<<0);//启用I2C模块
}

/**************************************************
功能:iic2启动
入口:无
出口:无
***************************************************/
u8 iic2_Hardware_Start(void)
{
        u16 cnt=0;
        I2C2->CR1|=1<<8;//起始条件产生
        while(((I2C2->SR1)&0x01)!=0x01)//起始条件已发送  0-->未发送   1-->已发送
        {
                if(++cnt>1000)return 0;
        }
        while(((I2C2->SR2)&0x03)!=0x03)//MSL+BUSY
        {
                if(++cnt>1000)return 0;
        }
        return 1;
}
wdshuang09 回答时间:2017-2-28 08:05:35
zero99 发表于 2016-12-13 14:17
楼主可以分享下怎么解决的

是对手册上写的,同时增加某一步出错判断,
ts2000 回答时间:2017-2-28 08:21:41
I2C的问题比较多,还是用模拟的比较好。

所属标签

相似问题

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版