E-Lock 之数据存储(1)

一、简介

图1-1 电子锁

 

早期,电子锁是一种通过密码输入控制电路或者芯片工作,从而控制机械开关的闭合,完成开锁、闭锁任务的电子产品。但随着科技的发展与人们对产品便捷多功能的需求,电子锁也迎来了蓬勃的发展。目前,电子锁不在是单一的密码开锁,而是融合了指纹、卡片、人脸识别多种技术来丰富电子锁的功能。一般,选用一种 MCU 芯片作为电子锁的主控芯片,再通过芯片的外设对各种外搭模块进行控制,从而完成电子锁的各种功能。而开锁的密码、指纹、卡片、开锁等信息都需要能够长久存储,由于 MCU 的 Flash 存储器是一种长寿命的非易失性(在断电情况下仍然能保存所存储的数据)的存储器,因此这些数据都会存储在主控 MCU 的 Flash 里,下面以 LPC54101 为主控芯片、外搭密码指纹卡片模块作详细介绍。

 

二、数据存储区域划分

图2-1 LPC54101 Flash 数据表

 

首先我们要对主控芯片的 Flash 的大小、分区情况详细了解,如 LP54101 芯片,Flash大小共有 512K,分为 16 个扇区,编号 0—15,每个扇区分为 128 页,每页有 256 字节,最小修改字节是 256 字节。然后大概估算程序代码所需空间及所有存储数据的空间,先大致分为代码区和数据区,之后再对数据区做详细规划,以 LPC54101 为例,可先分代码区和数据区各 256K。之后再计算出每个模块的数据总量,划分存储范围。 如指纹每个需 2K,共需要 100 个,总占内存 200k;卡片每张占 16 字节,共需要 100 张卡片,总占内存 7*256 字节;密码每个占 16 字节,共需要 10 个密码,总占 160 字节;开锁记录每条 9 字节,共需要 500 条,总占内存 4500 字节,计算出各模块总内存后,需注意该芯片 Flash的最小修改字节为 256 字节,所以规划的各模块空间必须是 256 的倍数,然后规划各模块起始地址及大小,这样总体内存就规划好了,之后再根据编程问题及客户需求作修改即可。

 

  • SDK 驱动函数介绍(详情可查阅 LPC54101 官方驱动库文件)

 

  1. status_t FLASHIAP_PrepareSectorForWrite(uint32_t startSector, uint32_t endSector)

该函数是准备写函数,功能是用于在调用写函数或擦除函数之前必须先调用此函数,否则写函数或擦除函数会出错。参考变量 startSector  是起始扇区编号, endSector 是末尾扇区编号,注意起始扇区编号需小于等于末尾扇区编号。

 

  1. status_t FLASHIAP_CopyRamToFlash ( uint32_t dstAddr, uint32_t *srcAddr, uint32_t numOfBytes, uint32_t systemCoreClock )

该函数是写数据函数,功能是把 RAM 里数据复制到 Flash 里,调用此函数前必须调用准备写函数。参考变量 dstAddr 是目标数据地址, srcAddr 是源地址指针, numOfBytes 是数据量,systemCoreClock 是系统时钟大小。

 

  1. status_t IAP_EraseSector(uint32_t startSector, uint32_t endSector, uint32_t systemCoreClock)

status_t IAP_ErasePage(uint32_t startPage, uint32_t endPage, uint32_t systemCoreClock)

这两函数均为擦除函数,前者为擦除扇区,后者用于擦除页。参考变量 startSector 为起始扇区编号,endSector 是末尾扇区编号,startPage 是起始页编号,endPage 是末尾页编号,systemCoreClock 是系统时钟大小。

 

4.status_t IAP_Compare(uint32_t dstAddr, uint32_t *srcAddr, uint32_t numOfBytes)

   该函数是写函数完成后,用于比较写入 Flash 数据和源数据是否一致,用于检测写入是否正确。参考变量 dstAddr 是目标地址,srcAddr 源地址指针,numOfBytes 是写入数据量。

 

   以上介绍的四个函数在把数据存储在 Flash 里都会用到,需要在在编程前彻底掌握这几个函数如何使用。

 

  • 软件编程

 

  1. 编程环境

硬件:LPC54101 芯片开发板,软件:Keil

 

  1. 主要程序代码
 uint8_t     *ptr = NULL;

ptr = malloc(RecordSize);
if (ptr == NULL)
{
#ifdef DEBUG_Sysrecord

printf("failed : malloc(RecordSize)\r\n");
#endif
return 1;
}

memcpy((uint8_t *)ptr,(SysCfg_Type*)pblTemplate,sizeof(SysCfg_Type));
ptr[sizeof(SysCfg_Type)] = SYSTEM_RECORD_DEFAULT_FLAG;



uint32_t s_SectorNum,pagestart;
s_SectorNum=SYSTEM_RECORDADDR/0x8000;
pagestart=s_SectorNum*128+(SYSTEM_RECORDADDR-LOCK_RECORDADDR)/256;

__disable_irq();

FLASHIAP_PrepareSectorForWrite(s_SectorNum, s_SectorNum);
FLASHIAP_ErasePage(pagestart,pagestart, SystemCoreClock);

FLASHIAP_PrepareSectorForWrite(s_SectorNum, s_SectorNum);
FLASHIAP_CopyRamToFlash(SYSTEM_RECORDADDR, (uint32_t *)&ptr[0], RecordSize,
SystemCoreClock);

free(ptr);

__enable_irq();

 

  1. 实验结果

把 SYSTEM_RECORDADDR 源地址的数据与写入 Flash 数据对比,若一致则写入正确。关于写入 Flash 的数据可在 Debugger 下查看,如下图所示,红色框为数据存入 Flash 地址,绿色框为写入数据,未写入数据显示 FF。

 

图4-1 Flash数据

 

  • 总结

 

以上介绍了把数据存储在 Flash 中的基本流程,即先了解主控 MCU 的 Flash 情况;然后对各模块数据划分存储区间;之后为软件编程做准备(了解相关库函数及 Flash 读写规则);最后则编程实现功能。关于以上提供的部分代码只能用于解决只有一份数据写入某个 Flash 地址,之后没有连续数据的情况。关于多份连续数据如何存储入 Flash,可以前往我的 E-Lock 系列博文的下一篇 E-Lock 之数据存储 (2) 中寻找答案。

 

  • 参考文献

 

  1. 《MCUXpresso SDK API Reference Manual_LPC5410x》——NXP 官网

★博文内容均由个人提供,与平台无关,如有违法或侵权,请与网站管理员联系。

★文明上网,请理性发言。内容一周内被举报5次,发文人进小黑屋喔~

评论