I2C协议读写EEPROM
设备写地址: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文件目录
led部分的配置可参考
【野火启明6M5开发板体验】1.开箱 中led引脚的配置
uart部分的配置可参考
【野火启明6M5开发板体验】2.WiFi模块的使用中uart4部分的引脚配置
配置完 generate以下即可。
#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 /* BASIC_H_ */
#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;
}
#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_ */
#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
#include "led.h"
void led_init(void)
{
/* 初始化配置引脚(这里重复初始化了,可以注释掉) */
R_IOPORT_Open (&g_ioport_ctrl, g_ioport.p_cfg);
}
#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
*
* Created on: 2022年12月30日
* 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);
}
#ifndef UART_H_
#define UART_H_
void uart4_init(void);
#endif /* UART_H_ */
更多回帖