野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 11365|回复: 6

硬件i2c的问题

[复制链接]
发表于 2021-11-4 09:23:44 | 显示全部楼层 |阅读模式
尝试了好几天了,i2c依旧是有问题(我的板子是F103)

我自己的程序的main是写1字节数据,再读1字节数据,再写1字节数据,中间没用检查就绪的函数,(一用就卡死),于是我加了个超长的延时,应该足够eerpom就绪了。i2c的代码写在后面吧。
       uint8_t date;
        bsp_i2c_init();
         bsp_i2c_at24c02_writebyte(0x01,0x11);
        date = bsp_i2c_at24c02_readbyte(0x01);
        bsp_i2c_at24c02_writebyte(0x01,0x11);


先来说说总体情况吧,跑一次我自己的程序,程序能运行到第二个读数据,但此时i2c就卡死了。复位,起始信号也发不出去。

尝试野火的例程,硬件i2c,发现还是卡死,起始信号也发送不了。复位,起始信号还是发送不了


尝试野火的软件i2c,卡死,显示超时。复位,实验成功。


这个时候i2c好像又好了,尝试硬件i2c的例程,没问题,成功运行。复位,还是成功运行了。之后怎么复位都可以成功运行。


总结了一下,好像跑一次我自己的程序就会让i2c失效,但跑两次软件模拟又好了。


于是乎我利用这个特性,跑两次软件模拟来进行复位,试了好几次,读取函数这里禁用应答和使用应答这里改了好几次,都没成功。第二个写函数这里检查总线一直处于忙。实在搞不明白了,就上来问了。。。



之后是我的i2c代码,没有用到宏。


void bsp_i2c_init(void)
{
        GPIO_InitTypeDef GPIO_InitStruct;
        I2C_InitTypeDef  I2C_InitStruct;
        //打开时钟
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
       
        //打开GPIO
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD; //pin6
        GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
        GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB,&GPIO_InitStruct);
       
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD; //pin7
        GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7;
        GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB,&GPIO_InitStruct);
         
        I2C_DeInit(I2C1);
        //打开i2c
        I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
        I2C_InitStruct.I2C_AcknowledgedAddress =I2C_AcknowledgedAddress_7bit ;
        I2C_InitStruct.I2C_ClockSpeed = 400000;
        I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2 ;
        I2C_InitStruct.I2C_Mode =I2C_Mode_I2C;
        I2C_InitStruct.I2C_OwnAddress1 = 0x02;
       
        I2C_Init(I2C1,&I2C_InitStruct);
       

        I2C_Cmd(I2C1,ENABLE);
}
void bsp_i2c_at24c02_writebyte(uint8_t address,uint8_t date)
{
        uint32_t i=4000000;
        while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)) ;
       
        //发送起始信号并检测
        I2C_GenerateSTART(I2C1,ENABLE );
        while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT )==ERROR);
       
       
        //发送地址和读写
        I2C_Send7bitAddress(I2C1,0xA0,I2C_Direction_Transmitter);
        while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED )==ERROR);
       
       
        //发送数据地址
        I2C_SendData(I2C1,address);
        while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED )==ERROR);
       
        //发送数据
        I2C_SendData(I2C1,date);
        while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED )==ERROR);
       
        //发送终止
        I2C_GenerateSTOP(I2C1,ENABLE);
       
        while(i--);
}

uint8_t bsp_i2c_at24c02_readbyte(uint8_t address)
{
        uint8_t date=0;
        uint32_t i=4000000;
        //发送起始信号并检测
        while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)) ;
        I2C_GenerateSTART(I2C1,ENABLE );
        while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT )==ERROR);
       
        //发送地址和读写
        I2C_Send7bitAddress(I2C1,0xA0,I2C_Direction_Transmitter);
        while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED )==ERROR);
       
        //发送数据地址
       
        I2C_SendData(I2C1,address);
        while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED)==ERROR);
       
        I2C_GenerateSTOP(I2C1,ENABLE);
        //发送起始信号并检测
        while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)) ;
        I2C_GenerateSTART(I2C1,ENABLE );
        while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT )==ERROR);
       
        //发送地址和读写
        I2C_Send7bitAddress(I2C1,0xA0,I2C_Direction_Receiver);
        while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED )==ERROR);

        //接收数据
        while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED  )==ERROR);
        date=I2C_ReceiveData(I2C1);

        //发送终止
        I2C_GenerateSTOP(I2C1,ENABLE);

       
        while(i--);
       
        return date ;
}



回复

使用道具 举报

发表于 2021-11-4 15:51:11 | 显示全部楼层
看你写的代码中读和写的地方有问题
首先读和写的器件地址不同
还有你在读的代码中是有一个暂停的,在时序要求中是没有那个中间的停止的
停止那一下相当于结束通讯了,打乱了你的读时序
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-11-4 17:08:25 | 显示全部楼层
一级菜鸟 发表于 2021-11-4 15:51
看你写的代码中读和写的地方有问题
首先读和写的器件地址不同
还有你在读的代码中是有一个暂停的,在时序要 ...

那个终止是我后来加来尝试的,忘记删了。。。没加也一样不行
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-11-4 17:10:18 | 显示全部楼层
一级菜鸟 发表于 2021-11-4 15:51
看你写的代码中读和写的地方有问题
首先读和写的器件地址不同
还有你在读的代码中是有一个暂停的,在时序要 ...

哪个器件地址啊
回复 支持 反对

使用道具 举报

发表于 2021-11-4 20:47:04 | 显示全部楼层
EEPROM的器件地址
读和写的地址不一样,仔细看一下教程
I2C手册上也有写
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-11-5 08:37:34 | 显示全部楼层
一级菜鸟 发表于 2021-11-4 20:47
EEPROM的器件地址
读和写的地址不一样,仔细看一下教程
I2C手册上也有写

哦哦,我看到了,谢谢提醒
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-11-5 08:40:23 | 显示全部楼层
一级菜鸟 发表于 2021-11-4 20:47
EEPROM的器件地址
读和写的地址不一样,仔细看一下教程
I2C手册上也有写

真的是这个问题,成功了。谢谢
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-11-24 08:46 , Processed in 0.036269 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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