SPI-STM32 (1)

• Pensado para comunicación con otros Microcontroladores o Periféricos: EEPROM serie (almacenamiento de datos no volátil

Views 114 Downloads 8 File size 2MB

Report DMCA / Copyright

DOWNLOAD FILE

Recommend stories

Citation preview

• 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 SDO

SDI

ESLAVO SDO SDI

• PROTOCOLO MAESTRO ESCLAVO • TRANSMISIÓN A CUATRO HILOS • TRANSMISIÓN SÍNCRONA

SCK

SCK

SS

SS

GERSON ABDIEL PEREZ VILLARROEL

• FULL-DUPLEX • SELECCIÓN DE ESCLAVO

SDO SDI MAESTRO SCK SS3 SS2 SS1

GERSON ABDIEL PEREZ VILLARROEL

SDO SDI SCK SS

ESLAVO 1

SDO SDI SCK SS

ESLAVO 2

SDO SDI SCK SS

ESLAVO 3

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

SDI

MISO

MISO

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 00 11 22 33

Lectura de dato dato yy cambio cambio de de tiempo tiempo Lectura de Lee Lee en en pendiente pendiente de de subida subida yy cambia cambia en en pendiente pendiente de de bajada bajada Lee Lee en en pendiente pendiente de de bajada bajada yy cambia cambia en en pendiente pendiente de de subida subida Lee Lee en en pendiente pendiente de de bajada bajada yy cambia cambia en en pendiente pendiente de de subida subida Lee Lee en en pendiente pendiente de de subida subida yy cambia cambia en en pendiente pendiente de de bajada bajada

CPOL CPOL

CPHA CPHA

00 00

00 11

11 11

00 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 { uint32_t Mode uint32_t Direction uint32_t DataSize uint32_t CLKPolarity uint32_t CLKPhase uint32_t NSS uint32_t BaudRatePrescaler uint32_t FirstBit uint32_t TIMode }SPI_InitTypeDef;

Especifica el tipo de configuración que tendrá el esclavo con el maestro: SPI_DIRECTION_2LINES - Modo full-duplex a 4 cables SPI_DIRECTION_2LINES_RXONLY - Modo Half-duplex a 4 cables SPI_DIRECTION_1LINE - Modo Half-duplex a 3 cables Especifica el tamaño de los bit a transmitir: SPI_DATASIZE_8BIT SPI_DATASIZE_16BIT Especifica la polaridad de SDK: SPI_POLARITY_LOW (CPOL=0) SPI_POLARITY_HIGH (CPOL= 1) 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:

Typedef struct { uint32_t Mode uint32_t Direction uint32_t DataSize uint32_t CLKPolarity uint32_t CLKPhase uint32_t NSS uint32_t BaudRatePrescaler uint32_t FirstBit uint32_t TIMode }SPI_InitTypeDef;

Especifica el comportamiento del pin NSS: SPI_NSS_SOFT SPI_NSS_HARD_INPUT SPI_NSS_HARD_OUTPUT Especifica el valor del pre-escalador de velocidad en baudios que se utilizará para configurar el reloj SCK de transmisión y recepción. Nota: El reloj de comunicación se deriva del reloj maestro. El reloj esclavo no necesita ser configurado. SPI_BAUDRATEPRESCALER_2 SPI_BAUDRATEPRESCALER_4 SPI_BAUDRATEPRESCALER_8 SPI_BAUDRATEPRESCALER_16 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 uint32_t Direction uint32_t DataSize uint32_t CLKPolarity uint32_t CLKPhase uint32_t NSS uint32_t BaudRatePrescaler uint32_t FirstBit uint32_t TIMode }SPI_InitTypeDef;

Especifica si las transferencias de datos comienzan desde MSB o un bit LSB. Este parámetro puede ser: SPI_FIRSTBIT_MSB SPI_FIRSTBIT_LSB

Especifica si el modo TI está habilitado o no. Este campo es utilizado para activar o desactivar la modalidad Texas Instrument. Este parámetro 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)); } }