I am trying to interface W5500 with STM32f103c8t6 using UDP . Problem is I can’t send data trough UDP socket but I can receive data from the UDP socket . Please help me to solve the problem
Thank you
I am trying to interface W5500 with STM32f103c8t6 using UDP . Problem is I can’t send data trough UDP socket but I can receive data from the UDP socket . Please help me to solve the problem
Thank you
There is not enough information in the question.
You have now written a question on the W5500 Ethernet Shield category. Are you using the W5500 Ethernet Shield?
Anyway, we need to know what code you used to help you.
In addition, we need information about what settings you have set up to send and receive data.
Hi i have following Wiznet W5100 board
http://www.ebay.in/itm/112321091012?aff_source=Sok-Goog
and i am interfacing it following STM32 Board using UDP
I am trying to make an Echo server. Whatever data is sent to my chip via W5500 , data is returned back to the PC. I have a C# program written by myself to send and receive data using UDP socket. I am Monitoring communication by Wireshark. UDP send from PC is working ok. i can see the data sent in wireshark and data is received without any problem in my C program. But when i send the data back to the PC, Function SendData is stuck inside while(1) loop
such that Sok_0_INTR_Value is always 0x04. I neither get timeout or send_ok.Please drop me a word if possible
Thank You
#define BSB_Common_Reg 0b00000 // Block Selection Bits - Common Reg
#define BSB_Sok_0_Reg 0b00001
#define Wiz_CS GPIO_Pin_3 // Port A
#define Wiz_RST GPIO_Pin_2 // Port A
unsigned volatile char DataRecieved = 0 ; // To be changed by Socket Interrupt = Volatile
int main(void)
{
LEDSetup();
SPI1_setup();
ExtInterruptLineConfig();
Wiz_Setup_A_INIT();
Wiz_Setup_B_OPEN();
unsigned short RecvCount = 0 ;
unsigned short Count = 0 ;
unsigned char Data[64];
unsigned char SCADAInfo[8];
while(1)
{
GPIO_SetBits(GPIOC, GPIO_Pin_8 | GPIO_Pin_9 );
Delay(1,500);
GPIO_ResetBits(GPIOC, GPIO_Pin_8 | GPIO_Pin_9 );
Delay(1,500);
RecvCount = DataRecievedCheck();
if( RecvCount )
{
GetData(Data , &Count ,SCADAInfo); // Recieve Data
SendData(Data ,Count );
__disable_irq();
RecvCount = 0 ; // Atomic
__enable_irq();
Wiz_Setup_B_OPEN(); // Wiz UDP = Open-Close Socket every Time. But NOT in Wiz TCP
}
}
return 1 ;
}
void Wiz_Setup_A_INIT(void)
{
unsigned short GAR = 0x0001 ; // Gateway 4 Bytes
unsigned short SUBR = 0x0005 ; // Subnet 4 Bytes
unsigned short SAR = 0x0009 ; // Source Hardware Address MAC - 6 Bytes
unsigned short SIPR = 0x000F ; // IP Address 4 Bytes
unsigned short RCR = 0x001B ; // Retry Count, Retry Attempts = RCR + 1, Set RCR = 2 so Attempts = 3
unsigned short SIMR = 0x0016 ; // Socket Interrupt Mask , Only enable for the Intterupts u would use , SIR = 0X00 = CLEARED BY STM32
// Reset
Delay(1,200);
GPIO_ResetBits(GPIOA, Wiz_RST);
Delay(1,5); // Reset Time = 1.5 Mili Sec
GPIO_SetBits(GPIOA, Wiz_RST);
Delay(1,2);
// Auto Negotionaion = 2 Chips decide their Speed ( 10 / 100 MBPs ) and Duplex ( Sigle / double)
// Link = Up => Auto Negotiation is success
// unsigned short PHYCFGR = 0x002E ;
// unsigned char PHYCFGRValue = 0x00 ; // If PHYCFGRValue && 0x01 = 1 => Link UP
// while( ( PHYCFGRValue & 0x01) != 0 ) // 0Th bit of PHYCFGR Reg = 1
// Wiz_Read_Multi( PHYCFGR , BSB_Common_Reg , &PHYCFGRValue , 1);
// Mode Reg = 0x00 after Reset = ok
unsigned char mac[] = {0x00,0x16,0x36,0xDE,0x58,0xF6};
unsigned char ip[] = {192,168,1,12}; // 0xC0 , 0xA8 , 0x01 , 0x0C
unsigned char subnet[] = {255,255,255,0}; // 255 = 0xFF
unsigned char gate[] = {192,168,1,1};
Wiz_Write_Multi(SAR , BSB_Common_Reg , mac , sizeof(mac));
Wiz_Write_Multi(SIPR , BSB_Common_Reg , ip, sizeof(ip));
Wiz_Write_Multi(SUBR , BSB_Common_Reg , subnet , sizeof(subnet));
Wiz_Write_Multi(GAR , BSB_Common_Reg , gate , sizeof(gate));
unsigned char RCRValue = 0x02 ; // Retry Count = 0x02 + 1 = 3
Wiz_Write_Multi(RCR , BSB_Common_Reg , &RCRValue , sizeof(RCRValue));
// Default RTR Retry Time At Reset = 2000 = 2000 x 0.1 = 200 MiLi Sec = OK
// Default IMR Interrupt Mask Reg = 0x00 = All Desabled = OK
unsigned char SIMRValue = 0x01 ; // Socket Interrupt Mask keep Socket Interrupts Active AS PER PROJECT Needs
Wiz_Write_Multi(SIMR , BSB_Common_Reg , &SIMRValue , sizeof(SIMRValue)); // Only Socket 0 Interrupt = Enable
}
void Wiz_Setup_B_OPEN(void)
{
unsigned short Sok_0_Mod_Reg = 0x0000 ; // Mode Offet Address
unsigned char Sok_0_Mod_Value = 0x02 ; // Sock 0 Mode = 0x22 = UDP
unsigned short Sok_0_Port_Reg = 0x0004 ; // 2 Bytes - Sock 0 Port Offset Address
unsigned char port[] = {0x13,0x88}; // 0x1388 = 5000
unsigned short Sok_0_Comand_Reg = 0x0001 ; //
unsigned char Comand_OPEN = 0x01 ; // Command Reg = 0x01 => Socket OPEN
unsigned char Comand_CLOSE = 0x10 ; // Command Reg = 0x10 => Socket CLOSE
unsigned short Sok_0_Status_Reg = 0x0003 ;
unsigned char Status_Socket = 0x00 ; // => 0x02 = UDP
START: // Label
Wiz_Write_Multi(Sok_0_Mod_Reg , BSB_Sok_0_Reg , &Sok_0_Mod_Value , 1); // Mode = 0x22 = UDP
Wiz_Write_Multi(Sok_0_Port_Reg , BSB_Sok_0_Reg , port , 2 ); // Port = 5000
Wiz_Write_Multi(Sok_0_Comand_Reg , BSB_Sok_0_Reg , &Comand_OPEN , 1 ); // Open Socket
Wiz_Read_Multi(Sok_0_Status_Reg , BSB_Sok_0_Reg , &Status_Socket , 1 ); // Get Socket Status
if(Status_Socket != 0x22 ) // Status Reg = 0x22 => Socket = UDP
{
Wiz_Write_Multi(Sok_0_Comand_Reg , BSB_Sok_0_Reg , &Comand_CLOSE , 1 ); // Close Socket
goto START ;
}
// else socket is opened , Keep looping till Socket is opened
}
unsigned short DataRecievedCheck(void) // Socket Recieve Size Register RSR != 0x0000 .
{
// if(DataRecieved) // data Recieved
// {
// __disable_irq();
// DataRecieved = 0 ; // Atomic
// __enable_irq();
// unsigned short Sok_0_IR_Reg = 0x0002 ; // Sock 0 Interrupt Reg
// unsigned char Sok_0_IR_Value = 0x1F ; // Write 1 to Clear Interupt
// Wiz_Write_Multi(Sok_0_IR_Reg , BSB_Sok_0_Reg , &Sok_0_IR_Value , 1);
// // Clearing S0_IR (writing 1) also clears SIR_0
// return 1;
// }
// return 0 ;
unsigned short Sok_0_RSR_reg = 0x0026 ; // 2 Bytes - Recieved Size
unsigned char RSRValue[] = {0x00,0x00};
Wiz_Read_Multi(Sok_0_RSR_reg , BSB_Sok_0_Reg , RSRValue , 2 );
unsigned short RCVCount = ( RSRValue[0] << 8 ) | RSRValue[1];
return RCVCount ;
}
unsigned char SendData(unsigned char* data , unsigned short count )
{
// UDP MTU = 1472 Deafult
unsigned char BSB_Sok_0_Tx_Buffer = 0b00010;
unsigned short Sok_0_Tx_FreeSize_Reg = 0x0020 ; // 2 bytes
unsigned char Sok_0_Tx_FreeSize_Value[] = {0x00 , 0x00};
unsigned short Sok_0_RemoteIP_Reg = 0x000C ; // 4 bytes
unsigned char Sok_0_RemoteIP_Value[] = {192, 168 , 1 , 8}; // SCADA PC IP
unsigned short Sok_0_RemotePort_Reg = 0x0010 ; // 2 bytes
unsigned char Sok_0_RemotePort_Value[] = {0x13 , 0x89}; // SCADA PC Listening Port 5001 = 0x1389
unsigned short Sok_0_Tx_WritePT_Reg = 0x0024 ; // 2 bytes
unsigned char Sok_0_Tx_WritePT_value[] = {0x00 , 0x00};
unsigned short Sok_0_Comand_Reg = 0x0001 ;
unsigned char Comand_SEND = 0x20 ; // 0x20 => Socket SEND
unsigned char Comand_CLOSE = 0x10 ;
unsigned short Sok_0_INTR_Reg = 0x0002 ;
unsigned char Sok_0_INTR_Value = 0x00 ; // Check which Interrupt occured, Reset by Writing 1
// unsigned short IR_Reg = 0x0015 ; // Chip Level Interrupt Register
// unsigned char IR_Value = 0x00 ;
unsigned short FreeSize = 0 ;
FREESIZE : // Label
Wiz_Read_Multi(Sok_0_Tx_FreeSize_Reg , BSB_Sok_0_Reg , Sok_0_Tx_FreeSize_Value , 2 );
FreeSize = ( Sok_0_Tx_FreeSize_Value[0] << 8 ) | Sok_0_Tx_FreeSize_Value[1];
if( FreeSize < count)
goto FREESIZE ;
Wiz_Write_Multi(Sok_0_RemoteIP_Reg , BSB_Sok_0_Reg , Sok_0_RemoteIP_Value , 4 ); // SCADA IP
Wiz_Write_Multi(Sok_0_RemotePort_Reg , BSB_Sok_0_Reg , Sok_0_RemotePort_Value , 2 ); // SCADA Listening Port
unsigned short dist_ptr = 0 ;
Wiz_Read_Multi(Sok_0_Tx_WritePT_Reg , BSB_Sok_0_Reg , Sok_0_Tx_WritePT_value , 2 );
dist_ptr = ( Sok_0_Tx_WritePT_value[0] << 8 ) | Sok_0_Tx_WritePT_value[1];
Wiz_Write_Multi(dist_ptr , BSB_Sok_0_Tx_Buffer , data , count ); // write Data to Wiz Tx Buffer
dist_ptr += count;
Sok_0_Tx_WritePT_value[0] = dist_ptr >> 8 ; // 0 = MS Byte
Sok_0_Tx_WritePT_value[1] = dist_ptr & 0x00FF ; // 1 = LS Byte
Wiz_Write_Multi(Sok_0_Tx_WritePT_Reg , BSB_Sok_0_Reg , Sok_0_Tx_WritePT_value , 2 );
Wiz_Write_Multi(Sok_0_Comand_Reg , BSB_Sok_0_Reg , &Comand_SEND , 1 ); // SEND
unsigned char success = 0 ;
while(1)
{
Wiz_Read_Multi(Sok_0_INTR_Reg , BSB_Sok_0_Reg , &Sok_0_INTR_Value , 1 ); // read Interrupt Reg
if( (Sok_0_INTR_Value & ( 1 << 4)) != 0 ) // Send Ok
{
success = 1 ; // Break out of While Loop
break;
}
if( (Sok_0_INTR_Value & ( 1 << 3)) != 0 ) // Send Time Out
{
success = 0 ;
break; // Break out of While Loop
}
}
Sok_0_INTR_Value = 0xFF; //
Wiz_Write_Multi(Sok_0_INTR_Reg , BSB_Sok_0_Reg , &Sok_0_INTR_Value , 1 ); // Reset S0_IR = Write 1
// IR_n = 1 To Reset INTR
Wiz_Write_Multi(Sok_0_Comand_Reg , BSB_Sok_0_Reg , &Comand_CLOSE , 1 ); // CLOSE
return success ;
}
void GetData(unsigned char* data , unsigned short* count , unsigned char* UDPInfoPack) // Socket Recieve Size Register RSR != 0x0000 .
{
unsigned short Sok_0_RD_Point_Reg = 0x0028 ; // 2 bytes
unsigned char Sok_0_RD_Point_value[] = {0x00 , 0x00};
Wiz_Read_Multi(Sok_0_RD_Point_Reg , BSB_Sok_0_Reg , Sok_0_RD_Point_value , 2 );
unsigned short src_ptr = ( Sok_0_RD_Point_value[0] << 8 ) | Sok_0_RD_Point_value[1];
unsigned char BSB_Sok_0_Rx_Buffer = 0b00011;
Wiz_Read_Multi(src_ptr , BSB_Sok_0_Rx_Buffer , UDPInfoPack , 8 );
*count = (*(UDPInfoPack + 6) << 8 ) | (*(UDPInfoPack + 7)) ;
src_ptr += 8;
Wiz_Read_Multi(src_ptr, BSB_Sok_0_Rx_Buffer , data , *count );
// Set Read-pointer of Socket_0
src_ptr += *count ;
src_ptr -= 8 ;
Sok_0_RD_Point_value[0] = src_ptr >> 8 ; // MS Byte
Sok_0_RD_Point_value[1] = src_ptr & 0x00FF ; // LS Byte
Wiz_Write_Multi(Sok_0_RD_Point_Reg , BSB_Sok_0_Reg , Sok_0_RD_Point_value , 2 );
// Set Command Recieve
unsigned short Sok_0_Comand_Reg = 0x0001 ;
unsigned char Comand_RECV = 0x04 ; // Command Reg = 0x01 => Socket RECV
Wiz_Write_Multi(Sok_0_Comand_Reg , BSB_Sok_0_Reg , &Comand_RECV , 1 ); // Command = RECV
// Reset Interrupts - Clearing S0_IR (writing 1) also clears SIR_0
// unsigned short Sok_0_IR_Reg = 0x0002 ; // Sock 0 Interrupt Reg
// unsigned char Sok_0_IR_Value = 0x1F ; // Write 1 to Clear Interupt
// Wiz_Write_Multi(Sok_0_IR_Reg , BSB_Sok_0_Reg , &Sok_0_IR_Value , 1);
// Close Socket, it Rsets Rx buffer pointer
unsigned char Comand_CLOSE = 0x10 ; // Command Reg = 0x10 => Socket CLOSE
Wiz_Write_Multi(Sok_0_Comand_Reg , BSB_Sok_0_Reg , &Comand_CLOSE , 1 ); // Close Socket
}
void Wiz_Write_Multi( unsigned short address , unsigned char BSB , unsigned char* bytes , unsigned short count )
{
unsigned char control = ( BSB << 3 ) | 0x04 ; // BSB_RW_OM
// BSB 5 Bits, R/W bit W = 1 R = 0, OM 2 Bits = 00 = VDM = Chip Slect is NOT ground
unsigned short x = 0 ;
GPIO_ResetBits(GPIOA, Wiz_CS);
Delay(0,15);
SPI_SendBye(address >> 8); // Offset Address High Byte
SPI_SendBye(address & 0x00FF); // Offset Address Low Byte
SPI_SendBye(control); // VDM
for( x = 0 ; x < count ; x++ ) // Send Data
SPI_SendBye(*bytes++); // * has precedence over ++
Delay(0,15);
GPIO_SetBits(GPIOA, Wiz_CS);
Delay(0,15);
}
void Wiz_Read_Multi( unsigned short address , unsigned char BSB , unsigned char* data , unsigned short count)
{
unsigned char control = BSB << 3 ; // BSB_RW_OM => R/W = 0 , OM = 00
// BSB 5 Bits, R/W bit W = 1 R = 0, OM 2 Bits = 00 = VDM = Chip Slect is NOT ground
unsigned short x = 0 ;
GPIO_ResetBits(GPIOA, Wiz_CS);
Delay(0,15);
SPI_SendBye(address >> 8); // Offset Address High Byte
SPI_SendBye(address & 0x00FF); // Offset Address Low Byte
SPI_SendBye(control); // VDM - Read
for( x = 0 ; x < count ; x++ ) // Read Data
*data++ = SPI_ReadByte(); // * has precedence over ++
Delay(0,15);
GPIO_SetBits(GPIOA, Wiz_CS);
Delay(0,15);
// In C Array cant be returned , so pass an array by REFERENCE and fill it
}
void SPI_SendBye(unsigned char byte)
{
while ( SPI_I2S_GetFlagStatus(SPI1 , SPI_I2S_FLAG_TXE) == RESET ); // sending data Wait
SPI_I2S_SendData(SPI1 , byte);
while ( SPI_I2S_GetFlagStatus(SPI1 , SPI_I2S_FLAG_RXNE) == RESET ); // Wait for data
byte = SPI_I2S_ReceiveData(SPI1); // Dummy read to generate clock
}
unsigned char SPI_ReadByte(void)
{
while ( SPI_I2S_GetFlagStatus(SPI1 , SPI_I2S_FLAG_TXE) == RESET );
SPI_I2S_SendData(SPI1 , 0xff); // Dummy write to generate clock
while ( SPI_I2S_GetFlagStatus(SPI1 , SPI_I2S_FLAG_RXNE) == RESET );
return (unsigned char)SPI_I2S_ReceiveData(SPI1);
}
void SPI1_setup(void)
{
// Enable clock for SPI1 AFIO GPIOA GPIOB
RCC->APB2ENR |= ( 1<<12 ) | ( 1<<0 ) | ( 1<<2 ) | ( 1<<3 );
// PA 3 = CS PA 2 = RST
GPIO_InitTypeDef GpioPin;
GpioPin.GPIO_Pin = Wiz_CS | Wiz_RST ;
GpioPin.GPIO_Speed = GPIO_Speed_2MHz;
GpioPin.GPIO_Mode = GPIO_Mode_Out_PP ; // CS = DO = Out Push Pull
GPIO_Init(GPIOA, &GpioPin);
GPIO_SetBits(GPIOA, Wiz_CS | Wiz_RST ); // CS + RST = High
// SCK = PA5 = Alternate Push Pull 10 MHz
// MISO = PA6 = Input pull up
// MOSI = PA7 = Alternate Push Pull 10 MHz
GpioPin.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7 ; // Clock + MOSI
GpioPin.GPIO_Speed = GPIO_Speed_10MHz;
GpioPin.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GpioPin);
// Few example say MOSI is Alternate Push Pull
GpioPin.GPIO_Pin = GPIO_Pin_6 ;
GpioPin.GPIO_Mode = GPIO_Mode_IPU; // Input Pull Up
GPIO_Init(GPIOA, &GpioPin); // Clock + MOSI
SPI_InitTypeDef MySPI;
MySPI.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
MySPI.SPI_Mode = SPI_Mode_Master;
MySPI.SPI_DataSize = SPI_DataSize_8b;
MySPI.SPI_CPOL = SPI_CPOL_Low; // Mode 0
MySPI.SPI_CPHA = SPI_CPHA_1Edge; // Mode 0
MySPI.SPI_NSS = SPI_NSS_Soft; // CS handles by Software
MySPI.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2 ; // 24 / 2 = 12 MHz < 33.3 MHz
MySPI.SPI_CRCPolynomial = 7;
SPI_Init(SPI1 , &MySPI);
SPI_Cmd(SPI1 , ENABLE);
}
// Tim 2 = General Purpose , CNT ARR PSC = 16 Bit in STM32F100RB.
void Tim2_init(unsigned char base) // base = 0 = Micro , base = 1 Mili
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
TIM_TimeBaseInitTypeDef TIM;
TIM_TimeBaseStructInit(&TIM);
if(base)
TIM.TIM_Prescaler = (SystemCoreClock/1000)-1; // 10 CNT = 1 Mili Sec
else
TIM.TIM_Prescaler = (SystemCoreClock/1000000)-1; // 1 CNT = 1 Micro Sec
TIM.TIM_Period = 0xFFFF - 1 ; // ARR 32 Bits
TIM.TIM_ClockDivision = 0;
TIM.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2,&TIM);
TIM2->CNT = 0 ; // Reset
TIM_Cmd(TIM2,ENABLE); // Timer Start
// STM32F100RB Tim CLK = SystemCoreClock
// STM32F4 Tim CLK = SystemCoreClock / 2
}
void Delay( unsigned char base , unsigned short Ticks) // 0 = Micro , 1 = Mili
{
Tim2_init(base); // Reset during Init
volatile unsigned short start = TIM2->CNT;
while((TIM2->CNT - start) <= Ticks);
// Stop timer
TIM_Cmd(TIM2,DISABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,DISABLE); // Power Save
}
void LEDSetup(void)
{
RCC->APB2ENR |= ( 1 << 4 );
GPIO_InitTypeDef GpioPin;
GpioPin.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 ;
GpioPin.GPIO_Speed = GPIO_Speed_10MHz;
GpioPin.GPIO_Mode = GPIO_Mode_Out_PP ;
GPIO_Init(GPIOC, &GpioPin);
}
void ExtInterruptLineConfig(void)
{
RCC->APB2ENR |= (1<<4) | (1<<0) ; // AFIO is must for EXTI
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 ;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOC, &GPIO_InitStruct);
EXTI_InitTypeDef EXTI_InitStruct;
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource0); // Port Source = GPIOC
EXTI_InitStruct.EXTI_Line = EXTI_Line0 ; // EXTI_Line0 = PA0 PB0 PC0 PD0 ....
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; // So EXTI_Line0 = PC0
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling; // Falling Edge
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStruct);
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn; // EXTI0_IRQn = EXTI_Line0
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x0F; // lowest priority
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x0F; // lowest subpriority
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
// NVIC_EnableIRQ(EXTI0_IRQn);
}
void EXTI0_IRQHandler(void) // Data Recieved
{
if(EXTI_GetITStatus(EXTI_Line0) != RESET)
DataRecieved = 1 ;
EXTI_ClearITPendingBit(EXTI_Line0); // Must
}
Hi i have following Wiznet W5100 board
* http://www.ebay.in/itm/112321091012?aff_source=Sok-Goog
and i am interfacing it following STM32 Board using UDP
* http://www.st.com/en/evaluation-tools/stm32vldiscovery.html
I am trying to make an Echo server. Whatever data is sent to my chip via W5500 , data is returned back to the PC. I have a C# program written by myself to send and receive data using UDP socket. I am Monitoring communication by Wireshark. UDP send from PC is working ok. i can see the data sent in wireshark and data is received without any problem in my C program. But when i send the data back to the PC, Function SendData is stuck inside while(1) loop such that Sok_0_INTR_Value is always 0x04. I neither get timeout or send_ok. Physically there is a direct connection by patch cable between W5500 and my laptop. and w5500 gateway defined as laptop IP
Thank You
#include<stm32f10x.h>
#include<stm32f10x_gpio.h>
#define BSB_Common_Reg 0b00000 // Block Selection Bits - Common Reg
#define BSB_Sok_0_Reg 0b00001
#define Wiz_CS GPIO_Pin_3 // Port A
#define Wiz_RST GPIO_Pin_2 // Port A
unsigned volatile char DataRecieved = 0 ; // To be changed by Socket Interrupt = Volatile
int main(void)
{
SPI1_setup();
Wiz_Setup_A_INIT();
Wiz_Setup_B_OPEN();
unsigned short RecvCount = 0 ;
unsigned short Count = 0 ;
unsigned char Data[64];
unsigned char SCADAInfo[8];
while(1)
{
GPIO_SetBits(GPIOC, GPIO_Pin_8 | GPIO_Pin_9 );
Delay(1,500); // 500 Mili Sec
GPIO_ResetBits(GPIOC, GPIO_Pin_8 | GPIO_Pin_9 );
Delay(1,500); // 500 Mili Sec
RecvCount = DataRecievedCheck();
if( RecvCount )
{
GetData(Data , &Count ,SCADAInfo); // Recieve Data = Closes Soket in the end
SendData(Data ,Count ); // Send Data = Closes Soket in the end
__disable_irq();
RecvCount = 0 ; // Atomic
__enable_irq();
Wiz_Setup_B_OPEN(); // Wiz UDP = Open-Close Socket every Time. But NOT in Wiz TCP
}
}
return 1 ;
}
void Wiz_Setup_A_INIT(void)
{
unsigned short GAR = 0x0001 ; // Gateway 4 Bytes
unsigned short SUBR = 0x0005 ; // Subnet 4 Bytes
unsigned short SAR = 0x0009 ; // Source Hardware Address MAC - 6 Bytes
unsigned short SIPR = 0x000F ; // IP Address 4 Bytes
unsigned short RCR = 0x001B ; // Retry Count, Retry Attempts = RCR + 1, Set RCR = 2 so Attempts = 3
unsigned short SIMR = 0x0016 ; // Socket Interrupt Mask , Only enable for the Intterupts u would use , SIR = 0X00 = CLEARED BY STM32
// Reset
Delay(1,200); // 200 Mili Sec
GPIO_ResetBits(GPIOA, Wiz_RST);
Delay(1,5); // Reset Time = 1.5 Mili Sec
GPIO_SetBits(GPIOA, Wiz_RST);
Delay(1,2); // 2 mili sec
// Auto Negotionaion = 2 Chips decide their Speed ( 10 / 100 MBPs ) and Duplex ( Sigle / double)
// Link = Up => Auto Negotiation is success
// unsigned short PHYCFGR = 0x002E ;
// unsigned char PHYCFGRValue = 0x00 ; // If PHYCFGRValue && 0x01 = 1 => Link UP
// while( ( PHYCFGRValue & 0x01) != 0 ) // 0Th bit of PHYCFGR Reg = 1
// Wiz_Read_Multi( PHYCFGR , BSB_Common_Reg , &PHYCFGRValue , 1);
// Mode Reg = 0x00 after Reset = ok
unsigned char mac[] = {0x00,0x16,0x36,0xDE,0x58,0xF6};
unsigned char ip[] = {192,168,1,12}; // 0xC0 , 0xA8 , 0x01 , 0x0C
unsigned char subnet[] = {255,255,255,0}; // 255 = 0xFF
unsigned char gate[] = {192,168,1,1};
// Direct connection by patch cable between W5500 and laptop. gateway defined as laptop IP
Wiz_Write_Multi(SAR , BSB_Common_Reg , mac , sizeof(mac));
Wiz_Write_Multi(SIPR , BSB_Common_Reg , ip, sizeof(ip));
Wiz_Write_Multi(SUBR , BSB_Common_Reg , subnet , sizeof(subnet));
Wiz_Write_Multi(GAR , BSB_Common_Reg , gate , sizeof(gate));
unsigned char RCRValue = 0x02 ; // Retry Count = 0x02 + 1 = 3
Wiz_Write_Multi(RCR , BSB_Common_Reg , &RCRValue , sizeof(RCRValue));
// Default RTR Retry Time At Reset = 2000 = 2000 x 0.1 = 200 MiLi Sec = OK
// Default IMR Interrupt Mask Reg = 0x00 = All Desabled = OK
unsigned char SIMRValue = 0x01 ; // Socket Interrupt Mask keep Socket Interrupts Active AS PER PROJECT Needs
Wiz_Write_Multi(SIMR , BSB_Common_Reg , &SIMRValue , sizeof(SIMRValue)); // Only Socket 0 Interrupt = Enable
}
void Wiz_Setup_B_OPEN(void)
{
unsigned short Sok_0_Mod_Reg = 0x0000 ; // Mode Offet Address
unsigned char Sok_0_Mod_Value = 0x02 ; // Sock 0 Mode = 0x22 = UDP
unsigned short Sok_0_Port_Reg = 0x0004 ; // 2 Bytes - Sock 0 Port Offset Address
unsigned char port[] = {0x13,0x88}; // 0x1388 = 5000
unsigned short Sok_0_Comand_Reg = 0x0001 ; //
unsigned char Comand_OPEN = 0x01 ; // Command Reg = 0x01 => Socket OPEN
unsigned char Comand_CLOSE = 0x10 ; // Command Reg = 0x10 => Socket CLOSE
unsigned short Sok_0_Status_Reg = 0x0003 ;
unsigned char Status_Socket = 0x00 ; // => 0x02 = UDP
START: // Label
Wiz_Write_Multi(Sok_0_Mod_Reg , BSB_Sok_0_Reg , &Sok_0_Mod_Value , 1); // Mode = 0x22 = UDP
Wiz_Write_Multi(Sok_0_Port_Reg , BSB_Sok_0_Reg , port , 2 ); // Port = 5000
Wiz_Write_Multi(Sok_0_Comand_Reg , BSB_Sok_0_Reg , &Comand_OPEN , 1 ); // Open Socket
Wiz_Read_Multi(Sok_0_Status_Reg , BSB_Sok_0_Reg , &Status_Socket , 1 ); // Get Socket Status
if(Status_Socket != 0x22 ) // Status Reg = 0x22 => Socket = UDP
{
Wiz_Write_Multi(Sok_0_Comand_Reg , BSB_Sok_0_Reg , &Comand_CLOSE , 1 ); // Close Socket
goto START ;
}
// else socket is opened , Keep looping till Socket is opened
}
unsigned short DataRecievedCheck(void) // Socket Recieve Size Register RSR != 0x0000 .
{
unsigned short Sok_0_RSR_reg = 0x0026 ; // 2 Bytes - Recieved Size
unsigned char RSRValue[] = {0x00,0x00};
Wiz_Read_Multi(Sok_0_RSR_reg , BSB_Sok_0_Reg , RSRValue , 2 );
unsigned short RCVCount = ( RSRValue[0] << 8 ) | RSRValue[1];
return RCVCount ;
}
unsigned char SendData(unsigned char* data , unsigned short count )
{
// UDP MTU = 1472 Deafult
unsigned char BSB_Sok_0_Tx_Buffer = 0b00010;
unsigned short Sok_0_Tx_FreeSize_Reg = 0x0020 ; // 2 bytes
unsigned char Sok_0_Tx_FreeSize_Value[] = {0x00 , 0x00};
unsigned short Sok_0_RemoteIP_Reg = 0x000C ; // 4 bytes
unsigned char Sok_0_RemoteIP_Value[] = {192, 168 , 1 , 8}; // SCADA PC IP
unsigned short Sok_0_RemotePort_Reg = 0x0010 ; // 2 bytes
unsigned char Sok_0_RemotePort_Value[] = {0x13 , 0x89}; // SCADA PC Listening Port 5001 = 0x1389
unsigned short Sok_0_Tx_WritePT_Reg = 0x0024 ; // 2 bytes
unsigned char Sok_0_Tx_WritePT_value[] = {0x00 , 0x00};
unsigned short Sok_0_Comand_Reg = 0x0001 ;
unsigned char Comand_SEND = 0x20 ; // 0x20 => Socket SEND
unsigned char Comand_CLOSE = 0x10 ;
unsigned short Sok_0_INTR_Reg = 0x0002 ;
unsigned char Sok_0_INTR_Value = 0x00 ; // Check which Interrupt occured, Reset by Writing 1
// unsigned short IR_Reg = 0x0015 ; // Chip Level Interrupt Register
// unsigned char IR_Value = 0x00 ;
unsigned short FreeSize = 0 ;
FREESIZE : // Label
Wiz_Read_Multi(Sok_0_Tx_FreeSize_Reg , BSB_Sok_0_Reg , Sok_0_Tx_FreeSize_Value , 2 );
FreeSize = ( Sok_0_Tx_FreeSize_Value[0] << 8 ) | Sok_0_Tx_FreeSize_Value[1];
if( FreeSize < count)
goto FREESIZE ;
Wiz_Write_Multi(Sok_0_RemoteIP_Reg , BSB_Sok_0_Reg , Sok_0_RemoteIP_Value , 4 ); // SCADA IP
Wiz_Write_Multi(Sok_0_RemotePort_Reg , BSB_Sok_0_Reg , Sok_0_RemotePort_Value , 2 ); // SCADA Listening Port
unsigned short dist_ptr = 0 ;
Wiz_Read_Multi(Sok_0_Tx_WritePT_Reg , BSB_Sok_0_Reg , Sok_0_Tx_WritePT_value , 2 );
dist_ptr = ( Sok_0_Tx_WritePT_value[0] << 8 ) | Sok_0_Tx_WritePT_value[1];
Wiz_Write_Multi(dist_ptr , BSB_Sok_0_Tx_Buffer , data , count ); // write Data to Wiz Tx Buffer
dist_ptr += count;
Sok_0_Tx_WritePT_value[0] = dist_ptr >> 8 ; // 0 = MS Byte
Sok_0_Tx_WritePT_value[1] = dist_ptr & 0x00FF ; // 1 = LS Byte
Wiz_Write_Multi(Sok_0_Tx_WritePT_Reg , BSB_Sok_0_Reg , Sok_0_Tx_WritePT_value , 2 );
Wiz_Write_Multi(Sok_0_Comand_Reg , BSB_Sok_0_Reg , &Comand_SEND , 1 ); // SEND
unsigned char success = 0 ;
while(1)
{
Wiz_Read_Multi(Sok_0_INTR_Reg , BSB_Sok_0_Reg , &Sok_0_INTR_Value , 1 ); // read Interrupt Reg
if( (Sok_0_INTR_Value & ( 1 << 4)) != 0 ) // Send Ok
{
success = 1 ; // Break out of While Loop
break;
}
if( (Sok_0_INTR_Value & ( 1 << 3)) != 0 ) // Send Time Out
{
success = 0 ;
break; // Break out of While Loop
}
}
Sok_0_INTR_Value = 0xFF;// IR_n = 1 To Reset INTR
Wiz_Write_Multi(Sok_0_INTR_Reg , BSB_Sok_0_Reg , &Sok_0_INTR_Value , 1 ); // Reset S0_IR = Write 1
Wiz_Write_Multi(Sok_0_Comand_Reg , BSB_Sok_0_Reg , &Comand_CLOSE , 1 ); // CLOSE
return success ;
}
void GetData(unsigned char* data , unsigned short* count , unsigned char* UDPInfoPack) // Socket Recieve Size Register RSR != 0x0000 .
{
unsigned short Sok_0_RD_Point_Reg = 0x0028 ; // 2 bytes
unsigned char Sok_0_RD_Point_value[] = {0x00 , 0x00};
Wiz_Read_Multi(Sok_0_RD_Point_Reg , BSB_Sok_0_Reg , Sok_0_RD_Point_value , 2 );
unsigned short src_ptr = ( Sok_0_RD_Point_value[0] << 8 ) | Sok_0_RD_Point_value[1];
unsigned char BSB_Sok_0_Rx_Buffer = 0b00011;
Wiz_Read_Multi(src_ptr , BSB_Sok_0_Rx_Buffer , UDPInfoPack , 8 );
*count = (*(UDPInfoPack + 6) << 8 ) | (*(UDPInfoPack + 7)) ;
src_ptr += 8;
Wiz_Read_Multi(src_ptr, BSB_Sok_0_Rx_Buffer , data , *count );
// Set Read-pointer of Socket_0
src_ptr += *count ;
src_ptr -= 8 ;
Sok_0_RD_Point_value[0] = src_ptr >> 8 ; // MS Byte
Sok_0_RD_Point_value[1] = src_ptr & 0x00FF ; // LS Byte
Wiz_Write_Multi(Sok_0_RD_Point_Reg , BSB_Sok_0_Reg , Sok_0_RD_Point_value , 2 );
// Set Command Recieve
unsigned short Sok_0_Comand_Reg = 0x0001 ;
unsigned char Comand_RECV = 0x04 ; // Command Reg = 0x01 => Socket RECV
Wiz_Write_Multi(Sok_0_Comand_Reg , BSB_Sok_0_Reg , &Comand_RECV , 1 ); // Command = RECV
// Reset Interrupts - Clearing S0_IR (writing 1) also clears SIR_0
// unsigned short Sok_0_IR_Reg = 0x0002 ; // Sock 0 Interrupt Reg
// unsigned char Sok_0_IR_Value = 0x1F ; // Write 1 to Clear Interupt
// Wiz_Write_Multi(Sok_0_IR_Reg , BSB_Sok_0_Reg , &Sok_0_IR_Value , 1);
// Close Socket, it Rsets Rx buffer pointer
unsigned char Comand_CLOSE = 0x10 ; // Command Reg = 0x10 => Socket CLOSE
Wiz_Write_Multi(Sok_0_Comand_Reg , BSB_Sok_0_Reg , &Comand_CLOSE , 1 ); // Close Socket
}
void Wiz_Write_Multi( unsigned short address , unsigned char BSB , unsigned char* bytes , unsigned short count )
{
unsigned char control = ( BSB << 3 ) | 0x04 ; // BSB_RW_OM
// BSB 5 Bits, R/W bit W = 1 R = 0, OM 2 Bits = 00 = VDM = Chip Slect is NOT ground
unsigned short x = 0 ;
GPIO_ResetBits(GPIOA, Wiz_CS);
Delay(0,15);
SPI_SendBye(address >> 8); // Offset Address High Byte
SPI_SendBye(address & 0x00FF); // Offset Address Low Byte
SPI_SendBye(control); // VDM
for( x = 0 ; x < count ; x++ ) // Send Data
SPI_SendBye(*bytes++); // * has precedence over ++
Delay(0,15);
GPIO_SetBits(GPIOA, Wiz_CS);
Delay(0,15);
}
void Wiz_Read_Multi( unsigned short address , unsigned char BSB , unsigned char* data , unsigned short count)
{
unsigned char control = BSB << 3 ; // BSB_RW_OM => R/W = 0 , OM = 00
// BSB 5 Bits, R/W bit W = 1 R = 0, OM 2 Bits = 00 = VDM = Chip Slect is NOT ground
unsigned short x = 0 ;
GPIO_ResetBits(GPIOA, Wiz_CS);
Delay(0,15);
SPI_SendBye(address >> 8); // Offset Address High Byte
SPI_SendBye(address & 0x00FF); // Offset Address Low Byte
SPI_SendBye(control); // VDM - Read
for( x = 0 ; x < count ; x++ ) // Read Data
*data++ = SPI_ReadByte(); // * has precedence over ++
Delay(0,15);
GPIO_SetBits(GPIOA, Wiz_CS);
Delay(0,15);
// In C Array cant be returned , so pass an array by REFERENCE and fill it
}
void SPI_SendBye(unsigned char byte)
{
while ( SPI_I2S_GetFlagStatus(SPI1 , SPI_I2S_FLAG_TXE) == RESET ); // sending data Wait
SPI_I2S_SendData(SPI1 , byte);
while ( SPI_I2S_GetFlagStatus(SPI1 , SPI_I2S_FLAG_RXNE) == RESET ); // Wait for data
byte = SPI_I2S_ReceiveData(SPI1); // Dummy read to generate clock
}
unsigned char SPI_ReadByte(void)
{
while ( SPI_I2S_GetFlagStatus(SPI1 , SPI_I2S_FLAG_TXE) == RESET );
SPI_I2S_SendData(SPI1 , 0xff); // Dummy write to generate clock
while ( SPI_I2S_GetFlagStatus(SPI1 , SPI_I2S_FLAG_RXNE) == RESET );
return (unsigned char)SPI_I2S_ReceiveData(SPI1);
}
void SPI1_setup(void)
{
// Enable clock for SPI1 AFIO GPIOA GPIOB
RCC->APB2ENR |= ( 1<<12 ) | ( 1<<0 ) | ( 1<<2 ) | ( 1<<3 );
// PA 3 = CS PA 2 = RST
GPIO_InitTypeDef GpioPin;
GpioPin.GPIO_Pin = Wiz_CS | Wiz_RST ;
GpioPin.GPIO_Speed = GPIO_Speed_2MHz;
GpioPin.GPIO_Mode = GPIO_Mode_Out_PP ; // CS = DO = Out Push Pull
GPIO_Init(GPIOA, &GpioPin);
GPIO_SetBits(GPIOA, Wiz_CS | Wiz_RST ); // CS + RST = High
// SCK = PA5 = Alternate Push Pull 10 MHz
// MISO = PA6 = Input pull up
// MOSI = PA7 = Alternate Push Pull 10 MHz
GpioPin.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7 ; // Clock + MOSI
GpioPin.GPIO_Speed = GPIO_Speed_10MHz;
GpioPin.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GpioPin);
// Few example say MOSI is Alternate Push Pull
GpioPin.GPIO_Pin = GPIO_Pin_6 ;
GpioPin.GPIO_Mode = GPIO_Mode_IPU; // Input Pull Up
GPIO_Init(GPIOA, &GpioPin); // Clock + MOSI
SPI_InitTypeDef MySPI;
MySPI.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
MySPI.SPI_Mode = SPI_Mode_Master;
MySPI.SPI_DataSize = SPI_DataSize_8b;
MySPI.SPI_CPOL = SPI_CPOL_Low; // Mode 0
MySPI.SPI_CPHA = SPI_CPHA_1Edge; // Mode 0
MySPI.SPI_NSS = SPI_NSS_Soft; // CS handles by Software
MySPI.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2 ; // 24 / 2 = 12 MHz < 33.3 MHz
MySPI.SPI_CRCPolynomial = 7;
SPI_Init(SPI1 , &MySPI);
SPI_Cmd(SPI1 , ENABLE);
}
This is a working UDP code both by polling and interrupt , tested on STM32F100RB
#include<stm32f10x.h>
#include<stm32f10x_gpio.h>
#include<stm32f10x_rcc.h>
#include<stm32f10x_usart.h>
#include<stm32f10x_tim.h>
#include<stm32f10x_spi.h>
#include<stm32f10x_exti.h>
#include<misc.h>
// ip.addr == 192.168.1.12
void Wiz_Write_Multi( unsigned short , unsigned char , unsigned char * , unsigned short ) ; // , , Pointer , Array Count
void Wiz_Read_Multi( unsigned short , unsigned char , unsigned char *, unsigned short ) ; // , , Pointer , Array Count
void LEDSetup(void);
void SPI1_setup(void);
void SPI_SendBye(unsigned char);
unsigned char SPI_ReadByte();
void Tim2_init(unsigned char);
void Delay( unsigned char , unsigned short); // 0 = Micro , 1 = Mili
void Wiz_Setup_A_INIT(void);
void Wiz_Setup_B_OPEN(void);
void ExtInterruptLineConfig(void) ;
void GetData(unsigned char* , unsigned short* , unsigned char*);
unsigned char SendData(unsigned char* , unsigned short);
unsigned short DataRecievedCheck(void);
#define BSB_Common_Reg 0b00000 // Block Selection Bits - Common Reg
#define BSB_Sok_0_Reg 0b00001
#define Wiz_CS GPIO_Pin_3 // Port A
#define Wiz_RST GPIO_Pin_2 // Port A
// __disable_irq();RecvCount = 0 ; // Atomic __enable_irq();
unsigned volatile char DataRecieved = 0 ; // To be changed by Socket Interrupt = Volatile
int main(void)
{
LEDSetup();
SPI1_setup();
ExtInterruptLineConfig();
Wiz_Setup_A_INIT();
Wiz_Setup_B_OPEN();
unsigned short RecvCount = 0 ;
unsigned short Count = 0 ;
unsigned char Data[64];
unsigned char SCADAInfo[8];
while(1)
{
GPIO_SetBits(GPIOC, GPIO_Pin_8 | GPIO_Pin_9 );
Delay(1,500);
GPIO_ResetBits(GPIOC, GPIO_Pin_8 | GPIO_Pin_9 );
Delay(1,500);
// RecvCount = DataRecievedCheck(); // if( RecvCount ) Polling
if( DataRecieved ) // Interrupt
{
DataRecieved = 0 ;
GetData(Data , &Count ,SCADAInfo); // Recieve Data = Closes Soket in the end
Wiz_Setup_B_OPEN();
SendData(Data ,Count ); // Send Data = Closes Soket in the end
Wiz_Setup_B_OPEN(); // Wiz UDP = Open-Close Socket every Time. But NOT in Wiz TCP
}
}
return 1 ;
}
void Wiz_Setup_A_INIT(void)
{
unsigned short GAR = 0x0001 ; // Gateway 4 Bytes
unsigned short SUBR = 0x0005 ; // Subnet 4 Bytes
unsigned short SAR = 0x0009 ; // Source Hardware Address MAC - 6 Bytes
unsigned short SIPR = 0x000F ; // IP Address 4 Bytes
unsigned short RCR = 0x001B ; // Retry Count, Retry Attempts = RCR + 1, Set RCR = 2 so Attempts = 3
unsigned short SIMR = 0x0018 ; // Socket Interrupt Mask , Only enable for the Intterupts u would use , SIR = 0X00 = CLEARED BY STM32
// Reset
Delay(1,200);
GPIO_ResetBits(GPIOA, Wiz_RST);
Delay(1,5); // Reset Time = 1.5 Mili Sec
GPIO_SetBits(GPIOA, Wiz_RST);
Delay(1,2);
// Auto Negotionaion = 2 Chips decide their Speed ( 10 / 100 MBPs ) and Duplex ( Sigle / double)
// Link = Up => Auto Negotiation is success
// unsigned short PHYCFGR = 0x002E ;
// unsigned char PHYCFGRValue = 0x00 ; // If PHYCFGRValue && 0x01 = 1 => Link UP
// while( ( PHYCFGRValue & 0x01) != 0 ) // 0Th bit of PHYCFGR Reg = 1
// Wiz_Read_Multi( PHYCFGR , BSB_Common_Reg , &PHYCFGRValue , 1);
// Mode Reg = 0x00 after Reset = ok
unsigned char mac[] = {0x00,0x16,0x36,0xDE,0x58,0xF6};
unsigned char ip[] = {192,168,1,12}; // 0xC0 , 0xA8 , 0x01 , 0x0C
unsigned char subnet[] = {255,255,255,0}; // 255 = 0xFF
unsigned char gate[] = {192,168,1,8}; // My Own laptop
// Direct connection by patch cable between W5500 and laptop. gateway defined as laptop IP
Wiz_Write_Multi(SAR , BSB_Common_Reg , mac , sizeof(mac));
Wiz_Write_Multi(SIPR , BSB_Common_Reg , ip, sizeof(ip));
Wiz_Write_Multi(SUBR , BSB_Common_Reg , subnet , sizeof(subnet));
Wiz_Write_Multi(GAR , BSB_Common_Reg , gate , sizeof(gate));
unsigned char RCRValue = 0x02 ; // Retry Count = 0x02 + 1 = 3
Wiz_Write_Multi(RCR , BSB_Common_Reg , &RCRValue , sizeof(RCRValue));
// Default RTR Retry Time At Reset = 2000 = 2000 x 0.1 = 200 MiLi Sec = OK
// Default IMR Interrupt Mask Reg = 0x00 = All Desabled = OK
unsigned char SIMRValue = 0x01 ; // Socket Interrupt Mask keep Socket Interrupts Active AS PER PROJECT Needs
Wiz_Write_Multi(SIMR , BSB_Common_Reg , &SIMRValue , sizeof(SIMRValue)); // Only Socket 0 Interrupt = Enable
}
void Wiz_Setup_B_OPEN(void)
{
unsigned short Sok_0_Mod_Reg = 0x0000 ; // Mode Offet Address
unsigned char Sok_0_Mod_Value = 0x02 ; // Sock 0 Mode = 0x22 = UDP
unsigned short Sok_0_Port_Reg = 0x0004 ; // 2 Bytes - Sock 0 Port Offset Address
unsigned char port[] = {0x13,0x88}; // 0x1388 = 5000
unsigned short Sok_0_Comand_Reg = 0x0001 ; //
unsigned char Comand_OPEN = 0x01 ; // Command Reg = 0x01 => Socket OPEN
unsigned char Comand_CLOSE = 0x10 ; // Command Reg = 0x10 => Socket CLOSE
unsigned short Sok_0_Status_Reg = 0x0003 ;
unsigned char Status_Socket = 0x00 ; // => 0x02 = UDP
START: // Label
Wiz_Write_Multi(Sok_0_Mod_Reg , BSB_Sok_0_Reg , &Sok_0_Mod_Value , 1); // Mode = 0x22 = UDP
Wiz_Write_Multi(Sok_0_Port_Reg , BSB_Sok_0_Reg , port , 2 ); // Port = 5000
Wiz_Write_Multi(Sok_0_Comand_Reg , BSB_Sok_0_Reg , &Comand_OPEN , 1 ); // Open Socket
Wiz_Read_Multi(Sok_0_Status_Reg , BSB_Sok_0_Reg , &Status_Socket , 1 ); // Get Socket Status
if(Status_Socket != 0x22 ) // Status Reg = 0x22 => Socket = UDP
{
Wiz_Write_Multi(Sok_0_Comand_Reg , BSB_Sok_0_Reg , &Comand_CLOSE , 1 ); // Close Socket
goto START ;
}
// else socket is opened , Keep looping till Socket is opened
}
unsigned short DataRecievedCheck(void) // Socket Recieve Size Register RSR != 0x0000 .
{
unsigned short Sok_0_RSR_reg = 0x0026 ; // 2 Bytes - Recieved Size
unsigned char RSRValue[] = {0x00,0x00};
Wiz_Read_Multi(Sok_0_RSR_reg , BSB_Sok_0_Reg , RSRValue , 2 );
unsigned short RCVCount = ( RSRValue[0] << 8 ) | RSRValue[1];
return RCVCount ;
}
unsigned char SendData(unsigned char* data , unsigned short count )
{
// Disable Interrupt during send, else Sending data will fire Send_OK or Time Out Interrupt
// which will make volatile DataRecieved = 1 so senddata will run again........making it Infinite Loop
// After send is complete , SIMR = 0x01 = Data Recieved interrupt will fire
unsigned short SIMR = 0x0018;
unsigned char SIMRValueDisable = 0x00 ; // Disable All Wiz Interrupt
unsigned char SIMRValueEnable0 = 0x01 ; // Enable Interrupt 0 Wiz Interrupt
Wiz_Write_Multi(SIMR , BSB_Common_Reg , &SIMRValueDisable , 1); // Disable Interrupt
// UDP MTU = 1472 Deafult
unsigned char BSB_Sok_0_Tx_Buffer = 0b00010;
unsigned short Sok_0_Tx_FreeSize_Reg = 0x0020 ; // 2 bytes
unsigned char Sok_0_Tx_FreeSize_Value[] = {0x00 , 0x00};
unsigned short Sok_0_RemoteIP_Reg = 0x000C ; // 4 bytes
unsigned char Sok_0_RemoteIP_Value[] = {192, 168 , 1 , 8}; // SCADA PC IP
unsigned short Sok_0_RemotePort_Reg = 0x0010 ; // 2 bytes
unsigned char Sok_0_RemotePort_Value[] = {0x13 , 0x89}; // SCADA PC Listening Port 5001 = 0x1389
unsigned short Sok_0_Tx_WritePT_Reg = 0x0024 ; // 2 bytes
unsigned char Sok_0_Tx_WritePT_value[] = {0x00 , 0x00};
unsigned short Sok_0_Comand_Reg = 0x0001 ;
unsigned char Comand_SEND = 0x20 ; // 0x20 => Socket SEND
unsigned char Comand_CLOSE = 0x10 ;
unsigned short Sok_0_INTR_Reg = 0x0002 ;
unsigned char Sok_0_INTR_Value = 0x00 ; // Check which Interrupt occured, Reset by Writing 1
// unsigned short IR_Reg = 0x0015 ; // Chip Level Interrupt Register
// unsigned char IR_Value = 0x00 ;
unsigned short FreeSize = 0 ;
FREESIZE : // Label
Wiz_Read_Multi(Sok_0_Tx_FreeSize_Reg , BSB_Sok_0_Reg , Sok_0_Tx_FreeSize_Value , 2 );
FreeSize = ( Sok_0_Tx_FreeSize_Value[0] << 8 ) | Sok_0_Tx_FreeSize_Value[1];
if( FreeSize < count)
goto FREESIZE ;
Wiz_Write_Multi(Sok_0_RemoteIP_Reg , BSB_Sok_0_Reg , Sok_0_RemoteIP_Value , 4 ); // SCADA IP
Wiz_Write_Multi(Sok_0_RemotePort_Reg , BSB_Sok_0_Reg , Sok_0_RemotePort_Value , 2 ); // SCADA Listening Port
unsigned short dist_ptr = 0 ;
Wiz_Read_Multi(Sok_0_Tx_WritePT_Reg , BSB_Sok_0_Reg , Sok_0_Tx_WritePT_value , 2 );
dist_ptr = ( Sok_0_Tx_WritePT_value[0] << 8 ) | Sok_0_Tx_WritePT_value[1];
Wiz_Write_Multi(dist_ptr , BSB_Sok_0_Tx_Buffer , data , count ); // write Data to Wiz Tx Buffer
dist_ptr += count;
Sok_0_Tx_WritePT_value[0] = dist_ptr >> 8 ; // 0 = MS Byte
Sok_0_Tx_WritePT_value[1] = dist_ptr & 0x00FF ; // 1 = LS Byte
Wiz_Write_Multi(Sok_0_Tx_WritePT_Reg , BSB_Sok_0_Reg , Sok_0_Tx_WritePT_value , 2 );
Wiz_Write_Multi(Sok_0_Comand_Reg , BSB_Sok_0_Reg , &Comand_SEND , 1 ); // SEND
unsigned char success = 0 ;
while(1)
{
Wiz_Read_Multi(Sok_0_INTR_Reg , BSB_Sok_0_Reg , &Sok_0_INTR_Value , 1 ); // read Interrupt Reg
if( (Sok_0_INTR_Value & ( 1 << 4)) != 0 ) // Send Ok
{
success = 1 ; // Break out of While Loop
break;
}
if( (Sok_0_INTR_Value & ( 1 << 3)) != 0 ) // Send Time Out
{
success = 0 ;
break; // Break out of While Loop
}
}
Sok_0_INTR_Value = 0x1F;// IR_n = 1 To Reset INTR
Wiz_Write_Multi(Sok_0_INTR_Reg , BSB_Sok_0_Reg , &Sok_0_INTR_Value , 1 ); // Reset S0_IR = Write 1
Wiz_Write_Multi(Sok_0_Comand_Reg , BSB_Sok_0_Reg , &Comand_CLOSE , 1 ); // CLOSE
// Enable only All Interrupt
Wiz_Write_Multi(SIMR , BSB_Common_Reg , &SIMRValueEnable0 , 1); // Disable Interrupt
return success ;
}
void GetData(unsigned char* data , unsigned short* count , unsigned char* UDPInfoPack) // Socket Recieve Size Register RSR != 0x0000 .
{
unsigned short Sok_0_RD_Point_Reg = 0x0028 ; // 2 bytes
unsigned char Sok_0_RD_Point_value[] = {0x00 , 0x00};
Wiz_Read_Multi(Sok_0_RD_Point_Reg , BSB_Sok_0_Reg , Sok_0_RD_Point_value , 2 );
unsigned short src_ptr = ( Sok_0_RD_Point_value[0] << 8 ) | Sok_0_RD_Point_value[1];
unsigned char BSB_Sok_0_Rx_Buffer = 0b00011;
Wiz_Read_Multi(src_ptr , BSB_Sok_0_Rx_Buffer , UDPInfoPack , 8 );
*count = (*(UDPInfoPack + 6) << 8 ) | (*(UDPInfoPack + 7)) ;
src_ptr += 8;
Wiz_Read_Multi(src_ptr, BSB_Sok_0_Rx_Buffer , data , *count );
// Set Read-pointer of Socket_0
src_ptr += *count ;
src_ptr -= 8 ;
Sok_0_RD_Point_value[0] = src_ptr >> 8 ; // MS Byte
Sok_0_RD_Point_value[1] = src_ptr & 0x00FF ; // LS Byte
Wiz_Write_Multi(Sok_0_RD_Point_Reg , BSB_Sok_0_Reg , Sok_0_RD_Point_value , 2 );
// Set Command Recieve
unsigned short Sok_0_Comand_Reg = 0x0001 ;
unsigned char Comand_RECV = 0x04 ; // Command Reg = 0x01 => Socket RECV
Wiz_Write_Multi(Sok_0_Comand_Reg , BSB_Sok_0_Reg , &Comand_RECV , 1 ); // Command = RECV
// Reset Interrupts - Clearing S0_IR (writing 1) also clears SIR_0
unsigned short Sok_0_IR_Reg = 0x0002 ; // Sock 0 Interrupt Reg
unsigned char Sok_0_IR_Value = 0x1F ; // Write 1 to Clear Interupt
Wiz_Write_Multi(Sok_0_IR_Reg , BSB_Sok_0_Reg , &Sok_0_IR_Value , 1);
// Close Socket, it Rsets Rx buffer pointer
unsigned char Comand_CLOSE = 0x10 ; // Command Reg = 0x10 => Socket CLOSE
Wiz_Write_Multi(Sok_0_Comand_Reg , BSB_Sok_0_Reg , &Comand_CLOSE , 1 ); // Close Socket
}
void Wiz_Write_Multi( unsigned short address , unsigned char BSB , unsigned char* bytes , unsigned short count )
{
unsigned char control = ( BSB << 3 ) | 0x04 ; // BSB_RW_OM
// BSB 5 Bits, R/W bit W = 1 R = 0, OM 2 Bits = 00 = VDM = Chip Slect is NOT ground
unsigned short x = 0 ;
GPIO_ResetBits(GPIOA, Wiz_CS);
Delay(0,15);
SPI_SendBye(address >> 8); // Offset Address High Byte
SPI_SendBye(address & 0x00FF); // Offset Address Low Byte
SPI_SendBye(control); // VDM
for( x = 0 ; x < count ; x++ ) // Send Data
SPI_SendBye(*bytes++); // * has precedence over ++
Delay(0,15);
GPIO_SetBits(GPIOA, Wiz_CS);
Delay(0,15);
}
void Wiz_Read_Multi( unsigned short address , unsigned char BSB , unsigned char* data , unsigned short count)
{
unsigned char control = BSB << 3 ; // BSB_RW_OM => R/W = 0 , OM = 00
// BSB 5 Bits, R/W bit W = 1 R = 0, OM 2 Bits = 00 = VDM = Chip Slect is NOT ground
unsigned short x = 0 ;
GPIO_ResetBits(GPIOA, Wiz_CS);
Delay(0,15);
SPI_SendBye(address >> 8); // Offset Address High Byte
SPI_SendBye(address & 0x00FF); // Offset Address Low Byte
SPI_SendBye(control); // VDM - Read
for( x = 0 ; x < count ; x++ ) // Read Data
*data++ = SPI_ReadByte(); // * has precedence over ++
Delay(0,15);
GPIO_SetBits(GPIOA, Wiz_CS);
Delay(0,15);
// In C Array cant be returned , so pass an array by REFERENCE and fill it
}
void SPI_SendBye(unsigned char byte)
{
while ( SPI_I2S_GetFlagStatus(SPI1 , SPI_I2S_FLAG_TXE) == RESET ); // sending data Wait
SPI_I2S_SendData(SPI1 , byte);
while ( SPI_I2S_GetFlagStatus(SPI1 , SPI_I2S_FLAG_RXNE) == RESET ); // Wait for data
byte = SPI_I2S_ReceiveData(SPI1); // Dummy read to generate clock
}
unsigned char SPI_ReadByte(void)
{
while ( SPI_I2S_GetFlagStatus(SPI1 , SPI_I2S_FLAG_TXE) == RESET );
SPI_I2S_SendData(SPI1 , 0xff); // Dummy write to generate clock
while ( SPI_I2S_GetFlagStatus(SPI1 , SPI_I2S_FLAG_RXNE) == RESET );
return (unsigned char)SPI_I2S_ReceiveData(SPI1);
}
void SPI1_setup(void)
{
// Enable clock for SPI1 AFIO GPIOA GPIOB
RCC->APB2ENR |= ( 1<<12 ) | ( 1<<0 ) | ( 1<<2 ) | ( 1<<3 );
// PA 3 = CS PA 2 = RST
GPIO_InitTypeDef GpioPin;
GpioPin.GPIO_Pin = Wiz_CS | Wiz_RST ;
GpioPin.GPIO_Speed = GPIO_Speed_2MHz;
GpioPin.GPIO_Mode = GPIO_Mode_Out_PP ; // CS = DO = Out Push Pull
GPIO_Init(GPIOA, &GpioPin);
GPIO_SetBits(GPIOA, Wiz_CS | Wiz_RST ); // CS + RST = High
// SCK = PA5 = Alternate Push Pull 10 MHz
// MISO = PA6 = Input pull up
// MOSI = PA7 = Alternate Push Pull 10 MHz
GpioPin.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7 ; // Clock + MOSI
GpioPin.GPIO_Speed = GPIO_Speed_10MHz;
GpioPin.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GpioPin);
// Few example say MOSI is Alternate Push Pull
GpioPin.GPIO_Pin = GPIO_Pin_6 ;
GpioPin.GPIO_Mode = GPIO_Mode_IPU; // Input Pull Up
GPIO_Init(GPIOA, &GpioPin); // Clock + MOSI
SPI_InitTypeDef MySPI;
MySPI.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
MySPI.SPI_Mode = SPI_Mode_Master;
MySPI.SPI_DataSize = SPI_DataSize_8b;
MySPI.SPI_CPOL = SPI_CPOL_Low; // Mode 0
MySPI.SPI_CPHA = SPI_CPHA_1Edge; // Mode 0
MySPI.SPI_NSS = SPI_NSS_Soft; // CS handles by Software
MySPI.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2 ; // 24 / 2 = 12 MHz < 33.3 MHz
MySPI.SPI_CRCPolynomial = 7;
SPI_Init(SPI1 , &MySPI);
SPI_Cmd(SPI1 , ENABLE);
}
// Tim 2 = General Purpose , CNT ARR PSC = 16 Bit in STM32F100RB.
void Tim2_init(unsigned char base) // base = 0 = Micro , base = 1 Mili
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
TIM_TimeBaseInitTypeDef TIM;
TIM_TimeBaseStructInit(&TIM);
if(base)
TIM.TIM_Prescaler = (SystemCoreClock/1000)-1; // 10 CNT = 1 Mili Sec
else
TIM.TIM_Prescaler = (SystemCoreClock/1000000)-1; // 1 CNT = 1 Micro Sec
TIM.TIM_Period = 0xFFFF - 1 ; // ARR 32 Bits
TIM.TIM_ClockDivision = 0;
TIM.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2,&TIM);
TIM2->CNT = 0 ; // Reset
TIM_Cmd(TIM2,ENABLE); // Timer Start
// STM32F100RB Tim CLK = SystemCoreClock
// STM32F4 Tim CLK = SystemCoreClock / 2
}
void Delay( unsigned char base , unsigned short Ticks) // 0 = Micro , 1 = Mili
{
Tim2_init(base); // Reset during Init
volatile unsigned short start = TIM2->CNT;
while((TIM2->CNT - start) <= Ticks);
// Stop timer
TIM_Cmd(TIM2,DISABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,DISABLE); // Power Save
}
void LEDSetup(void)
{
RCC->APB2ENR |= ( 1 << 4 );
GPIO_InitTypeDef GpioPin;
GpioPin.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 ;
GpioPin.GPIO_Speed = GPIO_Speed_10MHz;
GpioPin.GPIO_Mode = GPIO_Mode_Out_PP ;
GPIO_Init(GPIOC, &GpioPin);
}
void ExtInterruptLineConfig(void)
{
RCC->APB2ENR |= (1<<4) | (1<<0) ; // AFIO is must for EXTI
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 ;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOC, &GPIO_InitStruct);
EXTI_InitTypeDef EXTI_InitStruct;
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource0); // Port Source = GPIOC
EXTI_InitStruct.EXTI_Line = EXTI_Line0 ; // EXTI_Line0 = PA0 PB0 PC0 PD0 ....
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; // So EXTI_Line0 = PC0
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling; // Falling Edge
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStruct);
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn; // EXTI0_IRQn = EXTI_Line0
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x0F; // lowest priority
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x0F; // lowest subpriority
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
// NVIC_EnableIRQ(EXTI0_IRQn);
}
void EXTI0_IRQHandler(void) // Data Recieved
{
if(EXTI_GetITStatus(EXTI_Line0) != RESET)
DataRecieved = 1 ;
EXTI_ClearITPendingBit(EXTI_Line0); // Must
}
Your question seems to have already been solved in the following article
Thank you for providing a good reference.
Thank you . Your code help me a lot
Well then develop the TCP code with Interrupt , test it and share it with me…
Copyright © 2017 WIZnet Co., Ltd. All Rights Reserved.