辉芒微教程第四篇《EEPROM-断电记忆开关状态》

辉芒微教程第四篇《EEPROM-断电记忆开关状态》

目录

一、本节课目标

二、电路原理

三、编程

(1)任务1:实现按键开关灯

(2)任务2:实现EEPROM的读写

(3)任务3:断电保存灯的开关状态

四、最后注意事项

第0篇: 辉芒微开源电路板链接.立创PCB

第1篇: 辉芒微教程第一篇《软件的安装与程序下载》

第2篇: 辉芒微教程第二篇《程序基本结构与点灯,延时函数》

第3篇: 辉芒微教程第三篇《IO口输入设置与按键切换继电器状态》

第4篇: 辉芒微教程第四篇《EEPROM-断电记忆开关状态》

第5篇: 辉芒微教程第五篇《定时器0实现LED灯的闪烁》

第6篇: 辉芒微教程第六篇《定时器1和定时器2多个定时器混用》

第7篇: 辉芒微教程第七篇《PWM是什么与PWM3调节LED灯的亮度》

第8篇: 辉芒微教程第八篇《PWM4/PWM5调节舵机的角度》

第9篇: 辉芒微教程第九篇《模拟串口打印数据》

第10篇:辉芒微教程第十篇《串口打印实战-EEPROM记忆日志数据打印》

第11篇:辉芒微教程第十一篇《ADC读取电压数据并且打印出来》

第12篇:辉芒微教程第十二篇《睡眠模式与待机省电计算》

第13篇:辉芒微教程第十三篇《按键外部中断唤醒》

第14篇:辉芒微教程第十四篇《IIC协议与读写24C02》

第15篇:辉芒微教程第十五篇《SPI协议与读取W25Q64》

第16篇:辉芒微教程第十六篇《IR红外发射》

第17篇:辉芒微教程第十七篇《IR红外接收》

第18篇:辉芒微教程第十八篇《防芯片运行宕机-看门狗》

第19篇:辉芒微教程第十九篇《有用的废话篇-项目综合开发的书写习惯》

第20篇:辉芒微教程第二十篇《有用的废话篇-怎么进行辉芒微软件上的量产工作》

第21篇:辉芒微教程第二十一篇《有用的废话篇-芯片选型+获取资料+如何读数据手册》

前言

EEPROM作为一个断电不会丢失的数据的单片机功能,在有些产品中起到很重要的功能,假设客户要求你的产品能够进行断电保存记忆,比如你做一个电机产品,它现在是运行的,但是设备断电了,客户要求来电的时候,如果设备断电前是开着的,那么来电的时候就要打开电机运行。那这时候EEPROM就起到很重要的功能了!!!

(此段新手能理解就理解,不能理解就算了)做过STM32的老表一般会把这种数据保存到Flash中,但是每次写入都不是一个个字节写入,而是先擦除几百字节或者上千字节,再一个个写入,这样写入很不方便,因为需要建立一个很大的数组(不然会擦除其他数据),这样就很占运行内存,特别是8位单片机这种,并且我也不需要保存那么多数据,不过辉芒微相对于其他国外或者国产单片机就非常有优势,芯片内置EEPROM,无需额外购买EEPROM,并且它可以实现一个个写入,这样就很省运行空间了!

一、本节课目标

掌握辉芒微EEPROM的使用,并且实现断电记忆灯的开关状态。

二、电路原理

我们的KEY键接在PC2上,直接接地,需要做软件消抖,我们的LED接着PC4上,需要使用高电平点亮,低电平熄灭。

三、编程

(1)任务1:实现按键开关灯

#include "SYSCFG.h" //这个芯片的必要头文件

/*-------------------------------------------------

* 函数名称:DelayUs

* 功能: 短延时函数 --16M-2T--大概快1%左右.

* 输入参数:Time延时时间长度 延时时长Time us

* 返回参数:无

-------------------------------------------------*/

void DelayUs(unsigned char Time)

{

unsigned char a;

for(a=0;a

{

NOP();

}

}

/*-------------------------------------------------

* 函数名称:DelayMs

* 功能: 短延时函数

* 输入参数:Time延时时间长度 延时时长Time ms

* 返回参数:无

-------------------------------------------------*/

void DelayMs(unsigned char Time)

{

unsigned char a,b;

for(a=0;a

{

for(b=0;b<5;b++)

{

DelayUs(197); //快1%

}

}

}

void interrupt ISR(void) //中断函数,本节无需要

{

}

void SingleChipConfig(void) //单片机配置函数

{

OSCCON = 0B01110001; //IRCF=111=16MHz/2T=8MHz,0.125us

INTCON = 0; //暂禁止所有中断

PORTA = 0B00000000;

TRISA = 0B00000000; //PA输入输出 0-输出 1-输入

PORTC = 0B00000000;

TRISC = 0B00000100; //PC输入输出 0-输出 1-输入

WPUA = 0B00000000; //PA端口上拉控制 1-开上拉 0-关上拉

WPUC = 0B00000100; //PC端口上拉控制 1-开上拉 0-关上拉

OPTION = 0B00001000; //Bit3=1,WDT MODE,PS=000=WDT RATE 1:1

MSCKCON = 0B00000000;

//Bit6->0,禁止PA4,PC5稳压输出

//Bit5->0,TIMER2时钟为Fosc

//Bit4->0,禁止LVR

CMCON0 = 0B00000111; //关闭比较器,CxIN为数字IO口

ANSEL = 0B00000000;

}

void main(void) //主函数

{

SingleChipConfig();

while(1)

{

if(!PC2)

{

DelayMs(50);

if(!PC2)

{

PC4 = !PC4;

while(PC2 == 0)

{

};

}

}

}

}

这个程序跟上节课差不多,不理解的朋友可以看上一篇章,接下来我们可以看一下效果;

DJI

(2)任务2:实现EEPROM的读写

void Eeprom_Write(unsigned char address,unsigned char value)//EEPROM写函数

{

CLRWDT();

EEADR = address;

asm("nop");

EEDAT = value;

EECON1 = 0x34;

WR = 1;

asm("nop");

asm("nop");

asm("nop");

while(WR==1)CLRWDT();

WREN1 = 0;

WREN2 = 0;

WREN3 = 0;

}

unsigned char Eeprom_Read(unsigned char address)//EEPROM读函数

{

unsigned char EepromData;

CLRWDT();

EEADR = address;

RD = 1;

EepromData = EEDAT;

RD = 0;

return(EepromData);

}

这个是EEPROM的写函数和读函数,其在辉芒微系列的8位单片机中,基本通用,其中的address是需要操作的地址,因为我们的芯片的EEPROM大小是256字节,因此其地址为0-255(对应16进制地址是0x00-0xff);

在编程软件里面,我们可以看到其EEPROM的初始化地址

由此看出,该芯片的EEPROM有256字节,默认每个字节的初始化大小为0xff,我们可以对单独的某个字节进行写入。

现在我们实验一下,在之前的程序上,加入我们的读写程序,并且程序运行一开始,在地址0xfe写入value值为0x8的数值。

#include "SYSCFG.h" //这个芯片的必要头文件

void Eeprom_Write(unsigned char address,unsigned char value)//EEPROM写函数

{

CLRWDT();

EEADR = address;

asm("nop");

EEDAT = value;

EECON1 = 0x34;

WR = 1;

asm("nop");

asm("nop");

asm("nop");

while(WR==1)CLRWDT();

WREN1 = 0;

WREN2 = 0;

WREN3 = 0;

}

unsigned char Eeprom_Read(unsigned char address)//EEPROM读函数

{

unsigned char EepromData;

CLRWDT();

EEADR = address;

RD = 1;

EepromData = EEDAT;

RD = 0;

return(EepromData);

}

/*-------------------------------------------------

* 函数名称:DelayUs

* 功能: 短延时函数 --16M-2T--大概快1%左右.

* 输入参数:Time延时时间长度 延时时长Time us

* 返回参数:无

-------------------------------------------------*/

void DelayUs(unsigned char Time)

{

unsigned char a;

for(a=0;a

{

NOP();

}

}

/*-------------------------------------------------

* 函数名称:DelayMs

* 功能: 短延时函数

* 输入参数:Time延时时间长度 延时时长Time ms

* 返回参数:无

-------------------------------------------------*/

void DelayMs(unsigned char Time)

{

unsigned char a,b;

for(a=0;a

{

for(b=0;b<5;b++)

{

DelayUs(197); //快1%

}

}

}

void interrupt ISR(void) //中断函数,本节无需要

{

}

void SingleChipConfig(void) //单片机配置函数

{

OSCCON = 0B01110001; //IRCF=111=16MHz/2T=8MHz,0.125us

INTCON = 0; //暂禁止所有中断

PORTA = 0B00000000;

TRISA = 0B00000000; //PA输入输出 0-输出 1-输入

PORTC = 0B00000000;

TRISC = 0B00000100; //PC输入输出 0-输出 1-输入

WPUA = 0B00000000; //PA端口上拉控制 1-开上拉 0-关上拉

WPUC = 0B00000100; //PC端口上拉控制 1-开上拉 0-关上拉

OPTION = 0B00001000; //Bit3=1,WDT MODE,PS=000=WDT RATE 1:1

MSCKCON = 0B00000000;

//Bit6->0,禁止PA4,PC5稳压输出

//Bit5->0,TIMER2时钟为Fosc

//Bit4->0,禁止LVR

CMCON0 = 0B00000111; //关闭比较器,CxIN为数字IO口

ANSEL = 0B00000000;

}

void main(void) //主函数

{

SingleChipConfig();

Eeprom_Write(0xfe,0x08);

while(1)

{

if(!PC2)

{

DelayMs(50);

if(!PC2)

{

PC4 = !PC4;

while(PC2 == 0)

{

};

}

}

}

}

当我们编译并且下载到板子的时候,旁边的EEPROM框会变成这样

其中的0xfe的value值变成了0x08,当然,因为我这行代码是放在While外面的,所以它算是程序的初始化,如果你试图在while里面进行动态改变,如果想要查看EEPROM的数值变化,那这样的方式是查看不了的。

那么如果我们调试的程序一定想要看到现在的EEPROM值是多少怎么办呢,方法有很多种,这里我们只介绍一种,我常用的,这里我们就用到我们前面安装的FMDProgrammer软件。我们先在程序里面写一个变量增加,每隔一秒写入一次。然后我们运行了一段时间,再用这个软件进行查看。

我们把上面的while程序变动下:

unsigned char count;

void main(void) //主函数

{

SingleChipConfig();

while(1)

{

if(!PC2)

{

DelayMs(50);

if(!PC2)

{

PC4 = !PC4;

count++;

Eeprom_Write(0xfe,count);

while(PC2 == 0)

{

};

}

}

}

}

每当我们按一下的时候,地址0xfe的value值增加1,记住我们按下去的次数,然后再去这个软件里面读取。

最终我们看到按下11(0x0b)次,具体是多少,要看你们自己按了多少次。

(3)任务3:断电保存灯的开关状态

接下来我们来写本节课的主题程序,即记录按键按下灯的状态到EEPROM中,当设备断电或者开机的时候,可以读取对应的地址值,从而初始化的时候对灯进行开或者关的状态。

#include "SYSCFG.h" //这个芯片的必要头文件

void Eeprom_Write(unsigned char address,unsigned char value)//EEPROM写函数

{

CLRWDT();

EEADR = address;

asm("nop");

EEDAT = value;

EECON1 = 0x34;

WR = 1;

asm("nop");

asm("nop");

asm("nop");

while(WR==1)CLRWDT();

WREN1 = 0;

WREN2 = 0;

WREN3 = 0;

}

unsigned char Eeprom_Read(unsigned char address)//EEPROM读函数

{

unsigned char EepromData;

CLRWDT();

EEADR = address;

RD = 1;

EepromData = EEDAT;

RD = 0;

return(EepromData);

}

/*-------------------------------------------------

* 函数名称:DelayUs

* 功能: 短延时函数 --16M-2T--大概快1%左右.

* 输入参数:Time延时时间长度 延时时长Time us

* 返回参数:无

-------------------------------------------------*/

void DelayUs(unsigned char Time)

{

unsigned char a;

for(a=0;a

{

NOP();

}

}

/*-------------------------------------------------

* 函数名称:DelayMs

* 功能: 短延时函数

* 输入参数:Time延时时间长度 延时时长Time ms

* 返回参数:无

-------------------------------------------------*/

void DelayMs(unsigned char Time)

{

unsigned char a,b;

for(a=0;a

{

for(b=0;b<5;b++)

{

DelayUs(197); //快1%

}

}

}

void interrupt ISR(void) //中断函数,本节无需要

{

}

void SingleChipConfig(void) //单片机配置函数

{

OSCCON = 0B01110001; //IRCF=111=16MHz/2T=8MHz,0.125us

INTCON = 0; //暂禁止所有中断

PORTA = 0B00000000;

TRISA = 0B00000000; //PA输入输出 0-输出 1-输入

PORTC = 0B00000000;

TRISC = 0B00000100; //PC输入输出 0-输出 1-输入

WPUA = 0B00000000; //PA端口上拉控制 1-开上拉 0-关上拉

WPUC = 0B00000100; //PC端口上拉控制 1-开上拉 0-关上拉

OPTION = 0B00001000; //Bit3=1,WDT MODE,PS=000=WDT RATE 1:1

MSCKCON = 0B00000000;

//Bit6->0,禁止PA4,PC5稳压输出

//Bit5->0,TIMER2时钟为Fosc

//Bit4->0,禁止LVR

CMCON0 = 0B00000111; //关闭比较器,CxIN为数字IO口

ANSEL = 0B00000000;

}

void main(void) //主函数

{

SingleChipConfig();

if( Eeprom_Read(0xfe)== 1 )

{

PC4 = 1;

}

else

{

PC4 = 0;

}

while(1)

{

if(!PC2)

{

DelayMs(50);

if(!PC2)

{

PC4 = !PC4;

Eeprom_Write(0xfe,PC4);

while(PC2 == 0)

{

};

}

}

}

}

初始化的if是读取EERPOM地址0xfe的数值,然后对其进行判断,如果返回结果是1则开灯,如果返回结果是0则关灯。

每次按键按下去的时候都会将PC4灯的状态保存到EEPROM中,这样下次设备开机的时候,就可以根据其数据对灯进行反应,我们可以看产品效果:

DJI

四、最后注意事项

不注意有可能做项目的时候自己坑自己哦!

无论是哪个品牌的单片机的EEPROM或者专门的EEPROM芯片,其写入都是有寿命的,不能跟无限制写入,比如我们的单片机,它可写入100K次(100 000次),因此在做项目的时候我们要考虑设备可能使用的次数,说人话就是不能频繁写入,假设我一天写100次,那你这个设备可以支持1000天,如果一天写入1000次,那么最多可写入100天(产品半年不到就可能废了,别逼你客户骂你)。