?? w5100.c
字號:
/********************************************************************************
提供商:成都浩然電子有限公司
網 址:http://www.hschip.com
時 間: 2007-11-30
本軟件包括5個部分:
1. W5100初始化
2. W5100的Socket初始化
3. Socket連接
如果Socket設置為TCP服務器模式,則調用Socket_Listen()函數,W5100處于偵聽狀態,直到遠程客戶端與它連接。
如果Socket設置為TCP客戶端模式,則調用Socket_Connect()函數,
每調用一次Socket_Connect(s)函數,產生一次連接,
如果連接不成功,則產生超時中斷,然后可以再調用該函數進行連接。
如果Socket設置為UDP模式,則調用Socket_UDP函數
4. Socket數據接收和發送
5. W5100中斷處理
置W5100為服務器模式的調用過程:W5100_Init()-->Socket_Init(s)-->Socket_Listen(s),設置過程即完成,等待客戶端的連接。
置W5100為客戶端模式的調用過程:W5100_Init()-->Socket_Init(s)-->Socket_Connect(s),設置過程即完成,并與遠程服務器連接。
置W5100為UDP模式的調用過程:W5100_Init()-->Socket_Init(s)-->Socket_UDP(s),設置過程即完成,可以與遠程主機UDP通信。
W5100產生的連接成功、終止連接、接收數據、發送數據、超時等事件,都可以從中斷狀態中獲得。
********************************************************************************/
#include <stm32f10x_lib.h> /* STM32F10x庫定義 */
#include"io_define.h"
#include"W5100.h" /* 定義W5100的寄存器地址、狀態 */
#define TRUE 0xff
#define FALSE 0x00
typedef unsigned char SOCKET;
extern void Delay(unsigned int d);
/* 端口數據緩沖區 */
extern unsigned char Rx_Buffer[1460]; /* 端口接收數據緩沖區 */
extern unsigned char Tx_Buffer[1460]; /* 端口發送數據緩沖區 */
/* 網絡參數寄存器 */
extern unsigned char Gateway_IP[4]; /* Gateway IP Address */
extern unsigned char Sub_Mask[4]; /* Subnet Mask */
extern unsigned char Phy_Addr[6]; /* Physical Address */
extern unsigned char IP_Addr[4]; /* Loacal IP Address */
extern unsigned char S0_Port[2]; /* Socket0 Port number */
extern unsigned char S0_DIP[4]; /* Socket0 Destination IP Address */
extern unsigned char S0_DPort[2]; /* Socket0 Destination Port number */
extern unsigned char S1_Port[2]; /* Socket1 Port number */
extern unsigned char S1_DIP[4]; /* Socket1 Destination IP Address */
extern unsigned char S1_DPort[2]; /* Socket1 Destination Port number */
extern unsigned char S2_Port[2]; /* Socket2 Port number */
extern unsigned char S2_DIP[4]; /* Socket2 Destination IP Address */
extern unsigned char S2_DPort[2]; /* Socket2 Destination Port number */
extern unsigned char S3_Port[2]; /* Socket3 Port number */
extern unsigned char S3_DIP[4]; /* Socket3 Destination IP Address */
extern unsigned char S3_DPort[2]; /* Socket3 Destination Port number */
extern unsigned char S0_State; /* Socket0 state recorder */
extern unsigned char S1_State; /* Socket1 state recorder */
extern unsigned char S2_State; /* Socket2 state recorder */
extern unsigned char S3_State; /* Socket3 state recorder */
#define S_INIT 0x01
#define S_CONN 0x02
extern unsigned char S0_Data; /* Socket0 receive data and transmit OK */
extern unsigned char S1_Data; /* Socket1 receive data and transmit OK */
extern unsigned char S2_Data; /* Socket2 receive data and transmit OK */
extern unsigned char S3_Data; /* Socket3 receive data and transmit OK*/
#define S_RECEIVE 0x01
#define S_TRANSMITOK 0x02
extern unsigned char W5100_Interrupt;
/* UDP Destionation IP address and Port number */
unsigned char UDP_DIPR[4];
unsigned char UDP_DPORT[2];
/*****************************************************************
*/
void Write_W5100_Address(unsigned short addr)
{
unsigned short i;
/* 設置地址為0x01 */
GPIO_SetBits(GPIOA, W5100_A0);
GPIO_ResetBits(GPIOA, W5100_A1);
/* 輸出地址值 */
i=GPIO_ReadOutputData(GPIOB);
i &= 0x00ff;
i = i | (addr & 0xff00);
GPIO_Write(GPIOB, i);
/* 置W5100的CS為低電平 */
GPIO_ResetBits(GPIOA, W5100_CS);
GPIO_ResetBits(GPIOA, W5100_WR);
/*寫入地址高8位 */
GPIO_SetBits(GPIOA, W5100_WR);
/* 置W5100的CS為高電平 */
GPIO_SetBits(GPIOA, W5100_CS);
/* 設置地址為0x02 */
GPIO_ResetBits(GPIOA, W5100_A0);
GPIO_SetBits(GPIOA, W5100_A1);
/* 輸出地址值 */
i=GPIO_ReadOutputData(GPIOB);
i &= 0x00ff;
i = i | (addr<<8);
GPIO_Write(GPIOB, i);
/* 置W5100的CS為低電平 */
GPIO_ResetBits(GPIOA, W5100_CS);
GPIO_ResetBits(GPIOA, W5100_WR);
/*寫入地址低8位 */
GPIO_SetBits(GPIOA, W5100_WR);
/* 置W5100的CS為高電平 */
GPIO_SetBits(GPIOA, W5100_CS);
/* 設置地址為0x11 */
GPIO_SetBits(GPIOA, W5100_A0);
}
/*****************************************************************
程序名:Read_W5100
輸入: 地址
輸出: 無
返回: 讀取的數據
說明:從W5100指定的地址讀取一個字節
*****************************************************************/
unsigned char Read_W5100(void)
{
unsigned short i;
GPIO_InitTypeDef GPIO_InitStructure;
/* 設置數據端口為輸入狀態 */
GPIO_InitStructure.GPIO_Pin = W5100_DATA;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* 置W5100的CS為低電平 */
GPIO_ResetBits(GPIOA, W5100_CS);
/* 讀取數據 */
GPIO_ResetBits(GPIOA, W5100_RD);
GPIO_SetBits(GPIOA, W5100_RD);
i=GPIO_ReadInputData(GPIOB);
/* 置W5100的CS為高電平 */
GPIO_SetBits(GPIOA, W5100_CS);
/* 設置為輸出狀態 */
GPIO_InitStructure.GPIO_Pin = W5100_DATA;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
i >>= 8;
return i;
}
/*****************************************************************
程序名:Write_W5100
輸入: 地址,字節數據
輸出: 無
返回: 無
說明:將一個字節寫入W5100指定的地址
*****************************************************************/
void Write_W5100(unsigned short dat)
{
unsigned short i;
/* 輸出數據到端口 */
i=GPIO_ReadOutputData(GPIOB);
i &= 0x00ff;
i = i | (dat<<8);
GPIO_Write(GPIOB, i);
/* 置W5100的CS為低電平 */
GPIO_ResetBits(GPIOA, W5100_CS);
/* 寫命令 */
GPIO_ResetBits(GPIOA, W5100_WR);
GPIO_SetBits(GPIOA, W5100_WR);
/* 置W5100的CS為高電平 */
GPIO_SetBits(GPIOA, W5100_CS);
}
/*------------------------------------------------------------------------------
W5100初始化函數
在使用W5100之前,對W5100初始化
------------------------------------------------------------------------------*/
void W5100_Init(void)
{
unsigned short i;
/* 地址為0x00 */
GPIO_ResetBits(GPIOA, W5100_A0|W5100_A1);
/* Set W5100 Indirect Bus, address increase */
i=GPIO_ReadOutputData(GPIOB);
i &= 0x00ff;
i |= 0x0300;
GPIO_Write(GPIOB, i);
/* 選中 W5100 */
GPIO_ResetBits(GPIOA, W5100_CS);
GPIO_ResetBits(GPIOA, W5100_WR);
/* 寫入數據 */
GPIO_SetBits(GPIOA,W5100_WR);
GPIO_SetBits(GPIOA, W5100_CS);
Delay(100); /*延時100ms,自己定義該函數*/
/*設置網關(Gateway)的IP地址,4字節 */
/*使用網關可以使通信突破子網的局限,通過網關可以訪問到其它子網或進入Internet*/
Write_W5100_Address(W5100_GAR);
for(i=0;i<4;i++)
Write_W5100(Gateway_IP[i]); /*Gateway_IP為4字節unsigned char數組,自己定義*/
/*設置子網掩碼(MASK)值,4字節。子網掩碼用于子網運算*/
Write_W5100_Address(W5100_SUBR);
for(i=0;i<4;i++)
Write_W5100(Sub_Mask[i]); /*SUB_MASK為4字節unsigned char數組,自己定義*/
/*設置物理地址,6字節,用于唯一標識網絡設備的物理地址值
該地址值需要到IEEE申請,按照OUI的規定,前3個字節為廠商代碼,后三個字節為產品序號
如果自己定義物理地址,注意第一個字節必須為偶數*/
Write_W5100_Address(W5100_SHAR);
for(i=0;i<6;i++)
Write_W5100(Phy_Addr[i]); /*PHY_ADDR6字節unsigned char數組,自己定義*/
/*設置本機的IP地址,4個字節
注意,網關IP必須與本機IP屬于同一個子網,否則本機將無法找到網關*/
Write_W5100_Address(W5100_SIPR);
for(i=0;i<4;i++)
Write_W5100(IP_Addr[i]); /*IP_ADDR為4字節unsigned char數組,自己定義*/
/*設置發送緩沖區和接收緩沖區的大小,參考W5100數據手冊*/
Write_W5100_Address(W5100_RMSR);
Write_W5100(0x55); /*Socket Rx memory size=2k*/
Write_W5100_Address(W5100_TMSR);
Write_W5100(0x55); /*Socket Tx mempry size=2k*/
/* 設置重試時間,默認為2000(200ms) */
Write_W5100_Address(W5100_RTR);
Write_W5100(0x07);
Write_W5100(0xd0);
/* 設置重試次數,默認為8次 */
Write_W5100_Address(W5100_RCR);
Write_W5100(8);
/* 啟動中斷,參考W5100數據手冊確定自己需要的中斷類型
IMR_CONFLICT是IP地址沖突異常中斷
IMR_UNREACH是UDP通信時,地址無法到達的異常中斷
其它是Socket事件中斷,根據需要添加 */
Write_W5100_Address(W5100_IMR);
Write_W5100(IMR_CONFLICT|IMR_UNREACH|IMR_S0_INT|IMR_S1_INT|IMR_S2_INT|IMR_S3_INT);
}
/****************************************************************************
Detect Gateway
input: None
Output: None
Return: if fail to detect gateway, return FALSE
if detect the gateway, return TRUE
****************************************************************************/
unsigned char Detect_Gateway(void)
{
unsigned char i;
Write_W5100_Address(W5100_S0_MR);
Write_W5100(S_MR_TCP); /*設置socket0為TCP模式 */
Write_W5100_Address(W5100_S0_CR);
Write_W5100(S_CR_OPEN); /*打開socket0*/
Write_W5100_Address(W5100_S0_SSR);
if(Read_W5100()!=S_SSR_INIT)
{
Write_W5100_Address(W5100_S0_CR);
Write_W5100(S_CR_CLOSE); /*打開不成功,關閉Socket,然后返回 */
return FALSE;
}
/*檢查網關及獲取網關的物理地址 */
Write_W5100_Address(W5100_S0_DIPR);
for(i=0;i<4;i++)
Write_W5100(IP_Addr[i]+1); /*向目的地址寄存器寫入與本機IP不同的IP值 */
Write_W5100_Address(W5100_S0_CR);
Write_W5100(S_CR_CONNECT); /*打開socket0的TCP連接 */
Delay(20); /* 延時20ms */
Write_W5100_Address(W5100_S0_DHAR);
i=Read_W5100(); /*讀取目的主機的物理地址,該地址就是網關地址*/
Write_W5100_Address(W5100_S0_CR);
Write_W5100(S_CR_CLOSE); /*關閉socket0*/
if(i==0xff)
{
/**********沒有找到網關服務器,或沒有與網關服務器成功連接***********/
/********** 自己添加處理代碼 ***********/
return FALSE;
}
return TRUE;
}
/******************************************************************************
Socket處理, 其它3個Socket的處理可參照此程序
*****************************************************************************
Socket初始化
如果成功則返回true, 否則返回false
-----------------------------------------------------------------------------*/
void Socket_Init(SOCKET s)
{
unsigned int i;
/*設置分片長度,參考W5100數據手冊,該值可以不修改*/
Write_W5100_Address(W5100_S0_MSS+s*0x100);
Write_W5100(0x05); /*最大分片字節數=1460*/
Write_W5100(0xb4);
/* Set Socket Port number */
switch(s)
{
case 0:
Write_W5100_Address(W5100_S0_PORT);
Write_W5100(S0_Port[0]); /* Set Local Socket Port number */
Write_W5100(S0_Port[1]);
Write_W5100_Address(W5100_S0_DPORT);
Write_W5100(S0_DPort[0]); /* Set Destination port number */
Write_W5100(S0_DPort[1]);
Write_W5100_Address(W5100_S0_DIPR);
for(i=0;i<4;i++)
Write_W5100(S0_DIP[i]); /* Set Destination IP Address */
break;
case 1:
Write_W5100_Address(W5100_S1_PORT);
Write_W5100(S1_Port[0]); /* Set Local Socket Port number */
Write_W5100(S1_Port[1]);
Write_W5100_Address(W5100_S1_DPORT);
Write_W5100(S1_DPort[0]); /* Set Destination port number */
Write_W5100(S1_DPort[1]);
Write_W5100_Address(W5100_S1_DIPR);
for(i=0;i<4;i++)
Write_W5100(S1_DIP[i]); /* Set Destination IP Address */
break;
case 2:
Write_W5100_Address(W5100_S2_PORT);
Write_W5100(S2_Port[0]); /* Set Local Socket Port number */
Write_W5100(S2_Port[1]);
Write_W5100_Address(W5100_S2_DPORT);
Write_W5100(S2_DPort[0]); /* Set Destination port number */
Write_W5100(S2_DPort[1]);
Write_W5100_Address(W5100_S2_DIPR);
for(i=0;i<4;i++)
Write_W5100(S2_DIP[i]); /* Set Destination IP Address */
break;
case 3:
Write_W5100_Address(W5100_S3_PORT);
Write_W5100(S3_Port[0]); /* Set Local Socket Port number */
Write_W5100(S3_Port[1]);
Write_W5100_Address(W5100_S3_DPORT);
Write_W5100(S3_DPort[0]); /* Set Destination port number */
Write_W5100(S3_DPort[1]);
Write_W5100_Address(W5100_S3_DIPR);
for(i=0;i<4;i++)
Write_W5100(S3_DIP[i]); /* Set Destination IP Address */
break;
default:
break;
}
}
/*-----------------------------------------------------------------------------
設置Socket為客戶端與遠程服務器連接
當本機Socket工作在客戶端模式時,引用該程序,與遠程服務器建立連接
如果設置成功則返回true,否則返回false
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -