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

在本教程中,我们将了解使用 pic16f877a 微控制器中的 eeprom 保存数据是多么容易。在大多数实时项目中,我们可能必须保存一些数据,即使关闭电源也不应删除这些数据。这听起来像是一个复杂的过程,但在xc8编译器的帮助下,只需使用一行代码即可完成此任务。如果数据在兆字节方面很大,那么我们可以连接sd卡等存储设备并将这些数据存储在其中。但是,如果数据很小,我们可以避免那些累人的过程,我们可以简单地使用pic微控制器中存在的eeprom来保存我们的数据并随时检索它。
pic16f877a 中的 eeprom:eeprom 代表“电子可擦除和可编程只读存储器”。顾名思义,它是pic微控制器内部的存储器,我们可以通过编程来写入/读取数据。仅当程序中提到这样做时,保存在此中的数据才会被删除。eeprom 中可用的存储空间量因每个微控制器而异;详细信息将照常在数据表中给出。在我们的pic16f877a案例中,可用空间为256字节,如其规格数据表中所述。现在让我们看看如何使用这 256 字节通过简单的实验设置来读/写数据。
电路图及说明:
该项目的电路图如上所示。我们已经连接了一个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的编程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屏幕上看到之前保存的值。
#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 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;
}

适用于下一代大功率应用的XHP™2封装
硬件滤波器设计,这些参数你注意到了吗?
LTC2207在S3C2440和EP3C25控制下的采集应用
践行数字化转型 全面“数智化美的”正破茧而出
TDA9815各引脚功能及电压
如何在PIC16F877A微控制器中使用EEPROM保存数据
汽车线束常见故障与原因
你心爱的合宙IoT Power-CC表来了
吉利科技集团旗下太力飞车Transition(TF-1)获得美国联邦航空局(FAA)适航证书
基于ST 意法半导体SPC572L MCU 和 L9779 驱动器的小型发动机 EFI(电子控制燃油喷射系统)解决方案
五类激光器各自的特点及应用范围
便携式集成微流控生物芯片用于B组链球菌快速诊断
DVCon China | 芯华章受邀出席设计与验证工业级高技术会议
如何用手机摄像头检测贫血
英特尔宣布在以色列增设250亿美元晶圆厂
冲击试验时断路器跳闸故障诊断分析
Ansoft Maxwell软件在小型化真空灭弧室绝缘优化设计中的应用解析
2023CESIS千人峰会 共话电子行业智能化
应急灯电路的工作原理
用LCR表测试无线充电系统中的线圈