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

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
楼主可以分享下怎么解决的

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

所属标签

相似问题

官网相关资源

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