Clion开发STM32之at24c02驱动的封装(I2C硬件驱动)

说明

  1. 本次使用的开发板为野火的指南者。
  2. 驱动和外设之间采用的是函数回调进行解耦操作。

I2C驱动的编写

通用I2C入口驱动

bsp_i2c_define.h

#ifndef STM32F103VET6_PROJECT_BSP_I2C_DEFINE_H
#define STM32F103VET6_PROJECT_BSP_I2C_DEFINE_H

#include "sys_core.h"

#define I2C_DEFAULT_CLK_SPEED (100000)
#define I2C_DEFAULT_OWN_ADDR (0)
#define I2C_DEFAULT_ADDRESSING_MODE (I2C_ADDRESSINGMODE_7BIT)
#define I2C_DEFAULT_DUAL_ADDRESS_MODE (I2C_DUALADDRESS_DISABLE)
#define I2C_DEFAULT_GENERAL_CALL_MODE (I2C_GENERALCALL_DISABLE)
#define I2C_DEFAULT_NO_STRETCH_MODE (I2C_NOSTRETCH_DISABLE)
/***********************************************************I2C1相关宏定义*******************************************************/
#define USE_I2C1_ENABLE (1)
#define I2C1_SCL_CLK_ENABLE()  __HAL_RCC_GPIOB_CLK_ENABLE()
#define I2C1_SCL_PIN GPIO_PIN_6
#define I2C1_SCL_PORT GPIOB
#define I2C1_SDA_CLK_ENABLE()  __HAL_RCC_GPIOB_CLK_ENABLE()
#define I2C1_SDA_PIN GPIO_PIN_7
#define I2C1_SDA_PORT GPIOB
extern I2C_HandleTypeDef i2c1_handle;

#endif //STM32F103VET6_PROJECT_BSP_I2C_DEFINE_H

bsp_i2c.h

#ifndef STM32F103VET6_PROJECT_BSP_I2C_H
#define STM32F103VET6_PROJECT_BSP_I2C_H

#include "I2C/bsp_i2c_define.h"
#include "I2C/bsp_i2c1.h"

extern I2C_InitTypeDef COM_I2c_Conf;

void I2C_Init(I2C_HandleTypeDef *handle, I2C_InitTypeDef *conf);

#endif //STM32F103VET6_PROJECT_BSP_I2C_H

bsp_i2c.c

#include "bsp_i2c.h"

/**
 * 默认串口配置
 */
I2C_InitTypeDef COM_I2c_Conf = {
        .ClockSpeed = I2C_DEFAULT_CLK_SPEED,
        .OwnAddress1 =I2C_DEFAULT_OWN_ADDR,
        .AddressingMode = I2C_DEFAULT_ADDRESSING_MODE,
        .DualAddressMode = I2C_DEFAULT_DUAL_ADDRESS_MODE,
        .OwnAddress2 = 0,
        .GeneralCallMode = I2C_DEFAULT_GENERAL_CALL_MODE,
        .NoStretchMode =I2C_DEFAULT_NO_STRETCH_MODE

};

void I2C_Init(I2C_HandleTypeDef *handle, I2C_InitTypeDef *conf) {
    I2C_InitTypeDef *ptr = NULL;
    if (conf != NULL) {
        ptr = conf;
    } else {
        ptr = &COM_I2c_Conf;
    }
    memcpy(&handle->Init, ptr, sizeof(I2C_InitTypeDef));
    if (HAL_I2C_Init(handle) != HAL_OK) {
        common_error_handle(__FILE__, __LINE__);
    }
}

I2C1 驱动

bsp_i2c1.h

#ifndef STM32F103VET6_PROJECT_BSP_I2C1_H
#define STM32F103VET6_PROJECT_BSP_I2C1_H

#include "bsp_i2c_define.h"

#endif //STM32F103VET6_PROJECT_BSP_I2C1_H

bsp_i2c1.c

#include "bsp_i2c.h"

static void msp_de_init(I2C_HandleTypeDef *handle);

static void msp_init(I2C_HandleTypeDef *handle);

I2C_HandleTypeDef i2c1_handle = {
        .Instance=I2C1,
#if (USE_HAL_I2C_REGISTER_CALLBACKS)
        .MspDeInitCallback=msp_de_init,
        .MspInitCallback = msp_init,
#endif
};
#if (USE_HAL_I2C_REGISTER_CALLBACKS)

static void msp_de_init(I2C_HandleTypeDef *handle) {
    /* Peripheral clock disable */
    __HAL_RCC_I2C1_CLK_DISABLE();

    /**I2C1 GPIO Configuration
    PB6     ------> I2C1_SCL
    PB7     ------> I2C1_SDA
    */
    HAL_GPIO_DeInit(I2C1_SCL_PORT, I2C1_SCL_PIN);
    HAL_GPIO_DeInit(I2C1_SDA_PORT, I2C1_SDA_PIN);
}

static void msp_init(I2C_HandleTypeDef *handle) {
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    I2C1_SCL_CLK_ENABLE();
    I2C1_SDA_CLK_ENABLE();
    /**I2C1 GPIO Configuration
    PB6     ------> I2C1_SCL
    PB7     ------> I2C1_SDA
    */
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

    GPIO_InitStruct.Pin = I2C1_SCL_PIN;
    HAL_GPIO_Init(I2C1_SCL_PORT, &GPIO_InitStruct);
    GPIO_InitStruct.Pin = I2C1_SDA_PIN;
    HAL_GPIO_Init(I2C1_SDA_PORT, &GPIO_InitStruct);
    /* I2C1 clock enable */
    __HAL_RCC_I2C1_CLK_ENABLE();
    /* USER CODE BEGIN I2C1_MspInit 1 */
    /* USER CODE END I2C1_MspInit 1 */
}

#endif

AT24C02驱动

dr_at24c02.h

#ifndef STM32F103VET6_PROJECT_DR_AT24C02_H
#define STM32F103VET6_PROJECT_DR_AT24C02_H

#include "dr_include.h"
/* AT24C01/02每页有8个字节 */
#define EEPROM_PAGESIZE       8
#define EEPROM_ADDRESS        0xA0

void AT24C02_Registry_Send(device_send_call_back call);

void AT24C02_Registry_Rec(device_rec_call_back call);

void AT24C02_BufferWrite(uint8_t addr, uint8_t *buf, uint16_t len);

bool AT24C02_ByteWrite(uint8_t addr, uint8_t data);

bool AT24C02_PageWrite(uint8_t addr, uint8_t *buf, uint16_t len);

bool AT24C02_BufferRead(uint8_t addr, uint8_t *buf, uint16_t size);

#endif //STM32F103VET6_PROJECT_DR_AT24C02_H

dr_at24c02.c

#include "dr_at24c02.h"

static device_send_call_back send_call = NULL;
static device_rec_call_back rec_call = NULL;

static bool send(uint16_t addr, void *data, uint16_t len) {
    if (send_call != NULL) {

        return send_call(addr, data, len);
    }
    return false;
}

static bool read(uint16_t addr, void *data, uint16_t len) {
    if (rec_call != NULL) {

        return rec_call(addr, data, len);
    }
    return false;
}

void AT24C02_Registry_Send(device_send_call_back call) {
    send_call = call;
}

void AT24C02_Registry_Rec(device_rec_call_back call) {
    rec_call = call;
}

/**
 *
 *
 * @param addr 写入地址
 * @param buf 数据
 * @param len 数据长度(字节数)
 */
void AT24C02_BufferWrite(uint8_t addr, uint8_t *buf, uint16_t len) {
    uint8_t Addr = addr % EEPROM_PAGESIZE;
    uint8_t count = EEPROM_PAGESIZE - Addr;
    uint8_t NumOfPage = len / EEPROM_PAGESIZE;
    uint8_t NumOfSingle = len % EEPROM_PAGESIZE;

    /* If addr is I2C_PageSize aligned  */
    if (Addr == 0) {
        /* If NumByteToWrite < I2C_PageSize */
        if (NumOfPage == 0) {
            AT24C02_PageWrite(addr, buf, NumOfSingle);
        }
            /* If NumByteToWrite > I2C_PageSize */
        else {
            while (NumOfPage--) {
                AT24C02_PageWrite(addr, buf, EEPROM_PAGESIZE);
                addr += EEPROM_PAGESIZE;
                buf += EEPROM_PAGESIZE;
            }

            if (NumOfSingle != 0) {
                AT24C02_PageWrite(addr, buf, NumOfSingle);
            }
        }
    }
        /* If addr is not I2C_PageSize aligned  */
    else {
        /* If NumByteToWrite < I2C_PageSize */
        if (NumOfPage == 0) {
            AT24C02_PageWrite(addr, buf, NumOfSingle);
        }
            /* If NumByteToWrite > I2C_PageSize */
        else {
            len -= count;
            NumOfPage = len / EEPROM_PAGESIZE;
            NumOfSingle = len % EEPROM_PAGESIZE;

            if (count != 0) {
                AT24C02_PageWrite(addr, buf, count);
                addr += count;
                buf += count;
            }
            while (NumOfPage--) {
                AT24C02_PageWrite(addr, buf, EEPROM_PAGESIZE);
                addr += EEPROM_PAGESIZE;
                buf += EEPROM_PAGESIZE;
            }
            if (NumOfSingle != 0) {
                AT24C02_PageWrite(addr, buf, NumOfSingle);
            }
        }
    }
}
/**
 * @brief 在EEPROM的一个写循环中可以写多个字节,但一次写入的字节数,不能超过EEPROM页的大小,AT24C02每页有8个字节
 * @param addr 写入地址
 * @param buf  数据
 * @param len  数据长度(字节数)
 * @return
 */
bool AT24C02_PageWrite(uint8_t addr, uint8_t *buf, uint16_t len) {
    return send(addr, buf, len);
}

/**
 * @brief 写一个字节到I2C EEPROM中
 * @param addr 写入地址
 * @param data 数据
 * @return
 */
bool AT24C02_ByteWrite(uint8_t addr, uint8_t data) {
    uint8_t buf[] = {data};
    return send(addr, buf, 1);
}

/**
 * @brief 从EEPROM里面读取一块数据
 * @param addr 读取地址
 * @param buf 存储数据
 * @param size 读取数量(字节)
 * @return
 */
bool AT24C02_BufferRead(uint8_t addr, uint8_t *buf, uint16_t size) {
    return read(addr, buf, size);
}

//    AT24C02_Registry_Send(at24c02_send);
//    AT24C02_Registry_Rec(at24c02_rec);
//static bool at24c02_send(uint16_t addr, void *data, uint16_t len) {
//    HAL_StatusTypeDef status = HAL_OK;
//    /* Write EEPROM_PAGESIZE */
//    status = HAL_I2C_Mem_Write(&i2c1_handle, EEPROM_ADDRESS, addr, I2C_MEMADD_SIZE_8BIT, (uint8_t *) (data), len, 100);
//    while (HAL_I2C_GetState(&i2c1_handle) != HAL_I2C_STATE_READY) {
//
//    }
//    /* Check if the EEPROM is ready for a new operation */
//    while (HAL_I2C_IsDeviceReady(&i2c1_handle, EEPROM_ADDRESS, 300, 300) == HAL_TIMEOUT);
//    /* Wait for the end of the transfer */
//    while (HAL_I2C_GetState(&i2c1_handle) != HAL_I2C_STATE_READY) {
//    }
//    if (status == HAL_OK) {
//        return true;
//    }
//
//    return false;
//
//}
//static bool at24c02_rec(uint16_t addr, void *data, uint16_t len) {
//    HAL_StatusTypeDef status = HAL_OK;
//
//    status = HAL_I2C_Mem_Read(&i2c1_handle, EEPROM_ADDRESS, addr, I2C_MEMADD_SIZE_8BIT, (uint8_t *) data, len, 1000);
//    if (status == HAL_OK) {
//        return true;
//    }
//    return false;
//}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

詩不诉卿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值