OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4925|回复: 6

硬件i2c的问题,不知道操作了什么导致总线一直被占用

[复制链接]

1

主题

4

帖子

0

精华

新手入门

积分
12
金钱
12
注册时间
2021-10-28
在线时间
3 小时
发表于 2021-11-4 09:30:28 | 显示全部楼层 |阅读模式
4金钱
尝试了好几天了,i2c依旧是有问题

我自己的程序的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代码,没有用到宏。(小声哔哔,我的板子是野火F103,正点原子的f407。f407的没有这个问题)


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 ;
}




正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

2

主题

592

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1458
金钱
1458
注册时间
2019-7-28
在线时间
137 小时
发表于 2021-11-4 10:06:13 | 显示全部楼层
用原子的软件模拟I2C试试吧
回复

使用道具 举报

0

主题

668

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1926
金钱
1926
注册时间
2021-8-13
在线时间
262 小时
发表于 2021-11-4 10:29:05 | 显示全部楼层
帮顶         
回复

使用道具 举报

13

主题

643

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2432
金钱
2432
注册时间
2019-12-28
在线时间
527 小时
发表于 2021-11-4 14:08:01 | 显示全部楼层
估计有什么地方卡死了,可以跑下仿真看看
回复

使用道具 举报

1

主题

4

帖子

0

精华

新手入门

积分
12
金钱
12
注册时间
2021-10-28
在线时间
3 小时
 楼主| 发表于 2021-11-4 17:12:16 | 显示全部楼层
狼里个狼121 发表于 2021-11-4 14:08
估计有什么地方卡死了,可以跑下仿真看看

都是写入的起始信号卡死
回复

使用道具 举报

1

主题

4

帖子

0

精华

新手入门

积分
12
金钱
12
注册时间
2021-10-28
在线时间
3 小时
 楼主| 发表于 2021-11-4 17:17:09 | 显示全部楼层
lpwithv 发表于 2021-11-4 10:06
用原子的软件模拟I2C试试吧

这个是野火的,我用的是野火的例程,正点原子的不知道对不对得上
回复

使用道具 举报

1

主题

4

帖子

0

精华

新手入门

积分
12
金钱
12
注册时间
2021-10-28
在线时间
3 小时
 楼主| 发表于 2021-11-5 08:44:02 | 显示全部楼层
我找到问题了,读取数据的时候读写位写错了,读取中第二个地址应该是0xA1才对,改正过来就没问题了。但至于为什么后面会锁死,就不清楚了。
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-9 22:20

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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