ENC28J60+Uip TCP Server/Client
接了一個專案要利用網路互相傳資料,必需同時開發TCP Server/Client 兩端,在網路找了一些範例
同樣是利用
ENC28J60+Uip 來開發,開始找到同是SPI2 的範例,所以下列
1~6項 是將 SPI2改為 SPI1所需注意的事項。但因為不是很了解 Uip TCP的應用,雖然改成
SPI1但仍無法完成通訊,在進一步研究 TCP 的通訊原理後發現在 IP應用上有問題,在修改 7, 8兩項後終於可以利用
TCP Server/Client 來 傳資料。(註 我此處用的範例是
ALIENTEK MINISTM32 擴展實驗21 ENC28J60網路模組實驗)
1. SPI2 修改為SPI1
• 由於範例程式用的是SPI2 原來引腳
• CS INT MISO
MOSI SCK RST
• PG8 PD2 PB14
PB15 PB13 PG6
• 現在的引腳
• CS INT MISO
MOSI SCK RST
• PC4 PC1 PA6
PA7 PA5 無
• 所以必需修改為SPI1
2. 系統頻率 HSE為12000000 , SYSTEM CLOCK 為72000000 ,HSE為12000000,所以鎖頻 PLL=6
由於範例程式用的是25M或者是8M的石英振盪器,所以必需在stm32f10x_conf.h的程式庫中的HSE定義改為12000000。
在main() 中設定為 Stm32_Clock_Init(9)其中 9 為鎖頻 PLL 的倍數。因此這個參數應改為
Stm32_Clock_Init(6); //System
Clock 設定
由於我們的石英振盪器為12M ,而我們希望 SYSTEM CLOCK 為72M ,HSE為12M,所以鎖頻 PLL=6
3. SPI 初始化 SPI1中 腳位定義需注意,尤其 CS腳位要宣告
• 由於範例程式用的是SPI2 原來引腳
• CS INT MISO
MOSI SCK RST
• PG8 PD2 PB14
PB15 PB13 PG6
• 現在的引腳
• CS INT MISO
MOSI SCK RST
• PC4 PC1 PA6
PA7 PA5 無
•
• GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
• GPIO_InitStructure.GPIO_Mode
= GPIO_Mode_Out_PP;
• GPIO_Init(GPIOB,
&GPIO_InitStructure);// GPIOB
• GPIO_SetBits(GPIOB,GPIO_Pin_4);
• ENC28J60.h 中 SPI 初始化 時注意 CS 腳位的PoutA(X) X的值需改變
• #define ENC28J60_CS PGout(4)
//ENC28J60
• 5. SPI 初始化 時SPI1_SetSpeed
若原來為 SPI2_SetSpeed 請修改為SPI1_SetSpeed,且原為SPI2 改為SPI1
void
SPI1_SetSpeed(u8 SpeedSet)
{
...
SPI1->CR1 &= ~0x0030;
• SPI1->CR1 |= 0x0008;
//====SPI SPPED 18MHZ
• SPI1->CR1|=1<<6; //SPI ENABLE
• }
• 6. ENC28J60.c 中delayms(1) 改為 10mS
ENC28J60_Write_Op(ENC28J60_SOFT_RESET,0,ENC28J60_SOFT_RESET);//
while(!(ENC28J60_Read(ESTAT)&ESTAT_CLKRDY)&&retry<500)
{
retry++;
delay_ms(10);
};
因SPI 的GPIO的速度被降低為 10M 又分頻為8,所以等待時間加長。
7. 網路互連要注要對方為Server 時的IP 位置
tcp_client_demo.c
void tcp_client_reconnect()
{
uip_ipaddr_t ipaddr;
uip_ipaddr(&ipaddr,192,168,1,101);
//設置IP為192.168.1.101
uip_connect(&ipaddr,htons(1400));
//埠為1400
}
注意雙方所連線的 IP及 Port 請參考下圖。
8. TCP服務 Server 的設定--1
• ========test.c (client 部份)
• int main(void)
• {
• ...
• uip_ipaddr(ipaddr, 192,168,1,16); //設置本地設置IP位址
• uip_sethostaddr(ipaddr);
• uip_ipaddr(ipaddr,
192,168,1,1); //設置閘道IP位址(其實就是你路由器的IP地址)
• uip_setdraddr(ipaddr);
• uip_ipaddr(ipaddr,
255,255,255,0); //設置網路遮罩
• uip_setnetmask(ipaddr);
• uip_listen(HTONS(1200)); //監聽1200埠,用於TCP Server
• //uip_listen(HTONS(80)); //監聽80埠,用於Web Server
• //tcp_client_reconnect(); //嘗試連接到TCP Server端,用於TCP Client
• _Rxflag = 0;
• while (1)
• {...}
• ...
• }
8. 完成TCP服務 Server----2
• ========tcp_demo.c (client 部份)
• //TCP應用介面函數(UIP_APPCALL) , 完成TCP服務(包括server和client)和HTTP服務
• void tcp_demo_appcall(void)
• {
• switch(uip_conn->lport)//本地監聽埠80和1200
• {
• case HTONS(80):
• httpd_appcall();
• break;
• case HTONS(1200):
• tcp_server_demo_appcall();
• break;
• default:
• break;
• }
• switch(uip_conn->rport) //遠端連接1400埠
• {
• case HTONS(1400): //此處client為1 400埠
• tcp_client_demo_appcall();
• break;
• default:
• break;
• }
• }
留言
張貼留言