Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: w5100 + STM32- не корректно принимаю данные по SPI
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
Метценгерштейн
В своей программе в терминалке получаю ответ от визнета 0x12, но осциллом вижу, что визнет выдает мне число 0х13, значит я не корректно его обрабатываю. Из даташита по визнету по SPI понятно, что данные выставляются, когда sck период только начался и он еще в лог.0. Так же и на картинке осцилла. Т.е. возможные комбинации выставлены как положено.
Код
      SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
      SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;

тогда почему мой STM32 не хочет видеть число 0x13 ?




здесь D4- MISO, т.е. вход STM32

перепробовал все полярности в STM32- ничего не улучшилось.
замыкал напрямую в STM32 MISO на MOSI- принимаю то, что отправляю. Если разъединяю перемычку, принимаю 0xFF, а с соединенной, именно то, что отправил.

Что еще можно предпринять?
Метценгерштейн
новая вводная:
замкнуты напрямую MISO на MOSI.
инициализация SPI
Код
        // SPI1  
        RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; //Тактирование модуля SPI1        
        SPI1->CR1 = 0
        | SPI_CR1_BR_2 | SPI_CR1_BR_0 //Baud rate = Fpclk/64
        | 0 * SPI_CR1_CPOL //Полярность тактового сигнала
        | 0 * SPI_CR1_CPHA //Фаза тактового сигнала
        | 0 * SPI_CR1_DFF //8 бит данных
        | 0 * SPI_CR1_LSBFIRST //MSB передается первым
        | 1 * SPI_CR1_SSM //Программный режим NSS
        | 1 * SPI_CR1_SSI //Аналогично состоянию, когда на входе NSS высокий уровень
        | 1 * SPI_CR1_MSTR //Режим Master
        | 1 * SPI_CR1_SPE; //Включаем SPI1
    ;
        SPI1->CR2 = SPI_CR2_SSOE; //Вывод NSS - выход управления slave select


а вот, что делаю в проге
Код
void WIZnet_main (void)
{
  WIZ_SPIInit();
  uint8_t temp=0;
  uint8_t data;
  Delay_ms(1);
  
  for (data=0; data < 0xff; data ++)
  {
    on (TestPin);
    
    Usart1_Send_Byte_HEX (data);
    Usart1_Send_String ("->");

    while(!(SPI1->SR & SPI_SR_TXE))
;
    
    SPI1->DR = data;
    while(!(SPI1->SR & SPI_SR_RXNE));
    temp = SPI1->DR;
    
    off (TestPin);
    
    Usart1_Send_Byte_HEX (temp);
    Usart1_Send_String ("\r\n");
  }
}


и при этом выводится следующее:
Код
00->01
01->00
02->03
03->02
04->05
05->04
06->07
07->06
08->09
09->08
0A->0B
0B->0A
0C->0D
0D->0C
0E->0F
0F->0E
10->11
11->10
12->13
13->12
14->15
15->14
16->17
17->16
18->19
19->18
...


а почему?
AHTOXA
Покажите настройки ног SPI.
Метценгерштейн
Код
void WIZ_SPIInit()
{      
        // настройка SCS вывода (GPIOB, GPIO_Pin_8)  
      GPIOB->MODER |= GPIO_MODER_MODER8_0;  //output
    GPIOB->OTYPER &= ~GPIO_OTYPER_OT_8;  //Output push-pull
    GPIOB->OSPEEDR |=GPIO_OSPEEDER_OSPEEDR8;  //40 MHz
    GPIOB->PUPDR &=~GPIO_PUPDR_PUPDR8;  //No pull-up, pull-down
    
        // настройка TestPin выхода  (GPIOB, GPIO_Pin_7)
    GPIOB->MODER |= GPIO_MODER_MODER7_0;  //output
    GPIOB->OTYPER &= ~GPIO_OTYPER_OT_7;  //Output push-pull
    GPIOB->OSPEEDR |=GPIO_OSPEEDER_OSPEEDR7;  //40 MHz
    GPIOB->PUPDR &=~GPIO_PUPDR_PUPDR7;  //No pull-up, pull-down
    
        // настрока вывода Reset   (GPIOB, GPIO_Pin_5)    
    GPIOB->MODER |= GPIO_MODER_MODER5_0;  //output
    GPIOB->OTYPER &= ~GPIO_OTYPER_OT_5;  //Output push-pull
    GPIOB->OSPEEDR |=GPIO_OSPEEDER_OSPEEDR5;  //40 MHz
    GPIOB->PUPDR &=~GPIO_PUPDR_PUPDR5;  //No pull-up, pull-down
    
        // Линини SPI1 (Master) настройка SCLK, MISO и MOSI
        // PA12(MOSI), PA11(MISO), PA5(SCK), PA4(NSS) - AF, Push-Pull, AF5(SPI1)
      GPIOA->MODER |= GPIO_MODER_MODER12_1 | GPIO_MODER_MODER11_1 | GPIO_MODER_MODER5_1; //Alternate function
      GPIOA->OTYPER &= ~(GPIO_OTYPER_OT_12 | GPIO_OTYPER_OT_11 | GPIO_OTYPER_OT_5); //Push-Pull
      GPIOA->AFR[1] |= (5<<16 | 5<<12); //PA12 = AF5, PA11 = AF5
      GPIOA->AFR[0] |= (5<<20 | 5<<16); //PA5 = AF5, PA4 = AF5

        // настройка внешнего прерывания на PB3
      RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
      SYSCFG->EXTICR[0] |= SYSCFG_EXTICR1_EXTI3_PB; // Connect EXTI line 3 to PB
      EXTI->IMR |= EXTI_IMR_MR3; // какую линию выбираем из 23-х (у нас 3-я)
      EXTI->FTSR |= EXTI_FTSR_TR3; // настройка фронта-среза на акт. 0
      NVIC_EnableIRQ(EXTI3_IRQn);  // NVIC_DisableIRQ(EXTI0_IRQn);
      NVIC_SetPriority(EXTI3_IRQn, 1); //приоритет
      
        // SPI1  
        RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; //Тактирование модуля SPI1        
        SPI1->CR1 = 0
        | SPI_CR1_BR_2 | SPI_CR1_BR_0 //Baud rate = Fpclk/64
        | 0 * SPI_CR1_CPOL //Полярность тактового сигнала
        | 0 * SPI_CR1_CPHA //Фаза тактового сигнала
        | 0 * SPI_CR1_DFF //8 бит данных
        | 0 * SPI_CR1_LSBFIRST //MSB передается первым
        | 1 * SPI_CR1_SSM //Программный режим NSS
        | 1 * SPI_CR1_SSI //Аналогично состоянию, когда на входе NSS высокий уровень
        | 1 * SPI_CR1_MSTR //Режим Master
        | 1 * SPI_CR1_SPE; //Включаем SPI1
         ;
        SPI1->CR2 = SPI_CR2_SSOE; //Вывод NSS - выход управления slave select
}
AHTOXA
А зачем у вас включается альтернативная функция для NSS? (Причём направление его не задано, то есть, оставлен на вход, по умолчанию.)
Остальное вроде нормально.
Попробуйте сделать NSS простым GPIO (и уберите SPI_CR2_SSOE из SPI1->CR2)
Метценгерштейн
исправил.
инициализация портов
Код
void WIZ_SPIInit()
{      
        // настройка SCS вывода (GPIOB, GPIO_Pin_8)  
      GPIOB->MODER |= GPIO_MODER_MODER8_0;  //output
    GPIOB->OTYPER &= ~GPIO_OTYPER_OT_8;  //Output push-pull
    GPIOB->OSPEEDR |=GPIO_OSPEEDER_OSPEEDR8;  //40 MHz
    GPIOB->PUPDR &=~GPIO_PUPDR_PUPDR8;  //No pull-up, pull-down
    
        // настройка TestPin выхода  (GPIOB, GPIO_Pin_7)
    GPIOB->MODER |= GPIO_MODER_MODER7_0;  //output
    GPIOB->OTYPER &= ~GPIO_OTYPER_OT_7;  //Output push-pull
    GPIOB->OSPEEDR |=GPIO_OSPEEDER_OSPEEDR7;  //40 MHz
    GPIOB->PUPDR &=~GPIO_PUPDR_PUPDR7;  //No pull-up, pull-down
    
        // настрока вывода Reset   (GPIOB, GPIO_Pin_5)    
    GPIOB->MODER |= GPIO_MODER_MODER5_0;  //output
    GPIOB->OTYPER &= ~GPIO_OTYPER_OT_5;  //Output push-pull
    GPIOB->OSPEEDR |=GPIO_OSPEEDER_OSPEEDR5;  //40 MHz
    GPIOB->PUPDR &=~GPIO_PUPDR_PUPDR5;  //No pull-up, pull-down
    
        // Линини SPI1 (Master) настройка SCLK, MISO и MOSI
        // PA12(MOSI), PA11(MISO), PA5(SCK),  Push-Pull, AF5(SPI1)
      GPIOA->MODER |= GPIO_MODER_MODER12_1 | GPIO_MODER_MODER11_1 | GPIO_MODER_MODER5_1; //Alternate function
      GPIOA->OTYPER &= ~(GPIO_OTYPER_OT_12 | GPIO_OTYPER_OT_11 | GPIO_OTYPER_OT_5); //Push-Pull
      GPIOA->AFR[1] |= (5<<16 | 5<<12); //PA12 = AF5, PA11 = AF5
      GPIOA->AFR[0] |= (5<<20); //PA5 = AF5

        // настройка внешнего прерывания на PB3
      RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
      SYSCFG->EXTICR[0] |= SYSCFG_EXTICR1_EXTI3_PB; // Connect EXTI line 3 to PB
      EXTI->IMR |= EXTI_IMR_MR3; // какую линию выбираем из 23-х (у нас 3-я)
      EXTI->FTSR |= EXTI_FTSR_TR3; // настройка фронта-среза на акт. 0
      NVIC_EnableIRQ(EXTI3_IRQn);  // NVIC_DisableIRQ(EXTI0_IRQn);
      NVIC_SetPriority(EXTI3_IRQn, 1); //приоритет
      
        // SPI1  
        RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; //Тактирование модуля SPI1        
        SPI1->CR1 = 0
        | SPI_CR1_BR_2 | SPI_CR1_BR_0 //Baud rate = Fpclk/64
        | 0 * SPI_CR1_CPOL //Полярность тактового сигнала
        | 0 * SPI_CR1_CPHA //Фаза тактового сигнала
        | 0 * SPI_CR1_DFF //8 бит данных
        | 0 * SPI_CR1_LSBFIRST //MSB передается первым
        | 1 * SPI_CR1_SSM //Программный режим NSS
        | 1 * SPI_CR1_SSI //Аналогично состоянию, когда на входе NSS высокий уровень
        | 1 * SPI_CR1_MSTR //Режим Master
        | 1 * SPI_CR1_SPE; //Включаем SPI1
         ;
        //SPI1->CR2 = SPI_CR2_SSOE; //Вывод NSS - выход управления slave select
}


сама ф-я
Код
void WIZnet_main (void)
{
  WIZ_SPIInit();
  uint8_t temp=0;
  uint8_t data;
  
  for (data=0; data < 10; data ++)
  {    
    Usart1_Send_Byte_HEX (data);
    Usart1_Send_String ("->");

    while(!(SPI1->SR & SPI_SR_TXE))
     ;
    
    SPI1->DR = data; //Пишем в буфер передатчика SPI1. После этого стартует обмен данными
    while(!(SPI1->SR & SPI_SR_RXNE)); //Ожидаем окончания приема данных модулем SPI1 (RXNE =1 - приемный буфер содержит данные)
    temp = SPI1->DR;//Считываем данные из приемного буфера SPI1. При этой операции происходит очистка буфера и сброс флага RXNE
    
    Usart1_Send_Byte_HEX (temp);
    Usart1_Send_String ("\r\n");
    
    Delay_ms(20);
  }
}


и то, что вывелось
Код
01->00
02->03
03->02
04->05
05->04
06->07
07->06
08->09
09->08


напомню, MISO на MOSI напрямую замкнуты
AHTOXA
А, вот ещё что. MISO нужно настроить как вход, а не как выход!
(Альтернативный конечно, можно с подтяжкой).
Метценгерштейн
похоже, что не надо. т.к. в одном
GPIOA->MODER
я ставлю или вход или выход или альтернатива.
тут-то я и выбираю альтернативу.
а она уже жестко привязана к ноге MISO.

тут еще что-то сидит.
AHTOXA
Окей. Попробуйте ещё не полагаться на значения по умолчанию для регистров.
То есть, вместо
Код
GPIOA->MODER |= GPIO_MODER_MODER12_1;
пишите
Код
GPIOA->MODER &= ~GPIO_MODER_MODER12;
GPIOA->MODER |= GPIO_MODER_MODER12_1;

И ещё. Добавьте строчки
Код
    SPI1->I2SCFGR &= ~SPI_I2SCFGR_I2SMOD;
    SPI1->CR2 = 0;
_перед_
Код
    SPI1->CR1 = ...

ЗЫ. А плата у вас случайно не F4DISCOVERY?
Метценгерштейн
попробую все проделать.
плата
STM32L152RBT6
такая

тоже самое все. разве что у меня нет регистра
SPI1->I2SCFGR &= ~SPI_I2SCFGR_I2SMOD;

не обнулял его.

проверяю еще идею и пойду ассемблер смотреть
Метценгерштейн
причесал чужой код под свой проц. в отдельном проекте. И, он работает!
у меня тоже самое, тот же код, те же ф-ии, и не работает. Как так?

Гляньте, кому не сложно. Может глаз замылился и не вижу очевидного?
http://files.mail.ru/CA973E3E6B124F4688677F583F8C721F
это рабочий проект
вывод:
Код
01->01
02->02
03->03
04->04
05->05
06->06
07->07
08->08
09->09


http://files.mail.ru/201299FB61304FBF979B8A7805554D6F
второй проект, кот. не работает.
в нем из main() я сразу иду в файл
WIZnet_5100 в ф-ю
WIZnet_main();

и дальше делаю все тоже самое.
но результат
Код
JþÖ˜ffË>03
03->02
04->05
05->04
06->07
07->06
08->09
09->08


так в чем же разница?

нашел причину:

как только в рабочий проект добавляю к проекту файл
startup_stm32l1xx_md.s из папки IAR, так сразу получаю ту же хрень.

и что тут делать?
Метценгерштейн
Продолжение исследования:

удаляя файл startup_stm32l1xx_md.s, я вынуждаю перейти проц на тактирование MSI 2,097 МГц.
Если файлом system_stm32l1xx.c, сгенерированным прогой, задана частота 32 МГц, хоть от кварца, хоть от RC, то и получается эта хрень с выводом.
Если тактирование 2,097 МГц, то все ОК.

А почему?
AHTOXA
Удаляя файл startup_stm32l1xx_md.s, вы удаляете таблицу векторов (и вектор сброса в том числе). Без вектора сброса программа не может работать в принципе. Возможно у вас в проекте два конфликтующих файла стартапа?
Метценгерштейн
нет, один файл стартапа.
проблема не в нем- проблема в том, что на 32 МГц не хочет работать ни в какую.
AHTOXA
Цитата(Метценгерштейн @ Feb 3 2013, 13:56) *
нет, один файл стартапа.

Тогда как же вы его удаляете? Что остаётся вместо стартапа, когда вы удаляете startup_stm32l1xx_md.s?
Метценгерштейн
не знаю, что остается) Мусор какой-то. И благодаря ему, работать начинает только от генератора MSI на 2 МГц.
в общем, факт налицо. от 32 МГц не хочет работать.
AHTOXA
Цитата(Метценгерштейн @ Feb 3 2013, 21:41) *
не знаю, что остается) Мусор какой-то.

Ага, и этот мусор случайно прыгает на __iar_program_start()? Так не бывает. Ищите, где у вас другой стартап.
Цитата(Метценгерштейн @ Feb 3 2013, 21:41) *
И благодаря ему, работать начинает только от генератора MSI на 2 МГц.

То есть, скорость SPI у вас меняется, но UART при этом работает на оной и той же скорости? (Вы же выводите в UART переданный и принятый байты).
Метценгерштейн
UART использует стандартные библиотеки, где в зависимости от частоты шины - они сами подгоняют скорости как надо. Вроде так было.

Скачайте проект, найдите там еще один файл инициализации. Обычно начало старта и есть нулевой адрес флеша. Просто пока попадает на него.

AHTOXA
Дело в том, что ваша функция main() вызывается из функции __iar_program_start(). Которая, в свою очередь, вызывается из стартапа (после SystemInit). То есть, выкинув стартап, вы не просто отменяете вызов инициализации (SystemInit()), а совсем исключаете возможность выполнения программы.
Проект я качал, там действительно только один стартап. Но, может быть, другой стартап лежит в другой папке, и поэтому не попал в архив? Или этот один стартап включён дважды.
(У меня нет IAR-а, я не могу проверить ваш проект.)
Метценгерштейн
этот файл включен только в проект. больше нигде его нет. в коде программы я его не использую. Тут, в общем, какой-то глюк. Как с SPI, так и с работой без этого стартапа.
Метценгерштейн
в общем, пришел к такому выводу:
при настройке в утилите тактовой частоты PCLK2 на 8 МГц через делитель APB2 prescaler, при этом сама частота шины = 32 МГц, вне зависимости от кварца или RC, то все работает.
Так же поднимал частоту системную до 12 МГц- все работало.
Получается, что наш SPI не хочет тактироваться от частот выше 12 МГц (а при частоте шины 32 МГц больше 8 МГц и не выставить)

А где в даташите это сказано?
Golikov A.
Сейчас у меня нет под рукой СТМ и ИАР не могу проверить, потому извиняюсь могу глупостей наговоритьsm.gif

1. у СТМ32 есть настройка максимальной частоты выходных ножек. По умолчанию там минимум стоит, поглядите может для СПИ эта настройка тоже имеет смысл...
2. У иар в среде есть свой мини стартап, то есть без стартап файла он сам добавить в вектор прерывание переход на маин, это может и быть вашим вторым стартапом, так проект и работает.

Еще раз оговорюсь могу обмануть, я уже пересел с ИАР на кеил, но что-то смутно помнится, что дело было так...
Golikov A.
В теме откуда я пришел, эта проблема решилась выставлением максимальной частоты работы порта, так что для СПИ эта настройка тоже имеет смысл.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.