说明
- 本章是根据RT-Thread源码中的I2C组件进行抽离,主要不习惯用RT-Thread
- 然后在结合at24cxx模块补充测试
- 也为了方便移植和独立于框架的限制。
正文
操作gpio部分
#ifndef STM32_F1XX_TEMPLATE_BSP_GPIO_H
#define STM32_F1XX_TEMPLATE_BSP_GPIO_H
#include "sys_core.h"
#define GPIO_A_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define GPIO_B_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
#define GPIO_C_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE()
#define GPIO_D_CLK_ENABLE() __HAL_RCC_GPIOD_CLK_ENABLE()
#define GPIO_E_CLK_ENABLE() __HAL_RCC_GPIOE_CLK_ENABLE()
#define GPIO_F_CLK_ENABLE() __HAL_RCC_GPIOF_CLK_ENABLE()
#define GPIO_G_CLK_ENABLE() __HAL_RCC_GPIOG_CLK_ENABLE()
#define gpio_init(port, pin, mode, pull, speed)\
do{\
__HAL_RCC_##port##_CLK_ENABLE();\
GPIO_InitTypeDef cnf ={pin,mode,pull,speed};\
HAL_GPIO_Init(port, &cnf);\
}while(0)
#define pin_high(port, pin) HAL_GPIO_WritePin(port,pin,GPIO_PIN_SET)
#define pin_low(port, pin) HAL_GPIO_WritePin(port,pin,GPIO_PIN_RESET)
#define stm_pin_set(port, pin, value) HAL_GPIO_WritePin(port,pin,value)
#define pin_read(port, pin) HAL_GPIO_ReadPin(port,pin)
#define pin_toggle(port, pin) HAL_GPIO_TogglePin(port,pin)
typedef enum {
pin_mode_output,
pin_mode_input,
pin_mode_input_pull_up,
pin_mode_input_pull_down,
pin_mode_output_od
} pin_mode_type;
sys_force_static_inline void gpio_clk_enable(GPIO_TypeDef *port) {
if (port == GPIOA)GPIO_A_CLK_ENABLE();
else if (port == GPIOB)GPIO_B_CLK_ENABLE();
else if (port == GPIOC)GPIO_C_CLK_ENABLE();
else if (port == GPIOD)GPIO_D_CLK_ENABLE();
else if (port == GPIOE)GPIO_E_CLK_ENABLE();
else if (port == GPIOF)GPIO_F_CLK_ENABLE();
else if (port == GPIOG)GPIO_G_CLK_ENABLE();
}
sys_force_static_inline void stm32_pin_mode(GPIO_TypeDef *port, uint32_t pin, pin_mode_type mode) {
GPIO_InitTypeDef GPIO_InitStruct = {
.Pin = pin, .Mode = GPIO_MODE_OUTPUT_PP, .Speed = GPIO_SPEED_FREQ_HIGH, .Pull = GPIO_NOPULL};
gpio_clk_enable(port);
switch (mode) {
case pin_mode_output: {
/* output setting */
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
break;
}
case pin_mode_input: {
/* input setting: not pull. */
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
break;
}
case pin_mode_input_pull_up: {
/* input setting: pull up. */
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
break;
}
case pin_mode_input_pull_down: {
/* input setting: pull down. */
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
break;
}
case pin_mode_output_od: {
/* output setting: od. */
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
break;
}
}
HAL_GPIO_Init(port, &GPIO_InitStruct);
}
#endif //STM32_F1XX_TEMPLATE_BSP_GPIO_H
头文件
#ifndef STM32_F1XX_TEMPLATE_BSP_I2C_SOFT_H
#define STM32_F1XX_TEMPLATE_BSP_I2C_SOFT_H
#include "bsp_include.h"
typedef struct {
uint32_t scl;
uint32_t sda;
GPIO_TypeDef *port_scl;
GPIO_TypeDef *port_sda;
} soft_i2c_cnf_t;
typedef struct {
soft_i2c_cnf_t *cnf;/*硬件配置信息*/
void (*w_sda)(soft_i2c_cnf_t *cnf, rt_uint32_t state);
void (*w_scl)(soft_i2c_cnf_t *cnf, rt_uint32_t state);
rt_int32_t (*r_sda)(soft_i2c_cnf_t *cnf);
rt_int32_t (*r_scl)(soft_i2c_cnf_t *cnf);
void (*us_delay)(rt_uint32_t us);
struct {
rt_uint32_t delay_us;
rt_uint32_t timeout;
} option;
} i2c_bit_ops_t; /*软件位操作*/
#define RT_I2C_WR 0x0000
#define RT_I2C_RD (1u << 0)
#define RT_I2C_ADDR_10BIT (1u << 2) /* this is a ten bit chip address */
#define RT_I2C_NO_START (1u << 4)
#define RT_I2C_IGNORE_NACK (1u << 5)
#define RT_I2C_NO_READ_ACK (1u << 6) /* when I2C reading, we do not ACK */
#define RT_I2C_NO_STOP (1u << 7)
typedef struct {
rt_uint16_t addr;
rt_uint16_t flags;
rt_uint16_t len;
rt_uint8_t *buf;
} rt_i2c_msg;
struct i2c_bus_device {
i2c_bit_ops_t *bit_ops;
struct {
void (*start)(i2c_bit_ops_t *bit_ops); /*开启*/
void (*stop)(i2c_bit_ops_t *bit_ops); /*停止*/
rt_int32_t (*w_byte)(i2c_bit_ops_t *bit_ops, uint8_t data); /*write 1 byte*/
rt_int32_t (*r_byte)(i2c_bit_ops_t *bit_ops);/*read 1 byte*/
rt_bool_t (*wait_ack)(i2c_bit_ops_t *bit_ops);/*等待应答*/
rt_int32_t (*send_ack_or_nack)(i2c_bit_ops_t *bit_ops, rt_int32_t ack); /*发送ack或nack*/
rt_uint32_t (*w_bytes)(i2c_bit_ops_t *bit_ops, rt_i2c_msg *msg);
rt_uint32_t (*r_bytes)(i2c_bit_ops_t *bit_ops, rt_i2c_msg *msg);
rt_int32_t (*send_address)(i2c_bit_ops_t *bit_ops, uint8_t addr, rt_int32_t retries);
rt_int32_t (*bit_send_address)(i2c_bit_ops_t *bit_ops, rt_i2c_msg *msg);
} api;
rt_uint32_t (*master_xfer)(i2c_bit_ops_t *bit_ops, rt_i2c_msg msgs[], rt_uint32_t num);
};/*I2C总线设备*/
typedef struct i2c_bus_device *i2c_bus_device_t;
void i2c_bus_init(i2c_bus_device_t device, i2c_bit_ops_t *i2c_ops, soft_i2c_cnf_t *cfg);
rt_size_t i2c_master_send(i2c_bus_device_t device, rt_uint16_t addr, rt_uint16_t flags, const rt_uint8_t *buf,
rt_uint32_t count);
rt_size_t i2c_master_rec(i2c_bus_device_t device, rt_uint16_t addr, rt_uint16_t flags, rt_uint8_t *buf,
rt_uint32_t count);
#endif //STM32_F1XX_TEMPLATE_BSP_I2C_SOFT_H
源码
#include "bsp_i2c_soft.h"
#include "sys_dbg.h"
/*————————————————————————————————————————————————基础外设层——————————————————————————————————————————————————*/
sys_force_static_inline void stm32_us_delay(rt_uint32_t us) {
uint32_t start, now, delta, reload, us_tick;
start = SysTick->VAL;
reload = SysTick->LOAD;
us_tick = SystemCoreClock / 1000000UL;
do {
now = SysTick->VAL;
delta = start > now ? start - now : reload + start - now;
} while (delta < us_tick * us);
}
sys_force_static_inline void w_sda(soft_i2c_cnf_t *cnf, rt_uint32_t state) {
if (state) {
pin_high(cnf->port_sda, cnf->sda);
} else {
pin_low(cnf->port_sda, cnf->sda);
}
}
sys_force_static_inline void w_scl(soft_i2c_cnf_t *cnf, rt_uint32_t state) {
if (state) {
pin_high(cnf->port_scl, cnf->scl);
} else {
pin_low(cnf->port_scl, cnf->scl);
}
}
sys_force_static_inline rt_int32_t r_sda(soft_i2c_cnf_t *cnf) {
return pin_read(cnf->port_sda, cnf->sda);
}
sys_force_static_inline rt_int32_t r_scl(soft_i2c_cnf_t *cnf) {
return pin_read(cnf->port_scl, cnf->scl);
}
sys_force_static_inline void i2c_soft_init(i2c_bit_ops_t *i2c_ops, soft_i2c_cnf_t *cfg) {
i2c_ops->option.delay_us = 1;
i2c_ops->option.timeout = 100;
i2c_ops->cnf = cfg;
i2c_ops->w_scl = w_scl;
i2c_ops->w_sda = w_sda;
i2c_ops->r_sda = r_sda;
i2c_ops->r_scl = r_scl;
i2c_ops->us_delay = stm32_us_delay;
stm32_pin_mode(cfg->port_scl, cfg->scl, pin_mode_output_od);
stm32_pin_mode(cfg->port_sda, cfg->sda, pin_mode_output_od);
pin_high(cfg->port_scl, cfg->scl);
pin_high(cfg->port_sda, cfg->sda);
}
/*————————————————————————————————————————————————设备层——————————————————————————————————————————————————*/
#define SET_SDA(ops, val) ops->w_sda(ops->cnf,val)
#define SET_SCL(ops, val) ops->w_scl(ops->cnf,val)
#define GET_SDA(ops) ops->r_sda(ops->cnf)
#define GET_SCL(ops) ops->r_scl(ops->cnf)
#define SDA_L(ops) SET_SDA(ops,0)
#define SDA_H(ops) SET_SDA(ops,1)
#define SCL_L(ops) SET_SCL(ops,0)
static void us_delay(i2c_bit_ops_t *bit_ops) {
bit_ops->us_delay((bit_ops->option.delay_us + 1) >> 1);
}
static void us_delay2(i2c_bit_ops_t *bit_ops) {
bit_ops->us_delay(bit_ops->option.delay_us);
}
static int SCL_H(i2c_bit_ops_t *bit_ops) {
rt_uint32_t start;
SET_SCL(bit_ops, 1);
start = HAL_GetTick();
while (!GET_SCL(bit_ops)) {
if ((HAL_GetTick() - start) > bit_ops->option.timeout)
return -1;
us_delay(bit_ops);
}
us_delay(bit_ops);
return 0;
}
sys_force_static_inline rt_int32_t send_ack_or_nack(i2c_bit_ops_t *bit_ops, rt_int32_t ack) {
if (ack)
SET_SDA(bit_ops, 0);
us_delay(bit_ops);
if (SCL_H(bit_ops) < 0) {
return -1;
}
SCL_L(bit_ops);
return 0;
}
sys_force_static_inline rt_bool_t wait_ack(i2c_bit_ops_t *bit_ops) {
bool ack;
SDA_H(bit_ops);
us_delay(bit_ops);
if (SCL_H(bit_ops) < 0) {
return -1;
}
ack = !GET_SDA(bit_ops); /* ACK : SDA pin is pulled low */
SCL_L(bit_ops);
return ack;
}/*等待应答*/
sys_force_static_inline void start(i2c_bit_ops_t *bit_ops) {
SDA_L(bit_ops);
us_delay(bit_ops);
SCL_L(bit_ops);
} /*开启*/
static void restart(i2c_bit_ops_t *bit_ops) {
SDA_H(bit_ops);
SCL_H(bit_ops);
us_delay(bit_ops);
SDA_L(bit_ops);
us_delay(bit_ops);
SCL_L(bit_ops);
}
sys_force_static_inline void stop(i2c_bit_ops_t *bit_ops) {
SDA_L(bit_ops);
us_delay(bit_ops);
SCL_H(bit_ops);
us_delay(bit_ops);
SDA_H(bit_ops);
us_delay2(bit_ops);
} /*停止*/
sys_force_static_inline rt_int32_t w_byte(i2c_bit_ops_t *bit_ops, uint8_t data) {
uint8_t bit;
for (int i = 7; i >= 0; i--) {
SCL_L(bit_ops);
bit = (data >> i) & 1;
SET_SDA(bit_ops, bit);
us_delay(bit_ops);
if (SCL_H(bit_ops) < 0) {
return -1;
}
}
SCL_L(bit_ops);
us_delay(bit_ops);
return wait_ack(bit_ops);
} /*write 1 byte*/
sys_force_static_inline rt_int32_t r_byte(i2c_bit_ops_t *bit_ops) {
uint8_t i;
uint8_t data = 0;
SDA_H(bit_ops);
us_delay(bit_ops);
for (i = 0; i < 8; i++) {
data <<= 1;
if (SCL_H(bit_ops) < 0) {
return -1;
}
if (GET_SDA(bit_ops))
data |= 1;
SCL_L(bit_ops);
us_delay2(bit_ops);
}
return data;
}
sys_force_static_inline rt_uint32_t w_bytes(i2c_bit_ops_t *bit_ops, rt_i2c_msg *msg) {
rt_int32_t ret;
size_t bytes = 0;
const uint8_t *ptr = msg->buf;
rt_int32_t count = msg->len;
uint16_t ignore_nack = msg->flags & RT_I2C_IGNORE_NACK;
while (count > 0) {
ret = w_byte(bit_ops, *ptr);
if ((ret > 0) || (ignore_nack && (ret == 0))) {
count--;
ptr++;
bytes++;
} else if (ret == 0) {
return 0;
} else {
return ret;
}
}
return bytes;
}
static rt_uint32_t r_bytes(i2c_bit_ops_t *bit_ops, rt_i2c_msg *msg) {
rt_int32_t val;
rt_int32_t bytes = 0; /* actual bytes */
uint8_t *ptr = msg->buf;
rt_int32_t count = msg->len;
const rt_uint32_t flags = msg->flags;
while (count > 0) {
val = r_byte(bit_ops);
if (val >= 0) {
*ptr = val;
bytes++;
} else {
break;
}
ptr++;
count--;
if (!(flags & RT_I2C_NO_READ_ACK)) {
val = send_ack_or_nack(bit_ops, count);
if (val < 0)
return val;
}
}
return bytes;
}
static rt_int32_t send_address(i2c_bit_ops_t *bit_ops, uint8_t addr, rt_int32_t retries) {
rt_int32_t i;
rt_int32_t ret = 0;
for (i = 0; i <= retries; i++) {
ret = w_byte(bit_ops, addr);
if (ret == 1 || i == retries)
break;
stop(bit_ops);
us_delay2(bit_ops);
start(bit_ops);
}
return ret;
}
static rt_int32_t bit_send_address(i2c_bit_ops_t *bit_ops, rt_i2c_msg *msg) {
uint16_t flags = msg->flags;
uint16_t ignore_nack = msg->flags & RT_I2C_IGNORE_NACK;
uint8_t addr1, addr2;
rt_int32_t retries = 0;
rt_int32_t ret;
// retries = ignore_nack ? 0 : bus->retries;
if (flags & RT_I2C_ADDR_10BIT) {
addr1 = 0xf0 | ((msg->addr >> 7) & 0x06);
addr2 = msg->addr & 0xff;
LOG_D("addr1: %d, addr2: %d", addr1, addr2);
ret = send_address(bit_ops, addr1, retries);
if ((ret != 1) && !ignore_nack) {
LOG_W("NACK: sending first addr");
return -RT_EIO;
}
ret = w_byte(bit_ops, addr2);
if ((ret != 1) && !ignore_nack) {
LOG_W("NACK: sending second addr");
return -RT_EIO;
}
if (flags & RT_I2C_RD) {
LOG_D("send repeated start condition");
restart(bit_ops);
addr1 |= 0x01;
ret = send_address(bit_ops, addr1, retries);
if ((ret != 1) && !ignore_nack) {
LOG_E("NACK: sending repeated addr");
return -RT_EIO;
}
}
} else {
/* 7-bit addr */
addr1 = msg->addr << 1;
if (flags & RT_I2C_RD)
addr1 |= 1;
ret = send_address(bit_ops, addr1, retries);
if ((ret != 1) && !ignore_nack)
return -8;
}
return 0;
}
/*————————————————————————————————————————————————协议逻辑层——————————————————————————————————————————————————*/
static rt_uint32_t bit_xfer(i2c_bit_ops_t *bit_ops, rt_i2c_msg msgs[], rt_uint32_t num) {
rt_i2c_msg *msg;
rt_int32_t i, ret;
uint16_t ignore_nack;
for (i = 0; i < num; i++) {
msg = &msgs[i];
ignore_nack = msg->flags & RT_I2C_IGNORE_NACK;
if (!(msg->flags & RT_I2C_NO_START)) {
if (i) {
restart(bit_ops);
} else {
LOG_D("send start condition\r\n");
start(bit_ops);
}
ret = bit_send_address(bit_ops, msg);
if ((ret != 0) && !ignore_nack) {
LOG_D("receive NACK from device addr 0x%02x msg %d\r\n",
msgs[i].addr, i);
goto out;
}
}
if (msg->flags & RT_I2C_RD) {
ret = r_bytes(bit_ops, msg);
if (ret >= 1)
LOG_D("read %d byte%s\r\n", ret, ret == 1 ? "" : "s");
if (ret < msg->len) {
if (ret >= 0)
ret = -8;
goto out;
}
} else {
ret = w_bytes(bit_ops, msg);
if (ret >= 1) {
LOG_D("write %d byte%s\r\n", ret, ret == 1 ? "" : "s");
}
if (ret < msg->len) {
if (ret >= 0)
ret = -1;
goto out;
}
}
}
ret = i;
out:
if (!(msg->flags & RT_I2C_NO_STOP)) {
stop(bit_ops);
}
return ret;
}
sys_force_static_inline void i2c_device_registry(i2c_bus_device_t device, i2c_bit_ops_t *op) {
device->bit_ops = op;
device->api.start = start;
device->api.stop = stop;
device->api.w_byte = w_byte;
device->api.r_byte = r_byte;
device->api.wait_ack = wait_ack;
device->api.send_ack_or_nack = send_ack_or_nack;
device->api.w_bytes = w_bytes;
device->api.r_bytes = r_bytes;
device->api.send_address = send_address;
device->api.bit_send_address = bit_send_address;
device->master_xfer = bit_xfer;
}
void i2c_bus_init(i2c_bus_device_t device, i2c_bit_ops_t *i2c_ops, soft_i2c_cnf_t *cfg) {
i2c_soft_init(i2c_ops, cfg);
i2c_device_registry(device, i2c_ops);
}
rt_size_t rt_i2c_transfer(i2c_bus_device_t device, rt_i2c_msg msgs[], rt_uint32_t num) {
if (device->master_xfer) {
return device->master_xfer(device->bit_ops, msgs, num);
}
return 0;
}
rt_size_t i2c_master_send(i2c_bus_device_t device,
rt_uint16_t addr,
rt_uint16_t flags,
const rt_uint8_t *buf,
rt_uint32_t count) {
rt_i2c_msg msg;
msg.addr = addr;
msg.flags = flags;
msg.len = count;
msg.buf = (uint8_t *) buf;
rt_size_t ret = rt_i2c_transfer(device, &msg, 1);
return (ret > 0) ? count : ret;
}
rt_size_t i2c_master_rec(i2c_bus_device_t device,
rt_uint16_t addr,
rt_uint16_t flags,
rt_uint8_t *buf,
rt_uint32_t count) {
rt_err_t ret;
rt_i2c_msg msg;
msg.addr = addr;
msg.flags = flags | RT_I2C_RD;
msg.len = count;
msg.buf = buf;
ret = rt_i2c_transfer(device, &msg, 1);
return (ret > 0) ? count : ret;
}
测试模块驱动(at24c02)
at24cxx,根据rt-thread里面搜索的包里面的源码来适配此驱动
头文件
#ifndef STM32_F1XX_TEMPLATE_MODULE_AT24CXX_H
#define STM32_F1XX_TEMPLATE_MODULE_AT24CXX_H
#include "bsp.h"
#define AT24C01 0
#define AT24C02 1
#define AT24C04 2
#define AT24C08 3
#define AT24C16 4
#define AT24C32 5
#define AT24C64 6
#define AT24C128 7
#define AT24C256 8
#define AT24C512 9
#define AT24CTYPE 10 // Number of supported types
#define EE_TWR 5
#ifndef EE_TYPE
#define EE_TYPE AT24C02
#endif
struct at24cxx_device {
i2c_bus_device_t i2c;
uint8_t AddrInput;
};
typedef struct at24cxx_device *at24cxx_device_t;
extern at24cxx_device_t at24cxx_init(i2c_bus_device_t i2c, uint8_t AddrInput);
extern rt_err_t at24cxx_read(at24cxx_device_t dev, uint32_t ReadAddr, uint8_t *pBuffer, uint16_t NumToRead);
extern rt_err_t at24cxx_write(at24cxx_device_t dev, uint32_t WriteAddr, uint8_t *pBuffer, uint16_t NumToWrite);
extern rt_err_t at24cxx_page_read(at24cxx_device_t dev, uint32_t ReadAddr, uint8_t *pBuffer, uint16_t NumToRead);
extern rt_err_t at24cxx_page_write(at24cxx_device_t dev, uint32_t WriteAddr, uint8_t *pBuffer, uint16_t NumToWrite);
extern rt_err_t at24cxx_check(at24cxx_device_t dev, uint16_t addr, uint8_t val);
#endif //STM32_F1XX_TEMPLATE_MODULE_AT24CXX_H
源文件
#define DBG_ENABLE
#define DBG_SECTION_NAME "at24xx"
#define DBG_LEVEL DBG_LOG
#include "sys_dbg.h"
#include "module-at24cxx.h"
#define AT24CXX_ADDR (0xA0 >> 1) //A0 A1 A2 connect GND
#if (EE_TYPE == AT24C01)
#define AT24CXX_PAGE_BYTE 8
#define AT24CXX_MAX_MEM_ADDRESS 128
#elif (EE_TYPE == AT24C02)
#define AT24CXX_PAGE_BYTE 8
#define AT24CXX_MAX_MEM_ADDRESS 256
#elif (EE_TYPE == AT24C04)
#define AT24CXX_PAGE_BYTE 16
#define AT24CXX_MAX_MEM_ADDRESS 512
#elif (EE_TYPE == AT24C08)
#define AT24CXX_PAGE_BYTE 16
#define AT24CXX_MAX_MEM_ADDRESS 1024
#elif (EE_TYPE == AT24C16)
#define AT24CXX_PAGE_BYTE 16
#define AT24CXX_MAX_MEM_ADDRESS 2048
#elif (EE_TYPE == AT24C32)
#define AT24CXX_PAGE_BYTE 32
#define AT24CXX_MAX_MEM_ADDRESS 4096
#elif (EE_TYPE == AT24C64)
#define AT24CXX_PAGE_BYTE 32
#define AT24CXX_MAX_MEM_ADDRESS 8192
#elif (EE_TYPE == AT24C128)
#define AT24CXX_PAGE_BYTE 64
#define AT24CXX_MAX_MEM_ADDRESS 16384
#elif (EE_TYPE == AT24C256)
#define AT24CXX_PAGE_BYTE 64
#define AT24CXX_MAX_MEM_ADDRESS 32768
#elif (EE_TYPE == AT24C512)
#define AT24CXX_PAGE_BYTE 128
#define AT24CXX_MAX_MEM_ADDRESS 65536
#endif
sys_force_static_inline rt_err_t read_regs(at24cxx_device_t dev, rt_uint8_t len, rt_uint8_t *buf) {
rt_i2c_msg msgs;
msgs.addr = AT24CXX_ADDR | dev->AddrInput;
msgs.flags = RT_I2C_RD;
msgs.buf = buf;
msgs.len = len;
if (dev->i2c->master_xfer(dev->i2c->bit_ops, &msgs, 1) == 1) {
return RT_EOK;
} else {
return -RT_ERROR;
}
}
sys_force_static_inline uint8_t at24cxx_read_one_byte(at24cxx_device_t dev, uint16_t readAddr) {
rt_uint8_t buf[2];
rt_uint8_t temp;
#if (EE_TYPE > AT24C16)
buf[0] = (uint8_t)(readAddr>>8);
buf[1] = (uint8_t)readAddr;
if (rt_i2c_master_send(dev->i2c, AT24CXX_ADDR, 0, buf, 2) == 0)
#else
buf[0] = readAddr;
if (i2c_master_send(dev->i2c, AT24CXX_ADDR | dev->AddrInput, 0, buf, 1) == 0)
#endif
{
return RT_ERROR;
}
read_regs(dev, 1, &temp);
return temp;
}
sys_force_static_inline rt_err_t
at24cxx_write_one_byte(at24cxx_device_t dev, uint16_t writeAddr, uint8_t dataToWrite) {
rt_uint8_t buf[3];
#if (EE_TYPE > AT24C16)
buf[0] = (uint8_t)(writeAddr>>8);
buf[1] = (uint8_t)writeAddr;
buf[2] = dataToWrite;
if (rt_i2c_master_send(dev->i2c, AT24CXX_ADDR, 0, buf, 3) == 3)
#else
buf[0] = writeAddr; //cmd
buf[1] = dataToWrite;
//buf[2] = data[1];
if (i2c_master_send(dev->i2c, AT24CXX_ADDR | dev->AddrInput, 0, buf, 2) == 2)
#endif
return RT_EOK;
else
return -RT_ERROR;
}
sys_force_static_inline rt_err_t
at24cxx_read_page(at24cxx_device_t dev, uint32_t readAddr, uint8_t *pBuffer, uint16_t numToRead) {
rt_i2c_msg msgs[2];
uint8_t AddrBuf[2];
msgs[0].addr = AT24CXX_ADDR | dev->AddrInput;
msgs[0].flags = RT_I2C_WR;
#if (EE_TYPE > AT24C16)
AddrBuf[0] = readAddr >> 8;
AddrBuf[1] = readAddr;
msgs[0].buf = AddrBuf;
msgs[0].len = 2;
#else
AddrBuf[0] = readAddr;
msgs[0].buf = AddrBuf;
msgs[0].len = 1;
#endif
msgs[1].addr = AT24CXX_ADDR | dev->AddrInput;
msgs[1].flags = RT_I2C_RD;
msgs[1].buf = pBuffer;
msgs[1].len = numToRead;
if (dev->i2c->master_xfer(dev->i2c->bit_ops, msgs, 2) == 0) {
return RT_ERROR;
}
return RT_EOK;
}
sys_force_static_inline rt_err_t
at24cxx_write_page(at24cxx_device_t dev, uint32_t wirteAddr, uint8_t *pBuffer, uint16_t numToWrite) {
rt_i2c_msg msgs[2];
uint8_t AddrBuf[2];
msgs[0].addr = AT24CXX_ADDR | dev->AddrInput;
msgs[0].flags = RT_I2C_WR;
#if (EE_TYPE > AT24C16)
AddrBuf[0] = wirteAddr >> 8;
AddrBuf[1] = wirteAddr;
msgs[0].buf = AddrBuf;
msgs[0].len = 2;
#else
AddrBuf[0] = wirteAddr;
msgs[0].buf = AddrBuf;
msgs[0].len = 1;
#endif
msgs[1].addr = AT24CXX_ADDR | dev->AddrInput;
msgs[1].flags = RT_I2C_WR | RT_I2C_NO_START;
msgs[1].buf = pBuffer;
msgs[1].len = numToWrite;
if (dev->i2c->master_xfer(dev->i2c->bit_ops, msgs, 2) <= 0) {
return RT_ERROR;
}
return RT_EOK;
}
at24cxx_device_t at24cxx_init(i2c_bus_device_t i2c, uint8_t AddrInput) {
at24cxx_device_t dev;
dev = rt_calloc(1, sizeof(at24cxx_device_t));
if (dev == NULL)
return dev;
dev->i2c = i2c;
dev->AddrInput = AddrInput;
return dev;
}
rt_err_t at24cxx_read(at24cxx_device_t dev, uint32_t ReadAddr, uint8_t *pBuffer, uint16_t NumToRead) {
if (ReadAddr + NumToRead > AT24CXX_MAX_MEM_ADDRESS) {
return RT_ERROR;
}
while (NumToRead) {
*pBuffer++ = at24cxx_read_one_byte(dev, ReadAddr++);
NumToRead--;
}
return RT_EOK;
}
rt_err_t at24cxx_write(at24cxx_device_t dev, uint32_t WriteAddr, uint8_t *pBuffer, uint16_t NumToWrite) {
uint16_t i = 0;
if (WriteAddr + NumToWrite > AT24CXX_MAX_MEM_ADDRESS) {
return RT_ERROR;
}
while (1) //NumToWrite--
{
if (at24cxx_write_one_byte(dev, WriteAddr, pBuffer[i]) == RT_EOK) {
bsp_ms_delay(2);
WriteAddr++;
}
if (++i == NumToWrite) {
break;
}
bsp_ms_delay(EE_TWR);
}
return RT_EOK;
}
rt_err_t at24cxx_check(at24cxx_device_t dev, uint16_t addr, uint8_t val) {
uint8_t temp;
temp = at24cxx_read_one_byte(dev, addr);
if (temp == val) return RT_EOK;
else {
at24cxx_write_one_byte(dev, addr, val);
bsp_ms_delay(EE_TWR); // wait 5ms befor next operation
temp = at24cxx_read_one_byte(dev, addr);
if (temp == val) return RT_EOK;
}
return RT_ERROR;
}
rt_err_t at24cxx_page_read(at24cxx_device_t dev, uint32_t ReadAddr, uint8_t *pBuffer, uint16_t NumToRead) {
rt_err_t result = RT_EOK;
uint16_t pageReadSize = AT24CXX_PAGE_BYTE - ReadAddr % AT24CXX_PAGE_BYTE;
if (ReadAddr + NumToRead > AT24CXX_MAX_MEM_ADDRESS) {
return RT_ERROR;
}
while (NumToRead) {
if (NumToRead > pageReadSize) {
if (at24cxx_read_page(dev, ReadAddr, pBuffer, pageReadSize)) {
result = RT_ERROR;
}
ReadAddr += pageReadSize;
pBuffer += pageReadSize;
NumToRead -= pageReadSize;
pageReadSize = AT24CXX_PAGE_BYTE;
} else {
if (at24cxx_read_page(dev, ReadAddr, pBuffer, NumToRead)) {
result = RT_ERROR;
}
NumToRead = 0;
}
}
return result;
}
rt_err_t at24cxx_page_write(at24cxx_device_t dev, uint32_t WriteAddr, uint8_t *pBuffer, uint16_t NumToWrite) {
rt_err_t result = RT_EOK;
uint16_t pageWriteSize = AT24CXX_PAGE_BYTE - WriteAddr % AT24CXX_PAGE_BYTE;
if (WriteAddr + NumToWrite > AT24CXX_MAX_MEM_ADDRESS) {
return RT_ERROR;
}
while (NumToWrite) {
if (NumToWrite > pageWriteSize) {
if (at24cxx_write_page(dev, WriteAddr, pBuffer, pageWriteSize)) {
result = RT_ERROR;
}
bsp_ms_delay(EE_TWR); // wait 5ms befor next operation
WriteAddr += pageWriteSize;
pBuffer += pageWriteSize;
NumToWrite -= pageWriteSize;
pageWriteSize = AT24CXX_PAGE_BYTE;
} else {
if (at24cxx_write_page(dev, WriteAddr, pBuffer, NumToWrite)) {
result = RT_ERROR;
}
bsp_ms_delay(EE_TWR); // wait 5ms befor next operation
NumToWrite = 0;
}
}
return result;
}
测试源码
#include "bsp_i2c_soft.h"
#include "module-at24cxx.h"
#define DBG_ENABLE
#define DBG_SECTION_NAME "at24xx_test"
#define DBG_LEVEL DBG_LOG
#include "sys_dbg.h"
soft_i2c_cnf_t I2C_Gpio_Cnf = {
.port_sda = GPIOB,
.port_scl =GPIOB,
.scl=GPIO_PIN_6,
.sda=GPIO_PIN_7,
};
i2c_bit_ops_t bit_ops = {
.option={
.delay_us =1,
.timeout=100
}
};
struct i2c_bus_device i2c_device;
at24cxx_device_t at24CxxDevice;
static void pre_init(void) {
}
static void init(void) {
i2c_bus_init(&i2c_device, &bit_ops, &I2C_Gpio_Cnf);
}
rt_uint8_t data[] = {12, 3, 4, 5, 7, 2, 5, 7, 4, 2};
rt_uint8_t read_data[10];
static void after_init(void) {
at24CxxDevice = at24cxx_init(&i2c_device, 0);
if (at24cxx_page_write(at24CxxDevice, 0x1, data, sizeof(data)) == RT_EOK) {
LOG_D("write data ok\r\n");
HAL_Delay(5);
if (at24cxx_page_read(at24CxxDevice, 0x1, read_data, sizeof(read_data)) == RT_EOK) {
LOG_D("read data ok\r\n");
}
}
}
//app_init_export(i2c_soft_test, pre_init, init, after_init);
文章来源地址https://www.toymoban.com/news/detail-499183.html
文章来源:https://www.toymoban.com/news/detail-499183.html
到了这里,关于Clion开发STM32之I2C驱动(参考RT-Thread)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!