IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 【RT-Thread Master】at24cxx软件包使用笔记 -> 正文阅读

[嵌入式]【RT-Thread Master】at24cxx软件包使用笔记

硬件介绍

  • 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进行初始化。于是输入下面的命令进行初始化。
at24cxx probe i2c1
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)
#else
	
	dev->AddrInput = readAddr >> 8;//增加这么一句话,根据读取地址,自动计算页地址A2A1A0
    buf[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)
#else
	dev->AddrInput = writeAddr >> 8;//增加这么一句话,根据写入地址,自动计算页地址A2A1A0
    buf[0] = writeAddr; //cmd
    buf[1] = dataToWrite;
    //buf[2] = data[1];

    if (rt_i2c_master_send(dev->i2c, AT24CXX_ADDR | dev->AddrInput, 0, buf, 2) == 2)
#endif
        return RT_EOK;
    else
        return -RT_ERROR;

}

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

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-05-10 12:04:54  更:2022-05-10 12:06:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 3:42:08-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码