A memória 93C66 possui 4K bits, que podem ser acessados como 256 posições de 16 bits ou 512 posições de 8 bits (vamos usá-la aqui no modo 16 bits). O datasheet (93C66.pdf) está nos arquivos do blog.
O protocolo SPI utiliza quatro sinais para a comunicação: SCLK (clock), SS (seleção do slave), MISO (dado do slave para o master) e MOSI (dado do master para o slave). O SPI permite que sejam feitas simultaneamente duas transferências de bits, uma em cada sentido.
O protocolo SPI possui quatro modos de clock (variando a posição de repouso e a borda para a transferência de dados). A 93C66 suporta um subconjunto do SPI denominado Microwire. O Microwire suporta somente um dos modos de clock e opera em half-duplex (transfere somente em um sentido de cada vez). Os diagramas abaixo mostram a leitura e gravação na 93C66
Um detalhe importante é que normalmente o protocolo SPI utiliza um sinal SS negado (nível baixo seleciona o slave), mas a 93C66 utiliza um sinal SS normal (nível alto seleciona).
A mesma USI do MSP430G2231 que usamos para comunicar por I2C no post anterior pode ser programada para operar como SPI.
Novamente o hardware é simples:
As rotinas de leitura e gravação e o programa de teste ficam:
#include "io430.h"
typedef unsigned char byte;
typedef unsigned int word;
// definições dos pinos de E/S no port 1
#define LED 0x01
#define CS 0x10
#define SDI 0x80
static void EEProm_WriteEnable (void);
static void EEProm_Write (word ender, word dado);
static word EEProm_Read (word ender);
static void WriteSPI (byte dado);
static word ReadSPI (void);
static void delay (void);
int main( void )
{
word i;
word dado;
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
// Programa entradas e saídas
P1SEL = 0;
P1DIR = (byte) ~SDI; // apenas SDI é entrada
P1OUT = 0;
// Alimentação já deve estar estável, vamos ligar o DCO
BCSCTL1 = CALBC1_1MHZ;
DCOCTL = CALDCO_1MHZ;
// Programa USI
// Clock = SMCLK/2 = 1/2 MHZ = 500 KHz, ativo low
USICKCTL = USIDIV0 | USISSEL1 | USICKPL | USISWRST;
// Habilitar pinos, MSB first, Master
USICTL0 = USIPE7 | USIPE6 | USIPE5 | USIMST;
// Modo SPI
USICTL1 = 0;
// 8 bit shift register
USICNT = 0;
// Libera USI para operação
USICKCTL &= ~USISWRST;
// Permite a gravação
EEProm_WriteEnable ();
// grava dados de teste
for (i = 0; i < 256; i++)
EEProm_Write (i, (i << 8) | i);
// Testa continuamente a leitura
while (1)
{
for (i = 0; i < 256; i++)
{
dado = EEProm_Read (i);
if (dado != ((i << 8) | i))
{
P1OUT |= LED;
while (1)
;
}
}
}
}
// habilita escrita na EEProm
static void EEProm_WriteEnable (void)
{
P1OUT |= CS;
delay ();
WriteSPI (0x04);
WriteSPI (0xFF);
delay ();
P1OUT &= ~CS;
delay ();
}
// escreve na EEProm
static void EEProm_Write (word ender, word dado)
{
// Escrita
P1OUT |= CS;
delay ();
WriteSPI (0x05);
WriteSPI (ender);
WriteSPI (dado >> 8);
WriteSPI (dado & 0xFF);
delay ();
P1OUT &= ~CS;
delay ();
// Espera concluir
P1OUT |= CS;
delay ();
while ((P1IN & SDI) == 0)
;
delay ();
P1OUT &= ~CS;
delay ();
}
// le da EEProm
static word EEProm_Read (word ender)
{
word dado;
P1OUT |= CS;
delay ();
WriteSPI (0x06);
WriteSPI (ender);
dado = ReadSPI ();
delay ();
P1OUT &= ~CS;
return dado;
}
static void WriteSPI (byte dado)
{
// Envia o byte
USISRL = dado;
USICTL0 |= USIOE;
USICNT = 8;
// espera fim da transferência
while ((USICTL1 & USIIFG) == 0)
;
}
static word ReadSPI (void)
{
byte d1, d2;
// Dispara a recepção de 1 bit (dummy)
USISRL = 0;
USICTL0 &= ~USIOE;
USICNT = 1;
// Aguarda receber
while ((USICTL1 & USIIFG) == 0)
;
// Dispara a recepção do byte mais significativo
USISRL = 0;
USICTL0 &= ~USIOE;
USICNT = 8;
// Aguarda receber
while ((USICTL1 & USIIFG) == 0)
;
d1 = USISRL;
// Dispara a recepção do byte menos significativo
USISRL = 0;
USICTL0 &= ~USIOE;
USICNT = 8;
// Aguarda receber
while ((USICTL1 & USIIFG) == 0)
;
d2 = USISRL;
return (d1 << 8) | d2;
}
// uma pausa curta (e grosseira)
static void delay (void)
{
int i;
for (i = 0; i < 100; i++)
;
}






Nenhum comentário:
Postar um comentário