• No se han encontrado resultados

09 2 ComunicacionSerie SPI

N/A
N/A
Protected

Academic year: 2020

Share "09 2 ComunicacionSerie SPI"

Copied!
20
0
0

Texto completo

(1)

9.2 SPI (Serial Peripheral Interface)

El módulo SPI es una interfase serial síncrona usada para comunicación con otros dispositivos o microcontroladores. Estos periféricos pueden ser memorias EEPROM, Flash ADC’s, DAC’s, sensores, etc.

La interfase SPI usa 2 líneas para transferir datos de manera Full-Duplex y una línea para sincronización (Figura 9-15).

Figura 9-15. Interfase SPI

Si se desean conectar varios dispositivos a la misma interfase SPI (configuración de bus), se requiere una línea adicional por cada dispositivo (conectada a Slave Select, SS) como se muestra en la Figura 9-16.

(2)

9.2.1 Módulo SPI

El módulo SPI está formado básicamente por un registro de corrimiento de 8 bits (SPIxSR), este registro desplaza los bits empezando con el MSB desde la línea SDI o hacia la línea SDO en sincronización con el reloj del pin SCKx.

Si el dsPIC está configurado como Maestro, el reloj es generado internamente (se deriva del reloj principal y 2 prescalers) y sale por el pin SCK.

Si el dsPIC está configurado como Esclavo, el reloj es recibido por el pin SCK.

(3)

En el módulo SPI se usan los siguientes registros SFR:

SPIxBUF: Este es el registro de Transmisión o Recepción de datos. Se usa para contener el dato que será transmitido o el dato recibido. Su dirección está compartida con los registros SPIxTXB y SPIxRXB. Si un usuario escribe en el registro SPIxBUF,

internamente el dato se escribe en SPIxTXB, y si el usuario lee el registro SPIxBUF, el dato es leido del registro SPIxRXB. Esto permite que puedan ocurrir transmisiones y recepciones simultáneamente. El usuario no puede escribir directamente en el registro

SPIxTXB o leer directamente del registro SPIxRXB, todo debe de hacerse mediante

SPIxBUF.

SPIxCON: En este registro de control se configuran los modos de operación del módulo.

SPIxSTAT: Este registro indica varios estados.

Además de estos registros, está el registro de desplazamiento (SPIxSR), el cual se usa para recorrer los datos hacia fuera o hacia dentro del puerto SPI. Este registro no está mapeado en memoria.

9.2.1.1

Pines del SPI

En el módulo SPI se usan los siguientes 4 pines (Figura 9-17):

SDIx: Entrada de datos.

SDOx: Salida de datos.

SCKx: Salida o entrada de reloj.

SSx: Selección de esclavo activo bajo o pulso frame synchronization.

(4)

9.2.2 Modos de operación

El módulo SPI tiene 3 modos de operación:

- Transmisión y recepción de 8 bits o 16 bits. - Modo Maestro o Esclavo.

- Modos Framed.

9.2.2.1

Transmisión y Recepción de 8-bits o 16-bits

Al igual que los demás módulos, existe un registro que permite configurar el módulo SPI llamado SPIxCON (Figura 9-18).

Figura 9-18. Registro SPIxCON

El bit MODE16 (SPIxCON<10>), permite al módulo SPI seleccionar entre comunicación de 8-bit o 16-bit. La funcionalidad es la misma solo cambia el número de bits recibidos o

transmitidos.

Si MODE16=0: La comunicación es de 8 bits. Si MODE16=1: La comunicación es de 16 bits.

Tome en cuenta lo siguiente:

- El módulo es reseteado cuando se cambia el valor de MODE16. Por lo tanto procure no cambiar este bit durante la operación normal.

(5)

9.2.2.2

Modo Maestro o Esclavo

Modo Maestro

Para trabajar en modo Maestro se debe hacer los siguientes pasos: 1. Si se usan interrupciones:

• Limpiar el bit SPIxIF en el registro IFSn correspondiente.

• Poner en “1” el bit SPIxIE en el registro IECn correspondiente.

• Configurar la prioridad en el registro IPCn correspondiente.

2. Ajustar el modo maestro en el registro SPIxCON con MSTEN (SPIxCON<5> = 1).

3. Limpiar el bit SPIROV (SPIxSTAT<6>). Este bit llamado Receive Overflow Flag bit, indica si se recibió un byte/palabra y fue descartado.

4. Habilitar la operación SPI poniendo en “1” el bit SPIEN (SPIxSTAT<15>).

5. Escribir el dato que desea ser transmitido al registro SPIxBUF. En este momento comienza la transmisión.

En el modo Maestro, el reloj del sistema es dividido y usado como reloj serial. Esta división de frecuencia se basa en los ajustes a los bits PPRE<1:0> (SPIxCON<1:0>) y SPRE<0:1>

(SPIxCON<4:2>). Dicho reloj serial es transmitido por el pin SCKx a los dispositivos Esclavos. Los pulsos de reloj solo son generados cuando hay un dato para trasmitirse.

Polaridad

El bit CKE (SPI Clock Edge Select bit) (SPIxCON<8>) determina en que flanco del reloj ocurre la transmisión.

Si CKE=0, el dato cambia en la transición de estado de reloj Idle a estado de reloj activo. Si CKE=1, el dato cambia en la transición de estado de reloj activo a estado de reloj Idle. Ahora bien, ¿que nivel significa Idle y Activo?

(6)

Operación en Modo Maestro

Los siguientes pasos describen la operación en modo Maestro:

1. Una vez que el módulo está configurado para modo Maestro, habilitado y el dato ha sido transmitido escribiendo en el registro SPIxBUF, el bit SPITBF (SPI Transmit Buffer Full Status bit) (SPIxSTAT<1>) se pone en “1” automáticamente indicando que la transmisión aun no comienza y que SPIxTXB está lleno.

2. Luego el contenido de SPIxTXB se mueve al registro de desplazamiento, SPIxSR y el bit

SPITBF se pone en “0”.

3. El módulo genera una serie de pulsos (8 o 16) desplazando los bits del dato a transmitir del registro SPIxSR al pin SDOx y simultáneamente desplaza hacia dentro el dato del pin SDIx

en el registro SPIxSR.

4. Cuando se completa la transferencia ocurre lo siguiente: - Se pone en “1” la bandera de interrupción, SPIxIF

- El contenido de SPIxSR (dato recibido) se pasa al registro SPIxRXB y se pone en “1” el bit SPIRBF (SPI Receivet Buffer Full Status bit) (SPIxSTAT<0>) indicando que el buffer de recepción está lleno. Una vez que el usuario lee el registro SPIxBUF se limpia este bit.

5. Si el bit antes indicado (SPIRBF) está en “1” y el módulo necesita transferir datos de

SPIxSR a SPIxRXB, el módulo pondrá en “1” el bit SPIROV (SPIxSTAT<6>) indicando un “desbordamiento”.

6. La transmisión de datos se puede hacer en cualquier momento escribiendo al registro

SPIxBUF, siempre y cuando el bit SPITBF esté en “0”. Esta escritura puede ocurrir mientras se están desplazando bits hacia fuera del registro SPIxSR, permitiendo de esta manera transmisiones continuas.

Existen 2 modos de leer el dato de entrada seleccionables con el bit SMP (SPI Data Input Sample Phase bit) (SPIxCON<9>).

(7)

En la Figura 9-19 se muestra el funcionamiento de una Transmisión/Recepción en modo Maestro.

(8)

Frecuencia del Reloj en modo Maestro

En el modo maestro, el módulo SPI del dsPIC es el que genera la señal de reloj y lo envía por el pin SCKx. Esta señal de reloj es derivada del ciclo de instrucción TCY, el cual pasa por dos divisores de frecuencia (Prescaler primario y prescaler secundario).

El prescaler primario es controlado con los bits PPRE (SPIxCON<1:0>): 00 : Prescaler primario 64:1

01 : Prescaler primario 16:1 10 : Prescaler primario 4:1 11 : Prescaler primario 1:1

El prescaler secundario es controlado con los bits SPRE (SPIxCON<4:2>): 000 : Prescaler secundario 8:1

001 : Prescaler secundario 7:1 010 : Prescaler secundario 6:1 011 : Prescaler secundario 5:1 100 : Prescaler secundario 4:1 101 : Prescaler secundario 3:1 110 : Prescaler secundario 2:1 111 : Prescaler secundario 1:1

De tal forma la frecuencia de la señal de reloj que sale por el pin SCKx está dada por la fórmula:

undario prescaler

rimario prescalerp

FCY FSCK

sec

(9)

9.2.2.2.1

Uso de una memoria EEPROM por SPI

En esta aplicación, usaremos el módulo SPI para comunicarnos con una memoria EEPROM 25LC1024, también llamadas EEPROM Seriales, SEE o E2.

Estas son memorias de bajo costo que contienen 1024kbits o 128kbytes de memoria no volátil.

Figura 9-20. Memoria EEPROM 25LC1024

Principio de Operación de la memoria 25LC1024

La 25LC1024 está diseñada para conectarse directamente con la interface SPI de un microcontrolador, contiene un registro de instrucción de 8 bits, la memoria es accesada a través del pin SI, con los datos muestreados en el flanco ascendente de SCK. El pin CS debe estar en nivel bajo y el pin HOLD en nivel alto durante la operación.

La Tabla 9-4 contiene la lista de las instrucciones que se realizan con la memoria.

(10)

En esta aplicación, el dsPIC funcionará en modo Maestro (MSTEN=1), y de acuerdo a las especificaciones de la memoria, el clock IDLE es nivel bajo y clock ACTIVE es nivel alto (CKP=0), además los datos son muestreados en la transición de Idle a Activo (CKE=0).

A continuación crearemos una librería con funciones para el manejo de la EEPROM.

Librería para manejo de memoria EEPROM

Archivo SEE.C

#include "SEE.h"

// Pines que se usaran para la señal CS #define CSEE _RF0

#define TCSEE _TRISF0

// Configuración del SPI

#define SPI_MASTER 0x0020 // 8-bit modo maestro, CKE=0, CKP=0 #define SPI_ENABLE 0x8000 // habilita SPI

// Comando 25LC1024

#define SEE_WRSR 1 // Escribe en el registro de estado #define SEE_WRITE 2 // Escribe dato

#define SEE_READ 3 // Lee dato

#define SEE_WDI 4 // Deshabilita escritura #define SEE_RDSR 5 // Lee registro de estado #define SEE_WEN 6 // Habilita escritura

// Inicializa el SPI

void IniciaSEE(void) {

TCSEE = 0; // hace el pin CS salida

CSEE = 1; // deselecciona la memoria EEPROM SPI1CON = SPI_MASTER; // configure modulo

SPI1STAT = SPI_ENABLE; // habilita el periférico

} //IniciaSEE

// Envia un dato y recibe uno

int EscribeSPI1( int i) {

SPI1BUF = i; // Escribe en el buffer de transmisión while( !SPI1STATbits.SPIRBF); // Espera a que termine la transferencia return SPI1BUF; // lee el valor recibido

}//EscribeSPI1

(11)

En esta librería, la función IniciaSEE inicializa el módulo SPI y configura el pin CS como salida.

La función EscribeSPI1 es una función bidireccional, la cual escribe un carácter al buffer y luego entra a un ciclo esperando que la bandera indique que se completó la transmisión y que se recibió un dato de regreso. Este dato recibido es regresado por la función.

Cuando nos comunicacmos con la memoria, hay ocasiones en que cuando enviamos un comando no recibimos nada, en este caso el valor regresado simplemente lo ignoramos. También hay casos en que se leen datos de la memoria pero no necesitamos enviar datos, en este caso podemos enviar un dato sin importancia mientras leemos el dato importante.

El Registro de Estado

La intrucción de lectura de registro de estado de la SEE (RDSR) nos permite conocer el estado de la memoria, el registro de estado tiene la siguiente forma:

Figura 9-21. Registro de Estado

En donde BP1 y BP0 nos indican que bloques de código están actualmente protegidos de acuerdo a la siguiente tabla:

(12)

El bit WEL (Write Enable Latch) indica el estado del Latch de habilitación de escritura y es de sólo lectura. Cuando lo ponemos en “1”, se permite la escritura, y cuando está en “0” no se permite la escritura, su valor al encender es de “0”. El valor de este bit puede ser actualizado por medio de los comandos WREN o WRDI sin importar el estado de protección de escritura.

El bit WIP (Write-in-Process) indica si la memoria está ocupada en una operación de escritura (“1”=ocupada, “0”=no ocupada). Es de solo lectura.

De acuerdo a la especificación de la memoria 25LC1024, para realizar una lectura del registro de estado (comando RDSR) se debe hacer de la siguiente manera:

Figura 9-22. Lectura del registro de estado

Esta operación puede realizarse de la siguiente manera:

CSEE = 0;

EscribeSPI1(SEE_STAT); // commando RDSR

i = EscribeSPI1( 0); // Envia dato sin importancia, lee registro de estado

CSEE = 1;

Para habilitar la escritura enviamos el comando WREN de la siguiente manera:

CSEE = 0;

(13)

Escribir en la EEPROM

Una vez que está habilitada la escritura, el usuario puede proceder a realizar una escritura en la SEE como se muestra en la Figura 9-23.

Figura 9-23. Secuencia para escribir un Byte

Primero se pone en nivel bajo CS, luego se envía una instrucción de escritura seguida de una dirección de 24 bits, donde los 7 bits más significativos no importan, y luego el dato que se desea escribir.

Una escritura se puede hacer de la siguiente manera:

// Escritura de un byte

CSEE = 0;

EscribeSPI1(SEE_WRITE); // Envia commando de escritura, ignora dato leido

EscribeSPI1(DIRECION_ALTA); // envía la parte alta de la dirección

EscribeSPI1(DIRECCION_MEDIA); // envía la parte media de la dirección EscribeSPI1(DIRECCION_BAJA); // envía la parte baja de la dirección

EscribeSPI1(dato); // envía el dato

CSEE = 1;

(14)

Un aspecto a tomar en cuenta es que cuando se realiza una escritura de menos de 256 bytes, los bytes restantes de la página se refrescan junto con los bytes escritos. Por esta razón, la resistencia de la memoria se especifica por páginas.

Figura 9-24. Escritura de página

(15)

Leer de la EEPROM

La lectura de la EEPROM es similar a la escritura pero en esta ocasión el dato sale por el pin SO de la memoria como se muestra en la Figura 9-25.

Figura 9-25. Secuencia para leer un byte

Se pueden realizar lecturas posteriores aprovechando la misma instrucción; en este caso el puntero de dirección interno se incremente automáticamente a la siguiente dirección. Si se llega a la última dirección (1FFFFh), el puntero se reinicia a 00000h, permitiendo ciclos de lectura de forma indefinida. La operación de lectura termina poniendo en nivel alto CS.

// Envia commando de lectura

CSEE = 0;

EscribeSPI1(SEE_READ); // Envía commando de lectura, ignora el dato leido

EscribeSPI1(DIRECION_ALTA); // envía la parte alta de la dirección

EscribeSPI1(DIRECCION_MEDIA); // envía la parte media de la dirección

EscribeSPI1(DIRECCION_BAJA); // envía la parte baja de la dirección

dato = EscribeSPI(0); // envía dato sin importancia, lee dato

// Aqui se pueden poner más lecturas

(16)

Librería Extendida para manejo de memoria SEE

A continuación se agregan más funciones a nuestra librería anterior.

Archivo SEE.C

#include <p30fxxxx.h> #include "SEE.h"

// Pines que se usaran para la señal CS #define CSEE _RF0

#define TCSEE _TRISF0

// Configuración del SPI

#define SPI_MASTER 0x0020 // 8-bit modo maestro, CKE=0, CKP=0 #define SPI_ENABLE 0x8000 // habilita SPI

// Comando 25LC1024

#define SEE_WRSR 1 // Escribe en el registro de estado #define SEE_WRITE 2 // Escribe comando

#define SEE_READ 3 // Lee comando

#define SEE_WDI 4 // Deshabilita escritura #define SEE_RDSR 5 // Lee registro de estado #define SEE_WEN 6 // Habilita escritura

/* Inicializa el SPI */ void IniciaSEE(void) {

TCSEE = 0; // hace el pin CS salida

CSEE = 1; // deselecciona la memoria EEPROM SPI1CON = SPI_MASTER; // configure modulo

SPI1STAT = SPI_ENABLE; // habilita el periférico

} //IniciaSEE

/* Envia un dato y recibe uno */ int EscribeSPI1( int i)

{

SPI1BUF = i; // Escribe en el buffer de transmisión while( !SPI1STATbits.SPIRBF); // Espera a que termine la transferencia return SPI1BUF; // lee el valor recibido

}//EscribeSPI1

/* Revisa el registro de estado */ int LeeSR(void)

{

int i; CSEE = 0;

EscribeSPI1(SEE_RDSR); i = EscribeSPI1(0); CSEE = 1;

(17)

/* Lee un dato de 16 bits empezando en una dirección par */ int LeeInt(long direccion)

{

int lsb, msb;

// Se espera hasta que se complete cualquier trabajo en progreso while ( LeeSR() & 0x1); // Revisa bit WIP

// Realiza una secuencia de lectura de 16 bits, es decir 2 lecturas consecutivas CSEE = 0;

EscribeSPI1(SEE_READ); // comando de lectura

EscribeSPI1(direccion>>16); // parte alta de la direccion EscribeSPI1(direccion>>8); // parte media de la direccion

EscribeSPI1(direccion & 0xFE); // parte baja de la direccion alineada msb = EscribeSPI1(0); // envia dato sin importancia, lee el msb lsb = EscribeSPI1(0); // envia dato sin importancia, lee el lsb

CSEE = 1;

return ( (msb<<8)+ lsb);

}//LeeInt

/* Habilita la escritura */ void HabilitaEscrituraSEE( void) {

CSEE = 0;

EscribeSPI1(SEE_WEN); CSEE = 1;

}//HabilitaEscritura

/* Escribe un dato de 16 bits en la SEE empezando en una direccion par */ void EscribeInt( long direccion, int dato)

{

// Se espera hasta que se complete cualquier trabajo en progreso while ( LeeSR() & 0x1); // Revisa bit WIP

// Realiza una escritura de página de 2 bytes CSEE = 0;

EscribeSPI1(SEE_WRITE); // Comando de escritura

EscribeSPI1(direccion>>16); // parte alta de la direccion EscribeSPI1(direccion>>8); // parte media de la direccion

EscribeSPI1(direccion & 0xFE); // parte baja de la direccion alineada EscribeSPI1(dato >> 8); // envia msb

EscribeSPI1(dato & 0xff); // envia lsb

CSEE = 1; }//EscribeInt

(18)

Archivo SEE.H

/* LIBRERIA SEE

* PARA MANEJO DE UNA MEMORIA EEPROM SERIAL 25LC1024

*/

void IniciaSEE(void);

int EscribeSPI1( int i);

int LeeSR(void);

int LeeInt(long direccion);

void HabilitaEscrituraSEE( void);

void EscribeInt( long direccion, int dato);

Programa 9-8. SEE.H

Ejemplo 9-3. Lee y Escribe en la SEE

El siguiente ejemplo hace uso de la librería anterior para leer un dato de una dirección de memoria, lo incrementa y guarda de nuevo. De tal manera que si este programa lo ejecuta varias veces reseteando el dsPIC, se debe de ver el valor incrementandose; inclusive si apaga el circuito y lo alimenta de nuevo.

#include <p30fxxxx.h> #include <stdio.h>

#include "../../librerias/SEE/SEE.h" #include "../../librerias/UART/uart1.h"

_FOSC(CSW_FSCM_ON & XT_PLL16); _FWDT(WDT_OFF); _FBORPOR(MCLR_EN & PWRT_64); _FGS(CODE_PROT_OFF);

int main() {

int dato;

(19)

// Habilita la escritura

HabilitaEscrituraSEE ();

// lee el contenido de la direccion de memoria 0x1234 dato = LeeInt(0x1234);

// Lo muestra en Hyperterminal printf("%d",dato);

// incrementa el valor actual dato++;

// Escribe el dato de vuelta EscribeInt( 0x1234, dato);

while(1);

} //main

Programa 9-9. Lee y escribe en la SEE

La ventana de proyecto debe verse como la siguiente:

(20)

Modo Esclavo

Para configurar el módulo SPI en modo esclavo: 1. Limpie el registro SPIxBUF.

2. Si usa interrupciones:

• Limpie el bit SPIxIF en el registro IFSn correspondiente.

• Active el bit SPIxIE en el registro IECn correspondiente.

• Configure la prioridad en los bits SPIxIP del registro IPCn correspondiente.

3. Configure el módulo en el registro SPIxCON con MSTEN (SPIxCON<5>) = 0. 4. Limpie el bit SMP (SPIxCON<9>).

5. Si el bit CKE está activo, entonces debe activar SSEN habilitando el pin SSx. 6. Limpie el bit SPIROV (SPIxSTAT<6>).

7. Habilite el módulo SPI activando el bit SPIEN (SPIxSTAT<15>).

En el modo Esclavo, los datos son transmitidos y recibidos mientras llegan pulsos en el pin

SCKx. Al igual que en modo Maestro, los bits CKP y CKE determinan el flanco de la transmisión y todo dato es enviado o leido del registro SPIxBUF.

Sincronización por Slave Select

El pin SSx permite el modo esclavo sincronizado. Si el bit SSEN (SPIxCON<7>) está en “1”, se permite la transmisión o recepción sólo si el pin SSx tiene un nivel bajo.

Operación Solo Recepción

Referencias

Documento similar

&#34;No porque las dos, que vinieron de Valencia, no merecieran ese favor, pues eran entrambas de tan grande espíritu […] La razón porque no vió Coronas para ellas, sería

Cedulario se inicia a mediados del siglo XVIL, por sus propias cédulas puede advertirse que no estaba totalmente conquistada la Nueva Gali- cia, ya que a fines del siglo xvn y en

Si se tiene en cuenta la distinción existente entre los con- ceptos de objeto material y objeto formal o método, el tridimensionalismo jurídico sería el enfoque de lo jurídico,

La última de las mesas, integrada por representantes del sector privado, abordará soluciones aplicadas a situaciones reales de Datos Abiertos para que sirvan de acicate a

b) El Tribunal Constitucional se encuadra dentro de una organiza- ción jurídico constitucional que asume la supremacía de los dere- chos fundamentales y que reconoce la separación

Primeros ecos de la Revolución griega en España: Alberto Lista y el filohelenismo liberal conservador español 369 Dimitris Miguel Morfakidis Motos.. Palabras de clausura

SelO Señal de control a un multiplexor que selecciona como dato a escribir en el registro de estado como flag de Overflow, el bit 2 del registro acumulador o el indicador de