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