linux i2c dev.h freq,STM32F103ZET(基于秉火开发板)+Cubemx(F1 V1.60库)+IIC+AT24C02(修复官方例程读写死机bug)...

首先说明下开发条件:

1、开发板:秉火霸道,STM32F103ZET

2、软件:Cubemx V4.23(F1 V1.60库)

3、硬件:AT24C02 256KByte

问题描述:Cubemx生成IIC代码会出现死机问题,或者压根运行不了!

问题原因:

1、ST为了规避飞利浦IIC专利问题,将STM32的硬件IIC设计的比较复杂,而且稳定性不怎么好,所以一般教程都不推荐使用。

2、Cubemx生成的代码有Bug!

解决办法:

1、设置

2d191b86ea36273e8095082e8a7ce8d0.png

2、IIC的回调函数里面需要将时钟初始化放在引脚初始化之前!

void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)

{

GPIO_InitTypeDef GPIO_InitStruct;

if(hi2c->Instance==I2C1)

{

/* USER CODE BEGIN I2C1_MspInit 0 */

__HAL_RCC_I2C1_CLK_ENABLE(); //默认生成的放在了引脚初始化后面!

/* USER CODE END I2C1_MspInit 0 */

/**I2C1 GPIO Configuration

PB6     ------> I2C1_SCL

PB7     ------> I2C1_SDA

*/

GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;

GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;

GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

/* Peripheral clock enable */

/* USER CODE BEGIN I2C1_MspInit 1 */

/* USER CODE END I2C1_MspInit 1 */

}

}

3、函数的具体应用需要结合AT24C02的数据手册,符合AT24C02的要求!

我们在读写IIC时,即使不知道IIC的协议是什么,直接调用 HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout) 这个函数就可以对IIC的设备进行读写,这就是Cubemx的优势!

我先解释下这个函数里面的几个变量:

I2C_HandleTypeDef *hi2c IIC的句柄

uint16_t DevAddress IIC设备的外部地址

uint16_t MemAddress IIC设备的内部地址

uint16_t MemAddSize 读写内部地址的方式,一般使用I2C_MEMADD_SIZE_8BIT方式

注意只有两种选择:I2C_MEMADD_SIZE_8BIT 或者 I2C_MEMADD_SIZE_16BIT

uint8_t *pData 写入的数组或者指针

uint16_t Size 写入的字节数!

注意:如果是AT24C02,这个字节数不能超过8!!!!!这也叫AT24C02的页写入!当然这是为了提高速度,如果你想不出错也不在乎速度,你可以将字节数设置为1,这样肯定不会出错!

28af5015cebfb14be8b3a7a9b7591111.png    uint32_t Timeout 时间超时

4、程序实现

注意:需要在写函数后面加入短延时!

uint8_t I2c_Buf_Write[256];

uint8_t I2c_Buf_Read[256];

uint8_t I2C_Test(void)

{

uint16_t i;

i2cStatus=HAL_I2C_IsDeviceReady(&hi2c1, 0xA0, 256, 1000);  //0表示ready

printf("i2cStatus = %d\r\n ", i2cStatus);

i2cStatus1=HAL_I2C_GetState(&hi2c1);//32表示ready  HAL_I2C_STATE_READY  = 0x20U,   /*!< Peripheral Initialized and ready for use  */

printf("i2cStatus1 = %d\r\n ", i2cStatus1);

printf("写入的数据\n\r");

for ( i=0; i<256; i++ ) //填充缓冲

{

I2c_Buf_Write[i] = i;

HAL_I2C_Mem_Write(&hi2c1, (uint16_t)EEPROM_Block0_ADDRESS, i, I2C_MEMADD_SIZE_8BIT, (uint8_t*)(&(I2c_Buf_Write[i])), 1, 10000);//一个字节一个字节写,如果需要页写入(不超过8),使用40行的函数

// HAL_I2C_Mem_Write(&hi2c1, (uint16_t)EEPROM_Block0_ADDRESS, 0x00, I2C_MEMADD_SIZE_8BIT,(uint8_t*)I2c_Buf_Write, 8, 10000);//不能超过8个字节,如果超过需要分开写,for循环里面改为i=i+8

printf("0xX ", I2c_Buf_Write[i]);

HAL_Delay(5);//不能少

}

EEPROM_INFO("\n\r写成功\n\r");

HAL_Delay(500);

EEPROM_INFO("\n\r读出的数据\n\r");

//将EEPROM读出数据顺序保持到I2c_Buf_Read中

//if(HAL_I2C_GetState(&hi2c1) == 0x20 ) //加入检测

if( HAL_I2C_IsDeviceReady(&hi2c1, 0xA0, 256, 1000) == HAL_OK)//另外一种检测方法

{

HAL_I2C_Mem_Read(&hi2c1, (uint16_t)(EEPROM_Block0_ADDRESS+1 ),0x00, I2C_MEMADD_SIZE_8BIT,(uint8_t *)I2c_Buf_Read, 256, 10000); //读对字节数没有限制

}

//将I2c_Buf_Read中的数据通过串口打印

for (i=0; i<256; i++)

{

printf("0xX ", I2c_Buf_Read[i]);

if(I2c_Buf_Read[i] != I2c_Buf_Write[i])

{

EEPROM_ERROR("0xX ", I2c_Buf_Read[i]);

EEPROM_ERROR("错误:I2C EEPROM写入与读出的数据不一致\n\r");

return 0;

}

}

EEPROM_INFO("I2C(AT24C02)读写测试成功\n\r");

return 1;

}

5、联系方式:微信Startingray,本人准备将cubemx的小bug解决的过程记录下来,也是给爱好者一点启示,欢迎微信和我沟通,共同进步!个人觉得Cubemx是未来的发展方向,可以使我们避免很多小错误,但是由于现在软件版本之间的兼容性,加上不同版本库之间存在的bug,还是需要我们在使用时时刻保持警惕!

2020.08.22重新学习记录:

1、开发板:秉火霸道,STM32F103ZET

2、软件:Cubemx V6.01(F1 V1.80库)

09a34c01175a4e48fcc93ee1fee46be3.png

还有IIC的7bit地址是0x50,但是调用的函数需要的是8bit表示的这个地址应该是0xA0

cc13131603c2d10f610551e53f7dc510.png

很遗憾IIC的BUG还存在,而且如果使用FSMC的时候,IIC的配置会影响FSMC,两者一起用的时候要注意。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值