硬件介绍

  • RT-Thread版本:V4.1.0
  • 软件包名称:at24cxx
  • MCU型号:AT32F407VET7
  • EEPROM型号:AT24C16

使用说明

1、使用menuconfig将软件包添加进入工程,路径如下所示。

2、把IIC总线打开,这里使用软件IIC,如果已经打开了就不用再次打开,IIC所用的引脚暂时先不管。

3、然后编译工程。

4、编译完成以后,打开工程,可以发现IIC驱动已经被添加进来了,at24cxx软件包也添加进来了。

5、然后我们进入at24cxx.h文件,修改我们EEPROM型号。我这里是AT24C6。

6、然后我们进入rtconfig.h文件里面,修改我们的IIC引脚。默认是22和23,这里我直接使用GET_PIN来获取引脚,但是这种方式的缺点就是每次menuconfig以后都要去修改一次,不过我也不是经常去menuconfig,测试时就暂时先这么改吧。

7、然后我们将工程编译一下,没有错误,下载到板子上。在shell中输入at24cxx,然后回车,就会弹出几个命令。分别是probe,read,write。

8、要想使用read/write命令,要先使用probe命令对AT24CXX进行初始化。于是输入下面的命令进行初始化。

9、然后就可以使用at24cxx read 和at24cxx write命令进行读写了。当然这个命令做得太简单了,只是读写都是从0地址开始,读写指定的位置的。而我想读写任意位置的数据,因此需要对命令进行改造一下。经过修改后的函数如下,这样我就可以读写任意位置的数据了。我们来演示一下。

static uint8_t opt_buffer[2048];void at24cxx(int argc, char *argv[])
{static at24cxx_device_t dev = RT_NULL;uint16_t opt_addr, opt_len;if (argc > 1){if (!strcmp(argv[1], "probe")){if (argc > 2){/* initialize the sensor when first probe */if (!dev || strcmp(dev->i2c->parent.parent.name, argv[2])){/* deinit the old device */if (dev){at24cxx_deinit(dev);}dev = at24cxx_init(argv[2], atoi(argv[3]));}}else{rt_kprintf("at24cxx probe <dev_name> <AddrInput> - probe sensor by given name\n");}}else if (!strcmp(argv[1], "read")){if (dev){if( argc != 4 ) //at24cxx read 0 2048{rt_kprintf("example: at24cxx read addr len.\n");return ;}opt_addr = atoi(argv[2]);opt_len = atoi(argv[3]);if( opt_len > sizeof(opt_buffer) ){rt_kprintf("read len must less than %d.\n", sizeof(opt_buffer));return ;}/* read the eeprom data */if( at24cxx_read(dev, opt_addr, opt_buffer, opt_len) == RT_EOK ){rt_kprintf("read at24cxx ok\n");for(uint16_t i=0; i<opt_len; i++){                    rt_kprintf("%02x ", opt_buffer[i]);}rt_kprintf("\n");for(uint16_t i=0; i<opt_len; i++){rt_kprintf("%02c ", opt_buffer[i]);}rt_kprintf("\n");}else{rt_kprintf("read at24cxx fail.\n");}                                  }else{rt_kprintf("Please using 'at24cxx probe <dev_name>' first\n");}}else if (!strcmp(argv[1], "write")){if (dev){if( argc != 4 ){rt_kprintf("example: at24cxx write address string.\n");return ;}opt_addr = atoi(argv[2]);if( at24cxx_write(dev, opt_addr, (uint8_t *)argv[3], rt_strlen(argv[3])) == RT_EOK ){rt_kprintf("write ok\n");}else{rt_kprintf("write fail\n");}}else{rt_kprintf("Please using 'at24cxx probe <dev_name>' first\n");}}else if (!strcmp(argv[1], "check")){if (at24cxx_check(dev) == 1){rt_kprintf("check faild \n");}}else{rt_kprintf("Unknown command. Please enter 'at24cxx0' for help\n");}}else{rt_kprintf("Usage:\n");rt_kprintf("at24cxx probe <dev_name>   - probe eeprom by given name\n");rt_kprintf("at24cxx check              - check eeprom at24cxx \n");rt_kprintf("at24cxx read               - read eeprom at24cxx data\n");rt_kprintf("at24cxx write              - write eeprom at24cxx data\n");}
}
MSH_CMD_EXPORT(at24cxx, at24cxx eeprom function);

10、我们从0地址开始读,读10个字节。命令格式如下:at24cxx read addr len。表示从addr地址开始读,读取len个字节,如果读取成功,就会将数据通过十六进制和字符的形式打印出来,是不是方便多啦。

11、写指令也是一样的,命令格式如下:at24cxx write addr string 表示从addr开始写,写入字符串string。

12、下面我就通过一个GIF来演示整个过程吧。因为我的项目中有使用easylog(一个打印日志的软件包,会影响我们观看shell的打印),因此我首先将esaylog先关闭,这步操作大家无需进行。

13、另外我还发现了一个问题,就是我的EEPROM是AT24C16,它是2048个字节大小的,但是我似乎无法正常读取256字节以后的地址。经过查看芯片手册发现,AT24C16一共有3位页地址,和8位的字地址,如下表所示。

页地址 数据
第0页 256字节
第1页 256字节
,
第15页 256字节

页地址,用来就控制这是第几页。字地址,用来表示页里面的第几个字节。
而页地址和字地址,是在什么时候发送的呢?我们去看EEPROM的芯片手册的,按字节写操作,会传入8位的字地址。这个就表示要写某页的第几个字节。

而页地址呢?怎么好像没有传入?别急,我们看下图,原来AT24C16没有器件地址,它的器件地址的3个位,用来作为页地址使用了。
也就是说,当我们要访问第256个地址的时候(从0开始计算),我们需要将页地址(器件地址)设置为1,字地址设置为0即可。

14、回过来看代码,我发现读写一个字节的函数的器件地址都是可设置的,AT24CXX_ADDR | dev->AddrInput就是EEPROM器件的地址。这个dev->AddrInput是我们使用probe命令的时候手动传入的,对于我们AT24C16而言使用上不太方便,因为我每次访问不同的地址就需要重新传一遍dev->AddrInput不太好,因此我对这两个读写函数改造一下,让dev->AddrInput可以根据我们传入的读写地址自动计算出来。于是修改后的读写一个字节的代码如下。

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)
#elsedev->AddrInput = readAddr >> 8;//增加这么一句话,根据读取地址,自动计算页地址A2A1A0buf[0] = readAddr;/* 对于AT24C16而言,EEPROM未使用器件地址引脚,总线上最多只能连接一个16K器件,A2、A1、A0是悬空的,可以接GND。也正是因为如此,AT24C16的器件地址后3位都为页地址位。*/if (rt_i2c_master_send(dev->i2c, AT24CXX_ADDR | dev->AddrInput, 0, buf, 1) == 0)
#endif{return RT_ERROR;}read_regs(dev, 1, &temp);return temp;
}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)
#elsedev->AddrInput = writeAddr >> 8;//增加这么一句话,根据写入地址,自动计算页地址A2A1A0buf[0] = writeAddr; //cmdbuf[1] = dataToWrite;//buf[2] = data[1];if (rt_i2c_master_send(dev->i2c, AT24CXX_ADDR | dev->AddrInput, 0, buf, 2) == 2)
#endifreturn RT_EOK;elsereturn -RT_ERROR;}

15、编译,下载,再去验证一下,看看能否成功读写0-2047地址的数据。如下图所示,正常啦。

【RT-Thread Master】at24cxx软件包使用笔记相关推荐

  1. rt thread系统下添加wiznet软件包后,不插网线CPU利用率100%问题

    rt thread系统下添加wiznet软件包后如果不插网线的话其他任务运行很卡,使用ps命令发现优先级低的任务很多都超时了 rt thread线程错误码 添加了一个可以查看CPU利用率的软件包CPU ...

  2. 使用RT Thread设备框架封装一个I2C设备——DS3231

    使用RT Thread设备框架封装一个I2C设备--DS3231 前言 ENV配置 I2C测试 将ds3231封装成一个字符设备 结语 前言 学习rt thread的I2C的时候,恰巧手上的板子留了d ...

  3. rt thread studio使用QBOOT和片外flash实现OTA升级

    我们这里要使用单片机外部flash作为OTA的下载分区,外部flash硬件连接关系 PB3-->SPI3_CLK PB4-->SPI3_MISO PB5-->SPI3_MOSI PE ...

  4. RT Thread Free Modbus移植问题整理

    RT Thread Free Modbus移植问题整理 问题描述: 在读写寄存器中,写数据正常,只能读1个寄存器的值,多个值会异常. 在移植过程中发现串口(或RS485)数据接收长度异常. 一.环境描 ...

  5. RT Thread根据开发板制作BSP方法

    之前一直不懂怎么使用RT Thread的软件包,感谢网上的大神,看了你们的博客后大概了解一些,在此做下记录.用RT Thread软件包需要RT Thread的系统,但是RT Thread和RT Thr ...

  6. stm32f407单片机rt thread 片外spi flash OTA升级配置示例

    参考地址https://www.rt-thread.org/document/site/application-note/system/rtboot/an0028-rtboot/ 第一步,生成Boot ...

  7. 基于GD32F103C8T6添加RT Thread nano设备框架并添加串口设备(以控制台console( uart0 )为例)

    最近没事琢磨了一下使用设备框架的问题.因为将串口注册到设备框架可以应用十分丰富的软件包. 于是就整理了一下手上的工程,重新将工程梳理了一遍. 像这样是十分清爽了,其中RTOS是操作系统源代码 并且学习 ...

  8. 关于RT thread系统节拍时钟的配置

    关于RT thread系统节拍时钟的配置                  -----本文基于rt-thread-3.1.3版本编写 首先,使用RTthread OS时,要配置(或者明白)它的系统节拍 ...

  9. rt thread 使用FAL遇到fal_init() undefined reference

    rt thread FAL 0.5版,之前有没有不知道,遇到一个坑. 在main.cpp里面已经 #include <fal.h> fal_init() 编译报错,说 fal_init() ...

  10. Yeelink平台使用——远程控制 RT Thread + LwIP+ STM32

    1.前言     [2014年4月重写该博文]     经过若干时间的努力终于搞定了STM32+LwIP和yeelink平台的数据互通,在学习的过程中大部分时间花在以太网协议栈学习上,但是在RT Th ...

最新文章

  1. mac远程redis_MAC安装redis
  2. ES6新特性5:类(Class)和继承(Extends)
  3. 公众号滑动图代码_脱离模板!教你自己动手制作公众号封面图
  4. mysql字符串逆时针旋转180度_mysql 函数示例(转)
  5. 弹出VIEW.非dialog
  6. php防止跨域提交,PHP防止跨域提交表单的简单示例
  7. 【译】Node.js 日志打印指南
  8. 信息学奥赛一本通 2053:【例3.3】三个数
  9. 使用canvas元素和JavaScript花费您的星期日(或任何一天)。
  10. Java银行类编程题
  11. SpringCloud的Ribbon负载均衡
  12. 拓端tecdat|R语言关联挖掘实例(购物篮分析)
  13. 阿里云云计算 41 阿里云CDN的工作原理
  14. 仿ofo首页眼睛跟随加速器移动效果
  15. SQL Server 2016 Always Encrypted(始终加密)
  16. 【轉】一個在台積電工作3年的工程師寫給學弟學妹們的信
  17. 魔兽地图编辑器插件YDWE的使用与基本设置6 输入管理器
  18. 2020_WWW_The Structure of Social Influence in Recommender Networks
  19. 基于AT89C51/52和DS18B20的温度传感器设计报告(后附代码)
  20. Eclipse入门教程

热门文章

  1. 我所理解的闭包是酱紫的
  2. 美国交通模型发展前沿一览——Caliper年度通讯
  3. ImageNet中1000类目标的编号所对应的具体类别
  4. 面试:你印象最深的BUG,举个例子
  5. marked转换html失败,解析markdown之marked
  6. LeetCode动态规划题解
  7. apple API常用英语名词
  8. flutter开发的即时聊天应用
  9. 【应急响应】Linux下变种DDG挖矿应急处理总结
  10. 国际商务礼仪与标准接待风范