1 如何在PIC16F877A微控制器中使用EEPROM保存数据-德赢Vwin官网 网

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

描述

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

PIC16F877A 中的 EEPROM:

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

电路图及说明:

EEPROM

该项目的电路图如上所示。我们已经连接了一个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的开关即可保存。模拟的快照如下所示。

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屏幕上看到之前保存的值。

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;
}
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表德赢Vwin官网 网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分