NUCLEO-F411RE RT-Thread 体验 (10) - GCC环境 AT24CXX的使用

NUCLEO-F411RE RT-Thread 体验 (10) - GCC环境 AT24CXX的使用

1、AT24CXX的移植

软件包下载

在reconfigure.h添加at24cxx的定义

在这里插入图片描述

Makefile里添加编译

在这里插入图片描述
这里我放在了User目录下,里面所有的.c文件都会被编译进去。

2、测试

封装一个结构体,将结构体填充后,写到eeprom中,然后从eeprom读出来,看数据是否一致。
在这里插入图片描述
结构体大小为120K,最小的at24c01 128K字节,也能读写。
at24C02测试如下:
在这里插入图片描述
at24C256测试如下:
在这里插入图片描述

3、修改后的代码

/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2019-04-13     XiaojieFan   the first version
 * 2019-12-04     RenMing      ADD PAGE WRITE and input address can be selected
 * 2022-10-11     GuangweiRen  Delay 2ms after writing one byte
 */
#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>

#include <string.h>
#include <stdlib.h>

#define DBG_ENABLE
#define DBG_SECTION_NAME "at24xx"
#define DBG_LEVEL DBG_LOG
#define DBG_COLOR

#include <rtdbg.h>

#include "at24cxx.h"

#ifdef PKG_USING_AT24CXX
#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
#endif

static rt_err_t read_regs(at24cxx_device_t dev, rt_uint8_t len, rt_uint8_t *buf)
{
    struct rt_i2c_msg msgs;

    msgs.addr = AT24CXX_ADDR;
    msgs.flags = RT_I2C_RD;
    msgs.buf = buf;
    msgs.len = len;

    if (rt_i2c_transfer(dev->i2c, &msgs, 1) == 1)
    {
        return RT_EOK;
    }
    else
    {
        return -RT_ERROR;
    }
}
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
    buf[0] = readAddr;
    if (rt_i2c_master_send(dev->i2c, AT24CXX_ADDR, 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
    buf[0] = writeAddr; //cmd
    buf[1] = dataToWrite;
    //buf[2] = data[1];


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

}

rt_err_t at24cxx_read_page(at24cxx_device_t dev, uint32_t readAddr, uint8_t *pBuffer, uint16_t numToRead)
{
    struct rt_i2c_msg msgs[2];
    uint8_t AddrBuf[2];

    msgs[0].addr = AT24CXX_ADDR;
    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;
#else
    AddrBuf[0] = readAddr;
    msgs[0].buf = AddrBuf;
    msgs[0].len = 1;
#endif

    msgs[1].addr = AT24CXX_ADDR ;
    msgs[1].flags = RT_I2C_RD;
    msgs[1].buf = pBuffer;
    msgs[1].len = numToRead;

    if(rt_i2c_transfer(dev->i2c, msgs, 2) == 0)
    {
        return RT_ERROR;
    }

    return RT_EOK;
}

rt_err_t at24cxx_write_page(at24cxx_device_t dev, uint32_t wirteAddr, uint8_t *pBuffer, uint16_t numToWrite)
{
    struct rt_i2c_msg msgs[2];
    uint8_t AddrBuf[2];

    msgs[0].addr = AT24CXX_ADDR ;
    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;
#else
    AddrBuf[0] = wirteAddr;
    msgs[0].buf = AddrBuf;
    msgs[0].len = 1;
#endif

    msgs[1].addr = AT24CXX_ADDR;
    msgs[1].flags = RT_I2C_WR | RT_I2C_NO_START;
    msgs[1].buf = pBuffer;
    msgs[1].len = numToWrite;

    if(rt_i2c_transfer(dev->i2c, msgs, 2) <= 0)
    {
        return RT_ERROR;
    }

    return RT_EOK;
}

rt_err_t at24cxx_check(at24cxx_device_t dev)
{
    uint8_t temp;
    RT_ASSERT(dev);

    temp = at24cxx_read_one_byte(dev, AT24CXX_MAX_MEM_ADDRESS - 1);
    if (temp == 0x55) return RT_EOK;
    else
    {
        at24cxx_write_one_byte(dev, AT24CXX_MAX_MEM_ADDRESS - 1, 0x55);
        rt_thread_mdelay(EE_TWR);                 // wait 5ms befor next operation
        temp = at24cxx_read_one_byte(dev, AT24CXX_MAX_MEM_ADDRESS - 1);
        if (temp == 0x55) return RT_EOK;
    }
    return RT_ERROR;
}

/**
 * This function read the specific numbers of data to the specific position
 *
 * @param bus the name of at24cxx device
 * @param ReadAddr the start position to read
 * @param pBuffer  the read data store position
 * @param NumToRead
 * @return RT_EOK  write ok.
 */
rt_err_t at24cxx_read(at24cxx_device_t dev, uint32_t ReadAddr, uint8_t *pBuffer, uint16_t NumToRead)
{
    rt_err_t result;
    RT_ASSERT(dev);

    if(ReadAddr + NumToRead > AT24CXX_MAX_MEM_ADDRESS)
    {
        return RT_ERROR;
    }

    result = rt_mutex_take(dev->lock, RT_WAITING_FOREVER);
    if (result == RT_EOK)
    {
        while (NumToRead)
        {
            *pBuffer++ = at24cxx_read_one_byte(dev, ReadAddr++);
            NumToRead--;
        }
    }
    else
    {
        LOG_E("The at24cxx could not respond  at this time. Please try again");
    }
    rt_mutex_release(dev->lock);

    return RT_EOK;
}

/**
 * This function read the specific numbers of data to the specific position
 *
 * @param bus the name of at24cxx device
 * @param ReadAddr the start position to read
 * @param pBuffer  the read data store position
 * @param NumToRead
 * @return RT_EOK  write ok.
 */
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;

    RT_ASSERT(dev);

    if(ReadAddr + NumToRead > AT24CXX_MAX_MEM_ADDRESS)
    {
        return RT_ERROR;
    }

    result = rt_mutex_take(dev->lock, RT_WAITING_FOREVER);
    if(result == RT_EOK)
    {
        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;
            }
        }
    }
    else
    {
        LOG_E("The at24cxx could not respond  at this time. Please try again");
    }

    rt_mutex_release(dev->lock);
    return result;
}

/**
 * This function write the specific numbers of data to the specific position
 *
 * @param bus the name of at24cxx device
 * @param WriteAddr the start position to write
 * @param pBuffer  the data need to write
 * @param NumToWrite
 * @return RT_EOK  write ok.at24cxx_device_t dev
 */
rt_err_t at24cxx_write(at24cxx_device_t dev, uint32_t WriteAddr, uint8_t *pBuffer, uint16_t NumToWrite)
{
    uint16_t i = 0;
    rt_err_t result;
    RT_ASSERT(dev);

    if(WriteAddr + NumToWrite > AT24CXX_MAX_MEM_ADDRESS)
    {
        return RT_ERROR;
    }

    result = rt_mutex_take(dev->lock, RT_WAITING_FOREVER);
    if (result == RT_EOK)
    {
        while (1) //NumToWrite--
        {
            if (at24cxx_write_one_byte(dev, WriteAddr, pBuffer[i]) == RT_EOK)
            {
                rt_thread_mdelay(2);
                WriteAddr++;
            }
            if (++i == NumToWrite)
            {
                break;
            }
            rt_thread_mdelay(EE_TWR);
        }
    }
    else
    {
        LOG_E("The at24cxx could not respond  at this time. Please try again");
    }
    rt_mutex_release(dev->lock);

    return RT_EOK;
}

/**
 * This function write the specific numbers of data to the specific position
 *
 * @param bus the name of at24cxx device
 * @param WriteAddr the start position to write
 * @param pBuffer  the data need to write
 * @param NumToWrite
 * @return RT_EOK  write ok.at24cxx_device_t dev
 */
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;

    RT_ASSERT(dev);

    if(WriteAddr + NumToWrite > AT24CXX_MAX_MEM_ADDRESS)
    {
        return RT_ERROR;
    }

    result = rt_mutex_take(dev->lock, RT_WAITING_FOREVER);
    if(result == RT_EOK)
    {
        while (NumToWrite)
        {
            if(NumToWrite > pageWriteSize)
            {
                if(at24cxx_write_page(dev, WriteAddr, pBuffer, pageWriteSize))
                {
                    result = RT_ERROR;
                }
                rt_thread_mdelay(EE_TWR);    // wait 5ms befor next operation

                WriteAddr += pageWriteSize;
                pBuffer += pageWriteSize;
                NumToWrite -= pageWriteSize;
                pageWriteSize = AT24CXX_PAGE_BYTE;
            }
            else
            {
                if(at24cxx_write_page(dev, WriteAddr, pBuffer, NumToWrite))
                {
                    result = RT_ERROR;
                }
                rt_thread_mdelay(EE_TWR);   // wait 5ms befor next operation

                NumToWrite = 0;
            }
        }
    }
    else
    {
        LOG_E("The at24cxx could not respond  at this time. Please try again");
    }

    rt_mutex_release(dev->lock);
    return result;
}

/**
 * This function initializes at24cxx registered device driver
 *
 * @param dev the name of at24cxx device
 *
 * @return the at24cxx device.
 */
at24cxx_device_t at24cxx_init(const char *i2c_bus_name)
{
    at24cxx_device_t dev;

    RT_ASSERT(i2c_bus_name);

    dev = rt_calloc(1, sizeof(struct at24cxx_device));
    if (dev == RT_NULL)
    {
        LOG_E("Can't allocate memory for at24cxx device on '%s' ", i2c_bus_name);
        return RT_NULL;
    }

    dev->i2c = rt_i2c_bus_device_find(i2c_bus_name);
    if (dev->i2c == RT_NULL)
    {
        LOG_E("Can't find at24cxx device on '%s' ", i2c_bus_name);
        rt_free(dev);
        return RT_NULL;
    }

    dev->lock = rt_mutex_create("mutex_at24cxx", RT_IPC_FLAG_FIFO);
    if (dev->lock == RT_NULL)
    {
        LOG_E("Can't create mutex for at24cxx device on '%s' ", i2c_bus_name);
        rt_free(dev);
        return RT_NULL;
    }
    return dev;
}

/**
 * This function releases memory and deletes mutex lock
 *
 * @param dev the pointer of device driver structure
 */
void at24cxx_deinit(at24cxx_device_t dev)
{
    RT_ASSERT(dev);

    rt_mutex_delete(dev->lock);

    rt_free(dev);
}

const char *eep_type[] = 
{
    "AT24C01",
    "AT24C02",
    "AT24C04",
    "AT24C08",
    "AT24C16",
    "AT24C32",
    "AT24C64",
    "AT24C128",
    "AT24C256",
    "AT24C512",
};

system_info at_system_info = {0};

void system_info_init(void)
{
    rt_sprintf(at_system_info.version,"%s %s",__DATE__,__TIME__);
    at_system_info.sysclk = HAL_RCC_GetSysClockFreq();
    at_system_info.hclk = HAL_RCC_GetHCLKFreq();
    at_system_info.apb1_clk = HAL_RCC_GetPCLK1Freq();
    at_system_info.apb2_clk = HAL_RCC_GetPCLK2Freq();
    rt_memcpy(at_system_info.eep_type,eep_type[EE_TYPE],rt_strlen(eep_type[EE_TYPE]));
    rt_sprintf(at_system_info.rt_thread_version, "%d.%d.%d build %s %s",RT_VERSION, 
                                            RT_SUBVERSION, RT_REVISION, __DATE__, __TIME__);

    at_system_info.romsize = 512;
    at_system_info.ramsize = 128;
}

void system_info_show(system_info *p_system_info)
{
    rt_kprintf(" System Info Get EepRom: \n");
    rt_kprintf(" System Version     : %s\n",p_system_info->version);
    rt_kprintf(" Eeprom Type        : %s\n",p_system_info->eep_type);
    rt_kprintf(" System Clock       : %ld\r\n",p_system_info->sysclk);
    rt_kprintf(" AHB Clock          : %ld\r\n",p_system_info->hclk);
    rt_kprintf(" APB1 Clock         : %ld\r\n",p_system_info->apb1_clk);
    rt_kprintf(" APB2 Clock         : %ld\r\n",p_system_info->apb2_clk);
    rt_kprintf(" RT-Thread Version  : %s\n",p_system_info->rt_thread_version);

    rt_kprintf(" System Info Size   : %ld K\n",sizeof(system_info));

}

int at24(int argc ,char *argv[])
{
    at24cxx_device_t dev = RT_NULL;
    system_info at_r_info = {0};


    if (argc != 1)
    {
        rt_kprintf("error, usage:  at24\n");
        return -1;
    }

    system_info_init();
    dev = at24cxx_init("i2c1");

    at24cxx_write(dev, 0, (uint8_t *)&at_system_info, sizeof(system_info));
    rt_kprintf("write system info ok\n");

    at24cxx_read(dev,0,(uint8_t *)&at_r_info,sizeof(system_info));
    system_info_show(&at_r_info);

    at24cxx_deinit(dev);

    return 0;
}

MSH_CMD_EXPORT(at24, at24cxx eeprom test);
#endif

.h文件

/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2019-04-13     XiaojieFan   the first version
 * 2019-12-04     RenMing      Use PAGE WRITE instead of BYTE WRITE and input address can be selected
 */

#ifndef __AT24CXX_H__
#define __AT24CXX_H__

#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#include <board.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
#endif

struct at24cxx_device
{
    struct rt_i2c_bus_device *i2c;
    rt_mutex_t lock;
};

typedef struct 
{
    char     version[24];
    uint32_t sysclk;
    uint32_t hclk;
    uint32_t apb1_clk;
    uint32_t apb2_clk;
    uint32_t ramsize;
    uint32_t romsize;
    char     eep_type[24];
    char     rt_thread_version[48];

}system_info;


typedef struct at24cxx_device *at24cxx_device_t;

extern at24cxx_device_t at24cxx_init(const char *i2c_bus_name);
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);

#endif

4、代码

代码下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值