Establishing connection with W5500, Novice

Hello, I am working on a project involving an EFM32ZG110F32 MCU communicating over SPI with the W5500. I can successfully read and write registers on the W5500. My next step is to communicate data from W5500 over ethernet to my computer application. I am very much a programming novice and have no experience coding with real hardware or with TCP/IP. Thus I am seeking some guidance to continue with my project as I am stuck for a while.

My project exists in Simplicity Studio. I have available to me the W5500 IO library and the loopback example for the Tiny Gecko, which I have modified to build/run on my Zero Gecko Chip. I am debugging with a Zero Gecko as well if that matters.

My problem seems to be that I am not establishing a socket connection. I have tried running the loopback example and pinging my device with Hercules while plugging in my project board to my PC. When I monitor traffic via Wireshark, I see that my PC is sending name queries to the device and not receiving a response. When I plug into a router, my device also does not show up. However I mostly am just probing around seeking results and greatly need someone to help mentor me through this.

I can certainly post snippets of my code if that will help, but I do not know where to start. Many thanks for your help.

Hello.

Are you trying to implement the Serial to Ethernet feature using the W5500?
First of all, I need to know what library or example you referenced.

If you only refer to ioLibrary, it depends on your code.
In this case, it is difficult to give more answers unless I check your code.

Have you ever referenced Opensource in Url below?
[url]https://github.com/Wiznet/WIZ550SR[/url]
The source at this URL is the source of the Serial to Ethernet module. If you have not already see so, please see this first.

In addition, I need network information (IP Address, SubnetMask, Gateway …) of your PC and network information applied to your device (W5500 + MCU).

Best regard,
Kei.

I believe that yes I am trying to use serial to Ethernet. I have an SI7013 temperature/humidity sensor transmitting data via I2C to my Zero Gecko MCU. I would like to take that data and transfer it via SPI to the W5500, and then transfer the data out via Ethernet to a controller/PC application. I2C and SPI are functioning well.

I am using code from the ioLibrary successfully for reads, writes, inits, resets, etc. Specifically I am using W5500.c, socket.c, and wizchip_conf.c. I am also referencing efm32tg840f32_w5500_20131220.zip, a loopback example for the Tiny Gecko.

I have been statically assigning an IP address, default gateway, and subnet mask using ctlnetwork(CN_SET_NETINFO,…).

A good pseudo code example of how to achieve what I am trying to do would be very helpful, as I am lacking direction. I have found little information in the spec and do not have a clear set of objectives as to how to transfer my data. I would like to even be able to plug my Ethernet device into a router and detect it. Then I think I can write a mini web-server and send data via XML. But first I need to establish connection.

I will take a look through your linked example and continue hammering away at this.

Thanks!

2 Likes

UDP-STM32F100-W5500- Working Code
#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>

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
}
3 Likes