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;
•          }    
•      }

留言

這個網誌中的熱門文章

STM32 RCC 的用途

STM32 I2C-EEPROM 的讀寫

數位濾波