Buscar este blog

martes, 11 de noviembre de 2014

PRACTICA # 18 Protocolo de comunicación SPI en PS


INTRODUCCION

  • El Bus SPI (del inglés Serial Peripheral Interface) es un estándar de comunicaciones, usado principalmente para la transferencia de información entre circuitos integrados en equipos electrónicos. El bus de interfaz de periféricos serie o bus SPI es un estándar para controlar casi cualquier dispositivo electrónico digital que acepte un flujo de bits serie regulado por un reloj (comunicación sincrónica).
  • Incluye una línea de reloj, dato entrante, dato saliente y un pin de chip select, que conecta o desconecta la operación del dispositivo con el que uno desea comunicarse. De esta forma, este estándar permite multiplexar las líneas de reloj.
  • Muchos sistemas digitales tienen periféricos que necesitan existir pero no ser rápidos. La ventajas de un bus serie es que minimiza el número de conductores,pines y el tamaño del circuito integrado. Esto reduce el coste de fabricar montar y probar la electrónica. Un bus de periféricos serie es la opción más flexible cuando se tiene tipos diferentes de periféricos serie. El hardware consiste en señales de reloj, data in,
    data out y chip select para cada circuito integrado que tiene que ser controlado. Casi cualquier dispositivo digital puede ser controlado con esta combinación de señales. Los dispositivos se diferencian en un número predecible de formas. Unos leen el dato cuando el reloj sube otros cuando el reloj baja. Algunos lo leen en el flanco de subida del reloj y otros en el flanco de bajada. Escribir es casi siempre en la dirección opuesta de la dirección de movimiento del reloj. Algunos dispositivos tienen dos relojes. Uno para capturar o mostrar los datos y el otro para el dispositivo interno.



El SPI es un protocolo síncrono. La sincronización y la transmisión de datos se realizan por medio de 4 señales:

·         SCLK (Clock): Es el pulso que marca la sincronización. Con cada pulso de este reloj, se lee o se envía un bit. También llamado TAKT (en Alemán).
·         MOSI (Master Output Slave Input): Salida de datos del Master y entrada de datos al Slave. También llamada SIMO.
·         MISO (Master Input Slave Output): Salida de datos del Slave y entrada al Master. También conocida por SOMI.
·         SS/Select: Para seleccionar un Slave, o para que el Master le diga al Slave que se active. También llamada SSTE.

La Cadena de bits es enviada de manera síncrona con los pulsos del reloj, es decir con cada pulso, el Master envía un bit. Para que empiece la transmisión el Master baja la señal SSTE ó SS/Select a cero, con esto el Slave se activa y empieza la transmisión, con un pulso de reloj al mismo tiempo que el primer bit es leído. Nótese que los pulsos de reloj pueden estar programados de manera que la transmisión del bit se realice en 4 modos diferentes, a esto se llama polaridad y fase de la transmisión:

·         1. Con el flanco de subida sin retraso.
·         2. Con el flanco de subida con retraso.
·         3. Con el flanco de bajada sin retraso.
·         4. Con el flanco de bajada con retraso.



  • Ejemplo de Frame SPI;


  • OBJETIVO.


Para iniciar la comunicación SPI con la tarjeta Zedboard debemos tener previamente un esclavo y un maestro que valide el sistema de comunicación. Para ello se propone un esquema de microcontroladores como el de la siguiente imagen:



  • El esquemático está compuesto por dos microcontroladores PIC18F2550 configurados con oscilador interno a 8 Mhz, velocidad de 2 Mhz en SPI, una terminal RS232 y un led de estatus en el PIN_B7.
  • La transmisión de ambos microcontroladores está configurada en MODO_A o MODO_0 como se muestra en la siguiente figura:



  • En la siguiente figura se muestran armados en un protoboard:



  • La idea es transferir 64 bytes del maestro al esclavo y este a su vez los retransmite nuevamente al maestro.
  • Maestro [0, 1, 2, … 63]  à Esclavo [0, 1, 2, … 63]  à Maestro [0, 1, 2, … 63] 


  • En la siguiente figura se muestra las transmisiones recibidas entre ambos:


  • Los códigos hexadecimales los puedes bajar de aquí:


ESCLAVO:
MAESTRO:

  • Ahora desarrollaremos la etapa del SPI Maestro con la Zedboard. Iniciando con la construcción de bloques en vivado de la siguiente manera:


  • La configuración en Zynq del SPI se muestra a continuación:




  • El código en SDK de eclipse es:


/***************************** Include Files *********************************/

#include "xparameters.h"            /* SDK generated parameters */
#include "xspips.h"                 /* SPI device driver */
#include "xil_printf.h"
#include "xgpio.h"

/************************** Constant Definitions *****************************/
/*
 * The following constant map to the XPAR parameters created in the
 * xparameters.h file. They are defined here such that a user can easily
 * change all the needed parameters in one place.
 */
#define SPI_DEVICE_ID               XPAR_XSPIPS_0_DEVICE_ID
#define GPIO_EXAMPLE_DEVICE_ID  XPAR_AXI_GPIO_0_DEVICE_ID
#define LED_CHANNEL 1

/*
 * The following constant specify the max amount of data the slave is
 * expecting to receive from the master.
 */
#define TEST_BUFFER_SIZE            64

//************************** Function Prototypes ******************************/

int SpiPsMasterPolledExample(XSpiPs *SpiInstancePtr, u16 SpiDeviceId);

/************************** Variable Definitions *****************************/
/*
 * The instances to support the device drivers are global such that they
 * are initialized to zero each time the program runs. They could be local
 * but should at least be static so they are zeroed.
 */
static XSpiPs SpiInstance;
XGpio Gpio;        // The Instance of the GPIO Driver

/*
 * The ReadBuffer is used to read to the data which it received from the SPI
 * Bus which master has sent.
 */

u8 SendBuffer[TEST_BUFFER_SIZE];    /**< Buffer for Transmitting Data */
u8 RecvBuffer[TEST_BUFFER_SIZE];    /**< Buffer for Receiving Data */

/*****************************************************************************/
/**
*
* Main function to call the SPI Slave Example.
*
* @param    None
*
* @return
*                       - XST_SUCCESS if successful
*                       - XST_FAILURE if not successful
*
* @note                 None
*
******************************************************************************/
int main(void)
{
            int Status;

            // Initialize the GPIO driver

            Status = XGpio_Initialize(&Gpio, GPIO_EXAMPLE_DEVICE_ID);
            if (Status != XST_SUCCESS) {
                 return XST_FAILURE;
            }

            // Clear the LEDs
            XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, 0);

            xil_printf(Microcarsil, 2014\n");

            xil_printf("Running SpiPS Master Polled Example \r\n");

            /*
             * Run the SpiPs Slave Polled example.
             */
            Status = SpiPsMasterPolledExample(&SpiInstance, SPI_DEVICE_ID);
            if (Status != XST_SUCCESS) {
                        xil_printf("SpiPs Master Polled Example Failed \r\n");
                        return XST_FAILURE;
            }

            xil_printf("Successfully ran SpiPs Master Polled Example \r\n");
            return XST_SUCCESS;
}

/*****************************************************************************
*
* The purpose of this function is to illustrate how to use the XSpiPs
* device driver in Slave mode. This function reads data from a SPI Master
* and will echo it back to the Master.
*
* @param    SpiDeviceId is the Instance Id of SPI in the system.
*
* @return
*                       - XST_SUCCESS if successful
*                       - XST_FAILURE if not successful
*
* @note                 None
*
*
*****************************************************************************/
int SpiPsMasterPolledExample(XSpiPs *SpiInstancePtr, u16 SpiDeviceId)
{
            int Status;
            unsigned char i=1;
            int Index;

            XSpiPs_Config *SpiConfig;

            for (Index = 0; Index < TEST_BUFFER_SIZE; Index++)
            {
                                    SendBuffer[Index] = Index;
                                    RecvBuffer[Index] = 0;
            }

            /*
             * Initialize the SPI driver so that it's ready to use
             */
            SpiConfig = XSpiPs_LookupConfig(SpiDeviceId);
            if (NULL == SpiConfig) {
                        return XST_FAILURE;
            }

            Status = XSpiPs_CfgInitialize(SpiInstancePtr, SpiConfig,
                                                            SpiConfig->BaseAddress);
            if (Status != XST_SUCCESS) {
                        return XST_FAILURE;
            }

            /*
            * Perform a self-test to check hardware build
            */
            Status = XSpiPs_SelfTest(SpiInstancePtr);
            if (Status != XST_SUCCESS) {
                                    return XST_FAILURE;
                        }

            XSpiPs_SetOptions(SpiInstancePtr, XSPIPS_MASTER_OPTION |  XSPIPS_FORCE_SSELECT_OPTION | XSPIPS_DECODE_SSELECT_OPTION | XSPIPS_MANUAL_START_OPTION//);// | control_val
                                    | XSPIPS_CLK_PHASE_1_OPTION | XSPIPS_CLK_ACTIVE_LOW_OPTION );

            XSpiPs_SetDelays(SpiInstancePtr, 255,255,255,255);

            XSpiPs_SetClkPrescaler(SpiInstancePtr, XSPIPS_CLK_PRESCALE_128);  // 1.25 Mhz

            XSpiPs_SetSlaveSelect(SpiInstancePtr, 0x1);


            while(1)
            {
                        XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, i++);

                        for(Index = 0; Index < TEST_BUFFER_SIZE; Index ++)
                        {
                                    XSpiPs_PolledTransfer(SpiInstancePtr, &SendBuffer[Index], NULL,1);
                                    usleep(50);      // 50 us
                        }
                        usleep(50000);      // 50 ms

                        for(Index = 0; Index < TEST_BUFFER_SIZE; Index ++)
                        {
                                                XSpiPs_PolledTransfer(SpiInstancePtr, &RecvBuffer[Index], &RecvBuffer[Index],1);
                                                usleep(50);      // 50 us
                        }

                        /*
                        * Verify received data is correct.
                        */
                        for(Index = 0; Index < TEST_BUFFER_SIZE; Index ++)
                        {
                                     xil_printf(" Master[%d] = %d\n",Index,RecvBuffer[Index]);
                        }

                        usleep(2000000);
            }

            return XST_SUCCESS;
}

  • Hacemos las mediciones respectivas del bus SPI con el analizador Analog Discovery Digilent: 

  • Sustituimos el microcontrolador maestro pic18f2550 por la zedboardy conectamos como se muestra en la siguiente figura:

  • Funcionando correctamente en debug:

  • SPI corriendo en la ZedBoard:














No hay comentarios.:

Publicar un comentario