1 / 1 / 0
Регистрация: 20.04.2017
Сообщений: 67
1

STM32+W5500 не работает

24.07.2020, 13:17. Показов 1902. Ответов 2
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте, пару лет назад писал программу на atmega32 и atmega328 для w5500, все работало отлично, сейчас пришлось пересесть на stm32 и тут начались проблемы. Первое что бросилось в глаза это, что в SPI нет передачи переменной длинны, но вопрос не об этом сейчас. Я написал программу используя примеры из интернета, библиотеки и даташит. Также пользовался старыми наработками работы с w5500 на atmega. Но он отказывается работать, ниже я приведу фотографии осциллограмма передачи и код настройки SPI и записи данных в w5500.

1. Код настройки и работы с SPI

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#include"stdbool.h"
#include"stm32f1xx.h"
#include"SPI.h"
 
void SPI1_ini(void)
{
    RCC->APB2ENR |= RCC_APB2ENR_SPI1EN | RCC_APB2ENR_IOPAEN ; //Turn on clock PORTA and SPI1
    
    //---------------------Settings Altrnative function PORTA--------------------
    //---------------------------------------------------------------------------   
    //---------------------------------------------------------------------------   
    //SCK: PA5  
        GPIOA->CRL &= ~(GPIO_CRL_MODE5_0 | GPIO_CRL_MODE5_1);//reset
        GPIOA->CRL &= ~(GPIO_CRL_CNF5_0  | GPIO_CRL_CNF5_1 );//reset    
        GPIOA->CRL |=  (GPIO_CRL_MODE5_0 | GPIO_CRL_MODE5_1);// Mode output 50 MHz PA5  
        GPIOA->CRL |= GPIO_CRL_CNF5_1;//Alternate function  output Push-pull
    //---------------------------------------------------------------------------
    //---------------------------------------------------------------------------
    //MISO: PA6 
        GPIOA->CRL &= ~(GPIO_CRL_MODE6_0 | GPIO_CRL_MODE6_1);//reset
        GPIOA->CRL &= ~(GPIO_CRL_CNF6_0  | GPIO_CRL_CNF6_1 );//reset
        GPIOA->CRL |= GPIO_CRL_CNF6_0;//Floating input
    //----------------------------------------------------------------------------
    //---------------------------------------------------------------------------   
    //MOSI: PA7 
        GPIOA->CRL &= ~(GPIO_CRL_MODE7_0 | GPIO_CRL_MODE7_1);//reset
        GPIOA->CRL &= ~(GPIO_CRL_CNF7_0  | GPIO_CRL_CNF7_1 );//reset
        GPIOA->CRL |= GPIO_CRL_MODE7_0 | GPIO_CRL_MODE7_1 ;
        GPIOA->CRL |= GPIO_CRL_CNF7_1 ;
    //---------------------------------------------------------------------------
    //CS: PA12
        GPIOA->CRH |= GPIO_CRH_MODE12_1 | GPIO_CRH_MODE12_0 ;// Output 50MHz
        GPIOA->CRH &= ~(GPIO_CRH_CNF12_1 | GPIO_CRH_CNF12_0 );// Output push-pull 
        GPIOA->BSRR |= GPIO_BSRR_BS12; //Up PINA12
    //---------------------------------------------------------------------------
    //---------------------------------------------------------------------------
    //---------------------------------------------------------------------------
    
    //1. Select the BR[2:0] bits to define the serial clock baud rate (see SPI_CR1 register).
        SPI1->CR1 &= ~( SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0 ) ; // divider 2
        //Uncomment the necessary divisor
        SPI1->CR1 |= ( SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0 ) ; //divider 256
        //SPI1->CR1 |= ( SPI_CR1_BR_2 | SPI_CR1_BR_1 ) ;              //divider 128
        //SPI1->CR1 |= ( SPI_CR1_BR_2 | SPI_CR1_BR_0 ) ;              //divider 64
        //SPI1->CR1 |= ( SPI_CR1_BR_2 ) ;                             //divider 32
        //SPI1->CR1 |= ( SPI_CR1_BR_1 | SPI_CR1_BR_0 ) ;              //divider 16
        //SPI1->CR1 |= ( SPI_CR1_BR_1 ) ;                             //divider 8
        //SPI1->CR1 |= ( SPI_CR1_BR_0 ) ;                             //divider 4
    //---------------------------------------------------------------------------
    
    
    //2. Select the CPOL and CPHA bits to define one of the four relationships between the
    //data transfer and the serial clock
        //CPOL: Clock polarity 0: CK to 0 when idle
        //CPHA: Clock phase 0: The first clock transition is the first data capture edge
        SPI1->CR1 &= ~( SPI_CR1_CPOL | SPI_CR1_CPHA );
    //---------------------------------------------------------------------------
    
    
    //3. Set the DFF bit to define 8- or 16-bit data frame format
    //DFF: Data frame format 0: 8-bit data frame format is selected for transmission/reception
        SPI1->CR1 &= ~SPI_CR1_DFF ;
    //---------------------------------------------------------------------------
    
    
    //4. Configure the LSBFIRST bit in the SPI_CR1 register to define the frame format
    //LSBFIRST: Frame format 0: MSB transmitted first
        SPI1->CR1 &= ~SPI_CR1_LSBFIRST; 
    //---------------------------------------------------------------------------
    
    
    //5. If the NSS pin is required in input mode, in hardware mode, connect the NSS pin to a
    //high-level signal during the complete byte transmit sequence. In NSS software mode,
    //set the SSM and SSI bits in the SPI_CR1 register. If the NSS pin is required in output
    //mode, the SSOE bit only should be set.
    //We don't use this function
    //---------------------------------------------------------------------------
    
    
    //6. The MSTR and SPE bits must be set (they remain set only if the NSS pin is connected
    //to a high-level signal)
    //MSTR: Master selection 0: Slave configuration ; 1: Master configuration ;
        SPI1->CR1 &= ~SPI_CR1_MSTR ;
        SPI1->CR1 |= SPI_CR1_MSTR ;
    //---------------------------------------------------------------------------
    //---------------------------------------------------------------------------
    //---------------------------------------------------------------------------
    
    
    //BIDIMODE: Bidirectional data mode enable 
    //0: 2-line unidirectional data mode selected
    //1: 1-line bidirectional data mode selected
        SPI1->CR1 &= ~SPI_CR1_BIDIMODE;
    //---------------------------------------------------------------------------
    
    
    //RXONLY: Receive only
    //This bit combined with the BIDImode bit selects the direction of transfer in 2-line
    //unidirectional mode. This bit is also useful in a multislave system in which this particular
    //slave is not accessed, the output from the accessed slave is not corrupted.
    //0: Full duplex (Transmit and receive)
    //1: Output disabled (Receive-only mode)
        //SPI1->CR1 &= ~SPI_CR1_RXONLY;
    //---------------------------------------------------------------------------
    //---------------------------------------------------------------------------
    
    
        unsigned int count = 0;
        while(1)
        {
            count++;
            if(count == 25000) break;
            __NOP();
        }
    //---------------------------------------------------------------------------   
        // Set TX interrupt
        //SPI1->CR2 |= SPI_CR2_TXEIE;
        // Set RX interrupt
        //SPI1->CR2 |= SPI_CR2_RXNEIE;
        
        //Set SPE: SPI enable 0: Peripheral disabled ; 1: Peripheral enabled ;
        SPI1->CR1 &= ~SPI_CR1_SPE ;
        SPI1->CR1 |= SPI_CR1_SPE ;
    //---------------------------------------------------------------------------
}
///////////////////////////////////////////////////////////////////////////////
void SPI1_TX_8bit(uint8_t *data, uint8_t lengthData)
{
    //uint8_t count = 0;
    while(!(SPI1->SR & SPI_SR_TXE)){}
    while((SPI1->SR & SPI_SR_BSY) == SPI_SR_BSY_Msk){}
    //uint16_t read_ =  SPI1->DR;
    //while(!(SPI1->SR & SPI_SR_TXE)){count++;if(count == 240) return;}
    while(lengthData!=0) 
    {
        SPI1->DR = *data++;
        lengthData--;
    }
}
///////////////////////////////////////////////////////////////////////////////
void SPI1_DROP_CS(void)
{
    while(!(SPI1->SR & SPI_SR_TXE)){}
    GPIOA->BRR = GPIO_BRR_BR12;
}
///////////////////////////////////////////////////////////////////////////////
void SPI1_UP_CS(void)
{ 
    uint8_t count = 0;
    while((SPI1->SR & SPI_SR_TXE) == ~SPI_SR_TXE_Msk){}
    //while((SPI1->SR & SPI_SR_RXNE) == SPI_SR_RXNE_Msk){}
    while((SPI1->SR & SPI_SR_BSY) == SPI_SR_BSY_Msk){}
    while(1){count++;if(count == 75){ count = 0; break;}__NOP();}
    GPIOA->BSRR = GPIO_BSRR_BS12;
}
///////////////////////////////////////////////////////////////////////////////
uint8_t SPI1_Read(void)
{
 // SPI1->DR = 0; //запускаем обмен
  
  //Ждем, пока не появится новое значение 
  //в буфере приемника
  while(!(SPI1->SR & SPI_SR_RXNE))
    ;
  
  //возвращаем значение буфера приемника
  return SPI1->DR;
}



2. Код настройки w5500 (В нем много мусора, его можно упросить)

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/*
*/
#include"stdbool.h"
#include"w5500.h"
#include"stdint.h"
#include"SPI.h"
#include"math.h"
#include"stm32f1xx.h"
 
//Шлюз
static uint8_t GatewayAddress [4] = { 0xC0, 0xA8, 0x00, 0x01};//192.168.0.1
//static uint8_t *ptr_GatewayAddress = GatewayAddress;
//Маска подсети
static uint8_t SubnetMaskAddress [4] = {0xFF,0xFF,0xFF,0x00};//255.255.255.0
//static uint8_t *ptr_SubnetMaskAddress = SubnetMaskAddress;
//MAC адрес
// FF 23 5F 63 21 38
static uint8_t SourceHardwareAddress [6] =  { 0xFF, 0x23, 0x5F, 0x63, 0x21, 0x38 };
//static uint8_t *ptr_SourceHardwareAddress = SourceHardwareAddress;
//IP источника
static uint8_t SourceIPAddress [4] = { 0xC0, 0xA8, 0x00, 0x0F};// 192.168.0.40
////////////////////////////////////////////////////////////////////////////////
static uint8_t NUM_PORT_SOCKET_0_1 = 0x13;
static uint8_t NUM_PORT_SOCKET_0_0 = 0x88;
////////////////////////////////////////////////////////////////////////////////
 
 
 
 
 
 
//Функция отправки адреса и контрольной суммы режим отправки неограниченной длины
void WriteAddrPhaseANDControlPhase(uint16_t AddrPhase, uint8_t BSB, bool RorW)
{
    uint8_t data = 0;
    uint8_t *ptr_data = &data;
    data = AddrPhase>>8;
    SPI1_TX_8bit(ptr_data,sizeof(data));//TX Hight Bits Addr
    data = 0;
    data |= (uint8_t)AddrPhase;
    SPI1_TX_8bit(ptr_data,sizeof(data));//TX Low Bits Addr
    data = 0;
    data |= (BSB << 3);
    if(RorW == true) data |= 1 << 2;
    SPI1_TX_8bit(ptr_data,sizeof(data));
}
 
void W5500IniGARx_SUBRx_SHARx_SIPRx(void)
{
        //uint8_t count = 0;
    //--------------------------------------------------------------------------------
        SPI1_DROP_CS();
        WriteAddrPhaseANDControlPhase(GAR0, SelectsComonRegister, true);
    //Transmit GatewayAddress
        SPI1_TX_8bit(GatewayAddress, sizeof(GatewayAddress[0]));
        SPI1_TX_8bit(GatewayAddress+1, sizeof(GatewayAddress[1]));
        SPI1_TX_8bit(GatewayAddress+2, sizeof(GatewayAddress[2]));
        SPI1_TX_8bit(GatewayAddress+3, sizeof(GatewayAddress[3]));
        SPI1_UP_CS();
        //while(count != 240 ){count++;__NOP();__NOP();}
    //--------------------------------------------------------------------------------
    //Transmit SubnetMaskAddress
        //SPI1_DROP_CS();
        //WriteAddrPhaseANDControlPhase(SUBR0, SelectsComonRegister, true);
    /*  SPI1_TX_8bit(SubnetMaskAddress, sizeof(SubnetMaskAddress[0]));
        SPI1_TX_8bit(SubnetMaskAddress+1, sizeof(SubnetMaskAddress[1]));
        SPI1_TX_8bit(SubnetMaskAddress+2, sizeof(SubnetMaskAddress[2]));
        SPI1_TX_8bit(SubnetMaskAddress+3, sizeof(SubnetMaskAddress[3]));
        //SPI1_UP_CS();
        //while(count !=240 ){count++;__NOP();__NOP();}
    //--------------------------------------------------------------------------------
    //Transmit SourceHardwareAddress
        //SPI1_DROP_CS();
        //WriteAddrPhaseANDControlPhase(SHAR0, SelectsComonRegister, true);
        SPI1_TX_8bit(SourceHardwareAddress, sizeof(SourceHardwareAddress[0]));
        SPI1_TX_8bit(SourceHardwareAddress+1, sizeof(SourceHardwareAddress[1]));
        SPI1_TX_8bit(SourceHardwareAddress+2, sizeof(SourceHardwareAddress[2]));
        SPI1_TX_8bit(SourceHardwareAddress+3, sizeof(SourceHardwareAddress[3]));
        SPI1_TX_8bit(SourceHardwareAddress+4, sizeof(SourceHardwareAddress[4]));
        SPI1_TX_8bit(SourceHardwareAddress+5, sizeof(SourceHardwareAddress[5]));
        //SPI1_UP_CS();
        //while(count !=240 ){count++;__NOP();__NOP();}
    //--------------------------------------------------------------------------------
    //Transmit SourceHardwareAddres
        //SPI1_DROP_CS();
        //WriteAddrPhaseANDControlPhase(SIPRO0, SelectsComonRegister, true);
        SPI1_TX_8bit(SourceIPAddress, sizeof(SourceIPAddress[0]));
        SPI1_TX_8bit(SourceIPAddress+1, sizeof(SourceIPAddress[1]));
        SPI1_TX_8bit(SourceIPAddress+2, sizeof(SourceIPAddress[2]));
        SPI1_TX_8bit(SourceIPAddress+3, sizeof(SourceIPAddress[3]));
        SPI1_UP_CS();
        //while(count !=240 ){count++;__NOP();__NOP();}*/
    //--------------------------------------------------------------------------------
}
//////////////////////////////////////////////////////////////////////////////////////////
 
 
void W5500_SettingsSocket(void)
{
    SPI1_DROP_CS();
    WriteAddrPhaseANDControlPhase(Sn_PORT0,SelectsSoket0Register,true);
    SPI1_TX_8bit(&NUM_PORT_SOCKET_0_1,sizeof(NUM_PORT_SOCKET_0_1));
    SPI1_TX_8bit(&NUM_PORT_SOCKET_0_0,sizeof(NUM_PORT_SOCKET_0_0));
    SPI1_UP_CS();
}


3. Осциллограммы на первой картинке показаны синхроимпульсы
На первом рисунке показаны синхроимпульсы желтым цветом, а данные которые я передаю красным.
На второй картинке красным синхроимпульсы, а желтым CS. У осциллографа два входа поэтому пришлось делать две фотографии. я там передаю GatewayAddress [4] = { 0xC0, 0xA8, 0x00, 0x01};//192.168.0.1 это данные ну, а в начале идет передача служебных данных.
Общая длина посылки 56 бита, я считал все совпадает, когда я пытаюсь прочитать из w5500, я ничего не получаю.


За ответы заранее спасибо, с Уважением NiKit_A
Миниатюры
STM32+W5500 не работает   STM32+W5500 не работает  
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
24.07.2020, 13:17
Ответы с готовыми решениями:

Работа с W5500
Доброго времени суток. Пытаюсь запустить Ethernet микруху W5500. Настройки работают, IP и порт...

STM32. SD карта работает в release, но не работает в debug
Здравствуйте. У меня следующая проблема: SD карта инициализируется только в release сборке. Если...

STM32 - Не работает ногодрыг на порту B, а на A и C работает
Здравствуйте! Все, я окончательно запутался. У меня не работает примитивный код на BluePill. ...

W5500 и arduino NANO
Всем привет. Привязываю китайский модуль W5500 к arduino NANO. Пишу в Atmel Studio на Си....

2
83 / 82 / 4
Регистрация: 20.11.2016
Сообщений: 251
22.07.2022, 22:04 2
NiKit_A, вы решили эту проблему?
0
83 / 82 / 4
Регистрация: 20.11.2016
Сообщений: 251
23.07.2022, 10:38 3
NiKit_A, я решил свою проблему со чтением/записью в регистры W5500.

Между активным сигналом выборки кристалла CS и самим кодом обращения к регистрам модуля я добавил временную задержку из нескольких команд __NOP().
0
23.07.2022, 10:38
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
23.07.2022, 10:38
Помогаю со студенческими работами здесь

Что вы думаете о W5500?
цена вопроса 2-3 доллара. полное решение для скажем сервера на камне. стоит ли мутить стеки на...

TrueStudio + w5500 Ethrnet
по мотивам описанного http://www.nazim.ru/2386 пытаюсь соединится с модулем w5500 использую...

WIZNET W5500 DipTrace Library
WIZNET W5500 DipTrace Library Библиотека Исходники

W5500, формирование импульса RESET RC цепочкой
Есть схема с W5500, на питание чипа есть ключ. Не хочется выделять отдельную ногу МК для управления...

printf() не работает в STM32
Здравствуйте все ! Мне в проекте надо выводить текст и переменные на терминал PuTTY. Использую...

Stm32 не работает I2C в FreeRTOS
День добрый. Подключаю модуль с EEPROM памятью к STM32F401. Если пытаюсь записать и прочитать...

Как работает ADC в STM32 ?
Добрый день ! Я тут балуюсь с Нуклео бордом и хочу замерить напряжение через ADC. Недолго думая...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
3
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru