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;
}
Сначала инициализируем диоды.
Это я сделал потому, что в отладке полученные данные не видно (почему хз). И правильность передачи я определяю проходом массив и тушением диода в случае ошибки.
В бесконечный цикл добавлено мигание диодом.
Вот и всё.






