0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何在PIC16F877A微控制器中使用EEPROM保存数据

科技观察员 来源:circuitdigest 作者:阿斯文斯·拉吉 2023-01-25 15:39 次阅读

在本教程中,我们将了解使用 PIC16F877A 微控制器中的 EEPROM 保存数据是多么容易。在大多数实时项目中,我们可能必须保存一些数据,即使关闭电源也不应删除这些数据。这听起来像是一个复杂的过程,但在XC8编译器的帮助下,只需使用一行代码即可完成此任务。如果数据在兆字节方面很大,那么我们可以连接SD卡等存储设备并将这些数据存储在其中。但是,如果数据很小,我们可以避免那些累人的过程,我们可以简单地使用PIC微控制器中存在的EEPROM来保存我们的数据并随时检索它。

PIC16F877A 中的 EEPROM:

EEPROM 代表“电子可擦除和可编程只读存储器”。顾名思义,它是PIC微控制器内部的存储器,我们可以通过编程来写入/读取数据。仅当程序中提到这样做时,保存在此中的数据才会被删除。EEPROM 中可用的存储空间量因每个微控制器而异;详细信息将照常在数据表中给出。在我们的PIC16F877A案例中,可用空间为256字节,如其规格数据表中所述。现在让我们看看如何使用这 256 字节通过简单的实验设置来读/写数据。

电路图及说明:

1.png

该项目的电路图如上所示。我们已经连接了一个LCD,以可视化保存和检索的数据。普通电位计连接到AN4模拟通道,因此馈入可变电压,该可变电压将用作要保存在EEPROM中的数据。我们还在RB0上使用了一个按钮,当按下这个按钮时,来自模拟通道的数据将保存在EEPROM中。

这种连接可以在面包板上进行。PIC微控制器的引脚排列如下表所示。

S.No: 引脚编号 引脚名称 已连接到
1 21 RD2 液晶显示器的 RS
2 22 RD3 液晶显示器的E
3 27 RD4 液晶屏D4
4 28 RD5 液晶屏D5
5 29 RD6 液晶屏D6
6 30 RD7 液晶屏D7
7 33 RBO/INT 按钮
8 7 AN4 电位计

模拟使用PIC EEPROM:

该项目还涉及使用 Proteus 设计的模拟,使用它我们可以在没有任何硬件的情况下模拟项目的工作。本教程末尾给出了此模拟的程序。您可以简单地从这里使用十六进制文件并模拟整个过程。

仿真过程中,您可以在LCD屏幕上可视化当前ADC值和保存在EEPROM中的数据。要将当前ADC值保存到EEPROM中,只需按下连接到RB0的开关即可保存。模拟的快照如下所示。

模拟使用PIC EEPROM的方法

EEPROM的编程PIC:

本教程的完整代码在本教程末尾给出。在我们的程序中,我们必须从ADC模块读取值,当按下按钮时,我们必须将该值保存在EEPROM中。由于我们已经了解了ADC和LCD接口,我将进一步解释从EEPROM保存和检索数据的代码。

根据数据表“这些器件具有 4 或 8K 字的程序闪存,PIC16F877A 的地址范围从 0000h 到 1FFFh”。这意味着每个EEPROM存储空间都有一个地址,可以通过该地址访问它,在我们的MCU中,该地址从0000h到1FFFh开始。

要将数据保存在特定的EEPROM地址中,只需使用以下行。

eeprom_write(0,adc);

这里的“adc”是一个整数类型的变量,其中存在要保存的数据。“0”是保存我们数据的EEPROM地址。语法“eeprom_write”由我们的XC8编译器提供,因此编译器将自动处理寄存器

要检索已存储在EEPROM中的数据并将其保存到变量中,可以使用以下代码行。

Sadc = (int)eeprom_read(0);

在这里,“Sadc”是保存来自EEPROM的数据的变量。“0”是我们从中检索数据的EEPROM地址。语法“eeprom_read”由我们的XC8编译器提供,因此编译器将自动处理寄存器。保存在EEPROM中的数据将采用十六进制类型。因此,我们通过在语法前加上 (int) 来将它们转换为整数类型。

加工:

一旦我们了解了代码的工作原理并准备好了硬件,我们就可以测试代码了。将代码上传到 PIC 微控制器并启动设置。如果一切按预期工作,则应在LCD中看到当前ADC值。现在,您可以按下按钮将ADC值保存到EEPROM。现在,您可以通过关闭整个系统并再次打开来检查值是否已保存。开机后,您应该会在LCD屏幕上看到之前保存的值。

PIC16F877A EEPROM 教程

#define _XTAL_FREQ 20000000
#define RS RD2
#define EN RD3
#define D4 RD4
#define D5 RD5
#define D6 RD6
#define D7 RD7
#include
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
//LCD Functions Developed by Circuit Digest.
void Lcd_SetBit(char data_bit) //Based on the Hex value Set the Bits of the Data Lines
{
if(data_bit& 1)
D4 = 1;
else
D4 = 0;
if(data_bit& 2)
D5 = 1;
else
D5 = 0;
if(data_bit& 4)
D6 = 1;
else
D6 = 0;
if(data_bit& 8)
D7 = 1;
else
D7 = 0;
}
void Lcd_Cmd(char a)
{
RS = 0;
Lcd_SetBit(a); //Incoming Hex value
EN = 1;
__delay_ms(4);
EN = 0;
}
void Lcd_Clear()
{
Lcd_Cmd(0); //Clear the LCD
Lcd_Cmd(1); //Move the curser to first position
}
void Lcd_Set_Cursor(char a, char b)
{
char temp,z,y;
if(a== 1)
{
temp = 0x80 + b - 1; //80H is used to move the curser
z = temp>>4; //Lower 8-bits
y = temp & 0x0F; //Upper 8-bits
Lcd_Cmd(z); //Set Row
Lcd_Cmd(y); //Set Column
}
else if(a== 2)
{
temp = 0xC0 + b - 1;
z = temp>>4; //Lower 8-bits
y = temp & 0x0F; //Upper 8-bits
Lcd_Cmd(z); //Set Row
Lcd_Cmd(y); //Set Column
}
}
void Lcd_Start()
{
Lcd_SetBit(0x00);
for(int i=1065244; i<=0; i--) NOP();
Lcd_Cmd(0x03);
__delay_ms(5);
Lcd_Cmd(0x03);
__delay_ms(11);
Lcd_Cmd(0x03);
Lcd_Cmd(0x02); //02H is used for Return home -> Clears the RAM and initializes the LCD
Lcd_Cmd(0x02); //02H is used for Return home -> Clears the RAM and initializes the LCD
Lcd_Cmd(0x08); //Select Row 1
Lcd_Cmd(0x00); //Clear Row 1 Display
Lcd_Cmd(0x0C); //Select Row 2
Lcd_Cmd(0x00); //Clear Row 2 Display
Lcd_Cmd(0x06);
}
void Lcd_Print_Char(char data) //Send 8-bits through 4-bit mode
{
char Lower_Nibble,Upper_Nibble;
Lower_Nibble = data&0x0F;
Upper_Nibble = data&0xF0;
RS = 1; // => RS = 1
Lcd_SetBit(Upper_Nibble>>4); //Send upper half by shifting by 4
EN = 1;
for(int i=2130483; i<=0; i--) NOP();
EN = 0;
Lcd_SetBit(Lower_Nibble); //Send Lower half
EN = 1;
for(int i=2130483; i<=0; i--) NOP();
EN = 0;
}
void Lcd_Print_String(char *a)
{
int i;
for(i=0;a[i]!='\\0';i++)
Lcd_Print_Char(a[i]); //Split the string using pointers and call the Char function
}
/*****End of LCD Functions*****/
//**ADC FUnctions***//
void ADC_Initialize()
{
ADCON0 = 0b01000001; //ADC ON and Fosc/16 is selected
ADCON1 = 0b11000000; // Internal reference voltage is selected
}
unsigned int ADC_Read(unsigned char channel)
{
ADCON0 &= 0x11000101; //Clearing the Channel Selection Bits
ADCON0 |= channel<<3; //Setting the required Bits
__delay_ms(2); //Acquisition time to charge hold capacitor
GO_nDONE = 1; //Initializes A/D Conversion
while(GO_nDONE); //Wait for A/D Conversion to complete
return ((ADRESH<<8)+ADRESL); //Returns Result
}
//***End of ADC Functions***//
int main()
{
int adc=0; //Variable to read ADC value
int a1,a2,a3,a4; //Variable to split ADC value into char
int Sadc=0; //Variable to read ADC value
int Sa1,Sa2,Sa3,Sa4; //Variable to split ADC value into char
TRISD = 0x00; //PORTD declared as output for interfacing LCD
TRISA4 =1; //AN4 declared as input
TRISB0 = 1;
OPTION_REG=0b00000000;
ADC_Initialize();
Lcd_Start();
Lcd_Clear();
while(1)
{
adc=ADC_Read(4); //Read ADC
//**Display ADC**//
a1 = (adc/1000)%10;
a2 = (adc/100)%10;
a3 = (adc/10)%10;
a4 = (adc/1)%10;
Lcd_Set_Cursor(1,1);
Lcd_Print_String("ADC:");
Lcd_Print_Char(a1+'0');
Lcd_Print_Char(a2+'0');
Lcd_Print_Char(a3+'0');
Lcd_Print_Char(a4+'0');
//**Display SADC**//
Sa1 = (Sadc/1000)%10;
Sa2 = (Sadc/100)%10;
Sa3 = (Sadc/10)%10;
Sa4 = (Sadc/1)%10;
Lcd_Set_Cursor(2,1);
Lcd_Print_String("Saved ADC:");
Lcd_Print_Char(Sa1+'0');
Lcd_Print_Char(Sa2+'0');
Lcd_Print_Char(Sa3+'0');
Lcd_Print_Char(Sa4+'0');
/*These devices have 4 or 8K words of
program Flash, with an address range from 0000h to
1FFFh for the PIC16F877A*/
if (RB0==0)
{eeprom_write(0,adc);}
Sadc = (int)eeprom_read(0);
Lcd_Set_Cursor(1,1);
Lcd_Print_String("ADC:");
}
return 0;
}
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 微控制器
    +关注

    关注

    48

    文章

    6813

    浏览量

    147670
  • PIC16F877A
    +关注

    关注

    2

    文章

    43

    浏览量

    21689
  • EEPROM
    +关注

    关注

    9

    文章

    928

    浏览量

    80348
收藏 人收藏

    评论

    相关推荐

    如何使用PIC微控制器旋转步进电机

    在本教程中,我们将步进电机与PIC微控制器PIC16F877A连接。
    发表于 11-15 17:25 1111次阅读
    如何使用<b class='flag-5'>PIC</b><b class='flag-5'>微控制器</b>旋转步进电机

    谁有pic16f877a中文资料?

    谁有pic16f877a中文资料? 
    发表于 07-15 13:22

    PIC16F877A

    菜鸟想问下各位,我想用PIC16F877A做个流水灯,所有端口输出高电平1S,然后输出低电平1s 。 单片机放在学习板上测试的时候是正常的,用prpteus仿真也正常,可是放到电路板上就不正常了,低电平时间很短,Led只是闪了一下。  哪位高手指点一下是什么原因,还是要怎样测试找出问题?
    发表于 07-28 14:32

    PIC16F877A在proteus中读写AT24C512

    此时把I2C DEBUGGER的SCL线连接到PIC16F877A和AT24C512的SCL线上,这样PIC16F877A可以正常的写AT24C512。当PIC16F877A发送启动信号且正常启动
    发表于 12-30 16:09

    PIC16F877A使用宏定义读写FlashROM

    MPLAB IDE v8.80PICC9.83读写PIC16F877A内部的EEPROM时可以使用头文件中的两个宏定义EEPROM_READ(unsigned char addr
    发表于 12-31 14:01

    PIC16F877A的中断优先级问题

    现在我需要通过串口来接收指令控制PIC16F877A的捕获脉冲行为,可以做到的是:接收到开捕获指令后,能正常开始捕获脉冲,但是再发送关闭指令却不能让它停下来,通过KIT3发现,在捕获的时候,串口不能
    发表于 06-06 21:18

    PIC16F877A中的EEPROM错误

    海都。我用C语言编写了一个简单的内部EEPROM程序,使用MPLAB和高技术C编译。在PIC16F877 A中,EEPROM为256字节。
    发表于 06-11 15:11

    PIC16F877A复位问题

    嗨,我还是新手,但是我有一个使用PIC16F877a的倒计时计划,而不是运行一个4位数的7段显示,并有5个按钮来选择倒计时的时间。在倒计时结束时,它发出3次哔哔声。它运行得很完美,但是会产生随机
    发表于 04-01 09:39

    pic16f877A的C语言电机控制,基于PIC16F877A单片机软件环分的步进电机控制系统.pdf 精选资料分享

    基于PIC16F877A单片机软件环分的步进电机控制系统产品与应用基PICl6F877A单片机软件于环 分的步进电机控制系统田丰果 贺莹武淑娟(贵州大学机械工程与自动化学院,贵阳 55
    发表于 09-01 08:39

    PIC16F877A单片机相关资料下载

    PIC16F877A单片机(配置字)1 MPLAB X V5.0,编译为XC8(V2.0)2MPLAB V5.0,编译为PICC1 MPLAB X V5.0,编译为XC8(V2.
    发表于 11-24 08:22

    PIC16F877A看门狗定时实验的相关资料推荐

    //*******************PIC16F877A 看门狗定时实验*******************// //PORTA,PORTB,PORTC,PORTD,PORTE复位时为输入
    发表于 11-25 07:52

    pic16f877a中文资料pdf

    pic16f877a中文资料
    发表于 07-15 13:20 4542次下载
    <b class='flag-5'>pic16f877a</b>中文资料pdf

    基于PIC16F877A的太阳能与市电互补照明系统控制器的设

    基于PIC16F877A的太阳能与市电互补照明系统控制器的设计 介绍了一款以单片机PIC16F877A控制核心的太阳能与市电互补照明系统控制器
    发表于 04-10 22:06 1276次阅读
    基于<b class='flag-5'>PIC16F877A</b>的太阳能与市电互补照明系统<b class='flag-5'>控制器</b>的设

    何在PIC16F877A微控制器中使用中断

    在本教程中,我们将学习如何 在PIC微控制器中使用外部中断 ,以及为什么/在哪里需要它们。
    的头像 发表于 01-25 15:32 1240次阅读
    如<b class='flag-5'>何在</b><b class='flag-5'>PIC16F877A</b><b class='flag-5'>微控制器</b><b class='flag-5'>中使</b>用中断

    PIC16F877A开发板原理图

    PIC16F877A开发板原理图免费下载。
    发表于 03-21 15:47 8次下载