Escolar Documentos
Profissional Documentos
Cultura Documentos
MEMÓRIA
METODOLOGIA
EEPROM; I2C Serão analisadas as características técnicas da EEPROM
24C02, uma memória externa ao 8051, bem como o ciclo
de vida útil e a estrutura de armazenamento organizada
em índices ou posições de memória. Para comunicação
CONTEÚDO entre o 8051 e a EEPROM será aplicado o protocolo de
PROGRAMÁTICO comunicação I2C abordado em seus aspectos gerais e a
biblioteca i2c.h proverá operações de leitura e escrita na
A memória EEPROM 24C02; memória cujos dados poderão ser conferidos no mapa
de memória em nível de simulação. Para salvar dados
Armazenamento de dados; índices; maiores do que 1 Byte a variável será quebrada em
Comunicação I2C; endereço I2C; A biblioteca i2c.h partes menores para tornar o seu armazenamento
Tags de identificação da string; possível.
Salvando e lendo dados;
A abordagem desta unidade de estudos utiliza a
Visualizando os dados da EEPROM no simulador; programação C para o microcontrolador AT89S52, da
apagando os dados da EEPROM; família MCS-51 ou popularmente chamada de “8051” de
Salvando tipo de dado int; modo que as informações salvas na EEPROM 24C02
sejam exibidas em display LCD 16x2. Depois a atividade
Tipos de dados em C;
é realizada com a programação C para o
flag carryout; microcontrolador PIC16F877A da família PIC 16F que
Avaliação: Entrega das Atividades propostas com dispõe de memória EEPROM interna.
memória EEPROM;
RECURSOS
Para desenvolver e experimentar este material é
necessário um computador com sistema operacional
APRESENTAÇÃO Windows XP ou posterior e baixar o pacote de
programas disponível em www.u8051.com.br o qual
Nesta unidade de estudos vamos conhecer o
contém as seguintes ferramentas de desenvolvimento:
funcionamento e a aplicação da memória EEPROM
Compilador 8051 (JFE Editor), Compilador PIC (PCW),
necessária para salvar informações antes do circuito ser
Software de simulação Proteus-ISIS.
desligado. Este componente tem como finalidade salvar
e recuperar valor de variáveis, senhas, configurações do
sistema, etc.
AVALIAÇÃO DE DESEMPENHO
As variáveis são alocadas na memória RAM do A secção ATIVIDADES PROPOSTAS apresenta um
microcontrolador e quando o sistema é desligado esses conjunto de exercícios de dificuldade incremental a fim
dados de execução são perdidos. Muitas aplicações não de avaliar o seu entendimento a cerca desta unidade de
podem perder os dados de execução, isto é, o sistema estudos.
precisa retomar o funcionamento a partir do ponto em
que estava antes da queda de energia, com a mesma
senha, os mesmos ajustes, por exemplo. Por isso, a
memória EEPROM se torna alternativa para reter os
RESULTADOS ESPERADOS
dados do sistema e recupera-la, mesmo que o sistema Ao concluir o desenvolvimento das atividades propostas,
permaneça desligado por anos. você deverá ser capaz de utilizar a memória EEPROM
para salvar e recuperar dados nestes modelos de
microcontroladores.
ID 208
ID 160
Fig. 3: Dois
1.1 dispositivos
Índice destino
char cont=26;
1.2 save_i2c(160, 0, cont);
ESQUEMÁTICO 8051 E /* P RO G R AM A 1 */
EEPROM 24C02
#include<at89x52.h>
#include<lcd.h>
#define BT_AVANCAR P3_2
#define BT_SOMAR P3_3
O circuito da figura 4 apresenta a conexão entre o #define EEPROM 160
microcontrolador e a memória. O Display LCD será utilizado #define sda P2_6
para exibir as operações de leitura e escrita na EEPROM. #define scl P2_7
#include<i2c.h>
void atualizaLCD();
void atualizaCursor();
void leMemoria();
//******************************
void main(){
leMemoria();
lcd_init();
atualizaLCD();
atualizaCursor();
while(1)
{
if(BT_SOMAR==0 && b1==0)
{
b1=1;
if(indice==0)
{
horaL++;
if(horaL>23) horaL=0;
save_i2c(EEPROM, 0, horaL);
}
if(indice==1)
{
minL++;
save_i2c(EEPROM, 1, minL);
}
atualizaLCD();
}
if(BT_SOMAR==1) b1=0;
1.7
VISUALIZANDO OS DADOS
1.6 DA EEPROM NO ISIS
EVENTO CLIQUE
Durante a simulação é possível visualizar os dados Armazenados
Observe que no programa 1 a definição BT_SOMAR equivale ao na memória EEPROM.
I/O P3.3. Para saber se o botão foi pressionado, o teste “if”
verifica respectivo I/O está em nível 0.
1.9 while(1)
{
VETORES EM C if(BT_SOMAR==0 && b1==0)
{
b1=1;
Um vetor é uma variável indexada, ou seja, comporta várias if(indice<8) //ajustando numero
informações do tipo de dado em que o vetor é declarado. {
num[indice]++;
Considere a seguinte declaração:
if(num[indice]>NUM_MAX)
{
char num[8]={5,1,9,9,6,0,2,6}; num[indice]=NUM_MIN;
}
O vetor num têm 8 índices e cada um armazena um dado do save_i2c(EEPROM, indice, num[indice]);
}
tipo char. Assim temos no vetor num os índices 0 ao 7 conforme else //ajustando nome
o exemplo abaixo. {
nome[indice-8]++;
num[0]
num[1]
num[2]
num[3]
num[4]
num[5]
num[6]
num[7]
if(nome[indice-8]>'E')
{
nome[indice-8]='A';
}
char num[8]={5 , 1 , 9 , 9 , 6 , 0 , 2 , 6 }; save_i2c(EEPROM, indice, nome[indice-8]);
}
atualizaLCD();
}
if(BT_SOMAR==1) b1=0;
Você pode sempre poderá conferir os dados que estão salvos Para recuperar o dado é preciso ler e “unir” os valores destes
na EEPROM. Para isso veja o tópico 1.7. mesmos índices aplicando multiplicação “*” e soma “+”.
0 1 2 3
1 (01) 44 (2C)
x 256 +
256 + 44 = 300
0 1 2 3
Quando a janela do mapa de memória for exibida, você poderá 255 (FF) 255 (FF)
ajustar o tamanho da fonte clicando nela com o botão direito e
x 256 +
escolhendo a opção Set Font.
65280 + 255 = 65535
FUNCIONAMENTO DO PROGRAMA 2
Vamos analisar o funcionamento do Programa 2 considerando O programa 3 utiliza os índices 0 e 1 da EEPROM para salvar a
que você já entendeu o Programa 1. Ao todo são 8 dígitos do variável int cont.
telefone e 4 dígitos para o nome, totalizando a navegação entre
11 campos de dados no LCD. Temos como referência a variável /* P RO G R AM A 3 */
indice.
SALVANDO DADO DE 16 }
atualizaLCD();
int cont=20000; 3
O parâmetro da função deverá ser: exibeInt(int variável) Digitar e compilar o programa 3 no software JFE;
Simular o programa 3 em conjunto com o esquemático
unsigned int cont=60000; da figura 4;
Parâmetro da função: exibeInt(unsigned int variável) Acrescentar a tecla ZERA conectada em P3.4;
Alterar o contador para suportar contagens até 50000,
long int cont=90000; bem como salvar essa faixa de valores;
Parâmetro da função: exibeInt(long int variável) Desafio supremo: exibir e salvar contagem até 99999
utilizando a variável long int cont. Dica: você usará os
Ao ler uma posição de memória você dever armazenar o dado valores /65536, /256%256 para salvar o dado em 3
numa variável que tenha essa capacidade de armazenamento. posições da memória EEPROM.
1.13
FLAG CARRYOUT
Quando tentamos executar uma operação de soma cujo
resultado seja maior do que a capacidade de armazenamento
da variável de destino, ocorre o “vai um” ou carryout flag (CY).
0 1 2 3
4 7
5 6
(dado: 25)
8 9 ... 255
FUNÇÕES DE ACESSO DA
3.2
EEPROM INTERNA DO PIC
O código seguir demonstra a leitura do índice 7 na EEPROM do
PIC:
índice
char cont;
cont=read_eeprom(7);
Comando Efeito
write_eeprom(índice, variável); Salva variável
no índice
variável=read_eeprom(índice); Busca dado
salvo no índice
int1 b1,b2;
signed char horaL, minL, horaD, minD, indice;
void atualizaLCD();
void atualizaCursor();
void leMemoria();
//******************************
void main()
{
set_tris_C(0b00000111);
leMemoria();
lcd_init();
atualizaLCD();
atualizaCursor();
while(1)
{
Engenharia Curso de microcontrolador online pic 8051 programação jfe pic c compiler projeto s microgenios gravador cu scopic aeci sp progisp u sbasp atmega Arduino faculdade unisinos feeva le.br pucrs ufrgs uninter faccat ita unisanta unoe ste anhanguera usp unesp feec feelt ufrj pucminas unitaumaua ime unopar fam ufsc pucpr fei fatec uninove ead uniceug
Anchieta uceff ufpel rogercom ufal edu br fpb up unifacs fatecpr feitep univap fen/ufg famen dombosco utfpr cefet uni pifam senai impacta unilasalle uva uc s.br unifor upe.br unig.br ifrs.edu.br
Observe que quando os I/O’s do PIC são utilizados para leitura if(input(AVANCAR)==0 && b2==0)
de sensores de contato (as teclas), os I/O’s utilizados devem ser {
configurados como input através da função set_tris. Por isso, b2=1;
esses I/O’s ficam em coletor aberto ou tristate, necessitando de indice++;
resistores pull up R1 e R2 para definir o estado lógico 1 destas if(indice>3) indice=0;
“entradas” de teclas. Veja a tabela 12. atualizaCursor();
}
Este esquema foi desenhado no software Proteus-ISIS versão 7
if(input(AVANCAR)==1) b2=0;
ou posterior utilizando os seguintes componentes:
}
Referência Componente }
PIC16F877A Microcontrolador PIC16F877A //******************************
LM016L Display LCD 16x2 void atualizaLCD()
BUTTON Botões AVANCAR e SOMAR {
lcd_cursor(0);
RES Resistor 4K7
lcd_gotoxy(1,1);
printf(lcd_putc, "LIG %02i:%02i", horaL, minL);
lcd_gotoxy(2,1);
Uma versão portátil deste
simulador pode ser printf(lcd_putc, "DES %02i:%02i", horaD, minD);
executada a partir da pasta atualizaCursor();
8051\ISIS77\BIN\ISIS.EXE }
//******************************
Figura 11: Executando o void atualizaCursor()
Simulador ISIS {
if(indice==0) lcd_gotoxy(1,6);
if(indice==1) lcd_gotoxy(1,9);
A biblioteca lcd.h comunica com o PIC através do PORT B, mas
esta definição pode ser editada dentro da biblioteca se //if(indice==2) lcd_gotoxy(?,?);
necessário. Para incluir o protocolo de comunicação com o LCD //if(indice==3) lcd_gotoxy(?,?);
você verá a declaração da biblioteca lcd.h na seguinte ordem: lcd_cursor(1);
}
#include<16F877A.h> //******************************
#fuses nowdt, nobrownout, xt, noput, noprotect void leMemoria()
#use delay(clock=4000000) {
#include<lcd.h> //busca na EEPROM as variaveis
horaL=read_eeprom(0);
minL=read_eeprom(?);
3.4 PROGRAMAÇÃO //horaD=read_eeprom(?);
A seguir temos a programação para o //minD=read_eeprom(?);
circuito da figura 10: ela permite ajustar os //Fig. 12: Tela do }
parâmetros de um temporizador: horário de programa 4
ligar e o horário de desligar um dispositivo
elétrico. Na figura 12 temos um exemplo de
execução o programa.
u8051.com.br MEMÓRIA EEPROM - Página 9/12
O funcionamento do programa 4 está detalhado no item 1.5, //******************************
mas o compilador aqui utilizado para o PIC é o PIC-C Compiler void atualizaLCD(){
que implementa algumas funções para manipular os I/O’s do char i;
microcontrolador. São elas: lcd_cursor(0);
lcd_gotoxy(1,1);
set_tris_IO(0bXXXXXXX); //IO é o PORT (A,B,C,D ou E) for(i=0;i<8;i++) lcd_putc(num[i]+48);
lcd_gotoxy(2,1);
for(i=0;i<4;i++) lcd_putc(nome[i]);
No PIC você deve especificar os I/O’s que serão utilizados como atualizaCursor();
entrada de dados (leitura de botões). A instrução set_tris define }
a direção dos dados sendo 0=Output e 1=Input. //******************************
void atualizaCursor(){
Comando em binário literal: set_tris_C(0b00000111); if(indice<8)lcd_gotoxy(1, indice+1);
Efeito: C7, C6, C5 e C4 são saídas. C3, C2, C1 e C0 são entradas else lcd_gotoxy(2, indice-7);
lcd_cursor(1);
I/O C7 C6 C5 C4 C3 C2 C1 C0 }
Val 0 0 0 0 0 1 1 1 //******************************
Direção Saída Saída Saída Saída Saída Entr Entr Entr void leMemoria(){
//comandos para ler os dados da EEPROM nos
Tabela 12: Definido a direção dos dados do PORT C //endereços 0 a 11
num[0]=read_eeprom(0);
A função input(IO) lê o nível lógico encontrado no I/O num[1]=read_eeprom(1);
especificado. A diretiva #use fast_io(IO) especifica que o //ler demais endereços...
programador irá decidir quais I/O’s serão entrada com o }
comando set_tris(IO).
TIPO DE DADO INT16 E SIGNED INT (PIC)
O tipo de dado signed int16 ou signed long suporta faixa de
SALVANDO NUMERO DE
3.5 valores negativos e positivos. O tipo int16 ou long opera
somente com a faixa de valores positiva. Na tabela a seguir
TELEFONE E NOME (PIC) temos um comparativo de alcance destes dois tipos de dados:
O programa 5 faz uso do vetor num que armazena o número
telefônico de 9 dígitos e do vetor nome para armazenar o nome Tipo de dado Alcance de armazenamento
de quem atende no respectivo número. signed int16 ou
signed long
-32768 a +32767
A figura 13 ilustra a tela de
execução do programa. int16 ou
long
0 a 65535
Fig. 13: Tela do programa 5 Tabela 13: Diferença entre o tipos de dado int16 e signed int16
#include<16F877A.h>
#fuses nowdt, nobrownout, xt, noput, noprotect
#use fast_io(C) 2 SALVANDO TIPO DE DADO INT16
#use delay(clock=4000000)
#include<lcd.h>
A EEPROM armazena dados de 8 bits (1 Byte), o tipo char em C.
#define AVANCAR PIN_C1 Mas existem aplicações em que se faz necessário salvar variáveis
#define SOMAR PIN_C0 do tipo int16 que tem o tamanho de 2 Bytes, ou seja, o dobro
do tipo char. Por isso, é necessário quebrar a variável int16 em
int1 b1,b2; duas partes que resultem em duas variáveis do tipo char. Para
char indice, num[8]={5,1,9,9,6,0,2,6}; ilustrar considere a variável int16 cont.
char nome[4]={'C','A','S','A'};
int16 cont=300;
void atualizaLCD();
void atualizaCursor(); O valor máximo de 1 Byte é 255. Então o valor 300 não pode ser
void leMemoria(); armazenado em um único índice da EEPROM. É necessário
//****************************** “quebrar” a variável int16 em duas variáveis char com a
void main(){ operação de divisão “/” e módulo “%” que obtém o resto da
leMemoria(); divisão.
lcd_init();
atualizaLCD(); cont=300;
atualizaCursor();
// Programa 5 cont/256; 300/256 = 1,17
while(1){ cont%256; 300%256 = 44
if(input(SOMAR)==0 && b1==0) {
b1=1;
if(indice<8){ Para salvar cont/256 no índice 0 e cont%256 no índice 1
num[indice]++; aplicamos os seguintes comandos:
write_eeprom(indice, num[indice]);
} write_eeprom(0, cont/256);
else{ write_eeprom(1, cont%256);
nome[indice-8]++;
if(nome[indice-8]>'E'){ Teremos os seguintes dados na memória interna do PIC:
nome[indice-8]='A';
0 1 2 3
} 1 (01) 44 (2C)
write_eeprom(indice, num[indice-8]);
} Tabela 5: valor 300 salvo dos índices 0 e 1 da EEPROM
atualizaLCD();
}
Para recuperar o dado é preciso ler e “unir” os valores destes
if(input(SOMAR)==1) b1=0;
mesmos índices aplicando multiplicação “*” e soma “+”.
if(input(AVANCAR)==0 && b2==0){ 0 1 2 3
b2=1; 1 (01) 44 (2C)
indice++;
x 256 +
if(indice>11) indice=0;
atualizaCursor(); 256 + 44 = 300
}
if(input(AVANCAR)==1) b2=0;
}
}
u8051.com.br MEMÓRIA EEPROM - Página 10/12
O programa 6 utiliza os índices 0 e 1 da EEPROM para salvar a ATIVIDADES PROPOSTAS
variável int16 cont.
1
// Programa 6 Desenhar o esquemático da figura 10 no software
#include<16F877A.h> simulador ISIS;
#fuses nowdt, nobrownout, xt, noput Digitar e compilar o programa 1 no software PIC-C
#use fast_io(C) Compiler;
#use delay(clock=4000000) Simular o programa 4 no software ISIS;
#include<lcd.h> Ampliar os ajustes das horas e minutos de todos os 4
campos da figura 12, limitando as horas e minutos em
#define SOMAR PIN_C0 valores válidos.
Salvar e recuperar os 4 campos de ajuste de tempo;
int1 b1;
int16 cont=12345;
void atualizaLCD();
2
void exibeInt(int16 valor); Digitar e compilar o programa 4 no software PIC-C
void atualizaCursor(); Compiler;
void leMemoria(); Simular o programa 4 em conjunto com o esquemático
//****************************** da figura 10;
void main(){ Simular o programa 5 em conjunto com o esquemático
leMemoria(); da figura 10;
lcd_init(); Os dígitos válidos do telefone devem ser somente 0 a 9;
atualizaLCD(); Ampliar o número de telefone para 11 dígitos;
atualizaCursor(); Ampliar o tamanho do nome de 4 para 8 letras que
while(1){ contemplem somente o alfabeto maiúsculo;
if(input(SOMAR)==0 && b1==0) { Salvar e recuperar todas as informações personalizáveis
b1=1; do usuário (telefone e nome);
cont++;
write_eeprom(0, cont/256);
write_eeprom(1, cont%256); 3
atualizaLCD(); Digitar e compilar o programa 6 no software JFE;
} Simular o programa 6 em conjunto com o esquemático
if(input(SOMAR)==1) b1=0; da figura 10;
} Acrescentar a tecla zera conectada no PORT C2;
} Alterar o contador para suportar contagens até 50000,
//****************************** bem como salvar essa faixa de valores na EEPROM;
void atualizaLCD(){ Desafio supremo: exibir e salvar contagem até 99999
lcd_cursor(0); utilizando a variável long int16 cont;
lcd_gotoxy(1,1);
exibeInt(cont);
atualizaCursor();
}
//******************************
void exibeInt(int16 valor){
printf(lcd_putc, "%05li", valor);
}
//******************************
void atualizaCursor(){
lcd_gotoxy(1,11);
lcd_cursor(1);
}
//******************************
CONCLUSÃO
void leMemoria(){
unsigned char parte2;
cont=(read_eeprom(0)*256);
parte2=read_eeprom(1);
Analisamos as características técnicas da EEPROM 24C02 e a
cont=cont+parte2;
} estrutura de armazenamento organizada em índices ou
posições de memória. Para comunicação entre o 8051 e a
EEPROM utilizou-se o protocolo de comunicação I2C com a
biblioteca i2c.h para ler e escrever dados, os quais puderam
A função exibeInt(tipo de dado) recebe como parâmetro o valor visualizados no mapa de memória em nível de simulação. Para
a ser exibido no LCD. O tipo de dado declarado na função deve salvar dados maiores do que 1 Byte, utilizou-se um algoritmo
ser do mesmo tipo de dado da variável que desejamos exibir. para quebrar a variável em partes menores para tornar o seu
Considere: armazenamento possível. Com a EEPROM externa no 8051 ou a
interna do PIC foi possível salvar e recuperar as informações,
char cont=200; mesmo após o circuito ser desligado. Para finalizar, é importante
Então o parâmetro da função deverá ser: considerar que toda memória EEPROM, seja externa ou
exibeInt(char variável) embutida no microcontrolador tem um ciclo de vida que reduz
a cada operação de escrita ou leitura de dados.
signed char cont=100;
Então o parâmetro da função deverá ser:
exibeInt(signed char variável)
#define TEMPO 1
//***************************************************
void delay_i2c(char i){
int j;
while(i--)
for(j=0;j<60;j++);
}
//***************************************************
void start(void){
sda=1;
delay_i2c(TEMPO);
scl=1;
delay_i2c(TEMPO);
sda=0;
}
//***************************************************
void stop(){
sda=0;
delay_i2c(TEMPO);
scl=1;
sda=1;
}
//***************************************************
void write(unsigned char dat){
unsigned char i;
for(i=0;i<8;i++){
scl=0;
sda=(dat&0x80>>i)?1:0;
delay_i2c(TEMPO);
scl=1;
}
}
//***************************************************
void ack(void){
scl=0;
delay_i2c(TEMPO);
sda=1;
delay_i2c(TEMPO);
scl=1;
delay_i2c(TEMPO);
scl=0;
}
//***************************************************
void noack(void){
scl=0;
delay_i2c(TEMPO);
sda=1;
delay_i2c(TEMPO);
scl=1;
}
//***************************************************
unsigned char read(){
unsigned char i,buff=0;
sda=1;
for(i=0;i<8;i++){
scl=1;
if(sda) buff|=(0x80>>i);
scl=0;
}
return buff;
}
//***************************************************
void save_i2c(char id,char addr,char ch){
start(); write(id); ack(); write(addr);
ack(); write(ch); ack(); stop();
delay_i2c(100);
}
//***************************************************
char read_i2c(char id,char addr){
unsigned char buff;
start(); write(id); ack();
write(addr); ack(); start();
write(id|1); ack(); buff=read();
noack(); stop();
return buff;
}