您的位置 首页 芯闻

单片机中的掉电存储办理

各位单片机程序猿们,在单片机程序设计的时候,经常碰到一些数据的掉电存储问题。往往这些数据量又不是很大,但是操作起来特别麻烦。每次变

各位单片机程序猿们,在单片机程序设计的时分,常常碰到一些数据的掉电存储问题。往往这些数据量又不是很大,可是操作起来特别费事。每次改变数据都得调用存储函数进行读写操作。今日总结一下近几天的思路,对一般单片机的的NV变量的办理给出一个较为便当的操作办法。

一般,咱们的数据都由8,16,32位组成,因而,在此例中,我给出16长度数据的接口函数,旨在标明这种办法的思路。详细读者能够依据自己的运用环境,自己改善。

首要,阐明下笔者的编程习气,笔者在编写单片机C程序的过程中,往往喜爱把程序中触及的东西封装成类似于面向对象思维中的类。把数据结构假想成类的特点,把对相应数据结构操作的函数,假想成类的办法。这种办法在实践编程过程中,往往给自己带来很大的便当。不只思路清晰,并且便于模块化办理自己的程序。

现在,咱们创立两个文件,分别为NV.h和NV.C,h文件作为NV办理的模块。NV.h中咱们来界说NV变量的数据结构(即笔者所以为的类的特点)和声明对NV操作的函数。
#ifndef _NV_
#define _NV_

//NV操作的状况界说
#define NV_Succeed 1

#defineNV_Failed 0
//界说16位长度的NV变量数据结构

structNV_Struct16
{
u16 Val; //NV16变量的值
u16 NVAddr; //NV16变量在存储器中的首地址
};
//声明外部调用函数
extern void NV16_Get(struct NV_Struct16 *temp);
u8 NV16_Set(struct NV_Struct16 *temp,u16 val);
#endif

在NV_Struct16中,咱们封装了一个叫做NV16的变量,其成员中有变量的值和在存储器中的首地址。在这里,仅仅给它界说了一个数据的结构,并没有界说实体变量,在C++或C#等面向对象程序设计办法中,这叫类的界说,并没有创立类的实体。这样做的意图,便是做到尽量把咱们这个NV操作模块从咱们编写的其他应用程序中笼统出来。

那么,接下来,咱们就来编写NV16变量的操作函数。在NV.C中,咱们增加两个函数,一个是获取NV变量的值,另一个是修正NV变量的值。

#include”NV.h”
#include”24CXX.h”
#defineCheckTimes 4 //写入时校验次数
#defineNV8_Enable 1 //NV8使能开关
#defineNV16_Enable 1 //NV16使能开关
#defineNV32_Enable 1 //NV32使能开关

//以下是NV_Struct16的操作函数

#ifNV16_Enable
voidNV16_Get(struct NV_Struct16 *temp)
{
temp->Val=AT24CXX_ReadLenByte(temp->NVAddr,2);
}
u8NV16_Set(struct NV_Struct16 *temp,u16 val)
{
u8 cnt=0;
if(temp->Val==val)returnNV_Succeed;
temp->Val=val;
AT24CXX_WriteLenByte(temp->NVAddr,temp->Val,2);
while(cntNVAddr,2)!=temp->Val)
cnt++;
if(cnt else return NV_Succeed;
}

#endif
在这个文件中,咱们调用了一个24CXX.h文件中供给的24CXX的读写函数,这部分在咱们移植的过程中是需求考虑的。下面贴出这个函数的原型,假如这个都不知道怎样写出来,那我也无语了。

//在AT24CXX里边的指定地址开端读出长度为Len的数据
//该函数用于读出16bit或许32bit的数据.
//ReadAddr :开端读出的地址
//返回值 :数据
//Len :要读出数据的长度2,4
u32AT24CXX_ReadLenByte(u16 ReadAddr,u8 Len)
{
u8 t;
u32 temp=0;
for(t=0;t {
temp<<=8;
temp+=AT24CXX_ReadOneByte(ReadAddr+Len-t-1);
}
return temp;
}

//在AT24CXX里边的指定地址开端写入长度为Len的数据
//该函数用于写入16bit或许32bit的数据.
//WriteAddr :开端写入的地址
//DataToWrite:数据数组首地址
//Len :要写入数据的长度2,4
voidAT24CXX_WriteLenByte(u16 WriteAddr,u32 DataToWrite,u8 Len)

{
u8 t;
for(t=0;t {
AT24CXX_WriteOneByte(WriteAddr+t,(DataToWrite>>(8*t))&0xff);
}
}

用以上办法来办理咱们的NV变量,在程序中会大大地削减咱们的工作量。下面来举一个简略的比如。记载设备开机次数,并从串口打印出来。
#include “相关头文件”
#include “NV.H”

#define Flag 0x33 //存储器初始化标志
#define FlagAddr 0x00
#define PowerOnTimesAddr 0x10 //将开机次数数据存储在0x10方位
//创立NV16非易失变量实体
struct NV_Struct16 PowerOnTimes;
struct NV_Struct16 MemFlag;

void NV_Init()
{
//NV地址装入
MemFlag.NVAddr=FlagAddr;
PowerOnTimes.NVAddr=PowerOnTimesAddr;
//查看存储器是否初始化
if(NV16_Get(&MemFlag)!=Flag)
{
NV16_Set(&MemFlag,Flag);
NV16_Set(&PowerOnTimes,0);
}
}

void main()
{
u16 times;
NV_Init();
times=NV16_Get(&PowerOnTimes);
NV16_Set(&PowerOnTimes,times++);
printf(“%d”,times);
while(1);
}
哈哈,这姿态,你的应用程序是不是很简练呀。喜爱那就测验下吧!

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/news/xinwen/318515.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部