SPI в stm32 — шлём из SPI1 в SPI2

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;
}

Сначала инициализируем диоды.
Это я сделал потому, что в отладке полученные данные не видно (почему хз). И правильность передачи я определяю проходом массив и тушением диода в случае ошибки.
В бесконечный цикл добавлено мигание диодом.
Вот и всё.

 

Похожий код:

Фото аватара
Алексей Петров

Программист, разработчик с 5 летним опытом работы. Учусь на разработчика игр на Unity и разработчика VR&AR реальности (виртуальной реальности). Основные языки программирования: C#, C++.

Оцените автора
Бла, бла код
Добавить комментарий