网站流量统计工具,泸州房产网,wordpress是一款强大的,怎么用FTP做网站STMCUBEMX_IIC_DMA_AT24C64读取和写入 说明#xff1a; 1、此例程只是从硬件IIC升级到DMA读写#xff0c;因为暂时存储的掉电不丢失数据不多#xff0c;一页就可以够用#xff0c;不用担心跨页读写的问题 2、使用DMA后#xff0c;程序确实是变快了#xff0c;但是也要注意…STMCUBEMX_IIC_DMA_AT24C64读取和写入 说明 1、此例程只是从硬件IIC升级到DMA读写因为暂时存储的掉电不丢失数据不多一页就可以够用不用担心跨页读写的问题 2、使用DMA后程序确实是变快了但是也要注意一个问题前一个时刻使用HAL_I2C_Mem_Read_DMA()函数把书从EEPROM读取出来了下一时刻不能着急立马使用读取出来的值因为此时DMA正在从IIC外设往内存中搬运数据要等待DMA搬运完成而使用HAL_I2C_Mem_Read()读取的话就没有这个问题因为他是阻塞性函数只有读取完成了程序才会往下继续执行 1、stmcubemx配置 2、逻辑分析仪捕捉发送和接收的过程更直观
写数据时候 读数据时候
3、应用代码
main.c
int main(void)
{
// SCB-VTOR FLASH_BASE | 0x14000; HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_DMA_Init();MX_I2C1_Init();while (1){}
}eeprom.h
#ifndef __EEPROM_H
#define __EEPROM_H
#include main.h
#include log.h
#include i2c.h
#include string.h#define AT24C64_ADDR 0xA0
#define AT24C64_ADDR_WRITE 0xA0
#define AT24C64_ADDR_READ 0xA1typedef struct eeprom24c64_message
{unsigned char eeprom_flow_number;unsigned char eeprom_pressure_number;unsigned char eeprom_pressure_mode;unsigned char eeprom_buzzer_sound;unsigned short eeprom_air_number;
}eeprom24c64_message_t;extern eeprom24c64_message_t eeprom24c64_data;void eeprom_24c64_init(void);
void eeprom_24c64_task(void);void eeprom_24c64_write(unsigned short addr,unsigned char *data,unsigned short len);
void eeprom_24c64_read(unsigned short addr,unsigned char *data,unsigned short len);
void eeprom_24c64_write_dma(unsigned short addr,unsigned char *data,unsigned short len);
void eeprom_24c64_read_dma(unsigned short addr,unsigned char *data,unsigned short len);#endif
eeprom.c
#include eeprom.heeprom24c64_message_t eeprom24c64_data {0,0,0,0,0};
eeprom24c64_message_t eeprom24c64_data_old {0,0,0,0,0};void eeprom_24c64_init(void)
{eeprom_24c64_read_dma(0x00,(unsigned char *)eeprom24c64_data,sizeof(eeprom24c64_data));HAL_Delay(2);//保证DMA已经把数据从外设搬运到内存中Debug_printf(init eeprom_flow_number:%d\r\n,eeprom24c64_data.eeprom_flow_number);Debug_printf(init eeprom_pressure_number:%d\r\n,eeprom24c64_data.eeprom_pressure_number);Debug_printf(init eeprom_pressure_mode:%d\r\n,eeprom24c64_data.eeprom_pressure_mode);Debug_printf(init eeprom_buzzer_sound:%d\r\n,eeprom24c64_data.eeprom_buzzer_sound);Debug_printf(init eeprom_air_number:%d\r\n,eeprom24c64_data.eeprom_air_number);/********************避免新生产的机器中EEPROM中读出的都是0xff*********************/if(eeprom24c64_data.eeprom_flow_number 0xff) eeprom24c64_data.eeprom_flow_number 0;if(eeprom24c64_data.eeprom_pressure_number 0xff) eeprom24c64_data.eeprom_pressure_number 0;if(eeprom24c64_data.eeprom_pressure_mode 0xff) eeprom24c64_data.eeprom_pressure_mode 0;if(eeprom24c64_data.eeprom_buzzer_sound 0xff) eeprom24c64_data.eeprom_buzzer_sound 0;if(eeprom24c64_data.eeprom_air_number 0xffff) eeprom24c64_data.eeprom_air_number 0;memcpy(eeprom24c64_data_old,eeprom24c64_data,sizeof(eeprom24c64_data));
}void eeprom_24c64_task(void)
{if(memcmp(eeprom24c64_data,eeprom24c64_data_old,sizeof(eeprom24c64_data)) ! 0){eeprom_24c64_write_dma(0x00,(unsigned char *)eeprom24c64_data,sizeof(eeprom24c64_data));HAL_Delay(50);eeprom_24c64_read_dma(0x00,(unsigned char *)eeprom24c64_data,sizeof(eeprom24c64_data));
// eeprom_24c64_read(0x00,(unsigned char *)eeprom24c64_data,sizeof(eeprom24c64_data));
// Debug_printf(/*************************************************************/\r\n);
// Debug_printf(eeprom_flow_number:%d\r\n,eeprom24c64_data.eeprom_flow_number);
// Debug_printf(eeprom_pressure_number:%d\r\n,eeprom24c64_data.eeprom_pressure_number);
// Debug_printf(eeprom_pressure_mode:%d\r\n,eeprom24c64_data.eeprom_pressure_mode);
// Debug_printf(eeprom_buzzer_sound:%d\r\n,eeprom24c64_data.eeprom_buzzer_sound);
// Debug_printf(eeprom_air_number:%d\r\n,eeprom24c64_data.eeprom_air_number);
// Debug_printf(/*************************************************************/\r\n);memcpy(eeprom24c64_data_old,eeprom24c64_data,sizeof(eeprom24c64_data));}
}void eeprom_24c64_write(unsigned short addr,unsigned char *data,unsigned short len)
{if(HAL_I2C_Mem_Write(hi2c1, AT24C64_ADDR_WRITE,addr,I2C_MEMADD_SIZE_16BIT,data,len,100) ! HAL_OK){Debug_error(eeprom_24c64_write fail!!!);}
}void eeprom_24c64_read(unsigned short addr,unsigned char *data,unsigned short len)
{if(HAL_I2C_Mem_Read(hi2c1, AT24C64_ADDR_READ,addr,I2C_MEMADD_SIZE_16BIT,data,len,100) ! HAL_OK){Debug_error(eeprom_24c64_read fail!!!);}
}void eeprom_24c64_write_dma(unsigned short addr,unsigned char *data,unsigned short len)
{if(HAL_I2C_Mem_Write_DMA(hi2c1, AT24C64_ADDR_WRITE,addr,I2C_MEMADD_SIZE_16BIT,data,len) ! HAL_OK){Debug_error(eeprom_24c64_write_dma fail!!!);}
}void eeprom_24c64_read_dma(unsigned short addr,unsigned char *data,unsigned short len)
{if(HAL_I2C_Mem_Read_DMA(hi2c1, AT24C64_ADDR_READ,addr,I2C_MEMADD_SIZE_16BIT,data,len) ! HAL_OK){Debug_error(eeprom_24c64_read_dma fail!!!);}
}预告一下跨页写入的算法 #define EEP_MAX_PAGE_SIZE 32 // 最大页写字节数
#define EEP_MAX_ROM_SIZE 8192 // EEROM容量
#define EEP_ADDR_SIZE 2 // EEROM地址字节数#define EEP_WRITE_DELAY_TIME (OS_TICKS_PER_SEC/10)#define SYS_HEAD_LEN 7 // 参数版本号,如果EEPROM中的参数版本号和程序中不同则更新参数
// EEPROM各地址分配
#define SYS_HEAD_ADDR 0 // 是否第一次运行标志地址
#define SYS_INFO_ADDR 7 // 系统信息保存地址
//#define PHONE_VOLUME_ADDR 199 // 电话音量保存地址
#define CENTER_NUM_ADDR 200 // 中心号码保存地址
#define PHONE_BOOK_NUM 392 // 呼入呼出电话条数,前四位保存呼入条数,后四位保存呼出条数
#define RING_IN_ADDR 393 // 呼入限制电话保存地址
#define RING_OUT_ADDR 852 // 呼出限制电话保存地址
#define VIRTUAL_PHONE_ADDR 1281 // 虚拟号码保存地址
#define AREA_ALARM_ADDR 1292 // 区域报警信息地址/*********************************************************************************************************
** 函数名称: EepromRead
** 功能描述: 读EEPROM处理函数在使用前必须定义最大页写字节数并且定义EEPROM的容量
** 输 入:
** buf:读取数据存放地址
** len:要读取的数据长度
** ptr:EEPROM存储位置
** 输 出: 实际读取的数据数目
********************************************************************************************************/
uint16 EepromRead(uint8 *buf , uint16 len , uint16 ptr)
{uint8 EeromAddr[2];EeromAddr[0] ptr 8;EeromAddr[1] ptr 0xff;return(I2cRead(AT24CXX , buf , EeromAddr , EEP_ADDR_SIZE , len));
}/*********************************************************************************************************
** 函数名称: EepromWrite
** 功能描述: 写EEPROM处理函数在使用前必须定义最大页写字节数并且定义EEPROM的容量
** 输 入:
** buf:所要发的数据
** len:要发的数据长度
** ptr:EEPROM存储位置
** 输 出: 实际所发的数据数目
********************************************************************************************************/
uint16 EepromWrite(uint8 *buf , uint16 len , uint16 ptr)
{uint8 bufTemp[EEP_MAX_PAGE_SIZE EEP_ADDR_SIZE] , i , j 0;uint8 flowSize , flowLen;uint16 sizeTemp , lenTemp 0;if((ptr len) (EEP_MAX_ROM_SIZE - 1)) // EEPROM溢出保护return 0;flowSize ptr % EEP_MAX_PAGE_SIZE;if(flowSize) // 如果不是在页的起点{flowLen EEP_MAX_PAGE_SIZE - flowSize; // 当前页可写长度if(flowLen len) // 所要写的数据将跨页{bufTemp[0] ptr 8; // 地址高位bufTemp[1] ptr; // 地址低位for(i 0;i flowLen;i)bufTemp[i EEP_ADDR_SIZE] buf[i];ptr flowLen; // 下次将写入的地址len - flowLen; // 剩余未写数据的长度sizeTemp I2cWrite(AT24CXX , bufTemp , flowLen EEP_ADDR_SIZE);//本次写入的长度OSTimeDly(EEP_WRITE_DELAY_TIME); // 写入延时lenTemp lenTemp sizeTemp - EEP_ADDR_SIZE;}else//所要写的数据未能跨页{bufTemp[0] ptr 8; // 地址高位bufTemp[1] ptr; // 地址低位for(i 0;i len;i)bufTemp[i EEP_ADDR_SIZE] buf[i];sizeTemp I2cWrite(AT24CXX , bufTemp , len EEP_ADDR_SIZE);OSTimeDly(EEP_WRITE_DELAY_TIME);return (sizeTemp - EEP_ADDR_SIZE); // 完毕返回}}while(len / EEP_MAX_PAGE_SIZE) //剩余未写数据长度仍大于整页长度{bufTemp[0] ptr 8; // 地址高位bufTemp[1] ptr; // 地址低位j lenTemp; for(i 0;i EEP_MAX_PAGE_SIZE;i)bufTemp[i EEP_ADDR_SIZE] buf[j i];ptr EEP_MAX_PAGE_SIZE;j EEP_MAX_PAGE_SIZE; // len - EEP_MAX_PAGE_SIZE;sizeTemp I2cWrite(AT24CXX , bufTemp , EEP_MAX_PAGE_SIZE EEP_ADDR_SIZE);OSTimeDly(EEP_WRITE_DELAY_TIME);lenTemp lenTemp sizeTemp - EEP_ADDR_SIZE;}if(len) // 剩余未写数据长度不足整页长度 {bufTemp[0] ptr 8; // 地址高位bufTemp[1] ptr; // 地址低位j lenTemp; for(i 0;i len;i)bufTemp[i EEP_ADDR_SIZE] buf[j i];sizeTemp I2cWrite(AT24CXX , bufTemp , len EEP_ADDR_SIZE);OSTimeDly(EEP_WRITE_DELAY_TIME);lenTemp lenTemp sizeTemp - EEP_ADDR_SIZE;}return lenTemp; // 返回写入的数据数目
}