W5500模塊-UDP模式收發(fā)代碼解析

MAIN.C
/
?* 描述? ? :W5500的端口0工作在UDP模式,端口通信不需要建立連接即可接收其它UDP模式端口發(fā)來的數(shù)據(jù),
?* 數(shù)據(jù)的前4個字節(jié)為對方端口IP地址,第5、6個字節(jié)為端口號,獲得對方IP和端口號后W5500端口0
?* 將定時給對應(yīng)端口發(fā)送字符串"\r\nWelcome To YiXinElec!\r\n",同時將接收
?* 到的數(shù)據(jù)回發(fā)給對應(yīng)端口。
?* 實(shí)驗(yàn)平臺:用戶STM32開發(fā)板 + YIXIN_W5500以太網(wǎng)(TCP/IP)模塊
?* 硬件連接:? PC5 -> W5500_RST? ? ?
?*? ? ? ? ? ? ?PA4 -> W5500_SCS? ? ??
?*? ? ? ? ? ? ?PA5 -> W5500_SCK? ??
?*? ? ? ? ? ? ?PA6 -> W5500_MISO? ??
?*? ? ? ? ? ? ?PA7 -> W5500_MOSI? ??
***************************************************************************************/
/*網(wǎng)絡(luò)參數(shù)*/
//網(wǎng)關(guān):192.168.1.1
//掩碼: 255.255.255.0
//物理地址:0C 29 AB 7C 00 01
//本機(jī)IP地址:192.168.1.199
//端口0的端口號:5000
//端口0的目的IP地址:192.168.1.190
//端口0的目的端口號:6000
#include "stm32f10x.h"
#include "W5500.h"
#include <string.h>
void RCC_Configuration(void); //設(shè)置系統(tǒng)時鐘為72MHZ(這個可以根據(jù)需要改)
void NVIC_Configuration(void); //STM32中斷向量表配配置
void Timer2_Init_Config(void); //Timer2初始化配置
void System_Initialization(void); //STM32系統(tǒng)初始化函數(shù)(初始化STM32時鐘及外設(shè))
void Delay(unsigned int d); //延時函數(shù)(ms)
unsigned int Timer2_Counter=0; //Timer2定時器計數(shù)變量(ms)
unsigned int W5500_Send_Delay_Counter=0; //W5500發(fā)送延時計數(shù)變量(ms)
/*******************************************************************************
* 函數(shù)名? : W5500_Initialization
* 描述? ? : W5500初始貨配置
* 輸入? ? : 無
* 輸出? ? : 無
* 返回值? : 無
* 說明? ? : 無
*******************************************************************************/
void W5500_Initialization(void)
{
? ? W5500_Init(); //初始化W5500寄存器函數(shù)
? ? Detect_Gateway(); //檢查網(wǎng)關(guān)服務(wù)器?
? ? Socket_Init(0); //指定Socket(0~7)初始化,初始化端口0
}
/*******************************************************************************
* 函數(shù)名? : Load_Net_Parameters
* 描述? ? : 裝載網(wǎng)絡(luò)參數(shù)
* 輸入? ? : 無
* 輸出? ? : 無
* 返回值? : 無
* 說明? ? : 網(wǎng)關(guān)、掩碼、物理地址、本機(jī)IP地址、端口號、目的IP地址、目的端口號、端口工作模式
*******************************************************************************/
void Load_Net_Parameters(void)
{
? ? Gateway_IP[0] = 192;//加載網(wǎng)關(guān)參數(shù)
? ? Gateway_IP[1] = 168;
? ? Gateway_IP[2] = 1;
? ? Gateway_IP[3] = 1;
? ? Sub_Mask[0]=255;//加載子網(wǎng)掩碼
? ? Sub_Mask[1]=255;
? ? Sub_Mask[2]=255;
? ? Sub_Mask[3]=0;
? ? Phy_Addr[0]=0x0c;//加載物理地址
? ? Phy_Addr[1]=0x29;
? ? Phy_Addr[2]=0xab;
? ? Phy_Addr[3]=0x7c;
? ? Phy_Addr[4]=0x00;
? ? Phy_Addr[5]=0x01;
? ? IP_Addr[0]=192;//加載本機(jī)IP地址
? ? IP_Addr[1]=168;
? ? IP_Addr[2]=1;
? ? IP_Addr[3]=199;
? ? S0_Port[0] = 0x13;//加載端口0的端口號5000?
? ? S0_Port[1] = 0x88;
? ? S0_Mode=UDP_MODE;//加載端口0的工作模式,UDP模式
}
/*******************************************************************************
* 函數(shù)名? : W5500_Socket_Set
* 描述? ? : W5500端口初始化配置
* 輸入? ? : 無
* 輸出? ? : 無
* 返回值? : 無
* 說明? ? : 分別設(shè)置4個端口,根據(jù)端口工作模式,將端口置于TCP服務(wù)器、TCP客戶端或UDP模式.
* 從端口狀態(tài)字節(jié)Socket_State可以判斷端口的工作情況
*******************************************************************************/
void W5500_Socket_Set(void)
{
? ? if(S0_State==0)//端口0初始化配置
? ? {
? ? if(S0_Mode==TCP_SERVER)//TCP服務(wù)器模式?
? ? {
? ? ? ? if(Socket_Listen(0)==TRUE)
? ? ? ? ? ? S0_State=S_INIT;
? ?? ? ?else
? ? ? ??? ? S0_State=0;
? ? }
? ? else if(S0_Mode==TCP_CLIENT)//TCP客戶端模式?
? ? {
? ? ? ? if(Socket_Connect(0)==TRUE)
? ?? ? ? ? ?S0_State=S_INIT;
? ? ? ? else
? ? ? ? ? ? S0_State=0;
? ? }
? ? else? //UDP模式?
? ? ?{
? ? ? ? if(Socket_UDP(0)==TRUE)
? ? ? ? ? ? S0_State=S_INIT|S_CONN;
? ?? ? ?else
? ? ? ??? ? S0_State=0;
? ?? ?}
? ? }
}
/*
* 函數(shù)名? : Process_Socket_Data
* 描述? ? : W5500接收并發(fā)送接收到的數(shù)據(jù)
* 輸入? ? : s:端口號
* 輸出? ? : 無
* 返回值? : 無
* 說明? ? : 本過程先調(diào)用S_rx_process()從W5500的端口接收數(shù)據(jù)緩沖區(qū)讀取數(shù)據(jù),
* 然后將讀取的數(shù)據(jù)從Rx_Buffer拷貝到Temp_Buffer緩沖區(qū)進(jìn)行處理。
* 處理完畢,將數(shù)據(jù)從Temp_Buffer拷貝到Tx_Buffer緩沖區(qū)。調(diào)用S_tx_process()
* 發(fā)送數(shù)據(jù)。
*******************************************************************************/
void Process_Socket_Data(SOCKET s)
{
? ? unsigned short size;
? ? size=Read_SOCK_Data_Buffer(s, Rx_Buffer);
? ? UDP_DIPR[0] = Rx_Buffer[0];
? ? UDP_DIPR[1] = Rx_Buffer[1];
? ? UDP_DIPR[2] = Rx_Buffer[2];
? ? UDP_DIPR[3] = Rx_Buffer[3];
? ? UDP_DPORT[0] = Rx_Buffer[4];
? ? UDP_DPORT[1] = Rx_Buffer[5];
? ? memcpy(Tx_Buffer, Rx_Buffer+8, size-8);
? ? Write_SOCK_Data_Buffer(s, Tx_Buffer, size);
}
/*******************************************************************************
* 函數(shù)名? : main
* 描述? ? : 主函數(shù),用戶程序從main函數(shù)開始運(yùn)行
* 輸入? ? : 無
* 輸出? ? : 無
* 返回值? : int:返回值為一個16位整形數(shù)
* 說明? ? : 無
*/
int main(void)
{
? ? System_Initialization(); //STM32系統(tǒng)初始化函數(shù)(初始化STM32時鐘及外設(shè))
? ? Load_Net_Parameters(); //裝載網(wǎng)絡(luò)參數(shù)
? ? W5500_Hardware_Reset(); //硬件復(fù)位W5500
? ? W5500_Initialization(); //W5500初始貨配置
? ? while (1)
? ? {
? ? ? ? W5500_Socket_Set();//W5500端口初始化配置
? ? ? ? W5500_Interrupt_Process();//W5500中斷處理程序框架
? ? ? ? ?if((S0_Data & S_RECEIVE) == S_RECEIVE)//如果Socket0接收到數(shù)據(jù)
? ? ? ? {
? ? ? ? ? ? S0_Data&=~S_RECEIVE;
? ? ? ? ? ? Process_Socket_Data(0);//W5500接收并發(fā)送接收到的數(shù)據(jù)
? ? ? ? }
? ? ? ? else if(W5500_Send_Delay_Counter >= 500)//定時發(fā)送字符串
? ? ? ?{
? ? ? ? ? ? ? if(S0_State == (S_INIT|S_CONN))
? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ?S0_Data&=~S_TRANSMITOK;
? ? ? ? ? ? ? ? ? ?memcpy(Tx_Buffer, "\r\nWelcome To YiXinElec!\r\n", 23);
? ? ? ? ? ? ? ? ? ?Write_SOCK_Data_Buffer(0, Tx_Buffer, 23);//指定Socket(0~7)發(fā)送數(shù)據(jù)處理,端口0發(fā)送23字節(jié)數(shù)據(jù)
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? W5500_Send_Delay_Counter=0;
? ? ? ? ? }
? ? ?}
}
/
* 函數(shù)名? : RCC_Configuration
* 描述? ? : 設(shè)置系統(tǒng)時鐘為72MHZ(這個可以根據(jù)需要改)
* 輸入? ? : 無
* 輸出? ? : 無
* 返回值? : 無
* 說明? ? : STM32F107x和STM32F105x系列MCU與STM32F103x系列MCU時鐘配置有所不同
*/
void RCC_Configuration(void)
{
? ? ? ? ? ? ? ? ErrorStatus HSEStartUpStatus;? ? ? ? ? ? ? ?//外部高速時鐘(HSE)的工作狀態(tài)變量
? ? ? ? ? ? ??? RCC_DeInit();? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//將所有與時鐘相關(guān)的寄存器設(shè)置為默認(rèn)值
? ? ? ? ? ? ??? RCC_HSEConfig(RCC_HSE_ON);? ? ? ? ? ? ? ? ? //啟動外部高速時鐘HSE?
? ? ? ? ? ? ?? HSEStartUpStatus = RCC_WaitForHSEStartUp(); //等待外部高速時鐘(HSE)穩(wěn)定
? ? ? ? ? ? ?? ?if(SUCCESS == HSEStartUpStatus)? ? ? ? ? ? ?//如果外部高速時鐘已經(jīng)穩(wěn)定
? ? ? ? ? ? ?? ?{
? ? ? ? ? ? ? ? ? ? ? ?/* Enable Prefetch Buffer */
? ? ? ? ? ? ? ? ? ? ?? ? ?FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //Flash設(shè)置
? ? ? ? ? ? ? ? ?? ? ?/* Flash 2 wait state */
? ? ? ? ? ? ? ? ? ? ? ? ??FLASH_SetLatency(FLASH_Latency_2);
? ??
? ? ? ? ? ? ? ? ? ? ? ??? RCC_HCLKConfig(RCC_SYSCLK_Div1); //設(shè)置AHB時鐘等于系統(tǒng)時鐘(1分頻)/72MHZ
? ? ? ? ? ? ? ? ? ? ?? ? ?RCC_PCLK2Config(RCC_HCLK_Div1);? //設(shè)置APB2時鐘和HCLK時鐘相等/72MHz(最大為72MHz)
? ? ? ? ? ? ? ? ? ? ?? ? ?RCC_PCLK1Config(RCC_HCLK_Div2);? //設(shè)置APB1時鐘是HCLK時鐘的2分頻/36MHz(最大為36MHz)
??
? #ifndef STM32F10X_CL? ? ? ? ? ? ? ? ?//如果使用的不是STM32F107x或STM32F105x系列MCU,PLL以下配置??
? RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); //PLLCLK = 8MHz * 9 = 72 MHz?
? #else? ? ? ? ? ? ? ? ? ? ? ?//如果使用的是STM32F107x或STM32F105x系列MCU,PLL以下配置
? ? //
? ? /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
? ? RCC_PREDIV2Config(RCC_PREDIV2_Div5);
? ? RCC_PLL2Config(RCC_PLL2Mul_8);
? ? RCC_PLL2Cmd(ENABLE); //使能PLL2?
? ? while (RCC_GetFlagStatus(RCC_FLAG_PLL2RDY) == RESET);//等待PLL2穩(wěn)定
? ? /* PLL configuration: PLLCLK = (PLL2 / 5) * 9 = 72 MHz */?
? ? RCC_PREDIV1Config(RCC_PREDIV1_Source_PLL2, RCC_PREDIV1_Div5);
? ? RCC_PLLConfig(RCC_PLLSource_PREDIV1, RCC_PLLMul_9);
#endif
? ? RCC_PLLCmd(ENABLE); //使能PLL
? ? while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); //等待PLL穩(wěn)定
? ? RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);?? //設(shè)置系統(tǒng)時鐘的時鐘源為PLL
? ? while(RCC_GetSYSCLKSource() != 0x08);? ? ? ? ? ? ? ?//檢查系統(tǒng)的時鐘源是否是PLL
? ? RCC_ClockSecuritySystemCmd(ENABLE);? ? ? ? ? ? ? ? ?//使能系統(tǒng)安全時鐘?
/* Enable peripheral clocks --------------------------------------------------*/
? /* Enable I2C1 and I2C1 clock */
? RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
? ?/* Enable GPIOA GPIOB SPI1 and USART1 clocks */
? RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB
| RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD
| RCC_APB2Periph_AFIO, ENABLE);? ??
? }
}
/
* 函數(shù)名? : NVIC_Configuration
* 描述? ? : STM32中斷向量表配配置
* 輸入? ? : 無
* 輸出? ? : 無
* 返回值? : 無
* 說明? ? : 設(shè)置KEY1(PC11)的中斷優(yōu)先組
*******************************************************************************/
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure; //定義NVIC初始化結(jié)構(gòu)體
? /* Set the Vector Table base location at 0x08000000 */
? NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //設(shè)置中斷優(yōu)先級組為1,優(yōu)先組(可設(shè)0~4位)
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //設(shè)置中斷向量號
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //設(shè)置搶先優(yōu)先級
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //設(shè)置響應(yīng)優(yōu)先級
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能NVIC
NVIC_Init(&NVIC_InitStructure);
}
/*******************************************************************************
* 函數(shù)名? : Timer2_Init_Config
* 描述? ? : Timer2初始化配置
* 輸入? ? : 無
* 輸出? ? : 無
* 返回? ? : 無?
* 說明? ? : 無
*******************************************************************************/
void Timer2_Init_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能Timer2時鐘
TIM_TimeBaseStructure.TIM_Period = 9; //設(shè)置在下一個更新事件裝入活動的自動重裝載寄存器周期的值(計數(shù)到10為1ms)
TIM_TimeBaseStructure.TIM_Prescaler = 7199; //設(shè)置用來作為TIMx時鐘頻率除數(shù)的預(yù)分頻值(10KHz的計數(shù)頻率)
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設(shè)置時鐘分割:TDTS = TIM_CKD_DIV1
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計數(shù)模式
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根據(jù)TIM_TimeBaseInitStruct中指定的參數(shù)初始化TIMx的時間基數(shù)單位
?
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE ); //使能TIM2指定的中斷
TIM_Cmd(TIM2, ENABLE);? //使能TIMx外設(shè)
}
/*******************************************************************************
* 函數(shù)名? : TIM2_IRQHandler
* 描述? ? : 定時器2中斷斷服務(wù)函數(shù)
* 輸入? ? : 無
* 輸出? ? : 無
* 返回? ? : 無?
* 說明? ? : 無
*******************************************************************************/
void TIM2_IRQHandler(void)
{
? ? if(TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
? ?{
? ? ? TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
? ? ? Timer2_Counter++;
? ? ? ?W5500_Send_Delay_Counter++;
? ? }
}
/*******************************************************************************
* 函數(shù)名? : System_Initialization
* 描述? ? : STM32系統(tǒng)初始化函數(shù)(初始化STM32時鐘及外設(shè))
* 輸入? ? : 無
* 輸出? ? : 無
* 返回? ? : 無?
* 說明? ? : 無
*******************************************************************************/
void System_Initialization(void)
{
? ?RCC_Configuration(); //設(shè)置系統(tǒng)時鐘為72MHZ(這個可以根據(jù)需要改)
? ?? NVIC_Configuration(); //STM32中斷向量表配配置
? ? SPI_Configuration(); //W5500 SPI初始化配置(STM32 SPI1)
? ? Timer2_Init_Config(); //Timer2初始化配置
? ? W5500_GPIO_Configuration(); //W5500 GPIO初始化配置
}
/
* 函數(shù)名? : Delay
* 描述? ? : 延時函數(shù)(ms)
* 輸入? ? : d:延時系數(shù),單位為毫秒
* 輸出? ? : 無
* 返回? ? : 無?
* 說明? ? : 延時是利用Timer2定時器產(chǎn)生的1毫秒的計數(shù)來實(shí)現(xiàn)的
*******************************************************************************/
void Delay(unsigned int d)
{
? ? ?Timer2_Counter=0;?
? ? ?while(Timer2_Counter < d);
}