Помогите разобраться с SPI!
Имеем 2 платы одна STM32F100 DISCOVERY Будет отпавлять На STM32L152 DISCOVERY Число.
Отправка вроде происходит, подключался логическим анализатором там есть движение, не могу разобраться с приемом.
То что пришло, по задумке выведет это в прерывании на встроенный дисплей и зажжет светодиод, а там только непонятное мерцание первого сегмента...
Код передатчика:
CODE
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x.h"
#include <stm32f10x_exti.h>
#include "misc.h"
#include "stm32f10x_spi.h"
#define SCK_Pin GPIO_Pin_5
#define SCK_Pin_Port GPIOA
#define MOSI_Pin GPIO_Pin_7
#define MOSI_Pin_Port GPIOA
#define MISO_Pin GPIO_Pin_6
#define MISO_Pin_Port GPIOA
#define SS_Pin GPIO_Pin_4
#define SS_Pin_Port GPIOA
void init_periph()
{
GPIO_InitTypeDef GPIO_LED;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_LED.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_14;
GPIO_LED.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_LED.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_LED);
GPIO_InitTypeDef GPIO_BUT;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2ENR_AFIOEN , ENABLE);
GPIO_BUT.GPIO_Pin = GPIO_Pin_0;
GPIO_BUT.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_BUT.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &GPIO_BUT);
}
void init_spi()
{
// включаем тактирование (=питание) на порты A, B и железный SPI1
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_SPI1, ENABLE);
GPIO_InitTypeDef PORT;
// выбрали ноги для настройки
PORT.GPIO_Pin = SCK_Pin | MOSI_Pin | MISO_Pin;;
// установили наименьшую скорость (максимальная скорость контроллера 4 Мбита в секунду)
PORT.GPIO_Speed = GPIO_Speed_2MHz;
// (важно!) определяем предназначение ног. здесь - выбор "альтернативной функции" ног
PORT.GPIO_Mode = GPIO_Mode_AF_PP;
// настроили ноги в порту А
GPIO_Init(GPIOA, &PORT);
// выбрали ноги для настройки
PORT.GPIO_Pin = SS_Pin;
// установили скорость (тут - без разницы)
PORT.GPIO_Speed = GPIO_Speed_2MHz;
// предназначение - общее, выход
PORT.GPIO_Mode = GPIO_Mode_Out_PP;
// настроили ноги в порту B
GPIO_Init(GPIOA, &PORT);
SPI_InitTypeDef SPIConf;
// указываем, что используем мы только передачу данных
SPIConf.SPI_Direction = SPI_Direction_1Line_Tx;
// указываем, что наше устройство - Master
SPIConf.SPI_Mode = SPI_Mode_Master;
// передавать будем по 8 бит (=1 байт)
SPIConf.SPI_DataSize = SPI_DataSize_8b;
// режим 00
SPIConf.SPI_CPOL = SPI_CPOL_Low;
SPIConf.SPI_CPHA = SPI_CPHA_1Edge;
SPIConf.SPI_NSS = SPI_NSS_Soft;
// установим скорость передачи (опытным путём выяснили, что разницы от изменения этого параметра нет)
SPIConf.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
// передаём данные старшим битом вперёд (т.е. слева направо)
SPIConf.SPI_FirstBit = SPI_FirstBit_MSB;
// внесём настройки в SPI
SPI_Init(SPI1, &SPIConf);
// включим SPI1
SPI_Cmd(SPI1, ENABLE);
// SS = 1
SPI_NSSInternalSoftwareConfig(SPI1, SPI_NSSInternalSoft_Set);
}
void SPISend(uint16_t data) {
SPI_I2S_SendData(SPI1, data); // отправили данные
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); // ждём, пока данные не отправятся
}
int main(void)
{
init_periph();
init_spi();
int i;
uint16_t data = 1;
GPIO_ResetBits(GPIOC, GPIO_Pin_4); // чип селект выбор
while(1)
{
for (i=0; i<1000000; i++){GPIO_SetBits(GPIOC, GPIO_Pin_8);}
SPISend(data);
for (i=0; i<1000000; i++){GPIO_ResetBits(GPIOC, GPIO_Pin_8);}
data++;
}
return 0;
}
#include "stm32f10x_rcc.h"
#include "stm32f10x.h"
#include <stm32f10x_exti.h>
#include "misc.h"
#include "stm32f10x_spi.h"
#define SCK_Pin GPIO_Pin_5
#define SCK_Pin_Port GPIOA
#define MOSI_Pin GPIO_Pin_7
#define MOSI_Pin_Port GPIOA
#define MISO_Pin GPIO_Pin_6
#define MISO_Pin_Port GPIOA
#define SS_Pin GPIO_Pin_4
#define SS_Pin_Port GPIOA
void init_periph()
{
GPIO_InitTypeDef GPIO_LED;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_LED.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_14;
GPIO_LED.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_LED.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_LED);
GPIO_InitTypeDef GPIO_BUT;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2ENR_AFIOEN , ENABLE);
GPIO_BUT.GPIO_Pin = GPIO_Pin_0;
GPIO_BUT.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_BUT.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &GPIO_BUT);
}
void init_spi()
{
// включаем тактирование (=питание) на порты A, B и железный SPI1
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_SPI1, ENABLE);
GPIO_InitTypeDef PORT;
// выбрали ноги для настройки
PORT.GPIO_Pin = SCK_Pin | MOSI_Pin | MISO_Pin;;
// установили наименьшую скорость (максимальная скорость контроллера 4 Мбита в секунду)
PORT.GPIO_Speed = GPIO_Speed_2MHz;
// (важно!) определяем предназначение ног. здесь - выбор "альтернативной функции" ног
PORT.GPIO_Mode = GPIO_Mode_AF_PP;
// настроили ноги в порту А
GPIO_Init(GPIOA, &PORT);
// выбрали ноги для настройки
PORT.GPIO_Pin = SS_Pin;
// установили скорость (тут - без разницы)
PORT.GPIO_Speed = GPIO_Speed_2MHz;
// предназначение - общее, выход
PORT.GPIO_Mode = GPIO_Mode_Out_PP;
// настроили ноги в порту B
GPIO_Init(GPIOA, &PORT);
SPI_InitTypeDef SPIConf;
// указываем, что используем мы только передачу данных
SPIConf.SPI_Direction = SPI_Direction_1Line_Tx;
// указываем, что наше устройство - Master
SPIConf.SPI_Mode = SPI_Mode_Master;
// передавать будем по 8 бит (=1 байт)
SPIConf.SPI_DataSize = SPI_DataSize_8b;
// режим 00
SPIConf.SPI_CPOL = SPI_CPOL_Low;
SPIConf.SPI_CPHA = SPI_CPHA_1Edge;
SPIConf.SPI_NSS = SPI_NSS_Soft;
// установим скорость передачи (опытным путём выяснили, что разницы от изменения этого параметра нет)
SPIConf.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
// передаём данные старшим битом вперёд (т.е. слева направо)
SPIConf.SPI_FirstBit = SPI_FirstBit_MSB;
// внесём настройки в SPI
SPI_Init(SPI1, &SPIConf);
// включим SPI1
SPI_Cmd(SPI1, ENABLE);
// SS = 1
SPI_NSSInternalSoftwareConfig(SPI1, SPI_NSSInternalSoft_Set);
}
void SPISend(uint16_t data) {
SPI_I2S_SendData(SPI1, data); // отправили данные
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); // ждём, пока данные не отправятся
}
int main(void)
{
init_periph();
init_spi();
int i;
uint16_t data = 1;
GPIO_ResetBits(GPIOC, GPIO_Pin_4); // чип селект выбор
while(1)
{
for (i=0; i<1000000; i++){GPIO_SetBits(GPIOC, GPIO_Pin_8);}
SPISend(data);
for (i=0; i<1000000; i++){GPIO_ResetBits(GPIOC, GPIO_Pin_8);}
data++;
}
return 0;
}
Код приемника:
CODE
#include "stm32l1xx_gpio.h"
#include "stm32l1xx_rcc.h"
#include "stm32l1xx.h"
#include "stm32l1xx_exti.h"
#include "misc.h"
#include "lcd_gpio_init.h"
#include "stm32l_discovery_lcd_new.h"
#include "stm32l1xx_spi.h"
#define SCK_Pin GPIO_Pin_13
#define SCK_Pin_Port GPIOB
#define MOSI_Pin GPIO_Pin_15
#define MOSI_Pin_Port GPIOB
#define MISO_Pin GPIO_Pin_14
#define MISO_Pin_Port GPIOB
#define SS_Pin GPIO_Pin_5
#define SS_Pin_Port GPIOA
void RCC_Configuration(void)
{
SystemInit(); // Сброс по умолчанию
GPIO_DeInit(GPIOA);
GPIO_DeInit(GPIOB);
GPIO_DeInit(GPIOC);
GPIO_DeInit(GPIOD);
GPIO_DeInit(GPIOE);
RCC_AHBPeriphClockCmd( RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB |
RCC_AHBPeriph_GPIOC | RCC_AHBPeriph_GPIOD |
RCC_AHBPeriph_GPIOE, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOAEN, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIODEN, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOBEN, ENABLE);
}
void init_led()
{
GPIO_InitTypeDef PORT;
PORT.GPIO_Pin = (GPIO_Pin_7 | GPIO_Pin_6);
PORT.GPIO_Mode = GPIO_Mode_OUT;
PORT.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init( GPIOB , &PORT);
}
void init_but()
{
GPIO_InitTypeDef BUTA;
BUTA.GPIO_Pin = GPIO_Pin_0;
BUTA.GPIO_Mode = GPIO_Mode_IN;
BUTA.GPIO_Mode = GPIO_PuPd_NOPULL; // Хардварная кнопка и так подтянута
BUTA.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init( GPIOA , &BUTA);
GPIO_InitTypeDef BUTD;
BUTD.GPIO_Pin = GPIO_Pin_2;
BUTD.GPIO_Mode = GPIO_Mode_IN;
BUTD.GPIO_Mode = GPIO_PuPd_UP;
BUTD.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init( GPIOD , &BUTD);
}
void spi()
{
// включаем тактирование железный SPI2
RCC_APB1PeriphClockCmd(RCC_APB1ENR_SPI2EN , ENABLE);
GPIO_InitTypeDef PORT;
// выбрали ноги для настройки
PORT.GPIO_Pin = SCK_Pin | MOSI_Pin | MISO_Pin;;
// установили наименьшую скорость (максимальная скорость контроллера 4 Мбита в секунду)
PORT.GPIO_Speed = GPIO_Speed_2MHz;
// (важно!) определяем предназначение ног. здесь - выбор "альтернативной функции" ног
PORT.GPIO_Mode = GPIO_Mode_AF;
// настроили ноги в порту B
GPIO_Init(GPIOB, &PORT);
// выбрали ноги для настройки
PORT.GPIO_Pin = SS_Pin;
// установили скорость (тут - без разницы)
PORT.GPIO_Speed = GPIO_Speed_2MHz;
// предназначение - общее, выход
PORT.GPIO_Mode = GPIO_Mode_IN;
// настроили ноги в порту A
GPIO_Init(GPIOA, &PORT);
SPI_I2S_DeInit(SPI2);
SPI_InitTypeDef SPIConf;
// указываем, что используем мы только передачу данных
SPIConf.SPI_Direction = SPI_Direction_1Line_Rx;
// указываем, что наше устройство - Прием
SPIConf.SPI_Mode = SPI_Mode_Slave;
// передавать будем по 8 бит (=1 байт)
SPIConf.SPI_DataSize = SPI_DataSize_8b;
// режим 00
SPIConf.SPI_CPOL = SPI_CPOL_Low;
SPIConf.SPI_CPHA = SPI_CPHA_1Edge;
SPIConf.SPI_NSS = SPI_NSS_Hard;
// установим скорость передачи (опытным путём выяснили, что разницы от изменения этого параметра нет)
SPIConf.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
// передаём данные старшим битом вперёд (т.е. слева направо)
SPIConf.SPI_FirstBit = SPI_FirstBit_MSB;
// внесём настройки в SPI
SPI_Init(SPI2, &SPIConf);
// включим SPI2
SPI_Cmd(SPI2, ENABLE);
// SS = 1
SPI_NSSInternalSoftwareConfig(SPI2, SPI_NSSInternalSoft_Set);
SPI_I2S_ITConfig(SPI2,SPI_I2S_IT_RXNE,ENABLE); //Включаем прерывание по приему байта
SPI_Cmd(SPI2, ENABLE); // Включаем модуль SPI2....
NVIC_EnableIRQ(SPI2_IRQn); //Разрешаем прерывания от SPI2
}
void SPI2_IRQHandler (void)
{
if (SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_RXNE)==SET) // Прерывание вызвано приемом байта ?
{
uint8_t data = SPI2->DR; //Читаем то что пришло
LCD_GLASS_Clear();
LCD_GLASS_DisplayString(data);
GPIO_SetBits(GPIOB, GPIO_Pin_6);
}
}
int main(void)
{
RCC_Configuration();
init_led();
init_but();
exiti();
gpio_init();
lcd_init();
spi();
}