Настройка SPI

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
Аватара пользователя
Andrey27
Первый раз сказал Мяу!
Сообщения: 24
Зарегистрирован: Вс май 11, 2014 23:24:21

Настройка SPI

Сообщение Andrey27 »

Всем привет! Изучаю STM32 решил подключить MicroSD к STM32F103C8T6. Подключил, настроил SPI2, карточка не отвечает. Тогда написал программно SPI дерганием ножек) и все отлично работает. Заметил при отладке что в аппаратном SPI контроллер зависает при приеме байта. Посмотрите настройки аппаратного SPI где я ошибся. Код:

Код: Выделить всё

   #include "stm32f10x.h"
   #include "stm32f10x_rcc.h"
   #include "stm32f10x_gpio.h"
   #include "stm32f10x_spi.h"
   #include "hd44780_driver.h"

   #define Set_0_DI     GPIOB -> BSRR = GPIO_BSRR_BR14   // Для програмного SPI
   #define Set_1_DI     GPIOB -> BSRR = GPIO_BSRR_BS14
   #define Get_X_DO     GPIOB -> IDR & GPIO_IDR_IDR15
   #define BeginTakt    GPIOB -> BSRR = GPIO_BSRR_BS13
   #define EndTakt      GPIOB -> BSRR = GPIO_BSRR_BR13

   #define SELECT()     GPIOB -> BSRR = GPIO_BSRR_BR12   // Управление CS
   #define DESELECT()   GPIOB -> BSRR = GPIO_BSRR_BS12

   #define CMD0   (0x40+0)  // Команды флешке microsd
   #define CMD8   (0x40+8)
   #define CMD55 (0x40+55)

void delay(uint32_t n)    // Задержка
 {
  while (n--) {}
 }

void INIT_SPI(void)  // Инициализация SPI прогрммного или аппаратного
 {
  /* //++++++++++++++++++++++++++++++
  SPI_InitTypeDef  SPI_2;
  GPIO_InitTypeDef PORTB;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);

  PORTB.GPIO_Pin = GPIO_Pin_12;
  PORTB.GPIO_Mode = GPIO_Mode_Out_PP;
  PORTB.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOB, &PORTB);

  PORTB.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
  PORTB.GPIO_Speed = GPIO_Speed_50MHz;
  PORTB.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOB, &PORTB);

  SPI_2.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  SPI_2.SPI_Mode = SPI_Mode_Master;
  SPI_2.SPI_DataSize = SPI_DataSize_8b;
  SPI_2.SPI_CPOL = SPI_CPOL_Low;
  SPI_2.SPI_CPHA = SPI_CPHA_1Edge;
  SPI_2.SPI_NSS = SPI_NSS_Soft;
  SPI_2.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
  SPI_2.SPI_FirstBit = SPI_FirstBit_MSB;
  SPI_2.SPI_CRCPolynomial = 7;
  SPI_Init(SPI2, &SPI_2);
  SPI_CalculateCRC(SPI2, DISABLE);
  SPI_Cmd(SPI2, ENABLE);
  SPI_NSSInternalSoftwareConfig(SPI2, SPI_NSSInternalSoft_Set);
  */  //++++++++++++++++++++++++++++++

  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14;
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  GPIO_Init(GPIOB, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_15;
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPD;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
 }

void Write_SPI(uint8_t Data) // Передача по SPI аппаратно или программно
 {
  /*  //++++++++++++++++++++++++++++++
  while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET){}
  SPI_I2S_SendData(SPI2, Data);
  */  //++++++++++++++++++++++++++++++

  uint8_t i;
  for (i = 0; i < 8; i++)
   {
   if ((Data & 0x80) == 0x00) Set_0_DI; else Set_1_DI;
   Data = Data << 1;
   BeginTakt;
   EndTakt;
   }
 }

uint8_t Read_SPI(void) // Прием по SPI аппаратно или программно
 {
  /*  //++++++++++++++++++++++++++++++
  while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET){} // Тут виснет
  return SPI_I2S_ReceiveData(SPI2);
  */  //++++++++++++++++++++++++++++++

  uint8_t i, Data = 0x00;
  Write_SPI(0xff);
  for(i = 0; i < 8; i++)
  {
   BeginTakt;
   Data = Data << 1;
   if (Get_X_DO) Data = Data | 0x01;
   EndTakt;
  }
  return Data;
 }

uint8_t Send_CMD(uint8_t cmd, uint32_t arg)  // Посылка команды карте
 {
  uint8_t n, res;
  if (cmd & 0x80)
  {
   cmd &= 0x7F;
   res = Send_CMD(CMD55, 0);
   if (res > 1) return res;
  }
  DESELECT();
  Read_SPI();
  SELECT();
  Read_SPI();
  Write_SPI(cmd);
  Write_SPI((uint8_t)(arg >> 24));
  Write_SPI((uint8_t)(arg >> 16));
  Write_SPI((uint8_t)(arg >> 8));
  Write_SPI((uint8_t)arg);
  n = 0x01;
  if (cmd == CMD0) n = 0x95;
  if (cmd == CMD8) n = 0x87;
  Write_SPI(n);
  n = 10;
  do
  {
   res = Read_SPI();
  } while ((res & 0x80) && --n);
  return res;
 }

uint8_t SD_Init(void)  // Перевод карты в SPI режим и посылка CMD0 инициализация начало.
 {
  uint8_t n;
  INIT_SPI();
  DESELECT();
  for (n = 16; n; n--) Read_SPI();
  SELECT();
  if (Send_CMD(CMD0, 0) == 1) {return 0;} else {return 1;}
 }

 int main(void)
  {
    delay(10000000);
   lcd_init();
   lcd_clear();
   lcd_set_xy(0,0);
   lcd_out("Init_LCD_OK");
   delay(10000000);

   lcd_clear();
   lcd_set_xy(0,0);
   if (SD_Init() == 0) lcd_out("MicroSD_OK"); else lcd_out("MicroSD_Error");

   while(1)
    {

    }
  }
Аватара пользователя
dosikus
Друг Кота
Сообщения: 3604
Зарегистрирован: Пн июл 28, 2008 22:12:01

Re: Настройка SPI

Сообщение dosikus »

Классический случай бесполезности SPL + полное непонимание процесса.
Вместо "изучении" недолибы надо было документацию изучать.
В SPI нет отдельных сущностей - Write и Read.
Все происходит одновременно и чтобы что-то считать надо что-то передать ...
Аватара пользователя
Andrey27
Первый раз сказал Мяу!
Сообщения: 24
Зарегистрирован: Вс май 11, 2014 23:24:21

Re: Настройка SPI

Сообщение Andrey27 »

Спасибо за подсказку. И правда забыл вставить в функции чтения, запись 0xff. После исправления ничего не виснет, но microsd не видит. Буду с регистрами настройки SPI разбираться. Просто в интернете куча примеров со стандартной библиотекой SPI, думал быстро настроить чтоб в регистры не лезть)
Аватара пользователя
dosikus
Друг Кота
Сообщения: 3604
Зарегистрирован: Пн июл 28, 2008 22:12:01

Re: Настройка SPI

Сообщение dosikus »

Andrey27 писал(а):но microsd не видит. Буду с регистрами настройки SPI разбираться.


В таких случаях крайне необходим логический анализатор. Тот же Saleae например .
Из возможного :
инит карточки делать на пониженной скорости, после успешной инициализации скорость поднять...
Аватара пользователя
Andrey27
Первый раз сказал Мяу!
Сообщения: 24
Зарегистрирован: Вс май 11, 2014 23:24:21

Re: Настройка SPI

Сообщение Andrey27 »

Купил логический анализатор Saleae. Подсоединил к SPI, посмотрел на осцирограммы при аппаратной реализации и программной. Сразу стало ясно что перепутаны MISO и MOSI местами. Программно MISO и MOSI я установил правилно а аппаратно они наоборот устанавливаются. Перепаял дорожки на плате :) По поводу анализатора, штука класс и не дорого ~20$.
Ответить

Вернуться в «ARM»