24系列EEPROM/FRAM通用驱动库移植到RT-Thread

2023-05-16

文章目录

  • 1 前言
  • 2 接口实现
    • 2.1 i2c收发函数实现
    • 2.2 页写延时函数
    • 2.3 写保护函数
    • 2.4 设备注册
  • 3 对接RT-Thread设备驱动
    • 3.1 标准设备驱动接口
    • 3.2 注册到RT-Thread
    • 3.3 导出到msh
    • 3.4 测试
  • 4 相关文章
  • 5 代码仓库


1 前言

  在此之前编写了一个24系列(i2c接口)EEPROM/FRAM通用驱动库。RT-Thread提供了一个完善的设备管理驱动框架,使得设备可以像访问文件一样访问,甚至支持POSIX标准(open、read、write、close)。现把EEPROM/FRAM通用驱动库移植到RT-Thread上。


2 接口实现

  驱动库做了良好的分层处理,移植到RT-Thread上只需实现_24cxx_dev_t数据结构中的i2c收发函数i2c_send_thend_recvi2c_send_thend_send即可。

/*24cxx eeprom devcie struct*/
typedef struct 
{
	int (*i2c_send_thend_recv)(uint8_t slave_addr, const void *send_buff, 	/* i2c bus fun */
				uint32_t send_size, void *recv_buff, uint32_t recv_size);
	int (*i2c_send_thend_send)(uint8_t slave_addr, const void *send_buff1,	/* i2c bus fun */
				uint32_t send_size1,const void *send_buff2, uint32_t send_size2);
	uint8_t	slave_addr;	/* eeprom i2c addr */
	_24_model_t	model;		/* eeprom model */
	void(*wp)(uint8_t ctrl);		/* protect of write function */
	void(*page_write_delay)(void);	/* there is a delay in continuous writin for EEPROM,FRAM not need */
	
}_24cxx_dev_t;
  • i2c_send_thend_recv,i2c“发送-接收”函数
  • i2c_send_thend_send,i2c“发送-发送”函数
  • slave,器件i2c地址,不包含读写位,如0x50
  • wp,写包含函数,器件wp引脚控制
  • page_write_delay,页写延时函数,对于EEPROM使用;FRAM则无需

2.1 i2c收发函数实现


  • RT-Thread上i2c“发送-接收”函数:

  “发送-接收” 函数用于读取i2c器件的寄存器值,对于EEPROM/FRAM则是读取存储地址的数据。

static int hw_i2c_send_then_recv(rt_uint8_t slave_addr, const void *send_buff, 
							 rt_uint32_t send_size, void *recv_buff, rt_uint32_t recv_size)
{
	struct rt_i2c_msg ee24_msg[2];
	rt_uint8_t ret_size = 0;

	ee24_msg[0].addr  = slave_addr;
	ee24_msg[0].flags = RT_I2C_WR;
	ee24_msg[0].buf   = (rt_uint8_t*)send_buff;
	ee24_msg[0].len   = send_size;
	ee24_msg[1].addr  = slave_addr;
	ee24_msg[1].flags = RT_I2C_RD;	
	ee24_msg[1].buf   = (rt_uint8_t*)recv_buff;
	ee24_msg[1].len   = recv_size;

	ret_size = rt_i2c_transfer(rt_at24c_i2c, ee24_msg, 2);

	if (ret_size == 2)
	{
		return _24CXX_OK;
	}
	else
	{
		return _24CXX_ERR_I2C_WR;	
	}
}

  • RT-Thread上i2c“发送-发送”函数:

  “发送-发送” 函数用于向i2c器件的寄存器写入数据,对于EEPROM/FRAM则是向存储地址写入数据。

static int hw_i2c_send_then_send(rt_uint8_t slave_addr, const void *send_buff1,
							 rt_uint32_t send_size1,const void *send_buff2, rt_uint32_t send_size2)
{
	struct rt_i2c_msg ee24_msg[2];
	rt_uint8_t ret_size = 0;

	ee24_msg[0].buf   = (rt_uint8_t*)send_buff1;
	ee24_msg[0].addr  = slave_addr;
	ee24_msg[0].flags = RT_I2C_WR;
	ee24_msg[0].len   = send_size1;
	ee24_msg[1].addr  = slave_addr;
	ee24_msg[1].flags = RT_I2C_WR  | RT_I2C_NO_START;
	ee24_msg[1].buf   = (rt_uint8_t*)send_buff2;
	ee24_msg[1].len   = send_size2;
	ret_size = rt_i2c_transfer(rt_at24c_i2c, ee24_msg, 2);
	
	if (ret_size == 2)
	{
		return _24CXX_OK;
	}
	else
	{
		return _24CXX_ERR_I2C_WR;	
	}
}

2.2 页写延时函数

  页写延时函数用于EEPROM相邻两页写入的等待时间。对于FRAM则不需要,因为FRAM写入速率快。本次测试的是FRAM,所以该函数为NULL。

/* EEPROM页写间延时函数 */
void hw_page_write_delay(void)
{
	rt_thread_mdelay(1);
}

2.3 写保护函数

  写保护,指的是器件的“wp”控制引脚;高电平时禁止写入;低电平允许写入;用于保护数据,防止意外被修改。因此,写保护函数即是一个GPIO控制函数。如果“wp”引脚常接地,该函数为NULL即可。

/* 写保护函数 */
void hw_wp_ctrl(rt_uint8_t ctrl)
{
    rt_pin_write(10, ctrl);
}

2.4 设备注册

/**
 * @brief  FM24CL04 device init
 */
const _24cxx_dev_t at24cxx_dev =
{
	hw_i2c_send_then_recv,
	hw_i2c_send_then_send,
	0x50,						/* eeprom address */
	_24C04_E,					/* eeprom model,eg FM24CL04 */
	RT_NULL,					/* no write protect */
	RT_NULL,					/* delay function,FRAM no need */
};

3 对接RT-Thread设备驱动

3.1 标准设备驱动接口

  分别实现RT-Thread设备驱动的open、read、write函数实体。

static rt_size_t rt_at24cxx_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
{
  	_24cxx_dev_t *p = RT_NULL;
	rt_int16_t ret = _24CXX_OK;
	
  	p = (_24cxx_dev_t*)dev->user_data;
	
  	ret = _24cxx_read(p, pos, buffer, size); 
	if (_24CXX_OK == ret)
	{
	  	return size;
	}
	else
	{
		return RT_ERROR;
	}
}
static rt_size_t rt_at24cxx_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
{
    _24cxx_dev_t *p = RT_NULL;
	rt_int16_t ret = _24CXX_OK;
	
  	p = (_24cxx_dev_t*)dev->user_data;
	
  	ret = _24cxx_write(p, pos, (rt_uint8_t*)buffer, size); 
	if (_24CXX_OK == ret)
	{
	  	return size;
	}
	else
	{
		return RT_ERROR;
	}
}
  • RT-Thread rt_device_t 提供一个私有数据user_data,我们用来保存EEPROM/FRAM驱动库设备_24cxx_dev_t

3.2 注册到RT-Thread

  最后将EEPROM/FRAM设备注册设备到RT-Thread设备管理框架中。

int rt_hw_at24cxx_init(void)
{		
    rt_at24c_i2c = rt_i2c_bus_device_find(AT24CXX_I2C_BUS);
    if (rt_at24c_i2c == RT_NULL)
    {
        LOG_E("i2c bus device %s not found!\r\n", AT24CXX_I2C_BUS);
        return -RT_ERROR;
    }				 	

    /* register rtc device */
    rt_at24c_dev.type   = RT_Device_Class_Char;
    rt_at24c_dev.init   = RT_NULL;
    rt_at24c_dev.open   = rt_at24cxx_open;
    rt_at24c_dev.close  = RT_NULL;
    rt_at24c_dev.read   = rt_at24cxx_read;
    rt_at24c_dev.write  = rt_at24cxx_write;
    rt_at24c_dev.control= RT_NULL;
    rt_at24c_dev.user_data 	= (void*)&at24cxx_dev;	/* ee24cxx device */;		
    rt_device_register(&rt_at24c_dev, AT24CXX_DEVICE_NAME, RT_DEVICE_FLAG_RDWR);
		
	LOG_D("at24cxx init succeed!\r\n");
	
    return 0;
}
INIT_DEVICE_EXPORT(rt_hw_at24cxx_init);

3.3 导出到msh

  为了方便测试,我们将读写功能到出到RT-Thread msh中。包括:

  • 片内读功能
  • 片内写功能
  • 片内擦除(写入0x00)功能

  详细实现过程,查阅文章末尾源代码。


3.4 测试

  • 查询注册设备名称
msh >list_device
device           type         ref count
-------- -------------------- ----------
24cxx    Character Device     0       
i2c1     I2C Bus              0       
pin      Miscellaneous Device 0       
uart2    Character Device     0       
uart1    Character Device     2       

  • 查询读写命令使用方法
msh >_24cxx_wr        
usage:
_24cxx_wr [eeprom dev] r     - read 24cxx 
_24cxx_wr [eeprom dev] w     - write 24cxx 
_24cxx_wr [eeprom dev] e     - erase 24cxx

  • 执行测试命令
_24cxx_wr 24cxx r 	# 读测试
_24cxx_wr 24cxx w	# 写测试
_24cxx_wr 24cxx e 	# 擦除测试

4 相关文章

【1】24系列EEPROM/FRAM通用接口


5 代码仓库

【1】GitHub
【2】码云

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

24系列EEPROM/FRAM通用驱动库移植到RT-Thread 的相关文章

  • QT多线程

    Qt多线程 1 QThread类 QThread类并不是代表一个新的线程 而是QT提供的一个接口 用于控制一个子线程 每个QThread的实例就代表着对一个新线程的一个控制类 对于第一次使用QT多线程的人 或许就会很迷惑很不适应 QThre
  • yield和join方法的使用。

    join方法用线程对象调用 如果在一个线程A中调用另一个线程B的join方法 线程A将会等待线程B执行完毕后再执行 yield可以直接用Thread类调用 yield让出CPU执行权给同等级的线程 如果没有相同级别的线程在等待CPU的执行权
  • java多线程实战( 多个线程 修改同一个变量)

    java多线程实战 多个线程 修改同一个变量 synchronized 同步 介绍 java多线程实战 需求 创建两个线程 分别输出 a b 要求输出总和为30个 线程介绍 一 定义线程 1 扩展java lang Thread类 此类中有
  • Linux 线程同步的三种方法

    线程的最大特点是资源的共享性 但资源共享中的同步问题是多线程编程的难点 linux下提供了多种方式来处理线程同步 最常用的是互斥锁 条件变量和信号量 一 互斥锁 mutex 通过锁机制实现线程间的同步 初始化锁 在Linux下 线程的互斥量
  • 【N32L40X】学习笔记14-在RT-thread系统中读取eeprom数据

    eeprom 说明 eeprom介绍 AT24C01A 1K串行EEPROM 内部组织16页8字节 1K需要一个7位数据字地址进行随机字寻址 AT24C02 2K串行EEPROM 内部组织32页8字节 2K需要一个8位数据字地址进行随机字寻
  • 线程进程协程的实现代码

    单线程 import time def run print hello world time sleep 1 if name main for i in range 5 run 多线程 import threading import tim
  • EEPROM芯片(24c02)使用详解(I2C通信时序分析、操作源码分析、原理图分析)

    1 前言 1 本文主要是通过24c02芯片来讲解I2C接口的EEPROM操作方法 包含底层时序和读写的代码 2 大部分代码是EEPROM芯片通用的 但是其中关于某些时间的要求 是和具体芯片相关的 和主控芯片和外设芯片都有关系 需要具体分析
  • 关于CoInitialize()

    在msdn中对于CoInitialize的解释如下 Initializes the COM library on the current apartment and identifies the concurrency model as s
  • java常见笔试题目

    1 下列那一行代码编译后不会出现警告或错误 1 char c a 2 byte b 257 3 boolean b null 4 int i 10 5 float f 1 3 2 下面这段代码编译时会发生什么情况 public class
  • Java 线程创建方法

    除了继承Thread 实现Runnable Callable三种创建线程方式外的第四种创建方式 实现java util concurrent ThreadFactory接口 实现newThread Runnable r 方法 这种方式应用于
  • JSVC简介之快速入门

    1 JSVC简介 Apache基金会会common 类似于guava 项目下的项目 2 为什么要使用JSVC java应用增加一种启动方式 Java的缺点 只能用main方法启动 应用能使用1024以下端口 为啥tomcat可以指定端口 系
  • 分析Java线程池执行原理

    Java并发编程源码分析系列 分析Java线程池的创建 上一篇已经对线程池的创建进行了分析 了解线程池既有预设的模板 也提供多种参数支撑灵活的定制 本文将会围绕线程池的生命周期 分析线程池执行任务的过程 线程池状态 首先认识两个贯穿线程池代
  • Qt中的线程详解

    概述 在多核时代 CPU 的主频已经进入瓶 颈 另辟蹊径地提高程序运行效率就是使用线程 充分利用多核的优势 线程可以看做是 轻量级进程 线程即可以由操作系统管理 也可以由应用程序管 1 为什么要使用线程 我们都知道 进程线程的概念是非常重要
  • 笔试题10:Runnable接口与Thread类的区别?

    1 线程类继承自Thread则不能继承自其它类 而Runnable接口可以 2 线程类继承自Thread相对于Runnable来说 使用线程的方法更方便一些 3 实现Runnable接口的线程类的多个线程 可以更方便的访问同一变量 而Thr
  • c++11std::thread扩展

    最近 整理一下学习c 的文章 看到一篇文章 其中提到了thread local和std future 觉得这两东西很有趣 于是网上搜了一些资料 觉得很有帮助 希望可以对大家学习c 线程有所帮助 http www cnblogs com ha
  • python_os.walk(dir)

    for root dirs files in os walk dir os walk返回一个三元组 path 对当前路径以及其下所有的子目录进行递归 dirs 当前路径下的子目录 files 当前路径下的文件 gt gt gt for r
  • 关于RT-Thread中优先级翻转问题的简记

    最近在学习RT Thread的相关知识 记录一下心得 优先级翻转 是指当一个高优先级线程试图通过信号量机制访问共享资源时 如果该信号量已被低优先级线程持有 而这个低优先级线程在运行过程中可能又被其他一些中等优先级的线程抢占 从而造成高优先级
  • python基于字典多线程目录枚举工具

    基于字典多线程目录枚举工具 整体思路 命令行参数获取 字典文件的读取 多线程访问 命令行参数获得 使用模块 sys getopt sys argv获取命令行执行的数据 参数获得 opt args getopt getopt sys argv
  • POSIX线程:API

    一 线程创建与取消 1 线程创建 1 1 线程与进程 相对进程而言 线程是一个更加接近于执行体的概念 它可以与同进程中的其他线程共享数据 但拥有自己的栈空间 拥有独立的执行序列 在串行程序基础上引入线程和进程是为了提高程序的并发度 从而提高
  • Java调用Win API

    官方网站 http jawinproject sourceforge net 把lib文件夹下的jawin jar和jawin stubs jar放到 JAVA HOME jre lib ext 目录下 把bin文件夹下的jawin dll

随机推荐

  • 时序数据库-3-[IoTDB]的安装与使用

    IoTDB官方文档手册 Apache IoTDB xff08 物联网数据库 xff09 是一体化收集 存储 管理与分析物联网时序数据的软件系统 Apache IoTDB 采用轻量式架构 xff0c 具有高性能和丰富的功能 xff0c 并与A
  • 【强烈推荐】基于STM32的TFT-LCD各种显示实现(内容详尽含代码)

    前言 xff1a TFT LCD模块作为人们日常生活中常见屏幕类型之一 xff0c 使用的受众面非常广阔 例如 xff1a 显示各个传感器数值 xff0c 显示精美界面 xff0c 多级化菜单系统等等都不离不开他的身影 可以说学会TFT L
  • 时序数据库-4-[IoTDB]的python3操作

    从采集到存储 xff1a 时序数据库到底怎么处理时间 xff1f iotdb官方文档手册 1 容器安装iotdb 可以使用docker volume create命令创建 docker 卷 此命令将在 var lib docker volu
  • [汇总]基于ESP32的四旋翼无人机开发纪实

    文章目录 一 项目说明1 已实现功能2 硬件配置 二 ESPlane2 0 开发笔记三 相关传感器驱动移植四 参考链接 ESPlane 项目更名为 ESP Drone 现已公开代码仓库和文档 代码仓库 xff1a https github
  • [填坑]Ubuntu安装显卡专有驱动后鼠标键盘无法使用

    问题描述 我在两个地方遇到了同样的问题 xff0c 解决方法也如出一辙 xff0c 由于没有研究源码 xff0c 暂不清楚原因 问题1描述 xff1a 为了解决Ubuntu下笔记本功耗问题 xff0c 在网友建议下我安装了bumblebee
  • uniapp-前后端开发app-系列01开篇

    系列文章目录 文章目录 系列文章目录前言一 开发工具 xff1f 二 项目架构三 具体内容实现 前言 提示 xff1a 这里可以添加本文要记录的大概内容 xff1a 随着app和小程序的发展 有没有开发一个模版 其他端程序都能用 uniap
  • TypeError: iter() returned non-iterator of type

    在使用Python迭代器时出现错误 xff1a class Fibs def init self self a 61 0 self b 61 1 def next self self a self b 61 self b self a 43
  • 【Linux应用编程】一个异步信号处理引起死锁问题的思考

    文章目录 1 前言2 为什么会产生死锁2 1 死锁2 2 分析2 3 结论 3 避免死锁4 举一反三5 死锁例子代码6 参考文章 1 前言 最近在维护别人的代码时 xff0c 遇到一个线程死锁问题 xff0c 一番折腾 xff0c 最终定位
  • 【RT-Thread】SGM706独立看门狗软件包

    文章目录 1 简介1 1 目录结构1 2 许可证 2 芯片介绍3 支持情况4 使用说明4 1 依赖4 2 获取软件包4 3 初始化4 4 启动看门狗4 5 msh finsh测试查看设备注册通过msh启动看门狗 5 注意事项6 联系方式 1
  • 利用tldr工具再也不怕记不住Linux命令

    文章目录 1 前言2 tldr3 安装4 使用 1 前言 linux命令非常多 xff0c 少用的命令往往易忘记 xff0c 甚至常用的语法较为复杂的命令也不好记住 当然有些太复杂的命令也不需要死记硬背 xff0c 我们往往会借助man命令
  • C++中的二阶构造函数

    文章目录 1 前言2 二阶构造3 总结 1 前言 构造函数用于创建对象时对象成员的初始化 xff0c 如赋初值 申请内存 加载文件等 xff0c 即是自动完成对象的初始化任务 在C 43 43 语言中 xff0c 构造函数执行顺序是 xff
  • open函数簇与fopen函数簇区别和用法

    文章目录 1 前言2 open与fopen区别2 1 标准不同2 2 层次不同2 3 适用对象不同 xff08 返回值不同 xff09 2 4 缓冲区2 5 效率不同 3 使用方法3 1 open3 2 fopen 1 前言 linux系统
  • 基于STM32的OLED多级菜单GUI实现(简化版智能手表)

    前言 xff1a 本文的OLED多级菜单UI 为一个综合性的STM32小项目 xff0c 使用多传感器 与OLED显示屏 实现智能终端 的效果 项目中的多级菜单UI使用了较为常见的结构体索引法 去实现功能与功能之间的来回切换 xff0c 搭
  • 【RTD】铂电阻测温原理与具体方法

    文章目录 1 基本原理2 铂电阻2 1 铂电阻测温原理2 2 铂电阻类型和测量方法2 2 1 两线式铂电阻2 2 2 三线式铂电阻2 2 3 四线式铂电阻 3 小结 相关文章 xff1a RTD 铂电阻测温原理与具体方法 RTD AD779
  • 【RTD】AD7793三线式铂电阻PT100/PT1000应用

    文章目录 1 AD7793简介2 AD7793 三线式铂电阻测量2 1 阻值计算 3 小结 相关文章 xff1a RTD 铂电阻测温原理与具体方法 RTD AD7793三线式铂电阻PT100 PT1000应用 RTD AD7793四线式铂电
  • 【RTD】AD7793四线式铂电阻PT100/PT1000应用

    文章目录 1 前言2 AD7793 四线式铂电阻测量2 1 阻值计算 3 小结 1 前言 上一篇文章描述的是RTD驱动芯片AD7793特点 xff0c 以及其与三线式RTD连接使用方法 本文描述四线式RTD与AD7793的使用 相关文章 x
  • 【RTD】AD7793两线式铂电阻PT100/PT1000应用

    文章目录 1 前言2 AD7793 两线式铂电阻测量2 1 阻值计算 3 小结 1 前言 上一篇文章描述的是RTD驱动芯片AD7793与四线式RTD连接使用方法 本文描述两线式RTD与AD7793的使用 相关文章 xff1a RTD 铂电阻
  • 【RTD】AD7793驱动程序

    文章目录 1 前言2 AD7793驱动程序2 1 spi访问接口2 2 寄存器和常用配置值2 3 初始化2 4 原始数据获取2 5 阻值换算 3 使用4 完整工程代码 1 前言 前面文章主要描述AD7793分别与两线 三线 四线RTD连接电
  • 【RTD】二分法查找和分段线性插值算法在RTD中应用

    文章目录 1 前言2 二分法查找2 1 复杂度2 2 实现 3 分段线性插值4 RTD实例 1 前言 处理器通过RTD采集电路 xff08 芯片 xff09 精确获得当前RTD电阻值后 xff0c 再结合RTD与温度线性关系表 xff0c
  • 24系列EEPROM/FRAM通用驱动库移植到RT-Thread

    文章目录 1 前言2 接口实现2 1 i2c收发函数实现2 2 页写延时函数2 3 写保护函数2 4 设备注册 3 对接RT Thread设备驱动3 1 标准设备驱动接口3 2 注册到RT Thread3 3 导出到msh3 4 测试 4