前言
I2C协议读写EEPROM
启明开发板的EEPROM
硬件引脚图
- EEPROM的引脚SCL对应启明开发板引脚P415
- EEPROM的引脚SDA对应启明开发板引脚P414
- A1/A2/A3接地,故A1/A2/A3为0(结合下图可判断出设备读写地址)
设备写地址:b 10100000(0xA0) 读地址 b 10100001(0xA1)
WP引脚(写保护功能)接地,不使用写保护。
创建项目
开发环境:
操作系统: windows 11
**IDE: e2studio **
仿真器: JLINK
下一步,
配置信息
在上一步中创建了一个裸项目,接下来打开新项目,打开configuration.xml
文件
切换到Stacks
卡片
点击新建的Stack,刷新属性窗口
其中 Channel的需要参考AT24C02连接开发板的引脚
结合硬件手册
可知AT24C02连接开发板的IIC2,所以在Channal中选择通道2
上升时间和下降时间最大值300ns,这里设置成120
从站地址:参考本篇硬件引脚图部分
引脚选择
Pin Group Selection 是引脚复用分配 - A 引脚或 B 引脚
,保存。点击右上角****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 int
typedef u8 b8;
#endif
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;
}
void I2C_EE_Init()
{
R_IIC_MASTER_Open(eeprom.p_ctrl, &eeprom_cfg);
R_BSP_SoftwareDelay(10, BSP_DELAY_UNITS_MILLISECONDS);
}
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);
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;
}
void I2C_EE_Writepage(unsigned char* ptr_write , unsigned char WriteAddr,unsigned char len)
{
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();
}
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 (Addr == 0) {
if (NumOfPage == 0) {
I2C_EE_Writepage(pBuffer, WriteAddr, NumOfSingle);
}
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);
}
}
}
else {
if (NumOfPage== 0) {
I2C_EE_Writepage(pBuffer, WriteAddr, NumOfSingle);
}
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);
}
}
}
}
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);
}
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);
}
void I2C_EE_WaitState(void)
{
while (timeout_ms)
{
R_BSP_SoftwareDelay(9U, BSP_DELAY_UNITS_MICROSECONDS);
timeout_ms--;
}
timeout_ms = 500;
}
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] = {};
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);
printf("\r\n读出的数据\n");
R_BSP_SoftwareDelay(10U, BSP_DELAY_UNITS_MILLISECONDS);
I2C_EE_BufferRead(I2c_Buf_Read, 0x00 , DATA_Size);
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_
#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
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
uart.c
* uart.c
*
* Created on: 2022年12月30日
* Author: jujub
*/
#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;
}
}
#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
结果演示
参考链接
[野火]瑞萨RA系列FSP库开发实战指南——I2C读写EEPROM