完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
用法:在结构体store_config_t内添加想要保存的配置即可,由于是整页擦除,为了不丢失其他配置,保存前需要同步整个store_config_t内容,然后再整体保存。
注意STORE_DATA_SIZE的值要大于store_config_t的大小。 读写配置参考test_flash调用方式。 #define DEF_CFG_VAL_U8 0xFF #define DEF_CFG_VAL_U16 0xFFFF typedef struct store_config_struct { uint8_t enable; uint8_t val_u8; int val_s16; uint16_t val_u16; } store_config_t; int load_config(store_config_t *p_store_cfg); int save_config(store_config_t *p_store_cfg); void test_flash(void); #define FLASH_STORE_ADDR_BASE 0x4700//位于地址末端.4700~47FF共256字节 #define PER_PAGE_SIZE 128 #define EN_OPtiMIZE_XDATA_BUFFER_SIZE #ifndef EN_OPTIMIZE_XDATA_BUFFER_SIZE #define STORE_DATA_SIZE 128 #else #define STORE_DATA_SIZE 16 /*set to sizeof(store_config_t) */ #endif volatile uint8_t xdata page_buffer[STORE_DATA_SIZE]; uint16_t Read_APROM_WORD(uint16_t *read_addr) { uint16_t rdata; uint16_t code *u16_addr = (uint16_t code *)read_addr; rdata = *u16_addr; return rdata; } #ifndef EN_OPTIMIZE_XDATA_BUFFER_SIZE void Write_DATAFLASH_DATA(uint16_t u16EPAddr, uint8_t *src_data_ptr, int src_data_len) { uint8_t looptmp=0; uint16_t u16_addrl_r; uint16_t RAMtmp; if (src_data_ptr == NULL || src_data_len <= 0) { #ifdef ERR_MSG printf("Write_DATAFLASH_DATA: input error!"CRLF); #endif return; } if (src_data_len > STORE_DATA_SIZE) { #ifdef ERR_MSG printf("Write_DATAFLASH_DATA: input error! data len=%u is too big to save!"CRLF, src_data_len); #endif return; } //Check page start address u16_addrl_r=(u16EPAddr/128)*128; //Save APROM data to XRAM0 #if 0 for(looptmp=0;looptmp<0x80;looptmp++) { RAMtmp = Read_APROM_BYTE((uint16_t *)(u16_addrl_r+looptmp)); page_buffer[looptmp] = RAMtmp & 0xFF; } #else for(looptmp=0; looptmp> 8) & 0xFF; page_buffer[looptmp+1] = RAMtmp & 0xFF; } #endif // Modify customer data in XRAM //page_buffer[u16EPAddr&0x7f] = u8EPData; memcpy((page_buffer + (u16EPAddr&0x7f)), (uint8_t *)src_data_ptr, src_data_len); //Erase APROM DATAFLASH page IAPAL = u16_addrl_r&0xff; IAPAH = (u16_addrl_r>>8)&0xff; IAPFD = 0xFF; set_IAPEN; set_APUEN; IAPCN = 0x22; set_IAPGO; //Save changed RAM data to APROM DATAFLASH set_IAPEN; set_APUEN; IAPCN = 0x21; for(looptmp=0;looptmp>8)&0xff; IAPFD = page_buffer[looptmp]; set_IAPGO; } clr_APUEN; clr_IAPEN; } #else void Write_DATAFLASH_DATA(uint16_t u16EPAddr, uint8_t *src_data_ptr, int src_data_len) { uint8_t looptmp=0; uint16_t u16_addrl_r; uint16_t RAMtmp; if (src_data_ptr == NULL || src_data_len <= 0) { #ifdef ERR_MSG printf("flashw: input error!"CRLF); #endif return; } if ((u16EPAddr&0x7f != 0) || (src_data_len > STORE_DATA_SIZE)) { #ifdef ERR_MSG /*u16EPAddr must start of this page */ printf("flashw: input error! data len=%u, target addr=0x%X!"CRLF, src_data_len, u16EPAddr); #endif return; } //Check page start address u16_addrl_r=(u16EPAddr/128)*128; //Save APROM data to XRAM0 for(looptmp=0; looptmp> 8) & 0xFF; if ((STORE_DATA_SIZE - 1) != looptmp) { page_buffer[looptmp+1] = RAMtmp & 0xFF; } } // Modify customer data in XRAM memcpy((page_buffer), (uint8_t *)src_data_ptr, src_data_len); //Erase APROM DATAFLASH page IAPAL = u16_addrl_r&0xff; IAPAH = (u16_addrl_r>>8)&0xff; IAPFD = 0xFF; set_IAPEN; set_APUEN; IAPCN = 0x22; set_IAPGO; //Save changed RAM data to APROM DATAFLASH set_IAPEN; set_APUEN; IAPCN = 0x21; for(looptmp=0;looptmp>8)&0xff; IAPFD = (looptmp < STORE_DATA_SIZE) ? page_buffer[looptmp] : 0xFF; set_IAPGO; } clr_APUEN; clr_IAPEN; } #endif void Read_DATAFLASH_DATA(uint16_t u16EPAddr, uint8_t *ptr, int len) { uint16_t i; uint16_t value; for (i = 0; i < len; i += 2) { value = Read_APROM_WORD((uint16_t *)(u16EPAddr + i)); *(ptr + i) = (value >> 8) & 0xFF; if ((len - 1) != i) { *(ptr + i + 1) = (value) & 0xFF; } } } int load_config(store_config_t *p_store_cfg) { if (!p_store_cfg) { return -1; } Read_DATAFLASH_DATA((uint16_t)(FLASH_STORE_ADDR_BASE), (uint8_t *)p_store_cfg, sizeof(store_config_t)); return 0; } int save_config(store_config_t *p_store_cfg) { if (!p_store_cfg) { return -1; } Write_DATAFLASH_DATA((uint16_t)(FLASH_STORE_ADDR_BASE), (uint8_t *)p_store_cfg, sizeof(store_config_t)); return 0; } void test_flash(void) { store_config_t tmp_store_cfg; tmp_store_cfg.enable = 89; tmp_store_cfg.val_u8 = 0xf1; tmp_store_cfg.val_s16 = -1612; tmp_store_cfg.val_u16 = 0x2F92; save_config(&tmp_store_cfg); memset(&tmp_store_cfg, 0, sizeof(store_config_t)); load_config(&tmp_store_cfg); printf("test_flash: 1 the store config EN=%bu, val_u8=0x%bX, temp=(%d, %X)"CRLF, tmp_store_cfg.enable, tmp_store_cfg.val_u8, tmp_store_cfg.val_s16, tmp_store_cfg.val_u16); tmp_store_cfg.enable = 0; tmp_store_cfg.val_u8 = 0x12; tmp_store_cfg.val_s16 = 0x3789; tmp_store_cfg.val_u16 = 0xE2; save_config(&tmp_store_cfg); memset(&tmp_store_cfg, 0, sizeof(store_config_t)); load_config(&tmp_store_cfg); printf("test_flash: 2 the store config EN=%bu, val_u8=0x%bX, temp=(%X, %X)"CRLF, tmp_store_cfg.enable, tmp_store_cfg.val_u8, tmp_store_cfg.val_s16, tmp_store_cfg.val_u16); tmp_store_cfg.enable = 6; tmp_store_cfg.val_u8 = 0xC3; tmp_store_cfg.val_s16 = 0xFFFF; tmp_store_cfg.val_u16 = 0x3F92; save_config(&tmp_store_cfg); memset(&tmp_store_cfg, 0, sizeof(store_config_t)); load_config(&tmp_store_cfg); printf("test_flash: 3 the store config EN=%bu, val_u8=0x%bX, temp=(%X, %X)"CRLF, tmp_store_cfg.enable, tmp_store_cfg.val_u8, tmp_store_cfg.val_s16, tmp_store_cfg.val_u16); // reset to default tmp_store_cfg.enable = 0; tmp_store_cfg.val_u8 = DEF_CFG_VAL_U8; tmp_store_cfg.val_s16 = DEF_CFG_VAL_U16; tmp_store_cfg.val_u16 = DEF_CFG_VAL_U16; save_config(&tmp_store_cfg); } |
|
相关推荐
1个回答
|
|
下面是一个简单的N76E003模拟EEPROM读取和保存应用配置的示例:
首先,在头文件中定义以下内容: #define STORE_ADDRESS 0x7E00 // 用于保存数据的起始地址,从0x7E00开始 #define STORE_DATA_SIZE 512 // 数据区大小,512字节 #define DEF_CFG_VAL_U8 0xFF // 默认uint8_t类型配置值 #define DEF_CFG_VAL_U16 0xFFFF // 默认uint16_t类型配置值 然后,在代码中定义结构体store_config_t,包含需要保存的配置项: typedef struct { uint8_t enable; // 开关状态 uint8_t val_u8; // uint8_t类型配置值 int val_s16; // int类型配置值 // 添加需要保存的配置项... } store_config_t; 接下来定义读取存储数据和保存数据的函数: void store_read_data(uint8_t *buf, uint16_t len) { IAPEN = 1; // 打开IAPEN位 IAPAL = STORE_ADDRESS & 0xFF; IAPAH = (STORE_ADDRESS >> 8) & 0xFF; IAPFD = 0xFF; IAPCN = READ_AP; // IAP读操作 set_IAPGO; // 启动IAP for (uint16_t i = 0; i < len; i++) { *(buf+i) = IAPFD; } IAPEN = 0; // 关闭IAPEN位 } void store_write_data(uint8_t *buf, uint16_t len) { IAPEN = 1; // 打开IAPEN位 IAPAL = STORE_ADDRESS & 0xFF; IAPAH = (STORE_ADDRESS >> 8) & 0xFF; IAPCN = PAGE_ERASE; // IAP整页擦除操作 set_IAPGO; // 启动IAP for (uint16_t i = 0; i < STORE_DATA_SIZE; i++) { IAPFD = 0xFF; set_IAPGO; } for (uint16_t i = 0; i < len; i++) { IAPCN = PROGRAM_AP; // IAP单字节编程操作 IAPFD = *(buf+i); set_IAPGO; IAPAL++; // 自动递增IAPAL寄存器 if (IAPAL == 0x00) { // 超过一个页的容量,自动跳到下一页 IAPAH++; IAPAL = 0x00; } } IAPEN = 0; // 关闭IAPEN位 } 最后,在main函数中调用store_read_data和store_write_data函数来读取和保存配置: int main(void) { store_config_t store_cfg; uint8_t buf[STORE_DATA_SIZE]; // 读取存储数据 store_read_data(buf, STORE_DATA_SIZE); // 如果存储数据为0xFF,说明没有保存过配置,使用默认值 if (buf[0] == DEF_CFG_VAL_U8 && buf[1] == DEF_CFG_VAL_U8 && buf[2] == DEF_CFG_VAL_U16) { store_cfg.enable = 0; store_cfg.val_u8 = 0; store_cfg.val_s16 = 0; // 初始化其他配置项... } else { memcpy(&store_cfg, buf, sizeof(store_config_t)); } // 同步结构体store_config_t内容 store_cfg.enable = 1; store_cfg.val_u8 = 100; store_cfg.val_s16 = -200; // 同步其他配置项... // 保存存储数据 memcpy(buf, &store_cfg, sizeof(store_config_t)); store_write_data(buf, STORE_DATA_SIZE); while(1); } |
|
|
|
只有小组成员才能发言,加入小组>>
3294 浏览 9 评论
2969 浏览 16 评论
3473 浏览 1 评论
9020 浏览 16 评论
4060 浏览 18 评论
1137浏览 3评论
589浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
579浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2313浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1876浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-3 21:07 , Processed in 1.222451 second(s), Total 84, Slave 63 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号