说明
- 本章是根据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: {GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;break;}case pin_mode_input: {GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_NOPULL;break;}case pin_mode_input_pull_up: {GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_PULLUP;break;}case pin_mode_input_pull_down: {GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_PULLDOWN;break;}case pin_mode_output_od: {GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;GPIO_InitStruct.Pull = GPIO_NOPULL;break;}}HAL_GPIO_Init(port, &GPIO_InitStruct);
}#endif
头文件
#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)
#define RT_I2C_NO_START (1u << 4)
#define RT_I2C_IGNORE_NACK (1u << 5)
#define RT_I2C_NO_READ_ACK (1u << 6)
#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); rt_int32_t (*r_byte)(i2c_bit_ops_t *bit_ops);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); 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);
};
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
源码
#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); 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);
}
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; 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;
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 {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
#define EE_TWR 5
#ifndef EE_TYPE
#define EE_TYPE AT24C02
#endifstruct 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
源文件
#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) #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
#endifsys_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)
#elsebuf[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)
#elsebuf[0] = writeAddr; buf[1] = dataToWrite;if (i2c_master_send(dev->i2c, AT24CXX_ADDR | dev->AddrInput, 0, buf, 2) == 2)
#endifreturn RT_EOK;elsereturn -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;
#elseAddrBuf[0] = readAddr;msgs[0].buf = AddrBuf;msgs[0].len = 1;
#endifmsgs[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;
#elseAddrBuf[0] = wirteAddr;msgs[0].buf = AddrBuf;msgs[0].len = 1;
#endifmsgs[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) {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); 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); 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); 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");}}}