SPI — один из самых распространенных интерфейсов для передачи данных между цифровыми микросхемами.
Естественно STM не обошли стороной его в своих микроконтроллерах.
Напишем программу, которая передаёт данные из SPI1 в SPI2, а затем проверяет правильность передачи.
Я буду использовать (как и во всех других статьях) stm32f4-discovery с мк stm32f407vgt6.
Приступим.
Заголовки:
#include <stm32f4xx_gpio.h> #include <stm32f4xx_rcc.h> #include <stm32f4xx_spi.h> #include <stm32f4_discovery.h>
Пересылаем из SPI1 в SPI2.
SPI 1:
- nss — pa4
- sck — pa5
- mosi — pa7
- miso — pa6
SPI 2:
- miso — pb14
- mosi — pb15
- sck — pb13
- nss — pb12
Соединяем 3 пина: mosi — mosi; miso-miso и sck-sck
nss можно не трогать.
Теперь настраиваем SPI 1:
void spi1_init() { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); // тактирование порта RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE); // тактирование SPI1 GPIO_InitTypeDef gpio; GPIO_StructInit(&gpio); gpio.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; gpio.GPIO_Mode = GPIO_Mode_AF; gpio.GPIO_Speed = GPIO_Speed_50MHz; gpio.GPIO_OType = GPIO_OType_PP; gpio.GPIO_PuPd = GPIO_PuPd_DOWN; GPIO_Init(GPIOA,&gpio); GPIO_PinAFConfig(GPIOA,GPIO_PinSource5,GPIO_AF_SPI1); GPIO_PinAFConfig(GPIOA,GPIO_PinSource6,GPIO_AF_SPI1); GPIO_PinAFConfig(GPIOA,GPIO_PinSource7,GPIO_AF_SPI1); SPI_I2S_DeInit(SPI1); SPI_InitTypeDef spi1; SPI_StructInit(&spi1); spi1.SPI_Mode = SPI_Mode_Master; spi1.SPI_DataSize = SPI_DataSize_16b; spi1.SPI_NSS = SPI_NSS_Soft; SPI_Init(SPI1,&spi1); SPI_Cmd(SPI1,ENABLE); }
Включаем тактирование порта и модуля SPI, затем настраиваем пины как AF. После чего инициализируем SPI 1 в режиме мастера (ведущего ус-ва) и запускаем его.
Аналогично делаем с SPI 2, за исключением того, что он будет работать в режиме ведомого ус-ва (slave).
void spi2_init() { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE); GPIO_InitTypeDef gpio; GPIO_StructInit(&gpio); gpio.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; gpio.GPIO_Mode = GPIO_Mode_AF; gpio.GPIO_Speed = GPIO_Speed_50MHz; gpio.GPIO_OType = GPIO_OType_PP; gpio.GPIO_PuPd = GPIO_PuPd_DOWN; GPIO_Init(GPIOB,&gpio); GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_SPI2); GPIO_PinAFConfig(GPIOB,GPIO_PinSource14,GPIO_AF_SPI2); GPIO_PinAFConfig(GPIOB,GPIO_PinSource15,GPIO_AF_SPI2); SPI_I2S_DeInit(SPI2); SPI_InitTypeDef spi2; SPI_StructInit(&spi2); spi2.SPI_Mode = SPI_Mode_Slave; spi2.SPI_DataSize = SPI_DataSize_16b; spi2.SPI_NSS = SPI_NSS_Soft; SPI_Init(SPI2,&spi2); SPI_Cmd(SPI2,ENABLE); }
Объявите буфер с данными для пересылки:
uint16_t SPI1_Buffer_Tx[32] = {0x0102, 0x0304, 0x0506, 0x0708, 0x090A, 0x0B0C, 0x0D0E, 0x0F10, 0x1112, 0x1314, 0x1516, 0x1718, 0x191A, 0x1B1C, 0x1D1E, 0x1F20, 0x2122, 0x2324, 0x2526, 0x2728, 0x292A, 0x2B2C, 0x2D2E, 0x2F30, 0x3132, 0x3334, 0x3536, 0x3738, 0x393A, 0x3B3C, 0x3D3E, 0x3F40};
И 2 функции. Одна для чтения, другая для записи данных:
void spi_send(uint16_t data) { SPI_I2S_SendData(SPI1,data); while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE) == RESET); // ждём пока данные уйдут } uint16_t spi_receve() { while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET); // ждём пока данные появтся uint16_t received = SPI_I2S_ReceiveData(SPI2); return received; }
Обратите внимание на задержки. Без них стабильности не ждите.
Собственно вызов всего добра:
int main() { STM_EVAL_LEDInit(LED3); STM_EVAL_LEDInit(LED4); STM_EVAL_LEDInit(LED5); STM_EVAL_LEDInit(LED6); spi1_init(); spi2_init(); STM_EVAL_LEDOn(LED5); uint16_t data[32]; STM_EVAL_LEDOn(LED3); int i=0; for (;i<33;i++){ spi_send(SPI1_Buffer_Tx[i]); data[i] = spi_receve(); if (data[i] == SPI1_Buffer_Tx[i]) { STM_EVAL_LEDOn(LED4); } } /* проверяем передачу */ for (i=0;i<33;i++){ if (data[i] != SPI1_Buffer_Tx[i]){ STM_EVAL_LEDOff(LED4); break; } } while(1) { STM_EVAL_LEDToggle(LED6); } return 0; }
Сначала инициализируем диоды.
Это я сделал потому, что в отладке полученные данные не видно (почему хз). И правильность передачи я определяю проходом массив и тушением диода в случае ошибки.
В бесконечный цикл добавлено мигание диодом.
Вот и всё.