野火科技
直播中

jf_23522415

2年用户 65经验值
擅长:可编程逻辑 嵌入式技术
私信 关注
[经验]

【野火启明6M5开发板体验】3.I2C协议读写EEPROM

前言

I2C协议读写EEPROM

启明开发板的EEPROM

image.png

硬件引脚图

image-20230107113437363

  • EEPROM的引脚SCL对应启明开发板引脚P415
  • EEPROM的引脚SDA对应启明开发板引脚P414
  • A1/A2/A3接地,故A1/A2/A3为0(结合下图可判断出设备读写地址)

image.png

image.png

设备写地址:b 10100000(0xA0) 读地址 b 10100001(0xA1)

image-20230107120425404

WP引脚(写保护功能)接地,不使用写保护。

创建项目

开发环境:

操作系统: windows 11

**IDE: e2studio **

仿真器: JLINK

image-20230107121442999

image-20230107121512407

image-20230107121538555

image-20230107121611861

下一步,

image-20230107121626895

image-20230107121650501

image-20230107121710376

配置信息

在上一步中创建了一个裸项目,接下来打开新项目,打开configuration.xml文件

切换到Stacks卡片

image-20230107121949830点击新建的Stack,刷新属性窗口

image-20230107122526323

image-20230107123313562

其中 Channel的需要参考AT24C02连接开发板的引脚

结合硬件手册

image-20230107123600390

可知AT24C02连接开发板的IIC2,所以在Channal中选择通道2

上升时间和下降时间最大值300ns,这里设置成120

从站地址:参考本篇硬件引脚图部分

引脚选择

image.png

image-20230107124751585

Pin Group Selection 是引脚复用分配 - A 引脚或 B 引脚

image-20230107124855289

,保存。点击右上角****generate project content

软件逻辑

**参考野火官方资料 **I2C——读写EEPROM,并做少许更改演示.

文件目录

src文件目录

  • basic.h
  • **eeprom.c **
  • ** eeprom.h **
  • **led.c **
  • led.h
  • uart.c
  • uart.h

led部分的配置可参考

【野火启明6M5开发板体验】1.开箱 中led引脚的配置

uart部分的配置可参考

【野火启明6M5开发板体验】2.WiFi模块的使用中uart4部分的引脚配置

配置完 generate以下即可。

basic.h

#ifndef BASIC_H_
#define BASIC_H_#include "uart.h"
#include "eeprom.h"
#include "led.h"#define s8  char
#define s16 short
#define s32 int
#define u8  unsigned char
#define u16 unsigned short
#define u32 unsigned inttypedef u8  b8;
​
​
​
#endif /* BASIC_H_ */

eeprom.c

#include "hal_data.h"
#include "uart.h"
#include "eeprom.h"
#include "basic.h"unsigned s32 timeout_ms = 500;
​
i2c_master_event_t g_i2c_callback_event;
static volatile b8 iic_complete = false;
​
​
​
void i2c_callback (i2c_master_callback_args_t * p_args)
{
    g_i2c_callback_event = p_args->event;
}
​
​
/**
* [url=home.php?mod=space&uid=2666770]@Brief[/url] I2C EEPROM初始化
* [url=home.php?mod=space&uid=3142012]@param[/url]   无
* @retval  无
*/
void I2C_EE_Init()
{
    R_IIC_MASTER_Open(eeprom.p_ctrl, &eeprom_cfg);
    R_BSP_SoftwareDelay(10, BSP_DELAY_UNITS_MILLISECONDS);
}
​
​
/**
* @brief 以单字节的方式到I2C EEPROM中
* @param
*   [url=home.php?mod=space&uid=2583231]@arg[/url] address:写地址
*   @arg byte:写的数据
* @retval  无
*/
void I2C_EE_ByteWrite(unsigned char address, unsigned char byte)
{
    iic_complete = false;
    unsigned char send_buffer[2] = {};
​
    send_buffer[0] = address;
    send_buffer[1] = byte;
    R_IIC_MASTER_Write(&eeprom_ctrl, &send_buffer[0], 2, false); //每当写完数据 false 总线拉高while ((I2C_MASTER_EVENT_TX_COMPLETE != g_i2c_callback_event) && timeout_ms)
    {
        R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MILLISECONDS);
        timeout_ms--;
    }
    timeout_ms = 500;
}
​
​
/**
* @brief   将缓冲区中的数据以页写入的方式写到I2C EEPROM中
* @param
*   @arg ptr_write:缓冲区指针
*   @arg WriteAddr:写地址
*     @arg len:写的长度
* @retval  无
*/
void I2C_EE_Writepage(unsigned char* ptr_write , unsigned char WriteAddr,unsigned char len)      //页写入   page 0~31
{
​
    unsigned char send_buffer[9] = {};
    send_buffer[0] = WriteAddr;
​
    for(unsigned char i = 0;i<len;i++)
    {
        send_buffer[1+i] = *(ptr_write+i);
    }
​
    R_IIC_MASTER_Write(&eeprom_ctrl, &send_buffer[0], len+1 , false);
​
    while ((I2C_MASTER_EVENT_TX_COMPLETE != g_i2c_callback_event) && timeout_ms)
    {
        R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MILLISECONDS);
        timeout_ms--;
    }
    timeout_ms = 500;
​
    I2C_EE_WaitState();
}
​
​
/**
* @brief   将缓冲区中的数据写到I2C EEPROM中
* @param
*   @arg pBuffer:缓冲区指针
*   @arg WriteAddr:写地址
*     @arg NumByteToWrite:写的字节数
* @retval  无
*/
void I2C_EE_BufferWrite(uint8_t* pBuffer, uint8_t WriteAddr,uint16_t NumByteToWrite)
{
    uint8_t NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0;
​
    Addr = WriteAddr % EEPROM_PAGESIZE;
    count = EEPROM_PAGESIZE - Addr;
    NumOfPage =  NumByteToWrite / EEPROM_PAGESIZE;
    NumOfSingle = NumByteToWrite % EEPROM_PAGESIZE;
​
    /* If WriteAddr is I2C_PageSize aligned  */
    if (Addr == 0) {
        /* If NumByteToWrite < I2C_PageSize */
        if (NumOfPage == 0) {
            I2C_EE_Writepage(pBuffer, WriteAddr, NumOfSingle);
        }
        /* If NumByteToWrite > I2C_PageSize */
        else {
            while (NumOfPage--) {
                I2C_EE_Writepage(pBuffer, WriteAddr, EEPROM_PAGESIZE);
                WriteAddr +=  EEPROM_PAGESIZE;
                pBuffer += EEPROM_PAGESIZE;
            }
​
            if (NumOfSingle!=0) {
                I2C_EE_Writepage(pBuffer, WriteAddr, NumOfSingle);
            }
        }
    }
    /* If WriteAddr is not I2C_PageSize aligned  */
    else {
        /* If NumByteToWrite < I2C_PageSize */
        if (NumOfPage== 0) {
            I2C_EE_Writepage(pBuffer, WriteAddr, NumOfSingle);
        }
        /* If NumByteToWrite > I2C_PageSize */
        else {
            NumByteToWrite -= count;
            NumOfPage =  NumByteToWrite / EEPROM_PAGESIZE;
            NumOfSingle = NumByteToWrite % EEPROM_PAGESIZE;
​
            if (count != 0) {
                I2C_EE_Writepage(pBuffer, WriteAddr, count);
                WriteAddr += count;
                pBuffer += count;
            }
​
            while (NumOfPage--) {
                I2C_EE_Writepage(pBuffer, WriteAddr, EEPROM_PAGESIZE);
                WriteAddr +=  EEPROM_PAGESIZE;
                pBuffer += EEPROM_PAGESIZE;
            }
            if (NumOfSingle != 0) {
                I2C_EE_Writepage(pBuffer, WriteAddr, NumOfSingle);
            }
        }
    }
}
​
​
​
/**
* @brief 读取I2C EEPROM数据
* @param
*   @arg ptr_read:读取缓冲区指针
*   @arg address:地址
*     @arg byte:读取的字节数
* @retval  无
*/
void I2C_EE_BufferRead(unsigned char* ptr_read,unsigned char address,unsigned char byte)
{
​
    unsigned char send_buffer[2] = {};
    unsigned char read_buffer[1] = {};
​
    send_buffer[0] = address;
    R_IIC_MASTER_Write(&eeprom_ctrl, &send_buffer[0], 1, true);
    while ((I2C_MASTER_EVENT_TX_COMPLETE != g_i2c_callback_event) && timeout_ms)
    {
        R_BSP_SoftwareDelay(400U, BSP_DELAY_UNITS_MICROSECONDS);
        timeout_ms--;
    }
    timeout_ms = 500;
​
    R_BSP_SoftwareDelay(250U, BSP_DELAY_UNITS_MICROSECONDS);
​
    R_IIC_MASTER_Read(&eeprom_ctrl, ptr_read, byte, false);
​
}
​
/**
* @brief I2C EEPROM清空数据
*/
void I2C_EE_Writedrase()
{
    unsigned char I2c_Buf_Write[256] = {};
    for(int i = 0 ; i<256 ; i++)
    {
        I2c_Buf_Write[i] = 0xff;
    }
    I2C_EE_BufferWrite(I2c_Buf_Write, 0x00 , 256);
}
​
​
/**
* @brief EEPROM等待数据写入成功
*/
void I2C_EE_WaitState(void)
{
    while (timeout_ms)
    {
        R_BSP_SoftwareDelay(9U, BSP_DELAY_UNITS_MICROSECONDS);
        timeout_ms--;
    }
    timeout_ms = 500;
}
​
​
​
/**
* @brief  I2C(AT24C02)读写测试
* @param  无
* @retval 正常返回1 ,不正常返回0
*/
uint8_t I2C_Test(void)
{
    uint16_t i;
    unsigned char DATA_Size = 30;
    unsigned char I2c_Buf_Write[33] = {};
    unsigned char I2c_Buf_Read[33] = {};
​
    //将I2c_Buf_Write中顺序递增的数据写入EERPOM中
    printf("写入的数据\r\n");
    for ( i=0; i<DATA_Size; i++ ) { //填充缓冲
        I2c_Buf_Write[i] =i;
        printf("0x%02X ", I2c_Buf_Write[i]);
        if (i%16 == 15)
            printf("\n");
    }
    I2C_EE_BufferWrite( I2c_Buf_Write, 0x00 , DATA_Size);
​
​
​
    //将EEPROM读出数据顺序保持到I2c_Buf_Read中
    printf("\r\n读出的数据\n");
    R_BSP_SoftwareDelay(10U, BSP_DELAY_UNITS_MILLISECONDS);
    I2C_EE_BufferRead(I2c_Buf_Read, 0x00 , DATA_Size);
​
​
​
    //将I2c_Buf_Read中的数据通过串口打印
    R_BSP_SoftwareDelay(10U, BSP_DELAY_UNITS_MILLISECONDS);
    for (i=0; i<DATA_Size; i++) {
        if (I2c_Buf_Read[i] != I2c_Buf_Write[i]) {
            printf("0x%02X \n", I2c_Buf_Read[i]);
            printf("错误:I2C EEPROM写入与读出的数据不一致\n");
            printf("%d\n",i);
            return 0;
        }
        printf("0x%02X ", I2c_Buf_Read[i]);
        if (i%16 == 15)
            printf("\n");
​
    }
    printf("\r\nI2C(AT24C02)读写测试成功\n");
    return 1;
}
​

eeprom.h

#ifndef EEPROM_H_
#define EEPROM_H_
​
​
/* AT24C01/02每页有8个字节 */
#define EEPROM_PAGESIZE           8
#define I2C_Register_SR1                ((uint8_t)0x14)void i2c_callback (i2c_master_callback_args_t * p_args);
void I2C_EE_Init();
void I2C_EE_ByteWrite(unsigned char address, unsigned char byte);
void I2C_EE_Writepage(unsigned char* ptr_write , unsigned char WriteAddr,unsigned char len);
void I2C_EE_BufferWrite(uint8_t* pBuffer, uint8_t WriteAddr,uint16_t NumByteToWrite);
void I2C_EE_BufferRead(unsigned char* ptr_read,unsigned char address,unsigned char byte);
void I2C_EE_WaitState(void);
void I2C_EE_Writedrase();
uint8_t I2C_Test(void);
​
​
​
#endif /* EEPROM_H_ */

hal_entry.c

#include "hal_data.h"
#include "basic.h"
​
FSP_CPP_HEADER
void R_BSP_WarmStart(bsp_warm_start_event_t event);
FSP_CPP_FOOTER
​
/*******************************************************************************************************************//**
 * main() is generated by the RA Configuration editor and is used to generate threads if an RTOS is used.  This function
 * is called by main() when no RTOS is used.
 **********************************************************************************************************************/
void hal_entry(void)
{
    /* TODO: add your own code here */
    I2C_EE_Init();
    uart4_init();
    led_init();
​
    printf("I2C外设读写测试例程 \r\n");
    R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_SECONDS);
​
    while (1)
    {
        I2C_EE_Writedrase();
        if (I2C_Test() ==1) {
            GREEN;
        } else {
            RED;
        }
​
        while(1);
    }
​
​
#if BSP_TZ_SECURE_BUILD
    /* Enter non-secure code */
    R_BSP_NonSecureEnter();
#endif
}
​
/*******************************************************************************************************************//**
 * This function is called at various points during the startup process.  This implementation uses the event that is
 * called right before main() to set up the pins.
 *
 * @param[in]  event    Where at in the start up process the code is currently at
 **********************************************************************************************************************/
void R_BSP_WarmStart(bsp_warm_start_event_t event)
{
    if (BSP_WARM_START_RESET == event)
    {
#if BSP_FEATURE_FLASH_LP_VERSION != 0
​
        /* Enable reading from data flash. */
        R_FACI_LP->DFLCTL = 1U;
​
        /* Would normally have to wait tDSTOP(6us) for data flash recovery. Placing the enable here, before clock and
         * C runtime initialization, should negate the need for a delay since the initialization will typically take more than 6us. */
#endif
    }
​
    if (BSP_WARM_START_POST_C == event)
    {
        /* C runtime environment and system clocks are setup. */
​
        /* Configure pins. */
        R_IOPORT_Open (&g_ioport_ctrl, g_ioport.p_cfg);
    }
}
​
#if BSP_TZ_SECURE_BUILD
​
BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable ();
​
/* Trustzone Secure Projects require at least one nonsecure callable function in order to build (Remove this if it is not required to build). */
BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable ()
{
​
}
#endif
​

led.c

​
​
#include "led.h"
​
​
void led_init(void)
{
    /* 初始化配置引脚(这里重复初始化了,可以注释掉) */
    R_IOPORT_Open (&g_ioport_ctrl, g_ioport.p_cfg);
}
​

led.h

​
​
#ifndef LED_H_
#define LED_H_#include "hal_data.h"#define RED                                                                     \
    R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_00, BSP_IO_LEVEL_LOW);\
    R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_03, BSP_IO_LEVEL_HIGH); \
    R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_04, BSP_IO_LEVEL_HIGH);#define BLUE                                                                    \
    R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_00, BSP_IO_LEVEL_HIGH); \
    R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_03, BSP_IO_LEVEL_LOW);\
    R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_04, BSP_IO_LEVEL_HIGH);#define GREEN                                                                   \
    R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_00, BSP_IO_LEVEL_HIGH); \
    R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_03, BSP_IO_LEVEL_HIGH); \
    R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_04, BSP_IO_LEVEL_LOW);#define LED_ON                                                                 \
    R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_00, BSP_IO_LEVEL_LOW); \
    R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_03, BSP_IO_LEVEL_LOW); \
    R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_04, BSP_IO_LEVEL_LOW);
​
​
#define LED_OFF                                                                  \
    R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_00, BSP_IO_LEVEL_HIGH); \
    R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_03, BSP_IO_LEVEL_HIGH); \
    R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_04, BSP_IO_LEVEL_HIGH);
​
​
void led_init(void);
​
#endif /* LED_H_ */

uart.c

* uart.c
 *
 *  Created on: 20221230日
 *      Author: jujub
 */
​
//#include <stdio.h>
#include "uart.h"
#include "hal_data.h"
#include "basic.h"volatile bool uSendComplete = false;
​
​
void uart4_callback(uart_callback_args_t *p_args)
{
    switch (p_args->event)
    {
       case UART_EVENT_RX_CHAR:
       {
             /* 把串口接收到的数据发送回去 */
             R_SCI_UART_Write(&g_uart4_ctrl, (uint8_t *)&(p_args->data), 1);
             break;
       }
       case UART_EVENT_TX_COMPLETE:
       {
           uSendComplete = true;
             break;
       }
       default:
             break;
    }
}
​
/* 重定向 printf 输出 */
#if defined __GNUC__ && !defined __clang__
int _write(int fd, char *pBuffer, int size); //防止编译警告
int _write(int fd, char *pBuffer, int size)
{
   (void)fd;
   R_SCI_UART_Write(&g_uart4_ctrl, (uint8_t *)pBuffer, (uint32_t)size);
   while(uSendComplete == false);
   uSendComplete = false;
​
   return size;
}
#else
int fputc(int ch, FILE *f)
{
   (void)f;
   R_SCI_UART_Write(&g_uart4_ctrl, (uint8_t *)&ch, 1);
   while(uSendComplete == false);
   uSendComplete = false;
​
   return ch;
}
#endif
​
​
void uart4_init(void)
{
    fsp_err_t err;
​
    err = R_SCI_UART_Open(&g_uart4_ctrl, &g_uart4_cfg);
    assert(FSP_SUCCESS == err);
}
​
​

uart.c

#ifndef UART_H_
#define UART_H_
​
​
void uart4_init(void);
​
#endif /* UART_H_ */

结果演示

image-20230107134957421

参考链接

[野火]瑞萨RA系列FSP库开发实战指南——I2C读写EEPROM

更多回帖

发帖
×
20
完善资料,
赚取积分