14 Comentários

Comunicação SPI – Parte 3 – Microcontrolador AT89S8253 + EEPROM 25LC256

AT89S8253
Este post faz parte da série Comunicação SPI. Leia também os outros posts da série:

Dando continuidade aos nossos artigos referentes à comunicação SPI, apresentamos no primeiro artigo as características elétricas e sua carta de sinais. No segundo artigo, demos continuidade a esses sinais e apresentamos de maneira mais simplificada como são algumas bibliotecas de comunicação. Acesse o artigo Comunicação SPI Parte I e Comunicação SPI Parte 2. Neste artigo vamos detalhar melhor as configurações de software para a comunicação SPI Master de um dispositivo bastante conhecido, o microcontrolador AT89S8253. Utilizando as chamadas que vamos criar, também escreveremos as rotinas necessárias de leitura e escrita para uma memória 25LC256. Os testes serão baseados no compilador SDCC na versão 3.3.1.

 

 

Prototipagem

 

Vamos adotar alguns protótipos de função como base para nossas funções. Essas funções serão implementadas de acordo com o núcleo, mas terá o mesmo SPI.H que descreveremos abaixo.

 

 

 

Comunicação SPI no AT89S8253

 

Para quem não conhece esse microcontrolador, trata-se de um conhecido núcleo de 8 bits fabricado pela Atmel. Possui um core 8051 (MCS51) rodando a 24MHz, com 12KBytes de Flash e 256Bytes de memória RAM. Permite o uso de memória RAM externa, podendo acessar até 64K. Também possui uma porta de comunicação USART, 32 IOs, 3 Timers de 16 bits, além do nosso desejado SPI.

 

Diagrama de blocks interno da SPI.

Diagrama de blocks interno da SPI.

 

A configuração do SPI é feita através de três registradores, SPCR (SPI Control Register), SPSR (SPI Status Register) e SPDR (SPI Data Register). O registrador SPDR possui um tamanho de 8 bits, e com a SPI configurada, basta escrever um byte nele para a comunicação acontecer automaticamente. Os outros registradores possuem configurações específicas, de acordo com cada bit, conforme veremos com detalhes abaixo:

 

SPI do AT89S8253.

SPI do AT89S8253.

 

SPI Control Register do AT89S8253

 

Mapa de bits do registrador SPCR.

Mapa de bits do registrador SPCR.

 

SPIE - SPI Interrupt Enable (Bit 7)

 

Este bit, em conjunto com ES no IE habilita a interrupção. É importante saber que esse microcontrolador compartilha a interrupção da serial, dessa forma é necessário fazer a separação da origem do dado (Serial ou SPI) dentro do tratamento da interrupção.

 

1 = SPI Interrupt Enable
0 = SPI Interrupt Disable

 

SPE - SPI Enable (Bit 6)

 

Este bit habilita o dispositivo SPI. Quando em 1, o dispositivo SPI estará habilitado e pronto para fazer a comunicação conforme configurado. Caso em 0, deixará o dispositivo desligado.

 

1 = SPI Enable
0 = SPI Disable

 

DORD - Data Order (Bit 5)

 

Ordem dos dados que trafegam no barramento SPI. Quando em 1, o primeiro bit transmitido é o LSB. Caso 0, o primeiro bit transferido será o MSB. Esta última é a situação mais comum dos dispositivos SPI.

 

0 = First bit MSB
1 = First bit LSB

 

MSTR - Master/Slave Select (Bit 4)

 

Este bit define se a comunicação será Master ou Slave. Quando em 1, o dispositivo irá se comportar como Master. O SS é considerado um GPIO e deve ser controlado por software. Caso 0, o dispositivo se comporta como Slave, e o SS é controlado pela SPI.

 

0 = Device is Slave
1 = Device is Master

 

CPOL - Clock Polarity (Bit 3) e CPHA - Clock Phase (Bit 2)

 

Esses dois bits definem o modo de operação da SPI. O CPOL indica a polaridade do clock. Quando em 1, SCK se manterá em alto quando não houver comunicação. Ele se manterá em baixo quando este bit estiver configurado como 0.

 

Já o CPHA configura a borda em que o dado será trocado. No entanto, é dependente do que foi configurado em CPOL. Para facilitar a compreensão, vamos analisar a carta de tempo de acordo com o modo.

 

Modos de operação da SPI.

Modos de operação da SPI.

 

Dessa forma, os modos de operação são:

 

Modo 0 - CPOL = 0 e CPHA = 0
Modo 1 - CPOL = 1 e CPHA = 0
Modo 2 - CPOL = 0 e CPHA = 1
Modo 3 - CPOL = 1 e CPHA = 1

 

SPR1 e SPR0 - SPI Clock Rate Select (Bits 1 e 0)

 

Esses bits selecionam a velocidade da comunicação quando a SPI está configurada como Master. Trata-se de um divisor para o clock principal do sistema, o FOSC, variando entre 4 e 128. Essa velocidade é afetada pelo bit X2 Mode, que dobra a velocidade de clock. Nesse caso, o divisor varia entre 2 e 64. Imaginando trabalhar com 24MHz (limite para esse componente), a velocidade será conforme abaixo.

 

SPR1 e SPR0 Divisor X2 Mode Clock
00 Clock / 2 1 12MHz
00 Clock / 4 0 6MHz
01 Clock / 8 1 3MHz
01 Clock / 16 0 1,5MHz
10 Clock / 32 1 750KHz
10 Clock / 64 0 375KHz
11 Clock / 64 1 375KHz
11 Clock / 128 0 187,5KHz

 

SPI Status Register do AT89S8253

 

Este registrador indica o status do dispositivo SPI. É nele que vamos verificar o final de uma transmissão (quando em Master) ou a troca de um dado (quando em Slave).

 

SPI Status Register.

SPI Status Register.

 

SPIF - SPI Interrupt Flag (Bit 7)

 

Quando uma transferência se completa, este bit é setado. Caso a interrupção esteja habilitada (SPIE=1 e ES=1), é feita a chamada da rotina de interrupção. Assim como foi dito anteriormente, a interrupção é compartilhada com a serial, então este bit também serve de identificação para saber a origem da chamada.

 

1 = Serial Transfer Complete
0 = No data Transfered

 

WCOL - Write Collision (Bit 6)

 

Este bit indica uma colisão de dados. Isso ocorre quando um byte está sendo transferido e a CPU escreve um novo dado. Em uma condição dessa, esse bit será setado, indicando o erro.

 

1 = Write Collision
0 = Data Ok

 

LDEN - Load Enable for the TX Buffer (Bit 5)

 

Quando ENH (visto mais abaixo) está setado, é seguro carregar o TX Buffer quando LDEN=1 e WCOL=0. LDEN permanecerá alto durante a transmissão dos bits 0 a 3, e baixo durante os bits de 4 a 7 do tempo de transmissão do frame da SPI.

 

1 = Carga de dados habilitada
0 = Carga de dados desabilitada

 

DISSO - Disable Slave Output Bit (Bit 1)

 

Quando este bit está ativo, MISO entrará em Tri-State. Dessa forma, mais de um Slave pode compartilhar a mesma interface com o mesmo Master. Pode-se utilizar o primeiro byte da comunicação como o endereço do dispositivo Slave, assim, somente o Slave selecionado poderá limpar o bit DISSO.

 

1 = Manterá MISO em Tri-State
0 = MISO em uso normal

 

ENH - Enhanced SPI Mode Select (Bit 0)

 

Este bit habilita o buffer duplo de comunicação. Com ele habilitado, a transferência de dados se dá de maneira mais rápida, mas deve-se tomar cuidado com a colisão de dados.

 

1 = Enhanced SPI Enable
0 = Enhanced SPI Disable

 

 

Implementação do Código no Microcontrolador AT89S8253

 

Uma vez que definimos a prototipagem e agora que conhecemos os registradores, podemos implementar o código das duas funções de nossa SPI. Primeiramente, vamos definir o cabeçalho do arquivo, que precisa definir a CPU utilizada. Para nosso compilador SDCC, o cabeçalho para o AT89S8253 é o at89s8253.h. Nele, encontramos a definição dos registradores que vamos utilizar.

 

 

A chamada de inicialização possui quatro parâmetros e nenhum retorno. Os parâmetros configuram o modo de operação, se a SPI será Master ou Slave, a velocidade da SPI (que nesse caso é o dividor usado) e a ordem dos bits (iniciando como MSB ou LSB).

 

 

Uma vez estando implementada a inicialização do dispositivo, precisamos fazer a implementação da troca de dados. Nesse caso, vamos nos atentar ao SPIF, pois ele é quem vai indicar que o dado foi transferido. Podemos ver essa implementação conforme o código abaixo:

 

 

 

Comunicação SPI no 25LC256

 

Uma vez que conhecemos a SPI do nosso microcontrolador, temos que conhecer a SPI do dispositivo com o qual vamos comunicar. Nesse caso, trata-se de uma memória EEPROM de 256Kbits (32KBytes). Como vimos no primeiro artigo, a SPI é definida como padrão para suportar até 2MHz. No entanto, este componente pode trabalhar a uma velocidade de até 10MHz, o que significa 10Mbps de transferência.

 

Pinagem da nossa memória 25LC256.

Pinagem da nossa memória 25LC256.

 

Este dispositivo também suporta até 1.000.000 ciclos de apagamento/escrita, retendo os dados por mais de 200 anos. Tem um tempo máximo de escrita de 5ms, e trabalha com páginas de 64 bytes.

 

AT89S8253 e 25L256: Esquemático da ligação.

AT89S8253 e 25L256: Esquemático da ligação.

 

Esta memória responde a uma lista de instruções (ou comandos) conhecidos, que são enviados como primeiro byte da comunicação SPI. A partir desse comando, o dispositivo passa responder de maneira mais abstrata, executando leitura, escrita, etc. A lista de comandos é dada conforme abaixo:

 

Lista de comandos da 25LC256.

Lista de comandos da 25LC256.

 

Como sabemos, a comunicação SPI exige a seleção do componente através de um sinal de SS (Slave Select). No nosso caso, esse sinal é definido como CS (Chip Select), mas possui exatamente a mesma função e irá se comportar da mesma forma.

 

A comunicação se dá dentro de um frame de SS. Uma vez com esse sinal ativo (em nível baixo), o Master envia primeiramente um byte de instrução. Em seguida os parâmetros de acordo com o devido comando. Vamos verificar os principais comandos e parâmetros para a leitura e gravação de dados nessa memória.

 

READ (03h)

 

AT89S8253: Instrução de leitura de dados.

Instrução de leitura de dados.

 

Essa instrução é responsável por fazer a leitura de um ou mais bytes de um endereço solicitado. Possui um formato bem simples: Uma vez baixado o SS, o primeiro byte enviado pelo Master é a instrução (03h), seguido por dois bytes de endereço. O endereço é começado pelo bit 15 ( bit mais significativo), terminando o primeiro byte pelo bit 8, seguido do segundo byte começado pelo bit 7 e terminado pelo bit 0 (bit menos significativo). Como a memória utilizada (25LC256) possui 32KB de memória, o endereço varia entre 0000h até 7FFFh. Isso significa que o bit mais significativo (bit 15) não serve de endereçamento. Esse componente irá ignorar esse bit, podendo ele ser 0 ou 1. No entanto, manteremos o padrão e enviaremos 0, para endereçar corretamente.

 

03h ADDR (15:8) ADDR (7:0) DATA

 

Por último, é transferido do Slave para o Master o byte do endereço selecionado. Caso o Master continua forçando a transferência, o endereço é automaticamente incrementado e o dado do endereço seguinte é transferido. Caso o endereço máximo seja atingido (7FFFh), o sistema retorna automaticamente para o endereço base (0000h) e recomeça o envio, que pode ser feito de maneira indefinida enquanto o Master continar forçando a troca de dados.

 

WRITE (02h)

 

Instrução de escrita no 25LC256.

Instrução de escrita no 25LC256.

 

Esta instrução faz a escrita de um ou mais bytes a partir do endereço informado. Possui uma estrutura muito similar ao comando READ. Primeiramente é enviado o byte de comando (02h) seguido por dois bytes de endereço. Da mesma forma, o bit 15 é ignorado, mas escreveremos 0.

 

Uma vez enviado os dois bytes de endereço, o byte seguinte é o dado a ser gravado. Caso mais bytes sejam enviados, o endereço é automaticamente incrementado e os dados serão gravados em sequência. No entanto, há um limite de até 64 bytes por ciclo de gravação.

 

02h ADDR (15:8) ADDR (7:0) Data

 

WREN (06h)

 

AT89S8253: Instrução WREN do 25LC256.

Instrução WREN do 25LC256.

 

Esta instrução habilita o processo de escrita de dados. Uma vez habilitado, o sistema pode fazer a escrita de dados.

 

 

Funções de Acesso à EEPROM 25LC256

 

Uma vez definidas as funções de acesso à SPI, e agora que conhecemos as informações técnicas da EEPROM 25LC256, podemos então definir o cabeçalho de funcionamento de nossa biblioteca de acesso à memória. Dessa forma, nosso arquivo EEPROM.H pode ser definido dessa forma.

 

 

Realmente é apresentado um cabeçalho bastante simples, uma vez que apenas estamos fazendo a leitura e escrita de dados. Dessa forma, vamos definir nosso arquivo EEPROM.C com as seguintes diretivas.

 

 

Essas definições apenas indicam os comandos e arquivos a serem incluídos no projeto. Após essas definições, temos a implementação da função de inicialização eeprom_init() conforme definimos no cabeçalho. Ela chama a inicialização da SPI e, em seguda, envia o comando de WREN.

 

 

Em seguida, vamos definir a função eeprom_read() e eeprom_write(). Assim como visto no estudo dos comandos e formas de onda da SPI, a implementação é muito similar, como é vista abaixo:

 

 

Fazendo uso dessas instruções é possível fazer a leitura e escrita de dados individuais na memória utilizando o microcontrolador AT89S8253 e a memória 25LC256.

 

 

Referências - Comunicação SPI parte 3 - Microcontrolador AT89S8253 + EEPROM 25LC256

 

25LC256 http://ww1.microchip.com/downloads/en/DeviceDoc/21822E.pdf
AT89S8253

http://www.atmel.com/Images/doc3286.pdf

http://www.atmel.com/devices/at89s8253.aspx

Arquiteture and Programming 8051 MCU's http://www.mikroe.com/chapters/view/67/chapter-4-at89s8253-microcontroller/
Coding SPI Software http://www.vikingexplorer.org/vikingftp/EDN071203-spi.pdf

 

Outros artigos da série

<< Comunicação SPI - Parte 2
Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.

Receba os melhores conteúdos sobre sistemas eletrônicos embarcados, dicas, tutoriais e promoções.

Hardware » Comunicação SPI - Parte 3 - Microcontrolador AT89S8253 + EEPROM 25LC256
Comentários:
Notificações
Notificar
guest
14 Comentários
recentes
antigos mais votados
Inline Feedbacks
View all comments
Sergio Fink
12/12/2018 22:39

Francesco Boa noite Estou desenvolvendo um sistema via SPI utilizando um STM32F030R8 e uma memoria flash. No caso o uC será o master e a memoria o slave. Após desenvolver toda a função em linguagem C que vai fazer desde a inicialização até a leitura dos dados escritos nesta memória, não consigo ler os dados que escrevi na memoria através do pino MISO da mesma. Segundo o datasheet desta memoria, a leitura dos dados pela MISO ocorre através da MOSI enviando o comando de leitura + endereço inicial onde os dados foram escritos. Após deveria ser possível ler os dados… Leia mais »

Lucas dos Santos
Lucas dos Santos
17/10/2018 11:21

Fala galera... Ótima matéria. Estou fazendo um sistema de programação da memória flash, e percebi que basicamente é este mesmo esquema, só que no meu caso vou utilizar o Atmega328/P, no datasheet desse MCU na pagina 362 (http://ww1.microchip.com/downloads/en/devicedoc/atmel-42735-8-bit-avr-microcontroller-atmega328-328p_datasheet.pdf) tem uma tabela, mas não estou entendo algumas partes dessa tabela. Minha duvida é na Write Program Memory Page, esse comando tem 4 bytes de campo, pelo que entendi vou enviar para o Atmega328/P (4C -- adr MSB(8) -- adr LSB(8) -- 00), depois do endereço, adr LSB(8), posso enviar os dados a serem gravados na flash do Atmega328/P? Nesse ultimo campo… Leia mais »

Pedro Henrique
Pedro Henrique
13/11/2014 10:15

Bom dia Francesco parabéns pelos artigos. Vendo os mesmo surgiu uma dúvida de como fazer para comunicar um Ethernet e USB host shield com Arduíno. Você poderia escrever algo sobre?? Obrigado.

Francesco Sacco
Reply to  Pedro Henrique
13/11/2014 16:55

Olá Pedro Henrique,

Obrigado pelo feedback.
Acho esses assuntos ótimos. Já estava estudando a possibilidade de fazer um sobre Ethernet, só não tenho certeza se utilizo o ENC28J60 ou o W5100.

Quanto o USB Host, também acho interessante, mas é um assunto um pouco mais demorado. Gostaria de fazer um partindo do básico da USB.

O que você me sugere? Indicar o uso do Arduino com o ENC28J60 ou o W5100?

Pedro Henrique
Pedro Henrique
Reply to  Francesco Sacco
19/11/2014 10:00

Opa Francesco, consegui aqui trabalhar com W5100 sem problemas... so não consigo fazer funcionar o W5100 junto com Usb Host mesmo realizando configurações/alterações no SS. Abraços.

Francesco Sacco
Reply to  Pedro Henrique
21/11/2014 15:25

Olá Pedro,
Qual a USB Host que está usando? Por acaso é um Arduino Due? Ou o Shield de USB Host?

Também é bacana dar uma olhada para ter certeza se as bordas e velocidades da SPI são as mesmas para os dois shields.

Cleiton Bueno
06/06/2014 10:53

Excelente post Francesco e muito didático, parabéns!
Será que ainda rola um post com memoria flash usando SPI? 🙂

Francesco Sacco
Reply to  Cleiton Bueno
08/06/2014 00:32

Olá Cleiton,
É claro que rola. Estava preparando um com o AT45xxx, mas acho que o SDCard é uma aplicação bem mais comum. Ela está na lista.

Tem algum outro dispositivo que você gostaria de comunicar?
Um abraço.

Cleiton Bueno
Reply to  Francesco Sacco
08/06/2014 17:36

É SD Card acho que esta saindo bastante hoje em dia, mas com AT45xxx seria show heim :).

Abraço

João Erasmo
Joao
22/05/2017 22:03

Boa noite,
Gostei muito da matéria, tirei muitas duvidas sobre comunicação SPI.
Muito bem explicado.
Fiquei com uma duvida apenas no ultimo código, na linha 41 é CMD_READ ou CMD_WRITE?

trackback
11/02/2015 06:19

[…] em uma placa, para troca de dados, por exemplo, entre um microcontrolador e uma memória externa [7]. Já a UART é muito utilizada para comunicação entre dispositivos externos à placa, como por […]

trackback
14/07/2014 09:05

[…] também a continuação desse artigo, o Comunicação SPI – Parte 3. Nele apresentamos um exemplo de comunicação entre o microcontrolador AT89S8253 e a memória […]

trackback
14/07/2014 09:04

[…] Parte 2, onde abordamos mais detalhes de comunicação e os fundamentos básicos de software, e Comunicação SPI – Parte 3, onde apresentamos um exemplo de comunicação entre um microcontrolador AT89S8253 e uma memória […]

Talvez você goste:

Séries



Outros da Série

Menu

WEBINAR
 

Soluções inteligentes para acionamento de MOSFETs/IGBTs com família STDRIVE

Data: 08/10 às 15:00h - Apoio: STMicroelectronics
 
INSCREVA-SE AGORA »



 
close-link