• Pensado para comunicación con otros Microcontroladores o Periféricos:
EEPROM serie (almacenamiento de datos no volátiles)
Registros de Desplazamiento (expansión de entradas y/o salidas)
Drivers de Displays (reducción de conexiones)
Conversores A/D (digitalización externa de señales)
• Permite la transmisión y recepción síncrona simultánea de datos de 8 bits.
• Para la comunicación debe existir un dispositivo Maestro (genera la señal
de reloj)y uno ó varios esclavos (reciben la señal de reloj).
MAESTRO ESLAVO
SDO • PROTOCOLO MAESTRO ESCLAVO
SDO
• TRANSMISIÓN A CUATRO HILOS
SDI SDI
• TRANSMISIÓN SÍNCRONA
SCK SCK
• FULL-DUPLEX
SS SS • SELECCIÓN DE ESCLAVO
GERSON ABDIEL PEREZ VILLARROEL
SDO
SDI ESLAVO 1
SCK
SDO
SS
SDI
MAESTRO
SCK
SS3 SS2 SS1 SDO
SDI ESLAVO 2
SCK
SS
SDO
SDI ESLAVO 3
SCK
SS
GERSON ABDIEL PEREZ VILLARROEL
ENVÍO/RECEPCIÓN
SIMULTÁNEA
Situación Inicial
GERSON ABDIEL PEREZ VILLARROEL
Situación Inicial
Situación Final
Intercambiados los 8 bits de
datos
GERSON ABDIEL PEREZ VILLARROEL
GERSON ABDIEL PEREZ VILLARROEL
INTERFACE SPI EN STM32
MAESTRO ESLAVO MAESTRO ESLAVO
SDO SDO MOSI MOSI
SDI MISO MISO
SDI
SCK SCK SCK SCK
SS SS SS SS
GERSON ABDIEL PEREZ VILLARROEL
INTERFACE SPI EN STM32
INTERFACE SPI EN STM32
Polaridad del Reloj
La polaridad del reloj se refiere al valor de tensión que tiene la salida del reloj cando no esta generando la
señal periódica. Por tanto, la salida puede mantenerse en alto o bajo mientras no se este enviado datos. Esta
polaridad es establecida por el bit de control CPOL.
Modos de envío de datos
Hay cuatro combinaciones de fase SCK y polaridad con respecto a los datos en serie, que están
determinados por los bits de control CPHA y CPOL. Los bits de datos se desplazan hacia afuera y se acoplan
en los bordes opuestos de la señal SCK, lo que garantiza un tiempo suficiente para que las señales de datos
se estabilicen. La siguiente tabla resume las configuraciones de SPCR.CPOL y SPCR.CPHA.
MODO SPI Lectura de dato y cambio de tiempo CPOL CPHA
0 Lee en pendiente de subida y cambia en pendiente de bajada 0 0
1 Lee en pendiente de bajada y cambia en pendiente de subida 0 1
2 Lee en pendiente de bajada y cambia en pendiente de subida 1 0
3 Lee en pendiente de subida y cambia en pendiente de bajada 1 1
MODO SPI
MODO SPI Lectura de dato
Lectura de dato yy cambio
cambio de
de tiempo
tiempo CPOL
CPOL CPHA
CPHA
00 Lee
Lee en
en pendiente
pendiente de
de subida
subida yy cambia
cambia enen pendiente
pendiente de
de bajada
bajada 00 00
11 Lee
Lee en
en pendiente
pendiente de
de bajada
bajada yy cambia
cambia en
en pendiente
pendiente de
de subida
subida 00 11
22 Lee
Lee en
en pendiente
pendiente de
de bajada
bajada yy cambia
cambia en
en pendiente
pendiente de
de subida
subida 11 00
33 Lee
Lee en
en pendiente
pendiente de
de subida
subida yy cambia
cambia en
en pendiente
pendiente de
de bajada
bajada 11 11
Interface SPI en el módulo SSP
La estructura principal de configuración del periférico SPI es:
Especifica modo maestro o esclavo: SPI_MODE_MASTER
SPI_MODE_SLAVE
Typedef struct
{ Especifica el tipo de configuración que tendrá el esclavo con el maestro:
uint32_t Mode SPI_DIRECTION_2LINES - Modo full-duplex a 4 cables
uint32_t Direction SPI_DIRECTION_2LINES_RXONLY - Modo Half-duplex a 4 cables
uint32_t DataSize SPI_DIRECTION_1LINE - Modo Half-duplex a 3 cables
uint32_t CLKPolarity
Especifica el tamaño de los bit a transmitir:
uint32_t CLKPhase
SPI_DATASIZE_8BIT SPI_DATASIZE_16BIT
uint32_t NSS
uint32_t BaudRatePrescaler Especifica la polaridad de SDK: SPI_POLARITY_LOW (CPOL=0)
uint32_t FirstBit SPI_POLARITY_HIGH (CPOL= 1)
uint32_t TIMode
}SPI_InitTypeDef; Especifica la fase de SDK: SPI_PHASE_1EDGE (CPHA=0 )
SPI_PHASE_2EDGE (CPHA=1 )
La estructura principal de configuración del periférico spi es:
Especifica el comportamiento del pin NSS:
SPI_NSS_SOFT
Typedef struct SPI_NSS_HARD_INPUT
{ SPI_NSS_HARD_OUTPUT
uint32_t Mode
uint32_t Direction Especifica el valor del pre-escalador de velocidad en baudios que se
uint32_t DataSize utilizará para configurar el reloj SCK de transmisión y recepción.
uint32_t CLKPolarity Nota: El reloj de comunicación se deriva del reloj maestro. El reloj esclavo
uint32_t CLKPhase no necesita ser configurado.
uint32_t NSS SPI_BAUDRATEPRESCALER_2
uint32_t BaudRatePrescaler SPI_BAUDRATEPRESCALER_4
uint32_t FirstBit SPI_BAUDRATEPRESCALER_8
uint32_t TIMode SPI_BAUDRATEPRESCALER_16
}SPI_InitTypeDef; SPI_BAUDRATEPRESCALER_32
SPI_BAUDRATEPRESCALER_64
SPI_BAUDRATEPRESCALER_128
SPI_BAUDRATEPRESCALER_256
La estructura principal de configuración del periférico spi es:
Typedef struct
{
uint32_t Mode Especifica si las transferencias de datos comienzan desde MSB o un bit
uint32_t Direction LSB. Este parámetro puede ser: SPI_FIRSTBIT_MSB SPI_FIRSTBIT_LSB
uint32_t DataSize
uint32_t CLKPolarity
uint32_t CLKPhase
uint32_t NSS
uint32_t BaudRatePrescaler
uint32_t FirstBit Especifica si el modo TI está habilitado o no. Este campo es utilizado
uint32_t TIMode para activar o desactivar la modalidad Texas Instrument. Este parámetro
}SPI_InitTypeDef; puede ser:
SPI_TIMODE_DISABLE SPI_TIMODE_ENABLE
Para inicializar la configuración del periférico se ejecuta la función:
HAL_SPI_Init (SPI_HandleTypeDef * hspi);
Para el Envío y Recepción de bytes de datos se usan la funciones provistas dentro de la librería HAL.
FUNCIONES POR SONDEO PARA LA CONFIGURACION MAESTRO Y ESCLAVO
• HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout);
• HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout);
Si el dispositivo esclavo tiene la capacidad de entablar la comunicacion Full-Duplex se puede usar la siguiente funcion para realizar
la transmission y recepcion de manera simultaneal.
• HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size, uint32_t Timeout);
FUNCIONES POR INTERRUPCION PARA LA CONFIGURACION MAESTRO Y ESCLAVO
HAL_SPI_Transmit_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size);
HAL_SPI_Receive_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size);
HAL_SPI_TransmitReceive_IT(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size);
Parámetros de las funciones
• hspi: Puntero a la estructura SPI_HandleTypeDef que contiene la información de la configuración
spi específica.
• pData: Puntero al buffer de datos. Especifica los bytes a enviar si es transmisor o los bytes a
recibir si es receptor.
• Size: Cantidad de datos a enviar.
• Timeout: Tiempo de espera para ejecutar la función.
PARA HABILITAR LA INTERRUPCION SE DEBE USAR LA FUNCION
• SPIx_IRQHandler( );
Las funciones de interrupcion llama a la function SPIX_IRQHandler( ); que a su vez llamara a una de las siguientes subrutinas
predefinidas:
• HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi);
• HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi);
• HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi);
Crear un programa maestro y un programa esclavo entre los cuales se pueda trasmitir un texto desde el
maestro hacia el esclavo en modo sondeo, haciendo uso del periférico SPI. El esclavo debe mostrar este
texto en la consola de una computadora usando el modulo UART.
MAESTRO:
SOLUCIÓN void SPI_Init(void)
{
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_1LINE;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLED;
__HAL_RCC_SPI1_CLK_ENABLE();
HAL_SPI_Init(&hspi1);
}
Crear un programa maestro y un programa esclavo entre los cuales se pueda trasmitir un texto desde el
maestro hacia el esclavo en modo sondeo, haciendo uso del periférico SPI. El esclavo debe mostrar este
texto en la consola de una computadora usando el modulo UART.
MAESTRO:
SOLUCIÓN
uint8_t texto [12]=“HOLA MUNDO\r\n”;
...
While(1)
{
HAL_SPI_Transmit(&hspi1,texto,sizeof(texto),HAL_MAX_DELAY);
HAL_Delay(500);
}
Crear un programa maestro y un programa esclavo entre los cuales se pueda trasmitir un texto desde el
maestro hacia el esclavo en modo sondeo, haciendo uso del periférico SPI. El esclavo debe mostrar este
texto en la consola de una computadora usando el modulo UART.
ESCLAVO:
SOLUCIÓN void SPI_Init(void)
{
hspi1.Instance = SPI2;
hspi1.Init.Mode = SPI_MODE_SLAVE;
hspi1.Init.Direction = SPI_DIRECTION_1LINE;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_HARD_INPUT ;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLED;
__HAL_RCC_SPI1_CLK_ENABLE();
HAL_SPI_Init(&hspi1);
}
Crear un programa maestro y un programa esclavo entre los cuales se pueda trasmitir un texto desde el
maestro hacia el esclavo en modo sondeo, haciendo uso del periférico SPI. El esclavo debe mostrar este
texto en la consola de una computadora usando el modulo UART.
ESCLAVO:
SOLUCIÓN
char texto1 [12];
...
While(1)
{
HAL_SPI_Receive(&hspi2,texto1,sizeof(texto1),HAL_MAX_DELAY);
HAL_UART_Transmit(&huart1,texto1,sizeof(texto1),HAL_MAX_DELAY);
}
Escribir un programa esclavo SPI, el cual reciba un texto desde el maestro en modo INTERRUPCIÓN,
haciendo uso del periférico SPI. El esclavo debe mostrar este texto en la consola de una computadora
usando el modulo UART.
SOLUCIÓN void MX_SPI_Init(void)
{
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_SLAVE;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
__HAL_RCC_SPI2_CLK_ENABLE();
HAL_SPI_Init(&hspi2);
HAL_NVIC_SetPriority(SPI2_IRQn, 0, 0); // habilitación de las interrupciones
HAL_NVIC_EnableIRQ(SPI2_IRQn);
}
Escribir un programa esclavo SPI, el cual reciba un texto desde el maestro en modo INTERRUPCIÓN,
haciendo uso del periférico SPI. El esclavo debe mostrar este texto en la consola de una computadora
usando el modulo UART.
SOLUCIÓN
#include "stm32f1xx.h"
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_UART1_Init(void);
static void MX_SPI_Init(void);
UART_HandleTypeDef huart1;
SPI_HandleTypeDef hspi2;
char texto[12];
Escribir un programa esclavo SPI, el cual reciba un texto desde el maestro en modo INTERRUPCIÓN,
haciendo uso del periférico SPI. El esclavo debe mostrar este texto en la consola de una computadora
usando el modulo UART. int main(void)
{
SOLUCIÓN HAL_Init();
SystemClock_Config();
MX_HAL_UART1_Init();
MX_GPIO_Init();
MX_SPI_Init();
HAL_SPI_Receive_IT(&hspi2, texto, sizeof(texto));
uint8_t aux=0;
while(1)
{ if(aux==1)
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_10);
aux=0;
}
}
}
Escribir un programa esclavo SPI, el cual se reciba un texto desde el maestro en modo INTERRUPCIÓN,
haciendo uso del periférico SPI. El esclavo debe mostrar este texto en la consola de una computadora
usando el modulo UART.
SOLUCIÓN
void SPI2_IRQHandler(void)
{
HAL_SPI_IRQHandler(&hspi2);
}
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
{
if (hspi->Instance == SPI2)
{
aux=1;
HAL_UART_Transmit(&huart1,texto,sizeof(texto),HAL_MAX_DELAY);
HAL_SPI_Receive_IT(&hspi2, texto,sizeof(texto));
}
}