HOME PROJETOS PROGRAMAÇÃO |
Nesta matéria vamos ensinar como acessar uma memória RAM externa ao microcontrolador.
O uso de uma memória RAM externa pode ser justificado se pensarmos que há projetos em que é necessário usar muito mais memória do que a disponível na RAM do microcontrolador para armazenar dados resultantes de cálculos, tabelas ou strings de caracteres e, quando isso acontece, só temos duas opções.
A primeira opção é escolher um microcontrolador que tenha memória RAM suficiente, o que pode tornar o projeto mais caro. Essa opção, é claro, a mais fácil de implementar quando existir um microcontrolador com RAM suficiente para atender as necessidades do projeto.
A segunda opção seria usar uma memória RAM externa. Essa opção não é muito fácil de implementar porém é a mais viável do ponto de vista da quantidade de memória RAM que se pode ter disponível para armazenamento de dados.
Antes de mais nada, devemos deixar claro que memória RAM é uma memória volátil que é apagada quando a energia é desligada.
Uma memória RAM (Randon Access Memory) é uma memória de acesso aleatório, isto é, os bytes que ela armazena podem ser acessados em qualquer sequência usando-se o número do byte que se deseja. Esse número é conhecido como endereço do byte.
As memórias RAM são vendidas em chips das mais diferentes formas, quantidade e número de pinos. Elas também têm diferentes características como tensão de alimentação diferentes, tempo de acesso diferentes e outras. A escolha de uma RAM adequada para um projeto fica por conta do projetista. A verdade é que quase todas elas funcionam da mesma maneira.
O chip de memória RAM geralmente tem 2 pinos de alimentação, um Vcc que é conectado ao pólo positivo da fonte, e um GND que deverá ser conectado ao pólo negativo.
O chip possui uma série de pinos para a porta de endereçamento. Por exemplo, a porta de endereçamento de um chip de memória RAM de 32KBytes (32767 Bytes) tem 15 pinos pois o número 32767 em notação binária se escreve b‘1 1 1 1 1 1 1 1 1 1 1 1 1 1 1‘ (com 15 dígitos 1). A notação hexadecimal para esse número é 0x7FFF. Assumimos que todos saibam como transformar números de uma base para outra.
O chip possui uma porta de dados de 8 bits para entrada (gravação) e saída (leitura) de dados.
O chip deve possuir, também, alguns pinos de controle para que possamos dizer a ele o que desejamos fazer. Basicamente só podemos fazer quatro coisas numa memória RAM:
O pino CE (Chip Enable) - esse pino habilita ou desabilita o chip de memória.
Esse pino deve receber um sinal de ativação do microcontrolador para que o chip de memória fique pronto
para receber/enviar bytes de/para o microcontrolador.
Dependendo do chip usado, esse sinal pode ser active-low ou active-high (ativado quando baixo ou ativado
quando alto).
Quando esse pino estiver desativado, o chip de memória vai ignorar todos os comandos de leitura e
gravação enviados a ele.
O pino WE (Write Enable) - esse pino habilita ou desabilita a gravação.
Toda vez que desejarmos gravar um byte na memória devemos colocar o dado na porta de dados (8 bits) e, em seguida,
ativar o sinal desse pino durante um determinado tempo para que o chip possa executar essa tarefa.
Passado o tempo determinado, deveremos desativar esse sinal. O tempo de ativação e desativação é muito pequeno,
devendo ser da ordem dos nanosegundos.
Do mesmo modo que o sinal CE, o sinal WE pode ser active-low ou active-high.
O pino OE (Output Enable) - esse pino habilita ou desabilita a leitura.
Toda vez que desejarmos
ler um byte na memória devemos ativar o sinal desse pino durante um determinado tempo para que o chip coloque o
byte desejado na porta de dados. Passado o tempo determinado, deveremos desativar esse sinal.
O tempo de ativação e desativação desse sinal também é muito pequeno, devendo ser da ordem dos nanosegundos.
Do mesmo modo que o sinal CE, o sinal WE pode ser active-low ou active-high.
Abaixo vemos procedimentos genéricos para se ler e gravar um byte numa memória RAM.
|
|
Para o nosso projeto vamos seleciona o chip de memória RAM UM61256FK-15 que tem capacidade
de 32kBytes.
Antes de continuar, faça o download do data sheet do UM61256FK
e dê uma olhada para conhecer suas características.
Abaixo, pode-se ver uma foto desse chip.
RAM UM61256FK-15 |
figura 1 |
Tensao de alimentação de 5V que elimina a necessidade de uma fonte de tensão diferente da alimentação do PIC.
Tempo de acesso de até 15ns (nanosegundos).
As entradas e saídas de dados permitem sua conexão direta com o microcontrolador, sem necessidade de circuitos auxiliares.
Os pinos de controle CE (pino 20), OE (pino 22) e WE (pino 27) são todos active-low, isto é, são ativados com sinal baixo (0v).
A porta de endereço é formada pelos pinos 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 21, 23, 24, 25 e 26.
A porta de dados é formada pelos pinos 11, 12, 13, 15, 16, 17, 18 e 19.
O pino 20 é da alimentação Vcc de 5v.
O pino 14 é o Ground.
Num projeto real devemos considerar que uma memória RAM externa, como a selecionada aqui, vai consumir muitas portas de I/O do microcontrolador, não deixando muitas para realizar outras tarefas. No nosso caso, excluindo-se os pinos de alimentação, o chip de memória RAM possui 26
74LS1164N |
figura 2 |
Com o objetivo de economizar portas de I/O do microcontrolador, devemos usar técnicas que permitam seu interfaceamento com a memória externa. Uma das maneiras de interfacear o microcontrolador e a memória externa é usar um método de comunicação serial onde apenas dois pino de I/O do microcontrolador sejam usados.
Apesar da porta de dados de 8 bits da RAM usarem 8 pinos de I/O do PORTB do PIC, apenas dois pino de I/O foram usados para fazer interface com a porta de endereços da memória RAM que tem 15 pinos (pinos 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 21, 23, 24, 25 e 26). Isso foi conseguido com dois shift registers 74LS164N serial-paralelo, cujo esquema pode ser visto na figura 2, conectados em cascata para receber serialmente do PIC os 15 bits de endereço e transmití-lo de forma paralela para a porta de endereço da RAM externa.
A figura 3 mostra o esquema elétrico de conexões da memória ao microcontrolador. Clique na imagem para ampliá-la. No esquema abaixo, o microcontrolador não foi representado mas apenas os pinos necessários para sua conexão com a memória RAM externa.
Observar que os dois shift registers 74LS164N de 8 bits (SHR-LSB e SHR-MSB) estão ligados para formar um único registrador de 16 bits que receberão o endereço de memória requerido.
Esquema Elétrico - Clique na imagem para ampliar |
figura 3 |
Para transmitir serialmente o endereço ao chip da RAM externa o PIC colocará os 16 bits, um de cada vez, no pino RA0 que está conectado ao pino 1 do registrador SHR-LSB. Com o pino RA1 o PIC enviará o sinal de clock para o pino de clock do registrador SHR-LSB (pino 8) que, por sua vez, está diretamente conectao ao pino de clock do registrador SHR-MSB (pino 8).
A cada transição de clock um dos 16 bit de endereço será enviado pelo PIC ao pino 1 do registrador SHR-LSB e o bit que está no pino 13 de SHR-LSB entrará pelo pino 1 de SHR-MSB. Após 16 transições de clock, o endereço completo ocupará todos os bits dos dois regitradores e estarão presentes na porta de endereço da RAM externa.
Todos os pinos do PORTB (RB0 a RB7) foram usados para a porta de dados e os pinos RA2, RA3 e RA4 foram usados para os sinaais de controle CE, OE e WE respectivamente.
O arquivo RAM-UM61256FK.zip contem o projeto completo para o MPLAB para verificar o funcionamento do uso de uma memória RAM externa. O código fonte esta escrito para um microcontrolador PIC18F4620 mas poderá ser implementado em qualquer microcontrolador da família PIC18F, bastando para isso mudar o código do processador nas diretivas LIST P=18F4620 e #include <P18F4620.INC>.
O programa apresentado neste projeto grava uma string de dados na memória RAM e, em seguida, lê essa string e mostra o resultado num LCD serial conectado aos pinos RD1 e RD2 do PIC. O LCD a ser usado segue o modêlo de projeto apresentado em Interface para LCD HD44780 com 2 fios
Mensagem no LCD |
figura 4 |
Este projeto também fornece algumas macros e funções para facilitar as operações de leitura e gravação na memória RAM que podem ser encontradas no arquivo "ramum61256_services.inc" que se encontra dentro do arquivo de distribuição do projeto.
Além disso, o programa também usa os serviços de comunicação com o LCD serial "lcd_services.inc", serviços de strings para facilitar as operações com cadeias de caracteres "string_services.inc" e serviços de retardo de tempo (delays) "delay_services.inc". Todos esses arquivod estão incluidos no programa com a diretiva #include. Os arquivos referentes a esses serviços formam uma infra estrutura de programação assembler e podem ser guardados numa biblioteca para serem usados em outro projetos.
O serviço de acesso a memória RAM, descrito no arquivo "ramum61256_services.inc", possui dois registradores que são usados para conter o endereço corrente da RAM que se deseja acessar, macros instruções e funções decontrole para leitura e gravação.
Os registradores de endereçamento são definidos pelo par RAM_ADDR1:RAM_ADDR0. Quando o programa é iniciado, esses registradores podem conter qualquer endereço e os pinos de controle da RAM podem assumir qualquer estado. A primeira coisa a fazer nesse momento é configurar o par RAM_ADDR1:RAM_ADDR0, fazendo-se uma chamada a função CALL RAM_INIT que, entre outras coisas, vai fazer os registradores apontarem para o inicio da RAM (endereço 0x0000) e configurar os pinos de controle da RAM externa.
Após a execução de CALL RAM_INIT, pode-se usar a macro RAM_ADDRESS <endereco> para especificar o endereço de memória que se deseja ler ou gravar. Essa macro carrega o par de registradores RAM_ADDR1:RAM_ADDR0 com o <endereco> e também envia o endereço para o bus da memória RAM. Após um endereço ter sido especificado, través da macro RAM_ADDRESS <endereco>, pode-se ler ou gravar um byte na memória.
Para ler um byte, faça uma chamada à função CALL RAM_GETCHAR. Essa função vai ler o byte no endereço especificado e colocá-lo no registrador W.
Para gravar um byte na memória RAM, carregue o registrador W com o valor desejado faça uma chamada à função CALL RAM_PUTCHAR.
Se desejar gravar vários bytes seguidos, a partir de um determinado endereço da RAM, use a macro
RAM_ADDRESS <endereco> para especificar o endereço inicial, em seguida use as funções
RAM_GETCHAR para ler ou RAM_PUTCHAR para gravar.
Após ler ou gravar o byte desejado use a função RAM_INC para avançar para
o endereço próximo endereço e repita a leitura ou a gravação.
RAM_ADDRESS <endereco>
A macro RAM_ADDRESS carrega o par de registradores de endereço RAM_ADDR1:RAM_ADDR0 com o endereço especificado no parametro <endereco> e o novo valor do endereço será enviado ao bus de endereço da RAM. Exemplo:
RAM_MVC <origem>, <numero>, <destino>
A macro RAM_MVC move, para o endereço <destino> da RAM externa, uma string de <numero> caracteres que se encontra na RAM do microcontrolador no endereço <origem>. Não há controle de estouro do endereço. Se isso acontecer, o par RAM_ADDR1:RAM_ADDR0 voltará a apontar para o início da RAM externa (endereço 0x0000). Exemplo:
RAM_GETCHAR
A função RAM_GETCHAR lê o endereço corrente da RAM, especificado pelo par RAM_ADDR1:RAM_ADDR0, e armazena o seu valor no registrador W.
RAM_INC
Esta função incrementa o endereço da RAM. O par de registradores de endereço RAM_ADDR1:RAM_ADDR0 será incrementado de uma unidade e o novo endereço será enviado ao bus de endereço da RAM.
RAM_INIT
Esta função inicializa o par de registradores de endereços RAM_ADDR1:RAM_ADDR0 fazendo-os apontar para a posição zero (0x0000) da memória e envia esse valor para o bus de endereço da RAM. Além disso, esta função desabilita a leitura e gravação e habilita o chip de memória para torná-lo disponível para as outras funções. Recomenda-se usar essa função uma única vez no início do programa.
RAM_PUTCHAR
A função RAM_PUTCHAR envia o conteúdo do registrador W para o endereço corrente da memoria RAM, especificado pelo par RAM_ADDR1:RAM_ADDR0.
RAM_SETADDR
Afunção RAM_SETADDR envia os 15 bits de endereço contidos no par de registradores RAM_ADDR0:RAM_ADDR1 para o bus de endereço da RAM. Esta função é de uso interno e não pode ser utilizada pelo programador.
H P S P I N Desde 04 de Março de 2010 Atualização: 14 de Nov de 2024 |