Clion开发STM32之I2C驱动(参考RT-Thread)

news/2024/11/19 0:29:00/

说明

  1. 本章是根据RT-Thread源码中的I2C组件进行抽离,主要不习惯用RT-Thread
  2. 然后在结合at24cxx模块补充测试
  3. 也为了方便移植和独立于框架的限制。

正文

操作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
#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 //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
#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; //cmdbuf[1] = dataToWrite;//buf[2] = data[1];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) //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 operationtemp = 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 operationWriteAddr += 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 operationNumToWrite = 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);

http://www.ppmy.cn/news/476775.html

相关文章

新生电脑Win10入门基础操作

1、电脑开机关机&#xff1a;设置开机画面和开机密码。 2、桌面设置: 1)如何把快捷方式发送到桌面&#xff1f; 2)如何设置显示"此电脑"图标&#xff1f; 3)如何设置壁纸&#xff1f; 4)在哪里查看屏幕分辨率&#xff1f; 5)如何设置桌面图…

谷歌火狐浏览器主页被劫持

唉&#xff0c;不听网页卫士迈克菲 联网顾问的提示&#xff0c;为了找激活win10的工具&#xff0c;访问了一些危险的网站&#xff0c;风雨工具、HEU_KMS什么的&#xff0c;搞得我360卫视查出了2个木马&#xff0c;但是访问的浏览器的主页被修改&#xff0c;一打开就是hao123网页…

新机开箱篇

哈喽!大家好,我又回来了!   这几天在想,怎么做一个时时刻刻有输出的人,有些混乱,可能是觉得有好多好东西想跟大家分享.   今天跟大家分享一些买来电脑后自己的一些小小心得和分享,下面开始正文了.  考虑到大家可能是第一次接触win10或者是第一次在开发层次上接触电脑,所以…

华为荣耀笔记本电脑Windows Defender受IT管理员限制的解决办法

华为荣耀笔记本电脑Windows Defender受IT管理员限制的解决办法 问题介绍华为荣耀解决办法其他常见的Windows Defender受IT管理员限制的解决办法1.卸载第三方杀毒软件2.企业电脑联系IT管理员3.CMD修改注册表4.重启服务5.更改策略组6.CMD更改策略组7.KMS激活8.病毒限制9.总结 问题…

从零开始手搓一个STM32与机智云的小项目——GPIO模拟时序控制外设1

文章目录 前言WS2812B1.模块简介2.时序介绍3.硬件介绍4.传输速率&#xff0c;以及帧数要求 代码1.初始化2.模拟时序1.复位函数2.发送0、1码3.封装发送函数 总结 前言 上一篇文章中介绍了整个板子的最基本功能模块——使用GPIO的通用输入输出实现简单的按键输入以及推挽输出控制…

第四章 运算符

1. 【两个对象相加】 锦囊01 数字相加 在Python中&#xff0c;经常会遇到使用“”进行数值相加的情况&#xff0c;常用应用如下&#xff1a; a 10 b 1 c 2.0 d 3.0print(ab) # 整数相加 print(cd) # 浮点数相加 print(ab) # 整数和浮点数相加 print(a .5) …

人工智能和机器学习在电气和电子行业的作用

电气和电子行业中使用的人工智能一词一般是指为模仿人类智能做出决策和解决相关问题而建立的各种系统和技术。近年来&#xff0c;工程师和科学家们已经探索了人工智能在电气系统中的不同应用和方式。 人工智能被纳入电气系统和消费电子产品的一些最常见的方式&#xff1a; - 专…

ad18学习笔记五:统计焊盘数量(board information)

AD18之后&#xff0c;Altium Designer改动比较大。下面将介绍AD19如何统计焊盘(PAD数量)与SMT贴片数量与插件数量 1&#xff1a; PCB 空白处 -> F11 -> Properties 选项卡 -> Board Information -> Pads 2&#xff1a; Pads 包括 通孔焊盘和贴片焊盘 Vias 包括过孔…