参考博客:
https://blog.csdn.net/PP_hui/article/details/112229696
1------这是IIC的初始化代码:
#include "i2c.h"
/* USER CODE BEGIN 0 */
// #define __HAL_AFIO_REMAP_I2C1_ENABLE() AFIO_REMAP_ENABLE(AFIO_MAPR_I2C1_REMAP)
/* USER CODE END 0 */
I2C_HandleTypeDef hi2c1;
/* I2C1 init function */
void MX_I2C1_Init(void)
{
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 100000;
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
// hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.OwnAddress1 = 0xA0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
Error_Handler();
}
}
void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(i2cHandle->Instance==I2C1)
{
/* USER CODE BEGIN I2C1_MspInit 0 */
/* USER CODE END I2C1_MspInit 0 */
__HAL_RCC_GPIOB_CLK_ENABLE();
/**I2C1 GPIO Configuration
PB8 ------> I2C1_SCL
PB9 ------> I2C1_SDA
*/
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;/
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
// __HAL_AFIO_REMAP_I2C1_ENABLE();
/* I2C1 clock enable */
__HAL_RCC_I2C1_CLK_ENABLE();
/* USER CODE BEGIN I2C1_MspInit 1 */
__I2C1_FORCE_RESET(); //通过总复位模块对I2C一次复位操作
__I2C1_RELEASE_RESET();
/* USER CODE END I2C1_MspInit 1 */
}
}
void HAL_I2C_MspDeInit(I2C_HandleTypeDef* i2cHandle)
{
if(i2cHandle->Instance==I2C1)
{
/* USER CODE BEGIN I2C1_MspDeInit 0 */
/* USER CODE END I2C1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_I2C1_CLK_DISABLE();
/**I2C1 GPIO Configuration
PB8 ------> I2C1_SCL
PB9 ------> I2C1_SDA
*/
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_8);
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_9);
/* USER CODE BEGIN I2C1_MspDeInit 1 */
/* USER CODE END I2C1_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
我根据参考的博客在 HAL_I2C_MspInit() 中添加了2行代码;
目的是进行一次IIC 总线的复位操作;
2---------除此之外还定义了一个接口:
作用:判断IIC总线是否busy,如果busy,则重新初始化IIC;
void I2C_Busy_C(void)
{
SET_BIT(hi2c1.Instance->CR1,I2C_CR1_SWRST);
CLEAR_BIT(hi2c1.Instance->CR1,I2C_CR1_SWRST);
HAL_I2C_MspInit(&hi2c1); //自定义函数
HAL_I2C_Init(&hi2c1);
}
3----在HAL_I2C_Mem_Write()时会busy,
解决方案:
调用HAL_I2C_Mem_Write()之前,先判断是否busy,如果busy则重新初始化,初始化结束后,再HAL_I2C_Mem_Write();
EEPROM_RES EEProm_Write(uint8_t addr,uint8_t* data,uint8_t size)
{
int ret = 0;
if(READ_BIT(hi2c1.Instance->SR2,I2C_SR2_BUSY) || READ_BIT(hi2c1.Instance->CR1,I2C_CR1_PE) == 0)
{
I2C_Busy_C();
}
ret = HAL_I2C_Mem_Write(&hi2c1,EEPROM_ADDR,addr,I2C_MEMADD_SIZE_8BIT,data,size,1000);
if(HAL_OK == ret)
{
HAL_UART_Transmit(&huart3,"EEPROM_OK\r\n", strlen("EEPROM_OK\r\n"),100);
return EEPROM_OK;
}
else if(HAL_ERROR == ret)
{
HAL_UART_Transmit(&huart3,"EEPROM_ERROR\r\n", strlen("EEPROM_ERROR\r\n"),100);
return EEPROM_ERROR;
}
else if(HAL_BUSY == ret)
{
HAL_UART_Transmit(&huart3,"HAL_BUSY\r\n", strlen("HAL_BUSY\r\n"),100);
return HAL_BUSY;
}
else if(HAL_TIMEOUT == ret)
{
HAL_UART_Transmit(&huart3,"HAL_TIMEOUT\r\n", strlen("HAL_TIMEOUT\r\n"),100);
return HAL_TIMEOUT;
}
}
总结:
1)修改MX_I2C1_Init();
2)创建重新初始化的接口I2C_Busy_C();
3) 在HAL_I2C_Mem_Write()之前,先判断是否busy,如果busy就调用I2C_Busy_C();复位总线;-------------->再调用HAL_I2C_Mem_Write();
没了;
下面的代码是AT24C02的所有相关代码:
1)iic初始化
#include "i2c.h"
/* USER CODE BEGIN 0 */
// #define __HAL_AFIO_REMAP_I2C1_ENABLE() AFIO_REMAP_ENABLE(AFIO_MAPR_I2C1_REMAP)
/* USER CODE END 0 */
I2C_HandleTypeDef hi2c1;
/* I2C1 init function */
void MX_I2C1_Init(void)
{
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 100000;
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
// hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.OwnAddress1 = 0xA0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
Error_Handler();
}
}
void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(i2cHandle->Instance==I2C1)
{
/* USER CODE BEGIN I2C1_MspInit 0 */
/* USER CODE END I2C1_MspInit 0 */
__HAL_RCC_GPIOB_CLK_ENABLE();
/**I2C1 GPIO Configuration
PB8 ------> I2C1_SCL
PB9 ------> I2C1_SDA
*/
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;/
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
// __HAL_AFIO_REMAP_I2C1_ENABLE();
/* I2C1 clock enable */
__HAL_RCC_I2C1_CLK_ENABLE();
/* USER CODE BEGIN I2C1_MspInit 1 */
__I2C1_FORCE_RESET(); //通过总复位模块对I2C一次复位操作
__I2C1_RELEASE_RESET();
/* USER CODE END I2C1_MspInit 1 */
}
}
void HAL_I2C_MspDeInit(I2C_HandleTypeDef* i2cHandle)
{
if(i2cHandle->Instance==I2C1)
{
/* USER CODE BEGIN I2C1_MspDeInit 0 */
/* USER CODE END I2C1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_I2C1_CLK_DISABLE();
/**I2C1 GPIO Configuration
PB8 ------> I2C1_SCL
PB9 ------> I2C1_SDA
*/
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_8);
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_9);
/* USER CODE BEGIN I2C1_MspDeInit 1 */
/* USER CODE END I2C1_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
2)main函数调用MX_I2C1_Init();
3)at24c02.h
#ifndef AT24C02_H
#define AT24C02_H
#include "stm32f4xx_hal.h"
#include "usart.h"
typedef enum{
EEPROM_OK,
EEPROM_ERROR
}EEPROM_RES;
extern I2C_HandleTypeDef hi2c1;
//AT24C02一共32页,每页8字节,共256字节;
//不能跨页写数据[比如:1个2字节的数据占用0x07和0x08两个地址,可能导致数据错乱]
//第一页地址:0x00-0x07
//第二页地址:0x08-0x0F
//第三页地址:0x10-0x17
//第四页地址:0x18-0x1F
//第五页地址:0x20-0x27
//第六页地址:0x28-0x2F
//第七页地址:0x30-0x37
//第八页地址:0x38-0x3F
//第九页地址:0x40-0x47
//第十页地址:0x48-0x4F
//第十一页地址:0x50-0x57
//第十二页地址:0x58-0x5F
//第十三页地址:0x60-0x67
//第十四页地址:0x68-0x6F
//第十五页地址:0x70-0x77
//第十六页地址:0x78-0x7F
//第十七页地址:0x80-0x87
//第十八页地址:0x88-0x8F
//第十九页地址:0x90-0x97
//第二十页地址:0x98-0x9F
//第二十一页地址:0xA0-0xA7
//第二十二页地址:0xA8-0xAF
//第二十三页地址:0xB0-0xB7
//第二十四页地址:0xB8-0xBF
//第二十五页地址:0xC0-0xC7
//第二十六页地址:0xC8-0xCF
//第二十七页地址:0xD0-0xD7
//第二十八页地址:0xD8-0xDF
//第二十九页地址:0xE0-0xE7
//第三十页地址:0xE8-0xEF
//第三十一页地址:0xF0-0xF7
//第三十二页地址:0xF8-0xFF
//由于各个参数的实际大小是不确定的,领导每明确要求;所以统一把长度设置为4字节
typedef enum{
E2ADDR_X_STEP=0x00,//X轴步进【0x00-0x03】
E2ADDR_Y_STEP=0x04,//Y轴步进【0x04-0x07】
E2ADDR_Z_STEP=0x08,//Z轴步进【0x08-0x0B】
E2ADDR_X_POS=0x0C,//X轴位置【0x0C-0x0F】
E2ADDR_Y_POS=0x10,//Y轴位置【0x10-0x13】
E2ADDR_Z_POS=0x14,//Z轴位置【0x14-0x17】
E2ADDR_X_SPEED=0x18,//X轴运行速度【0x18-0x1B】
E2ADDR_Y_SPEED=0x1C,//Y轴运行速度【0x1C-0x1F】
E2ADDR_Z_SPEED=0x20,//Z轴运行速度【0x20-0x23】
E2ADDR_X_ACC=0x24,//X轴运行加速度【0x24-0x27】
E2ADDR_Y_ACC=0x28,//Y轴运行加速度【0x28-0x2B】
E2ADDR_Z_ACC=0x2C,//Z轴运行加速度【0x2C-0x2F】
E2ADDR_X_CHECKSELF_SPEED = 0x30,//X轴自检速度【0x30-0x33】
E2ADDR_Y_CHECKSELF_SPEED = 0x34,//Y轴自检速度【0x34-0x37】
E2ADDR_Z_CHECKSELF_SPEED = 0x38,//Z轴自检速度【0x38-0x3B】
E2ADDR_X_CHECKSELF_ACC = 0x3C,//X轴自检加速度【0x3C-0x3F】
E2ADDR_Y_CHECKSELF_ACC = 0x40,//Y轴自检加速度【0x40-0x43】
E2ADDR_Z_CHECKSELF_ACC = 0x44,//Z轴自检加速度【0x44-0x47】
}AT24C02_APP_ADDR;
#define PARAMNULL 0xFFFFFFFF
#define USER_PARAM_NULL(TYPE,PARAM,VALUE) ((TYPE)PARAMNULL == PARAM)?(PARAM = VALUE):(PARAM);
#define EE_SIZE 256//bytes
#define EEPROM_ADDR 0xa0
struct Device_Param{
int32_t step;
int32_t pos;
int32_t speed;
int32_t acc;
int32_t check_speed;
int32_t check_acc;
};
void AT24C02_Read_Test(void);
void AT24C02_Write_Test(void);
void I2c_EraseChip(void);
#endif
4)at24c02.c
#include "AT24C02.h"
void I2C_Busy_C(void)
{
SET_BIT(hi2c1.Instance->CR1,I2C_CR1_SWRST);
CLEAR_BIT(hi2c1.Instance->CR1,I2C_CR1_SWRST);
HAL_I2C_MspInit(&hi2c1); //自定义函数
HAL_I2C_Init(&hi2c1);
}
// ————————————————
// 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
// 原文链接:https://blog.csdn.net/PP_hui/article/details/112229696
EEPROM_RES EEProm_Write(uint8_t addr,uint8_t* data,uint8_t size)
{
int ret = 0;
if(READ_BIT(hi2c1.Instance->SR2,I2C_SR2_BUSY) || READ_BIT(hi2c1.Instance->CR1,I2C_CR1_PE) == 0)
{
I2C_Busy_C();
}
ret = HAL_I2C_Mem_Write(&hi2c1,EEPROM_ADDR,addr,I2C_MEMADD_SIZE_8BIT,data,size,1000);
if(HAL_OK == ret)
{
HAL_UART_Transmit(&huart3,"EEPROM_OK\r\n", strlen("EEPROM_OK\r\n"),100);
return EEPROM_OK;
}
else if(HAL_ERROR == ret)
{
HAL_UART_Transmit(&huart3,"EEPROM_ERROR\r\n", strlen("EEPROM_ERROR\r\n"),100);
return EEPROM_ERROR;
}
else if(HAL_BUSY == ret)
{
HAL_UART_Transmit(&huart3,"HAL_BUSY\r\n", strlen("HAL_BUSY\r\n"),100);
return HAL_BUSY;
}
else if(HAL_TIMEOUT == ret)
{
HAL_UART_Transmit(&huart3,"HAL_TIMEOUT\r\n", strlen("HAL_TIMEOUT\r\n"),100);
return HAL_TIMEOUT;
}
}
EEPROM_RES EEProm_Read(uint8_t addr,uint8_t *buf,uint16_t size)
{
if(HAL_OK != HAL_I2C_Mem_Read(&hi2c1,EEPROM_ADDR,addr,I2C_MEMADD_SIZE_8BIT,buf,size,1000))
{
HAL_UART_Transmit(&huart3,"EEPROM_ERROR\r\n", strlen("EEPROM_ERROR\r\n"),100);
return EEPROM_ERROR;
}
HAL_Delay(10);
HAL_UART_Transmit(&huart3,"EEPROM_OK\r\n", strlen("EEPROM_OK\r\n"),100);
return EEPROM_OK;
}
void I2c_EraseChip(void)
{
uint16_t i=0;
uint8_t erase[8] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
HAL_UART_Transmit(&huart3,"will erase chip\r\n", strlen("will erase chip\r\n"),100);
for( i=0; i<(EE_SIZE/8); i++)
{
if(HAL_OK != HAL_I2C_Mem_Write(&hi2c1, EEPROM_ADDR, i*8,I2C_MEMADD_SIZE_8BIT, erase, 8, 1000))
{
Error_Handler();
HAL_UART_Transmit(&huart3,"EEPROM_ERROR\r\n", strlen("EEPROM_ERROR\r\n"),100);
}
else{
HAL_UART_Transmit(&huart3,"EEPROM_OK\r\n", strlen("EEPROM_OK\r\n"),100);
}
HAL_Delay(10);
}
}
// void Platform_Init(void)
// {
// //读取EEPROM存储的数据
// EEProm_Read(E2_JPB_LEFT,(uint8_t*)at24c02_data_4byte,4);
// EEProm_Read(E2_JPB_RIGHT,(uint8_t*)at24c02_data_4byte,4);
// EEProm_Read(E2_LIGHTSWITCH,(uint8_t*)&at24c02_data_1byte,1);
// EEProm_Read(E2_LIGHTBRIGHTNESS,(uint8_t*)&at24c02_data_1byte,1);
// EEProm_Read(E2_LIGHTBOOTVALUE,(uint8_t*)&at24c02_data_1byte,1);
// EEProm_Read(E2_ZOOM_POSLIMIT,(uint8_t*)&at24c02_data_4byte,4);
// EEProm_Read(E2_ZOOM_POSZERO,(uint8_t*)&at24c02_data_4byte,4);
// EEProm_Read(E2_ZOOM_SPEEDSELFTEST,(uint8_t*)&at24c02_data_2byte,2);
// EEProm_Read(E2_ZOOM_SPEEDRUN,(uint8_t*)&at24c02_data_2byte,2);
// EEProm_Read(E2_ZOOM_STEP,(uint8_t*)&at24c02_data_2byte,2);
// EEProm_Read(E2_Z_POSLIMIT,(uint8_t*)&at24c02_data_4byte,4);
// EEProm_Read(E2_Z_POSZERO,(uint8_t*)&at24c02_data_4byte,4);
// EEProm_Read(E2_Z_SPEEDSELFTEST,(uint8_t*)&at24c02_data_2byte,2);
// EEProm_Read(E2_Z_SPEEDRUN,(uint8_t*)&at24c02_data_2byte,2);
// EEProm_Read(E2_Z_STEP,(uint8_t*)&at24c02_data_2byte,2);
// }
int32_t XPosition = 0;
void param_init(void)
{
USER_PARAM_NULL(int32_t,XPosition,0);
}
struct Device_Param Device_XMotor = {
.step = 0,
.pos = 0,
.speed = 0,
.acc = 0,
.check_speed = 0,
.check_acc = 0
};
void AT24C02_Write_Test(void)
{
///E2ADDR_X_STEP
int32_t ret=0;
uint8_t debugData[30] = 0;
Device_XMotor.step = 4;
ret = EEProm_Write(E2ADDR_X_STEP,(uint8_t*)&Device_XMotor.step,4);
sprintf(debugData,"\r\nSET E2ADDR_X_STEP=%d\r\n\r\n",ret);
HAL_UART_Transmit(&huart3,debugData, strlen(debugData),100);
}
void AT24C02_Read_Test(void)
{
int32_t ret=0;
uint8_t debugData[30] = 0;
EEProm_Read(E2ADDR_X_STEP,(uint8_t*)&ret,4);
sprintf(debugData,"\r\nE2ADDR_X_STEP=%d\r\n\r\n",ret);
HAL_UART_Transmit(&huart3,debugData, strlen(debugData),100);
}