segunda-feira, dezembro 30, 2013

Conectando uma EEProm ao MSP430 - 93C66

Vamos ver neste post uma outra opção de memória EEProm para usar com a Launchpad. A 93C66 é uma memória um pouco mais esquisita que a 24C256, mas pode ser encontrada por preços menores. A comunicação com o microcontrolador utiliza um outro protocolo serial, o SPI.

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:
  1. #include "io430.h"  
  2.   
  3. typedef unsigned char  byte;  
  4. typedef unsigned int   word;  
  5.   
  6. // definições dos pinos de E/S no port 1  
  7. #define  LED        0x01  
  8. #define  CS         0x10  
  9. #define  SDI        0x80  
  10.   
  11. static void EEProm_WriteEnable (void);  
  12. static void EEProm_Write (word ender, word dado);  
  13. static word EEProm_Read (word ender);  
  14. static void WriteSPI (byte dado);  
  15. static word ReadSPI (void);  
  16. static void delay (void);  
  17.   
  18. int main( void )  
  19. {  
  20.     word i;  
  21.     word dado;  
  22.       
  23.     // Stop watchdog timer to prevent time out reset  
  24.     WDTCTL = WDTPW + WDTHOLD;  
  25.   
  26.     // Programa entradas e saídas  
  27.     P1SEL = 0;  
  28.     P1DIR = (byte) ~SDI;     // apenas SDI é entrada  
  29.     P1OUT = 0;  
  30.   
  31.     // Alimentação já deve estar estável, vamos ligar o DCO  
  32.     BCSCTL1 = CALBC1_1MHZ;  
  33.     DCOCTL  = CALDCO_1MHZ;  
  34.   
  35.     // Programa USI  
  36.       // Clock = SMCLK/2 = 1/2 MHZ = 500 KHz, ativo low  
  37.     USICKCTL  = USIDIV0 | USISSEL1 | USICKPL | USISWRST;  
  38.       // Habilitar pinos, MSB first, Master  
  39.     USICTL0 = USIPE7 | USIPE6 | USIPE5 | USIMST;  
  40.       // Modo SPI  
  41.     USICTL1 = 0;  
  42.       // 8 bit shift register  
  43.     USICNT = 0;  
  44.       // Libera USI para operação  
  45.     USICKCTL  &= ~USISWRST;  
  46.   
  47.     // Permite a gravação  
  48.     EEProm_WriteEnable ();  
  49.       
  50.     // grava dados de teste  
  51.     for (i = 0; i < 256; i++)  
  52.       EEProm_Write (i, (i << 8) | i);  
  53.       
  54.     // Testa continuamente a leitura  
  55.     while (1)  
  56.     {  
  57.       for (i = 0; i < 256; i++)  
  58.       {  
  59.           dado = EEProm_Read (i);  
  60.           if (dado != ((i << 8) | i))  
  61.           {  
  62.             P1OUT |= LED;  
  63.             while (1)  
  64.               ;  
  65.           }  
  66.       }  
  67.     }  
  68. }  
  69.   
  70. // habilita escrita na EEProm  
  71. static void EEProm_WriteEnable (void)  
  72. {  
  73.   P1OUT |= CS;  
  74.   delay ();  
  75.   WriteSPI (0x04);   
  76.   WriteSPI (0xFF);  
  77.   delay ();  
  78.   P1OUT &= ~CS;  
  79.   delay ();  
  80. }  
  81.   
  82.   
  83. // escreve na EEProm  
  84. static void EEProm_Write (word ender, word dado)  
  85. {  
  86.   // Escrita  
  87.   P1OUT |= CS;  
  88.   delay ();  
  89.   WriteSPI (0x05);   
  90.   WriteSPI (ender);  
  91.   WriteSPI (dado >> 8);  
  92.   WriteSPI (dado & 0xFF);  
  93.   delay ();  
  94.   P1OUT &= ~CS;  
  95.   delay ();  
  96.   
  97.   // Espera concluir  
  98.   P1OUT |= CS;  
  99.   delay ();  
  100.   while ((P1IN & SDI) == 0)  
  101.     ;  
  102.   delay ();  
  103.   P1OUT &= ~CS;  
  104.   delay ();  
  105. }  
  106.   
  107. // le da EEProm  
  108. static word EEProm_Read (word ender)  
  109. {  
  110.   word dado;  
  111.     
  112.   P1OUT |= CS;  
  113.   delay ();  
  114.   WriteSPI (0x06);   
  115.   WriteSPI (ender);  
  116.   dado = ReadSPI ();  
  117.   delay ();  
  118.   P1OUT &= ~CS;  
  119.   return dado;  
  120. }  
  121.   
  122. static void WriteSPI (byte dado)  
  123. {  
  124.   // Envia o byte  
  125.   USISRL = dado;  
  126.   USICTL0 |= USIOE;  
  127.   USICNT = 8;  
  128.     
  129.   // espera fim da transferência  
  130.   while ((USICTL1 & USIIFG) == 0)  
  131.     ;  
  132. }  
  133.   
  134. static word ReadSPI (void)  
  135. {  
  136.   byte d1, d2;  
  137.     
  138.   // Dispara a recepção de 1 bit (dummy)  
  139.   USISRL = 0;  
  140.   USICTL0 &= ~USIOE;  
  141.   USICNT = 1;  
  142.     
  143.   // Aguarda receber  
  144.   while ((USICTL1 & USIIFG) == 0)  
  145.     ;  
  146.   
  147.   // Dispara a recepção do byte mais significativo  
  148.   USISRL = 0;  
  149.   USICTL0 &= ~USIOE;  
  150.   USICNT = 8;  
  151.     
  152.   // Aguarda receber  
  153.   while ((USICTL1 & USIIFG) == 0)  
  154.     ;  
  155.   d1 = USISRL;  
  156.   
  157.     // Dispara a recepção do byte menos significativo  
  158.   USISRL = 0;  
  159.   USICTL0 &= ~USIOE;  
  160.   USICNT = 8;  
  161.     
  162.   // Aguarda receber  
  163.   while ((USICTL1 & USIIFG) == 0)  
  164.     ;  
  165.   d2 = USISRL;  
  166.     
  167.   return (d1 << 8) | d2;  
  168. }  
  169.   
  170. // uma pausa curta (e grosseira)  
  171. static void delay (void)  
  172. {  
  173.   int i;  
  174.   for (i = 0; i < 100; i++)  
  175.     ;  
  176. }  

Nenhum comentário: