说明
- 本次使用的开发板为野火的指南者。
- 驱动和外设之间采用的是函数回调进行解耦操作。
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;
//}