[开发工具] 【新定义MCU开发板测评】NBK-RD8x3x 核心板+EBS003 IOT扩展板网口客户端+OLED显示

[复制链接]
 楼主| 比神乐 发表于 2023-1-22 15:59 | 显示全部楼层 |阅读模式
最近捣鼓网口,写的TCP客户端程序,正常收发数据,用OLED显示本机IP地址和网关。之所以没显示子网掩码,是因为实在显示不开了。
原理图:
0.jpg


1.jpg

2.jpg

3.jpg
代码,主程序:
  1. #include "SC_Init.h"        // MCU initialization header file, including all firmware library header files
  2. #include "SC_it.h"
  3. #include "..\Drivers\SCDriver_list.h"
  4. #include "HeadFiles\SysFunVarDefine.h"
  5. #include "..\Apps\w5500.h"
  6. #include <string.h>
  7. /**************************************Generated by EasyCodeCube*************************************/
  8. unsigned int Timer2_Counter=0; //Timer2?¨ê±?÷??êy±?á?(ms)
  9. unsigned int W5500_Send_Delay_Counter=0; //W5500·¢?í?óê±??êy±?á?(ms)
  10. unsigned char temp=0;
  11. /*******************************************************************************
  12. * oˉêy??  : W5500_Initialization
  13. * ?èê?    : W55003?ê???????
  14. * ê?è?    : ?T
  15. * ê?3?    : ?T
  16. * ·μ???μ  : ?T
  17. * ?μ?÷    : ?T
  18. *******************************************************************************/
  19. void W5500_Initialization(void)
  20. {
  21.         W5500_Init();                //3?ê??ˉW5500??′??÷oˉêy
  22.         Detect_Gateway();        //?ì2éí?1?·t???÷
  23.         Socket_Init(0);                //???¨Socket(0~7)3?ê??ˉ,3?ê??ˉ???ú0
  24. }

  25. /*******************************************************************************
  26. * oˉêy??  : Load_Net_Parameters
  27. * ?èê?    : ×°??í???2?êy
  28. * ê?è?    : ?T
  29. * ê?3?    : ?T
  30. * ·μ???μ  : ?T
  31. * ?μ?÷    : í?1??¢?ú???¢??àíμ??·?¢±??úIPμ??·?¢???úo??¢??μ?IPμ??·?¢??μ????úo??¢???ú1¤×÷?£ê?
  32. *******************************************************************************/
  33. void Load_Net_Parameters(void)
  34. {
  35.         Gateway_IP[0] = 169;//?ó??í?1?2?êy
  36.         Gateway_IP[1] = 254;
  37.         Gateway_IP[2] = 159;
  38.         Gateway_IP[3] = 1;

  39.         Sub_Mask[0]=255;//?ó??×óí??ú??
  40.         Sub_Mask[1]=255;
  41.         Sub_Mask[2]=0;
  42.         Sub_Mask[3]=0;

  43.         Phy_Addr[0]=0x6D;//?ó????àíμ??·
  44.         Phy_Addr[1]=0x58;
  45.         Phy_Addr[2]=0x49;
  46.         Phy_Addr[3]=0xFC;
  47.         Phy_Addr[4]=0xA9;
  48.         Phy_Addr[5]=0xB4;

  49.         IP_Addr[0]=169;//?ó??±??úIPμ??·
  50.         IP_Addr[1]=254;
  51.         IP_Addr[2]=159;
  52.         IP_Addr[3]=40;

  53.         S0_Port[0] = 0x13;//?ó?????ú0μ????úo?5000
  54.         S0_Port[1] = 0x88;

  55.         S0_DIP[0]=169;//?ó?????ú0μ???μ?IPμ??·
  56.         S0_DIP[1]=254;
  57.         S0_DIP[2]=159;
  58.         S0_DIP[3]=18;
  59.        
  60.         S0_DPort[0] = 0x17;//?ó?????ú0μ???μ????úo?6000
  61.         S0_DPort[1] = 0x70;

  62.         S0_Mode=TCP_CLIENT;//?ó?????ú0μ?1¤×÷?£ê?,TCP?í?§???£ê?
  63. }

  64. /*******************************************************************************
  65. * oˉêy??  : W5500_Socket_Set
  66. * ?èê?    : W5500???ú3?ê??ˉ????
  67. * ê?è?    : ?T
  68. * ê?3?    : ?T
  69. * ·μ???μ  : ?T
  70. * ?μ?÷    : ·?±eéè??4?????ú,?ù?Y???ú1¤×÷?£ê?,?????ú??óúTCP·t???÷?¢TCP?í?§???òUDP?£ê?.
  71. *                        ′ó???ú×′ì?×??úSocket_State?éò??D?????úμ?1¤×÷?é??
  72. *******************************************************************************/
  73. void W5500_Socket_Set(void)
  74. {
  75.         if(S0_State==0)//???ú03?ê??ˉ????
  76.         {
  77.                 if(S0_Mode==TCP_SERVER)//TCP·t???÷?£ê?
  78.                 {
  79.                         if(Socket_Listen(0)==TRUE)
  80.                                 S0_State=S_INIT;
  81.                         else
  82.                                 S0_State=0;
  83.                 }
  84.                 else if(S0_Mode==TCP_CLIENT)//TCP?í?§???£ê?
  85.                 {
  86.                         if(Socket_Connect(0)==TRUE)
  87.                                 S0_State=S_INIT;
  88.                         else
  89.                                 S0_State=0;
  90.                 }
  91.                 else//UDP?£ê?
  92.                 {
  93.                         if(Socket_UDP(0)==TRUE)
  94.                                 S0_State=S_INIT|S_CONN;
  95.                         else
  96.                                 S0_State=0;
  97.                 }
  98.         }
  99. }

  100. /*******************************************************************************
  101. * oˉêy??  : Process_Socket_Data
  102. * ?èê?    : W5500?óê?2¢·¢?í?óê?μ?μ?êy?Y
  103. * ê?è?    : s:???úo?
  104. * ê?3?    : ?T
  105. * ·μ???μ  : ?T
  106. * ?μ?÷    : ±?1y3ì?èμ÷ó?S_rx_process()′óW5500μ????ú?óê?êy?Y?o3????áè?êy?Y,
  107. *                        è?oó???áè?μ?êy?Y′óRx_Buffer??±′μ?Temp_Buffer?o3?????DD′|àí?£
  108. *                        ′|àííê±?£???êy?Y′óTemp_Buffer??±′μ?Tx_Buffer?o3????£μ÷ó?S_tx_process()
  109. *                        ·¢?íêy?Y?£
  110. *******************************************************************************/
  111. void Process_Socket_Data(SOCKET s)
  112. {
  113.         unsigned short size;
  114.         size=Read_SOCK_Data_Buffer(s, Rx_Buffer);
  115. <font color="#0000ff">        if(Rx_Buffer[0]=='1')
  116.                 GPIO_WriteHigh(LED_PORT, LED);
  117.         if(Rx_Buffer[0]=='0')
  118.                 GPIO_WriteLow(LED_PORT, LED);</font>
  119.         memcpy(Tx_Buffer, Rx_Buffer, size);                       
  120.         Write_SOCK_Data_Buffer(s, Tx_Buffer, size);
  121. }
  122. /*************************************.Generated by EasyCodeCube.************************************/
  123. /*****************************************************************************************************
  124. * Function Name: main
  125. * Description  : This function implements main function.
  126. * Arguments    : None
  127. * Return Value : None
  128. ******************************************************************************************************/
  129. void main(void)
  130. {       
  131.         unsigned char bai,shi,ge;
  132.         unsigned char temp1,temp2;
  133.     /*<Generated by EasyCodeCube begin>*/
  134.     /*<UserCodeStart>*//*<SinOne-Tag><36>*/
  135.     IcResourceInit();
  136.     /*<UserCodeEnd>*//*<SinOne-Tag><36>*/
  137.     /*<UserCodeStart>*//*<SinOne-Tag><4>*/
  138.         Load_Net_Parameters();                //×°??í???2?êy       
  139.         W5500_Hardware_Reset();                //ó2?t?′??W5500
  140.         W5500_Initialization();                //W55003?ê???????
  141.         OLED_Init();
  142.         OLED_Clear();
  143.         OLED_ShowChar(0,0,73,16);                                //I
  144.         OLED_ShowChar(8,0,80,16);                                   //P
  145.         OLED_ShowCHinese( 16 , 0 , 0 );                        //地
  146.     OLED_ShowCHinese( 32 , 0 , 1 );                        //址
  147.     OLED_ShowChar(48,0,58,16);

  148. <font color="#ff0000">    temp=Read_W5500_1Byte(0x000f);
  149.         bai=temp/100;
  150.     shi=temp%100/10;
  151.         ge=temp%10;
  152.         temp1=0;
  153.         if(bai!=0)
  154.         {
  155.                 OLED_ShowChar(temp1,2 ,bai+48,16);
  156.                 temp1+=8;
  157.                 OLED_ShowChar(temp1,2 ,shi+48,16);
  158.                 temp1+=8;
  159.                 OLED_ShowChar(temp1,2 ,ge+48,16);
  160.                
  161.         }
  162.         else
  163.         {
  164.                 if(shi!=0)
  165.                 {
  166.                          OLED_ShowChar(temp1,2 ,shi+48,16);
  167.                          temp1+=8;
  168.                          OLED_ShowChar(temp1,2 ,ge+48,16);
  169.                          
  170.                 }
  171.                 else
  172.                 {
  173.                          OLED_ShowChar(temp1,2 ,ge+48,16);
  174.                          
  175.                 }
  176.         }
  177.         temp1+=8;
  178.         OLED_ShowChar(temp1,2 ,46,16);
  179.         temp=Read_W5500_1Byte(0x0010);
  180.         bai=temp/100;
  181.     shi=temp%100/10;
  182.         ge=temp%10;
  183.         if(bai!=0)
  184.         {
  185.                 temp1+=8;
  186.                 OLED_ShowChar(temp1,2 ,bai+48,16);
  187.                 temp1+=8;
  188.                 OLED_ShowChar(temp1,2 ,shi+48,16);
  189.                 temp1+=8;
  190.                 OLED_ShowChar(temp1,2 ,ge+48,16);
  191.                
  192.         }
  193.         else
  194.         {
  195.                 if(shi!=0)
  196.                 {
  197.                          temp1+=8;
  198.                          OLED_ShowChar(temp1,2 ,shi+48,16);
  199.                          temp1+=8;
  200.                          OLED_ShowChar(temp1,2 ,ge+48,16);
  201.                          
  202.                 }
  203.                 else
  204.                 {
  205.                          temp1+=8;
  206.                          OLED_ShowChar(temp1,2 ,ge+48,16);
  207.                          
  208.                 }
  209.         }
  210.         temp1+=8;
  211.         OLED_ShowChar(temp1,2 ,46,16);
  212.         temp=Read_W5500_1Byte(0x0011);
  213.         bai=temp/100;
  214.     shi=temp%100/10;
  215.         ge=temp%10;
  216.         if(bai!=0)
  217.         {
  218.                 temp1+=8;
  219.                 OLED_ShowChar(temp1,2 ,bai+48,16);
  220.                 temp1+=8;
  221.                 OLED_ShowChar(temp1,2 ,shi+48,16);
  222.                 temp1+=8;
  223.                 OLED_ShowChar(temp1,2 ,ge+48,16);
  224.                
  225.         }
  226.         else
  227.         {
  228.                 if(shi!=0)
  229.                 {
  230.                          temp1+=8;
  231.                          OLED_ShowChar(temp1,2 ,shi+48,16);
  232.                          temp1+=8;
  233.                          OLED_ShowChar(temp1,2 ,ge+48,16);
  234.                          
  235.                 }
  236.                 else
  237.                 {
  238.                          temp1+=8;
  239.                          OLED_ShowChar(temp1,2 ,ge+48,16);
  240.                          
  241.                 }
  242.         }
  243.         temp1+=8;
  244.         OLED_ShowChar(temp1,2 ,46,16);
  245.         temp=Read_W5500_1Byte(0x0012);
  246.         bai=temp/100;
  247.     shi=temp%100/10;
  248.         ge=temp%10;
  249.         if(bai!=0)
  250.         {
  251.                 temp1+=8;
  252.                 OLED_ShowChar(temp1,2 ,bai+48,16);
  253.                 temp1+=8;
  254.                 OLED_ShowChar(temp1,2 ,shi+48,16);
  255.                 temp1+=8;
  256.                 OLED_ShowChar(temp1,2 ,ge+48,16);
  257.                
  258.         }
  259.         else
  260.         {
  261.                 if(shi!=0)
  262.                 {
  263.                          temp1+=8;
  264.                          OLED_ShowChar(temp1,2 ,shi+48,16);
  265.                          temp1+=8;
  266.                          OLED_ShowChar(temp1,2 ,ge+48,16);
  267.                          
  268.                 }
  269.                 else
  270.                 {
  271.                          temp1+=8;
  272.                          OLED_ShowChar(temp1,2 ,ge+48,16);
  273.                          
  274.                 }
  275.         }
  276. //    OLED_ShowCHinese( 0 , 2 , 2 );
  277. //    OLED_ShowCHinese( 16 , 2 , 3 );
  278. //    OLED_ShowCHinese( 32 , 2 , 4 );
  279. //    OLED_ShowCHinese( 48 , 2 , 5 );
  280. //    OLED_ShowChar(64,2,58,16);

  281.     OLED_ShowCHinese( 0 , 4 , 3 );                 //网
  282.         OLED_ShowCHinese( 16 , 4 , 6 );               //关
  283.     OLED_ShowChar(32,4 ,58,16);
  284.         temp=Read_W5500_1Byte(0x0001);
  285.         bai=temp/100;
  286.     shi=temp%100/10;
  287.         ge=temp%10;
  288.         temp2=0;
  289.         if(bai!=0)
  290.         {
  291.                 OLED_ShowChar(temp2,6 ,bai+48,16);
  292.                 temp2+=8;
  293.                 OLED_ShowChar(temp2,6 ,shi+48,16);
  294.                 temp2+=8;
  295.                 OLED_ShowChar(temp2,6 ,ge+48,16);
  296.                
  297.         }
  298.         else
  299.         {
  300.                 if(shi!=0)
  301.                 {
  302.                          OLED_ShowChar(temp2,6 ,shi+48,16);
  303.                          temp2+=8;
  304.                          OLED_ShowChar(temp2,6 ,ge+48,16);
  305.                          
  306.                 }
  307.                 else
  308.                 {
  309.                          OLED_ShowChar(temp2,6 ,ge+48,16);
  310.                          
  311.                 }
  312.         }
  313.         temp2+=8;
  314.         OLED_ShowChar(temp2,6 ,46,16);
  315.         temp=Read_W5500_1Byte(0x0002);
  316.         bai=temp/100;
  317.     shi=temp%100/10;
  318.         ge=temp%10;
  319.         if(bai!=0)
  320.         {
  321.                 temp2+=8;
  322.                 OLED_ShowChar(temp2,6 ,bai+48,16);
  323.                 temp2+=8;
  324.                 OLED_ShowChar(temp2,6 ,shi+48,16);
  325.                 temp2+=8;
  326.                 OLED_ShowChar(temp2,6 ,ge+48,16);
  327.                
  328.         }
  329.         else
  330.         {
  331.                 if(shi!=0)
  332.                 {
  333.                          temp2+=8;
  334.                          OLED_ShowChar(temp2,6 ,shi+48,16);
  335.                          temp2+=8;
  336.                          OLED_ShowChar(temp2,6 ,ge+48,16);
  337.                          
  338.                 }
  339.                 else
  340.                 {
  341.                          temp2+=8;
  342.                          OLED_ShowChar(temp2,6 ,ge+48,16);
  343.                          
  344.                 }
  345.         }
  346.         temp2+=8;
  347.         OLED_ShowChar(temp2,6 ,46,16);
  348.         temp=Read_W5500_1Byte(0x0003);
  349.         bai=temp/100;
  350.     shi=temp%100/10;
  351.         ge=temp%10;
  352.         if(bai!=0)
  353.         {
  354.                 temp2+=8;
  355.                 OLED_ShowChar(temp2,6 ,bai+48,16);
  356.                 temp2+=8;
  357.                 OLED_ShowChar(temp2,6 ,shi+48,16);
  358.                 temp2+=8;
  359.                 OLED_ShowChar(temp2,6 ,ge+48,16);
  360.                
  361.         }
  362.         else
  363.         {
  364.                 if(shi!=0)
  365.                 {
  366.                          temp2+=8;
  367.                          OLED_ShowChar(temp2,6 ,shi+48,16);
  368.                          temp2+=8;
  369.                          OLED_ShowChar(temp2,6 ,ge+48,16);
  370.                          
  371.                 }
  372.                 else
  373.                 {
  374.                          temp2+=8;
  375.                          OLED_ShowChar(temp2,6 ,ge+48,16);
  376.                          
  377.                 }
  378.         }
  379.         temp2+=8;
  380.         OLED_ShowChar(temp2,6 ,46,16);
  381.         temp=Read_W5500_1Byte(0x0004);
  382.         bai=temp/100;
  383.     shi=temp%100/10;
  384.         ge=temp%10;
  385.         if(bai!=0)
  386.         {
  387.                 temp2+=8;
  388.                 OLED_ShowChar(temp2,6 ,bai+48,16);
  389.                 temp2+=8;
  390.                 OLED_ShowChar(temp2,6 ,shi+48,16);
  391.                 temp2+=8;
  392.                 OLED_ShowChar(temp2,6 ,ge+48,16);
  393.                
  394.         }
  395.         else
  396.         {
  397.                 if(shi!=0)
  398.                 {
  399.                          temp2+=8;
  400.                          OLED_ShowChar(temp2,6 ,shi+48,16);
  401.                          temp2+=8;
  402.                          OLED_ShowChar(temp2,6 ,ge+48,16);
  403.                          
  404.                 }
  405.                 else
  406.                 {
  407.                          temp2+=8;
  408.                          OLED_ShowChar(temp2,6 ,ge+48,16);
  409.                          
  410.                 }
  411.         }
  412. </font>       
  413. //        Write_W5500_1Byte(0x0001,192);
  414. //        temp=Read_W5500_1Byte(0x0001);
  415.     /*****MainLoop*****/
  416.     while(1)
  417.     {
  418.         /*<UserCodeStart>*//*<SinOne-Tag><14>*/
  419.         /***User program***/
  420.                 W5500_Socket_Set();//W5500???ú3?ê??ˉ????

  421.                 W5500_Interrupt_Process();//W5500?D??′|àí3ìDò?ò?ü

  422.                 if((S0_Data & S_RECEIVE) == S_RECEIVE)//è?1?Socket0?óê?μ?êy?Y
  423.                 {
  424.                         S0_Data&=~S_RECEIVE;
  425.                         Process_Socket_Data(0);//W5500?óê?2¢·¢?í?óê?μ?μ?êy?Y
  426.                 }
  427.                 else if(W5500_Send_Delay_Counter >= 50000)//?¨ê±·¢?í×?·?′?
  428.                 {
  429.                         if(S0_State == (S_INIT|S_CONN))
  430.                         {
  431.                                 S0_Data&=~S_TRANSMITOK;
  432.                                 memcpy(Tx_Buffer, "\r\nWelcome To ChaungWeiElec!\r\n", 27);
  433.                                 Write_SOCK_Data_Buffer(0, Tx_Buffer, 27);//???¨Socket(0~7)·¢?íêy?Y′|àí,???ú0·¢?í27×??úêy?Y
  434.                         }
  435.                         W5500_Send_Delay_Counter=0;
  436.                 }
  437.                 W5500_Send_Delay_Counter++;
  438.         /*<UserCodeEnd>*//*<SinOne-Tag><14>*/
  439.         /*<Begin-Inserted by EasyCodeCube for Condition>*/
  440.     }
  441.     /*<UserCodeEnd>*//*<SinOne-Tag><4>*/
  442.     /*<Generated by EasyCodeCube end>*/
  443. }

W5500的驱动程序:
  1. #include "SC_Init.h"        // MCU initialization header file, including all firmware library header files
  2. #include "SC_it.h"
  3. #include "..\Drivers\SCDriver_list.h"
  4. #include "HeadFiles\SysFunVarDefine.h"               
  5. #include "..\Apps\W5500.h"       

  6. /***************----- 网络参数变量定义 -----***************/
  7. unsigned char Gateway_IP[4];//网关IP地址
  8. unsigned char Sub_Mask[4];        //子网掩码
  9. unsigned char Phy_Addr[6];        //物理地址(MAC)
  10. unsigned char IP_Addr[4];        //本机IP地址

  11. unsigned char S0_Port[2];        //端口0的端口号(5000)
  12. unsigned char S0_DIP[4];        //端口0目的IP地址
  13. unsigned char S0_DPort[2];        //端口0目的端口号(6000)

  14. unsigned char UDP_DIPR[4];        //UDP(广播)模式,目的主机IP地址
  15. unsigned char UDP_DPORT[2];        //UDP(广播)模式,目的主机端口号

  16. /***************----- 端口的运行模式 -----***************/
  17. unsigned char S0_Mode =3;        //端口0的运行模式,0:TCP服务器模式,1:TCP客户端模式,2:UDP(广播)模式
  18. #define TCP_SERVER        0x00        //TCP服务器模式
  19. #define TCP_CLIENT        0x01        //TCP客户端模式
  20. #define UDP_MODE        0x02        //UDP(广播)模式

  21. /***************----- 端口的运行状态 -----***************/
  22. unsigned char S0_State =0;        //端口0状态记录,1:端口完成初始化,2端口完成连接(可以正常传输数据)
  23. #define S_INIT                0x01        //端口完成初始化
  24. #define S_CONN                0x02        //端口完成连接,可以正常传输数据

  25. /***************----- 端口收发数据的状态 -----***************/
  26. unsigned char S0_Data;                //端口0接收和发送数据的状态,1:端口接收到数据,2:端口发送数据完成
  27. #define S_RECEIVE         0x01        //端口接收到一个数据包
  28. #define S_TRANSMITOK 0x02        //端口发送一个数据包完成

  29. /***************----- 端口数据缓冲区 -----***************/
  30. unsigned char Rx_Buffer[2048];        //端口接收数据缓冲区
  31. unsigned char Tx_Buffer[2048];        //端口发送数据缓冲区

  32. unsigned char W5500_Interrupt;        //W5500中断标志(0:无中断,1:有中断)

  33. void Delay(unsigned int  x)
  34. {
  35.     unsigned int i,j;

  36.     for(j=0;j<5;j++)
  37.                 for(i=0;i<x;i++);
  38. }
  39. /*******************************************************************************
  40. * 函数名  : SPI1_Send_Byte
  41. * 描述    : SPI1发送1个字节数据
  42. * 输入    : dat:待发送的数据
  43. * 输出    : 无
  44. * 返回值  : 无
  45. * 说明    : 无
  46. *******************************************************************************/
  47. void SPI1_Send_Byte(unsigned char dat)
  48. {
  49.                 USCI2_SPI_SendData_8(dat);
  50. }

  51. /*******************************************************************************
  52. * 函数名  : SPI1_Send_Short
  53. * 描述    : SPI1发送2个字节数据(16位)
  54. * 输入    : dat:待发送的16位数据
  55. * 输出    : 无
  56. * 返回值  : 无
  57. * 说明    : 无
  58. *******************************************************************************/
  59. void SPI1_Send_Short(unsigned short dat)
  60. {
  61.         SPI1_Send_Byte(dat/256);//写数据高位
  62.         SPI1_Send_Byte(dat);        //写数据低位
  63. }

  64. /*******************************************************************************
  65. * 函数名  : Write_W5500_1Byte
  66. * 描述    : 通过SPI1向指定地址寄存器写1个字节数据
  67. * 输入    : reg:16位寄存器地址,dat:待写入的数据
  68. * 输出    : 无
  69. * 返回值  : 无
  70. * 说明    : 无
  71. *******************************************************************************/
  72. void Write_W5500_1Byte(unsigned short reg, unsigned char dat)
  73. {
  74.         GPIO_WriteLow(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为低电平

  75.         SPI1_Send_Short(reg);//通过SPI1写16位寄存器地址
  76.         SPI1_Send_Byte(FDM1|RWB_WRITE|COMMON_R);//通过SPI1写控制字节,1个字节数据长度,写数据,选择通用寄存器
  77.         SPI1_Send_Byte(dat);//写1个字节数据

  78.         GPIO_WriteHigh(W5500_SCS_PORT, W5500_SCS); //置W5500的SCS为高电平
  79. }

  80. /*******************************************************************************
  81. * 函数名  : Write_W5500_2Byte
  82. * 描述    : 通过SPI1向指定地址寄存器写2个字节数据
  83. * 输入    : reg:16位寄存器地址,dat:16位待写入的数据(2个字节)
  84. * 输出    : 无
  85. * 返回值  : 无
  86. * 说明    : 无
  87. *******************************************************************************/
  88. void Write_W5500_2Byte(unsigned short reg, unsigned short dat)
  89. {
  90.         GPIO_WriteLow(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为低电平
  91.                
  92.         SPI1_Send_Short(reg);//通过SPI1写16位寄存器地址
  93.         SPI1_Send_Byte(FDM2|RWB_WRITE|COMMON_R);//通过SPI1写控制字节,2个字节数据长度,写数据,选择通用寄存器
  94.         SPI1_Send_Short(dat);//写16位数据

  95.         GPIO_WriteHigh(W5500_SCS_PORT, W5500_SCS); //置W5500的SCS为高电平
  96. }

  97. /*******************************************************************************
  98. * 函数名  : Write_W5500_nByte
  99. * 描述    : 通过SPI1向指定地址寄存器写n个字节数据
  100. * 输入    : reg:16位寄存器地址,*dat_ptr:待写入数据缓冲区指针,size:待写入的数据长度
  101. * 输出    : 无
  102. * 返回值  : 无
  103. * 说明    : 无
  104. *******************************************************************************/
  105. void Write_W5500_nByte(unsigned short reg, unsigned char *dat_ptr, unsigned short size)
  106. {
  107.         unsigned short i;

  108.         GPIO_WriteLow(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为低电平       
  109.                
  110.         SPI1_Send_Short(reg);//通过SPI1写16位寄存器地址
  111.         SPI1_Send_Byte(VDM|RWB_WRITE|COMMON_R);//通过SPI1写控制字节,N个字节数据长度,写数据,选择通用寄存器

  112.         for(i=0;i<size;i++)//循环将缓冲区的size个字节数据写入W5500
  113.         {
  114.                 SPI1_Send_Byte(*dat_ptr++);//写一个字节数据
  115.         }

  116.         GPIO_WriteHigh(W5500_SCS_PORT, W5500_SCS); //置W5500的SCS为高电平
  117. }

  118. /*******************************************************************************
  119. * 函数名  : Write_W5500_SOCK_1Byte
  120. * 描述    : 通过SPI1向指定端口寄存器写1个字节数据
  121. * 输入    : s:端口号,reg:16位寄存器地址,dat:待写入的数据
  122. * 输出    : 无
  123. * 返回值  : 无
  124. * 说明    : 无
  125. *******************************************************************************/
  126. void Write_W5500_SOCK_1Byte(SOCKET s, unsigned short reg, unsigned char dat)
  127. {
  128.         GPIO_WriteLow(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为低电平       
  129.                
  130.         SPI1_Send_Short(reg);//通过SPI1写16位寄存器地址
  131.         SPI1_Send_Byte(FDM1|RWB_WRITE|(s*0x20+0x08));//通过SPI1写控制字节,1个字节数据长度,写数据,选择端口s的寄存器
  132.         SPI1_Send_Byte(dat);//写1个字节数据

  133.         GPIO_WriteHigh(W5500_SCS_PORT, W5500_SCS); //置W5500的SCS为高电平
  134. }

  135. /*******************************************************************************
  136. * 函数名  : Write_W5500_SOCK_2Byte
  137. * 描述    : 通过SPI1向指定端口寄存器写2个字节数据
  138. * 输入    : s:端口号,reg:16位寄存器地址,dat:16位待写入的数据(2个字节)
  139. * 输出    : 无
  140. * 返回值  : 无
  141. * 说明    : 无
  142. *******************************************************************************/
  143. void Write_W5500_SOCK_2Byte(SOCKET s, unsigned short reg, unsigned short dat)
  144. {
  145.         GPIO_WriteLow(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为低电平
  146.                        
  147.         SPI1_Send_Short(reg);//通过SPI1写16位寄存器地址
  148.         SPI1_Send_Byte(FDM2|RWB_WRITE|(s*0x20+0x08));//通过SPI1写控制字节,2个字节数据长度,写数据,选择端口s的寄存器
  149.         SPI1_Send_Short(dat);//写16位数据

  150.         GPIO_WriteHigh(W5500_SCS_PORT, W5500_SCS); //置W5500的SCS为高电平
  151. }

  152. /*******************************************************************************
  153. * 函数名  : Write_W5500_SOCK_4Byte
  154. * 描述    : 通过SPI1向指定端口寄存器写4个字节数据
  155. * 输入    : s:端口号,reg:16位寄存器地址,*dat_ptr:待写入的4个字节缓冲区指针
  156. * 输出    : 无
  157. * 返回值  : 无
  158. * 说明    : 无
  159. *******************************************************************************/
  160. void Write_W5500_SOCK_4Byte(SOCKET s, unsigned short reg, unsigned char *dat_ptr)
  161. {
  162.         GPIO_WriteLow(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为低电平
  163.                        
  164.         SPI1_Send_Short(reg);//通过SPI1写16位寄存器地址
  165.         SPI1_Send_Byte(FDM4|RWB_WRITE|(s*0x20+0x08));//通过SPI1写控制字节,4个字节数据长度,写数据,选择端口s的寄存器

  166.         SPI1_Send_Byte(*dat_ptr++);//写第1个字节数据
  167.         SPI1_Send_Byte(*dat_ptr++);//写第2个字节数据
  168.         SPI1_Send_Byte(*dat_ptr++);//写第3个字节数据
  169.         SPI1_Send_Byte(*dat_ptr++);//写第4个字节数据

  170.         GPIO_WriteHigh(W5500_SCS_PORT, W5500_SCS); //置W5500的SCS为高电平
  171. }

  172. /*******************************************************************************
  173. * 函数名  : Read_W5500_1Byte
  174. * 描述    : 读W5500指定地址寄存器的1个字节数据
  175. * 输入    : reg:16位寄存器地址
  176. * 输出    : 无
  177. * 返回值  : 读取到寄存器的1个字节数据
  178. * 说明    : 无
  179. *******************************************************************************/
  180. unsigned char Read_W5500_1Byte(unsigned short reg)
  181. {
  182.         unsigned char i;

  183.         GPIO_WriteLow(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为低电平
  184.                        
  185.         SPI1_Send_Short(reg);//通过SPI1写16位寄存器地址
  186.         SPI1_Send_Byte(FDM1|RWB_READ|COMMON_R);//通过SPI1写控制字节,1个字节数据长度,读数据,选择通用寄存器

  187. //        i=SPI_I2S_ReceiveData(SPI1);
  188. //        SPI1_Send_Byte(0x00);//发送一个哑数据
  189. //        i=SPI_I2S_ReceiveData(SPI1);//读取1个字节数据
  190.         i=USCI2_SPI_ReceiveData_8_1();
  191.         i=USCI2_SPI_ReceiveData_8();
  192.         GPIO_WriteHigh(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为高电平
  193.         return i;//返回读取到的寄存器数据
  194. }

  195. /*******************************************************************************
  196. * 函数名  : Read_W5500_SOCK_1Byte
  197. * 描述    : 读W5500指定端口寄存器的1个字节数据
  198. * 输入    : s:端口号,reg:16位寄存器地址
  199. * 输出    : 无
  200. * 返回值  : 读取到寄存器的1个字节数据
  201. * 说明    : 无
  202. *******************************************************************************/
  203. unsigned char Read_W5500_SOCK_1Byte(SOCKET s, unsigned short reg)
  204. {
  205.         unsigned char i;

  206.         GPIO_WriteLow(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为低电平
  207.                        
  208.         SPI1_Send_Short(reg);//通过SPI1写16位寄存器地址
  209.         SPI1_Send_Byte(FDM1|RWB_READ|(s*0x20+0x08));//通过SPI1写控制字节,1个字节数据长度,读数据,选择端口s的寄存器

  210. //        i=SPI_I2S_ReceiveData(SPI1);
  211. //        SPI1_Send_Byte(0x00);//发送一个哑数据
  212. //        i=SPI_I2S_ReceiveData(SPI1);//读取1个字节数据
  213.         i=USCI2_SPI_ReceiveData_8_1();
  214.         i=USCI2_SPI_ReceiveData_8();
  215.         GPIO_WriteHigh(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为高电平
  216.         return i;//返回读取到的寄存器数据
  217. }

  218. /*******************************************************************************
  219. * 函数名  : Read_W5500_SOCK_2Byte
  220. * 描述    : 读W5500指定端口寄存器的2个字节数据
  221. * 输入    : s:端口号,reg:16位寄存器地址
  222. * 输出    : 无
  223. * 返回值  : 读取到寄存器的2个字节数据(16位)
  224. * 说明    : 无
  225. *******************************************************************************/
  226. unsigned short Read_W5500_SOCK_2Byte(SOCKET s, unsigned short reg)
  227. {
  228.         unsigned short i;

  229.         GPIO_WriteLow(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为低电平
  230.                        
  231.         SPI1_Send_Short(reg);//通过SPI1写16位寄存器地址
  232.         SPI1_Send_Byte(FDM2|RWB_READ|(s*0x20+0x08));//通过SPI1写控制字节,2个字节数据长度,读数据,选择端口s的寄存器

  233. //        i=SPI_I2S_ReceiveData(SPI1);
  234. //        SPI1_Send_Byte(0x00);//发送一个哑数据
  235. //        i=SPI_I2S_ReceiveData(SPI1);//读取高位数据
  236.         i=USCI2_SPI_ReceiveData_8_1();
  237.         i=USCI2_SPI_ReceiveData_8();
  238.         i*=256;
  239.         //SPI1_Send_Byte(0x00);//发送一个哑数据
  240.        
  241.         i+=USCI2_SPI_ReceiveData_8();//读取低位数据

  242.         GPIO_WriteHigh(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为高电平
  243.         return i;//返回读取到的寄存器数据
  244. }

  245. /*******************************************************************************
  246. * 函数名  : Read_SOCK_Data_Buffer
  247. * 描述    : 从W5500接收数据缓冲区中读取数据
  248. * 输入    : s:端口号,*dat_ptr:数据保存缓冲区指针
  249. * 输出    : 无
  250. * 返回值  : 读取到的数据长度,rx_size个字节
  251. * 说明    : 无
  252. *******************************************************************************/
  253. unsigned short Read_SOCK_Data_Buffer(SOCKET s, unsigned char *dat_ptr)
  254. {
  255.         unsigned short rx_size;
  256.         unsigned short offset, offset1;
  257.         unsigned short i;
  258.         unsigned char j;

  259.         rx_size=Read_W5500_SOCK_2Byte(s,Sn_RX_RSR);
  260.         if(rx_size==0) return 0;//没接收到数据则返回
  261.         if(rx_size>1460) rx_size=1460;

  262.         offset=Read_W5500_SOCK_2Byte(s,Sn_RX_RD);
  263.         offset1=offset;
  264.         offset&=(S_RX_SIZE-1);//计算实际的物理地址

  265.         GPIO_WriteLow(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为低电平

  266.         SPI1_Send_Short(offset);//写16位地址
  267.         SPI1_Send_Byte(VDM|RWB_READ|(s*0x20+0x18));//写控制字节,N个字节数据长度,读数据,选择端口s的寄存器
  268.         //j=SPI_I2S_ReceiveData(SPI1);
  269.         j=USCI2_SPI_ReceiveData_8_1();
  270.         if((offset+rx_size)<S_RX_SIZE)//如果最大地址未超过W5500接收缓冲区寄存器的最大地址
  271.         {
  272.                 for(i=0;i<rx_size;i++)//循环读取rx_size个字节数据
  273.                 {
  274. //                        SPI1_Send_Byte(0x00);//发送一个哑数据
  275. //                        j=SPI_I2S_ReceiveData(SPI1);//读取1个字节数据
  276.                         j=USCI2_SPI_ReceiveData_8();
  277.                         *dat_ptr=j;//将读取到的数据保存到数据保存缓冲区
  278.                         dat_ptr++;//数据保存缓冲区指针地址自增1
  279.                 }
  280.         }
  281.         else//如果最大地址超过W5500接收缓冲区寄存器的最大地址
  282.         {
  283.                 offset=S_RX_SIZE-offset;
  284.                 for(i=0;i<offset;i++)//循环读取出前offset个字节数据
  285.                 {
  286. //                        SPI1_Send_Byte(0x00);//发送一个哑数据
  287. //                        j=SPI_I2S_ReceiveData(SPI1);//读取1个字节数据
  288.                         j=USCI2_SPI_ReceiveData_8();
  289.                         *dat_ptr=j;//将读取到的数据保存到数据保存缓冲区
  290.                         dat_ptr++;//数据保存缓冲区指针地址自增1
  291.                 }
  292.                 GPIO_WriteHigh(W5500_SCS_PORT, W5500_SCS); //置W5500的SCS为高电平

  293.                 GPIO_WriteLow(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为低电平

  294.                 SPI1_Send_Short(0x00);//写16位地址
  295.                 SPI1_Send_Byte(VDM|RWB_READ|(s*0x20+0x18));//写控制字节,N个字节数据长度,读数据,选择端口s的寄存器
  296.                 //j=SPI_I2S_ReceiveData(SPI1);
  297.                 j=USCI2_SPI_ReceiveData_8_1();
  298.                 for(;i<rx_size;i++)//循环读取后rx_size-offset个字节数据
  299.                 {
  300. //                        SPI1_Send_Byte(0x00);//发送一个哑数据
  301. //                        j=SPI_I2S_ReceiveData(SPI1);//读取1个字节数据
  302.                         j=USCI2_SPI_ReceiveData_8();
  303.                         *dat_ptr=j;//将读取到的数据保存到数据保存缓冲区
  304.                         dat_ptr++;//数据保存缓冲区指针地址自增1
  305.                 }
  306.         }
  307.         GPIO_WriteHigh(W5500_SCS_PORT, W5500_SCS); //置W5500的SCS为高电平

  308.         offset1+=rx_size;//更新实际物理地址,即下次读取接收到的数据的起始地址
  309.         Write_W5500_SOCK_2Byte(s, Sn_RX_RD, offset1);
  310.         Write_W5500_SOCK_1Byte(s, Sn_CR, RECV);//发送启动接收命令
  311.         return rx_size;//返回接收到数据的长度
  312. }

  313. /*******************************************************************************
  314. * 函数名  : Write_SOCK_Data_Buffer
  315. * 描述    : 将数据写入W5500的数据发送缓冲区
  316. * 输入    : s:端口号,*dat_ptr:数据保存缓冲区指针,size:待写入数据的长度
  317. * 输出    : 无
  318. * 返回值  : 无
  319. * 说明    : 无
  320. *******************************************************************************/
  321. void Write_SOCK_Data_Buffer(SOCKET s, unsigned char *dat_ptr, unsigned short size)
  322. {
  323.         unsigned short offset,offset1;
  324.         unsigned short i;

  325.         //如果是UDP模式,可以在此设置目的主机的IP和端口号
  326.         if((Read_W5500_SOCK_1Byte(s,Sn_MR)&0x0f) != SOCK_UDP)//如果Socket打开失败
  327.         {               
  328.                 Write_W5500_SOCK_4Byte(s, Sn_DIPR, UDP_DIPR);//设置目的主机IP                 
  329.                 Write_W5500_SOCK_2Byte(s, Sn_DPORTR, UDP_DPORT[0]*256+UDP_DPORT[1]);//设置目的主机端口号                               
  330.         }

  331.         offset=Read_W5500_SOCK_2Byte(s,Sn_TX_WR);
  332.         offset1=offset;
  333.         offset&=(S_TX_SIZE-1);//计算实际的物理地址

  334.         GPIO_WriteLow(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为低电平

  335.         SPI1_Send_Short(offset);//写16位地址
  336.         SPI1_Send_Byte(VDM|RWB_WRITE|(s*0x20+0x10));//写控制字节,N个字节数据长度,写数据,选择端口s的寄存器

  337.         if((offset+size)<S_TX_SIZE)//如果最大地址未超过W5500发送缓冲区寄存器的最大地址
  338.         {
  339.                 for(i=0;i<size;i++)//循环写入size个字节数据
  340.                 {
  341.                         SPI1_Send_Byte(*dat_ptr++);//写入一个字节的数据               
  342.                 }
  343.         }
  344.         else//如果最大地址超过W5500发送缓冲区寄存器的最大地址
  345.         {
  346.                 offset=S_TX_SIZE-offset;
  347.                 for(i=0;i<offset;i++)//循环写入前offset个字节数据
  348.                 {
  349.                         SPI1_Send_Byte(*dat_ptr++);//写入一个字节的数据
  350.                 }
  351.                 GPIO_WriteHigh(W5500_SCS_PORT, W5500_SCS); //置W5500的SCS为高电平

  352.                 GPIO_WriteLow(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为低电平

  353.                 SPI1_Send_Short(0x00);//写16位地址
  354.                 SPI1_Send_Byte(VDM|RWB_WRITE|(s*0x20+0x10));//写控制字节,N个字节数据长度,写数据,选择端口s的寄存器

  355.                 for(;i<size;i++)//循环写入size-offset个字节数据
  356.                 {
  357.                         SPI1_Send_Byte(*dat_ptr++);//写入一个字节的数据
  358.                 }
  359.         }
  360.         GPIO_WriteHigh(W5500_SCS_PORT, W5500_SCS); //置W5500的SCS为高电平

  361.         offset1+=size;//更新实际物理地址,即下次写待发送数据到发送数据缓冲区的起始地址
  362.         Write_W5500_SOCK_2Byte(s, Sn_TX_WR, offset1);
  363.         Write_W5500_SOCK_1Byte(s, Sn_CR, SEND);//发送启动发送命令                               
  364. }

  365. /*******************************************************************************
  366. * 函数名  : W5500_Hardware_Reset
  367. * 描述    : 硬件复位W5500
  368. * 输入    : 无
  369. * 输出    : 无
  370. * 返回值  : 无
  371. * 说明    : W5500的复位引脚保持低电平至少500us以上,才能重围W5500
  372. *******************************************************************************/
  373. void W5500_Hardware_Reset(void)
  374. {
  375.         GPIO_WriteLow(W5500_RST_PORT, W5500_RST);//复位引脚拉低
  376.         Delay(500);
  377.         GPIO_WriteHigh(W5500_RST_PORT, W5500_RST);//复位引脚拉高
  378.         Delay(2000);
  379.         while((Read_W5500_1Byte(PHYCFGR)&LINK)==0);//等待以太网连接完成
  380. }

  381. /*******************************************************************************
  382. * 函数名  : W5500_Init
  383. * 描述    : 初始化W5500寄存器函数
  384. * 输入    : 无
  385. * 输出    : 无
  386. * 返回值  : 无
  387. * 说明    : 在使用W5500之前,先对W5500初始化
  388. *******************************************************************************/
  389. void W5500_Init(void)
  390. {
  391.         u8 i=0;

  392.         Write_W5500_1Byte(MR, RST);//软件复位W5500,置1有效,复位后自动清0
  393.         Delay(10);//延时10ms,自己定义该函数

  394.         //设置网关(Gateway)的IP地址,Gateway_IP为4字节unsigned char数组,自己定义
  395.         //使用网关可以使通信突破子网的局限,通过网关可以访问到其它子网或进入Internet
  396.         Write_W5500_nByte(GAR, Gateway_IP, 4);
  397.                        
  398.         //设置子网掩码(MASK)值,SUB_MASK为4字节unsigned char数组,自己定义
  399.         //子网掩码用于子网运算
  400.         Write_W5500_nByte(SUBR,Sub_Mask,4);               
  401.        
  402.         //设置物理地址,PHY_ADDR为6字节unsigned char数组,自己定义,用于唯一标识网络设备的物理地址值
  403.         //该地址值需要到IEEE申请,按照OUI的规定,前3个字节为厂商代码,后三个字节为产品序号
  404.         //如果自己定义物理地址,注意第一个字节必须为偶数
  405.         Write_W5500_nByte(SHAR,Phy_Addr,6);               

  406.         //设置本机的IP地址,IP_ADDR为4字节unsigned char数组,自己定义
  407.         //注意,网关IP必须与本机IP属于同一个子网,否则本机将无法找到网关
  408.         Write_W5500_nByte(SIPR,IP_Addr,4);               
  409.        
  410.         //设置发送缓冲区和接收缓冲区的大小,参考W5500数据手册
  411.         for(i=0;i<8;i++)
  412.         {
  413.                 Write_W5500_SOCK_1Byte(i,Sn_RXBUF_SIZE, 0x02);//Socket Rx memory size=2k
  414.                 Write_W5500_SOCK_1Byte(i,Sn_TXBUF_SIZE, 0x02);//Socket Tx mempry size=2k
  415.         }

  416.         //设置重试时间,默认为2000(200ms)
  417.         //每一单位数值为100微秒,初始化时值设为2000(0x07D0),等于200毫秒
  418.         Write_W5500_2Byte(RTR, 0x07d0);

  419.         //设置重试次数,默认为8次
  420.         //如果重发的次数超过设定值,则产生超时中断(相关的端口中断寄存器中的Sn_IR 超时位(TIMEOUT)置“1”)
  421.         Write_W5500_1Byte(RCR,8);
  422. }

  423. /*******************************************************************************
  424. * 函数名  : Detect_Gateway
  425. * 描述    : 检查网关服务器
  426. * 输入    : 无
  427. * 输出    : 无
  428. * 返回值  : 成功返回TRUE(0xFF),失败返回FALSE(0x00)
  429. * 说明    : 无
  430. *******************************************************************************/
  431. unsigned char Detect_Gateway(void)
  432. {
  433.         unsigned char ip_adde[4];
  434.         ip_adde[0]=IP_Addr[0]+1;
  435.         ip_adde[1]=IP_Addr[1]+1;
  436.         ip_adde[2]=IP_Addr[2]+1;
  437.         ip_adde[3]=IP_Addr[3]+1;

  438.         //检查网关及获取网关的物理地址
  439.         Write_W5500_SOCK_4Byte(0,Sn_DIPR,ip_adde);//向目的地址寄存器写入与本机IP不同的IP值
  440.         Write_W5500_SOCK_1Byte(0,Sn_MR,MR_TCP);//设置socket为TCP模式
  441.         Write_W5500_SOCK_1Byte(0,Sn_CR,OPEN);//打开Socket       
  442.         Delay(5);//延时5ms        
  443.        
  444.         if(Read_W5500_SOCK_1Byte(0,Sn_SR) != SOCK_INIT)//如果socket打开失败
  445.         {
  446.                 Write_W5500_SOCK_1Byte(0,Sn_CR,CLOSE);//打开不成功,关闭Socket
  447.                 return FALSE;//返回FALSE(0x00)
  448.         }

  449.         Write_W5500_SOCK_1Byte(0,Sn_CR,CONNECT);//设置Socket为Connect模式                                               

  450.         do
  451.         {
  452.                 u8 j=0;
  453.                 j=Read_W5500_SOCK_1Byte(0,Sn_IR);//读取Socket0中断标志寄存器
  454.                 if(j!=0)
  455.                 Write_W5500_SOCK_1Byte(0,Sn_IR,j);
  456.                 Delay(5);//延时5ms
  457.                 if((j&IR_TIMEOUT) == IR_TIMEOUT)
  458.                 {
  459.                         return FALSE;       
  460.                 }
  461.                 else if(Read_W5500_SOCK_1Byte(0,Sn_DHAR) != 0xff)
  462.                 {
  463.                         Write_W5500_SOCK_1Byte(0,Sn_CR,CLOSE);//关闭Socket
  464.                         return TRUE;                                                       
  465.                 }
  466.         }while(1);
  467. }

  468. /*******************************************************************************
  469. * 函数名  : Socket_Init
  470. * 描述    : 指定Socket(0~7)初始化
  471. * 输入    : s:待初始化的端口
  472. * 输出    : 无
  473. * 返回值  : 无
  474. * 说明    : 无
  475. *******************************************************************************/
  476. void Socket_Init(SOCKET s)
  477. {
  478.         //设置分片长度,参考W5500数据手册,该值可以不修改       
  479.         Write_W5500_SOCK_2Byte(0, Sn_MSSR, 1460);//最大分片字节数=1460(0x5b4)
  480.         //设置指定端口
  481.         switch(s)
  482.         {
  483.                 case 0:
  484.                         //设置端口0的端口号
  485.                         Write_W5500_SOCK_2Byte(0, Sn_PORT, S0_Port[0]*256+S0_Port[1]);
  486.                         //设置端口0目的(远程)端口号
  487.                         Write_W5500_SOCK_2Byte(0, Sn_DPORTR, S0_DPort[0]*256+S0_DPort[1]);
  488.                         //设置端口0目的(远程)IP地址
  489.                         Write_W5500_SOCK_4Byte(0, Sn_DIPR, S0_DIP);                       
  490.                        
  491.                         break;

  492.                 case 1:
  493.                         break;

  494.                 case 2:
  495.                         break;

  496.                 case 3:
  497.                         break;

  498.                 case 4:
  499.                         break;

  500.                 case 5:
  501.                         break;

  502.                 case 6:
  503.                         break;

  504.                 case 7:
  505.                         break;

  506.                 default:
  507.                         break;
  508.         }
  509. }

  510. /*******************************************************************************
  511. * 函数名  : Socket_Connect
  512. * 描述    : 设置指定Socket(0~7)为客户端与远程服务器连接
  513. * 输入    : s:待设定的端口
  514. * 输出    : 无
  515. * 返回值  : 成功返回TRUE(0xFF),失败返回FALSE(0x00)
  516. * 说明    : 当本机Socket工作在客户端模式时,引用该程序,与远程服务器建立连接
  517. *                        如果启动连接后出现超时中断,则与服务器连接失败,需要重新调用该程序连接
  518. *                        该程序每调用一次,就与服务器产生一次连接
  519. *******************************************************************************/
  520. unsigned char Socket_Connect(SOCKET s)
  521. {
  522.         Write_W5500_SOCK_1Byte(s,Sn_MR,MR_TCP);//设置socket为TCP模式
  523.         Write_W5500_SOCK_1Byte(s,Sn_CR,OPEN);//打开Socket
  524.         Delay(5);//延时5ms
  525.         if(Read_W5500_SOCK_1Byte(s,Sn_SR)!=SOCK_INIT)//如果socket打开失败
  526.         {
  527.                 Write_W5500_SOCK_1Byte(s,Sn_CR,CLOSE);//打开不成功,关闭Socket
  528.                 return FALSE;//返回FALSE(0x00)
  529.         }
  530.         Write_W5500_SOCK_1Byte(s,Sn_CR,CONNECT);//设置Socket为Connect模式
  531.         return TRUE;//返回TRUE,设置成功
  532. }

  533. /*******************************************************************************
  534. * 函数名  : Socket_Listen
  535. * 描述    : 设置指定Socket(0~7)作为服务器等待远程主机的连接
  536. * 输入    : s:待设定的端口
  537. * 输出    : 无
  538. * 返回值  : 成功返回TRUE(0xFF),失败返回FALSE(0x00)
  539. * 说明    : 当本机Socket工作在服务器模式时,引用该程序,等等远程主机的连接
  540. *                        该程序只调用一次,就使W5500设置为服务器模式
  541. *******************************************************************************/
  542. unsigned char Socket_Listen(SOCKET s)
  543. {
  544.         Write_W5500_SOCK_1Byte(s,Sn_MR,MR_TCP);//设置socket为TCP模式
  545.         Write_W5500_SOCK_1Byte(s,Sn_CR,OPEN);//打开Socket       
  546.         Delay(5);//延时5ms
  547.         if(Read_W5500_SOCK_1Byte(s,Sn_SR)!=SOCK_INIT)//如果socket打开失败
  548.         {
  549.                 Write_W5500_SOCK_1Byte(s,Sn_CR,CLOSE);//打开不成功,关闭Socket
  550.                 return FALSE;//返回FALSE(0x00)
  551.         }       
  552.         Write_W5500_SOCK_1Byte(s,Sn_CR,LISTEN);//设置Socket为侦听模式       
  553.         Delay(5);//延时5ms
  554.         if(Read_W5500_SOCK_1Byte(s,Sn_SR)!=SOCK_LISTEN)//如果socket设置失败
  555.         {
  556.                 Write_W5500_SOCK_1Byte(s,Sn_CR,CLOSE);//设置不成功,关闭Socket
  557.                 return FALSE;//返回FALSE(0x00)
  558.         }

  559.         return TRUE;

  560.         //至此完成了Socket的打开和设置侦听工作,至于远程客户端是否与它建立连接,则需要等待Socket中断,
  561.         //以判断Socket的连接是否成功。参考W5500数据手册的Socket中断状态
  562.         //在服务器侦听模式不需要设置目的IP和目的端口号
  563. }

  564. /*******************************************************************************
  565. * 函数名  : Socket_UDP
  566. * 描述    : 设置指定Socket(0~7)为UDP模式
  567. * 输入    : s:待设定的端口
  568. * 输出    : 无
  569. * 返回值  : 成功返回TRUE(0xFF),失败返回FALSE(0x00)
  570. * 说明    : 如果Socket工作在UDP模式,引用该程序,在UDP模式下,Socket通信不需要建立连接
  571. *                        该程序只调用一次,就使W5500设置为UDP模式
  572. *******************************************************************************/
  573. unsigned char Socket_UDP(SOCKET s)
  574. {
  575.         Write_W5500_SOCK_1Byte(s,Sn_MR,MR_UDP);//设置Socket为UDP模式*/
  576.         Write_W5500_SOCK_1Byte(s,Sn_CR,OPEN);//打开Socket*/
  577.         Delay(5);//延时5ms
  578.         if(Read_W5500_SOCK_1Byte(s,Sn_SR)!=SOCK_UDP)//如果Socket打开失败
  579.         {
  580.                 Write_W5500_SOCK_1Byte(s,Sn_CR,CLOSE);//打开不成功,关闭Socket
  581.                 return FALSE;//返回FALSE(0x00)
  582.         }
  583.         else
  584.                 return TRUE;

  585.         //至此完成了Socket的打开和UDP模式设置,在这种模式下它不需要与远程主机建立连接
  586.         //因为Socket不需要建立连接,所以在发送数据前都可以设置目的主机IP和目的Socket的端口号
  587.         //如果目的主机IP和目的Socket的端口号是固定的,在运行过程中没有改变,那么也可以在这里设置
  588. }

  589. /*******************************************************************************
  590. * 函数名  : W5500_Interrupt_Process
  591. * 描述    : W5500中断处理程序框架
  592. * 输入    : 无
  593. * 输出    : 无
  594. * 返回值  : 无
  595. * 说明    : 无
  596. *******************************************************************************/
  597. void W5500_Interrupt_Process(void)
  598. {
  599.         unsigned char i,j;

  600. IntDispose:

  601.         i=Read_W5500_1Byte(SIR);//读取端口中断标志寄存器       
  602.         if((i & S0_INT) == S0_INT)//Socket0事件处理
  603.         {
  604.                 j=Read_W5500_SOCK_1Byte(0,Sn_IR);//读取Socket0中断标志寄存器
  605.                 Write_W5500_SOCK_1Byte(0,Sn_IR,j);
  606.                 if(j&IR_CON)//在TCP模式下,Socket0成功连接
  607.                 {
  608.                         S0_State|=S_CONN;//网络连接状态0x02,端口完成连接,可以正常传输数据
  609.                 }
  610.                 if(j&IR_DISCON)//在TCP模式下Socket断开连接处理
  611.                 {
  612.                         Write_W5500_SOCK_1Byte(0,Sn_CR,CLOSE);//关闭端口,等待重新打开连接
  613.                         Socket_Init(0);                //指定Socket(0~7)初始化,初始化端口0
  614.                         S0_State=0;//网络连接状态0x00,端口连接失败
  615.                 }
  616.                 if(j&IR_SEND_OK)//Socket0数据发送完成,可以再次启动S_tx_process()函数发送数据
  617.                 {
  618.                         S0_Data|=S_TRANSMITOK;//端口发送一个数据包完成
  619.                 }
  620.                 if(j&IR_RECV)//Socket接收到数据,可以启动S_rx_process()函数
  621.                 {
  622.                         S0_Data|=S_RECEIVE;//端口接收到一个数据包
  623.                 }
  624.                 if(j&IR_TIMEOUT)//Socket连接或数据传输超时处理
  625.                 {
  626.                         Write_W5500_SOCK_1Byte(0,Sn_CR,CLOSE);// 关闭端口,等待重新打开连接                        
  627.                         S0_State=0;//网络连接状态0x00,端口连接失败
  628.                 }
  629.         }

  630.         if(Read_W5500_1Byte(SIR) != 0)
  631.                 goto IntDispose;
  632. }

W5500.H部分代码:
  1. /***************----- W5500 GPIO定义 -----***************/
  2. #define W5500_SCS                GPIO_PIN_7        //定义W5500的CS引脚         
  3. #define W5500_SCS_PORT        GPIO0
  4.        
  5. #define W5500_RST                GPIO_PIN_3        //定义W5500的RST引脚
  6. #define W5500_RST_PORT        GPIO0

  7. #define LED                GPIO_PIN_1        //定义LED引脚
  8. #define LED_PORT        GPIO0
效果图:

9.jpg 10.jpg
代码中红色的部分是设置好IP地址网关以后从相应寄存器里读出来显示的。
8.jpg
收到下位机发来的数据。
上位机往下位机发1
7.jpg
点亮板子上的LED灯。
6.jpg
上位机往下位机发0
5.jpg
板子上的熄灭。
4.jpg
点灯灭灯的程序

评论

我还没来得及拆封,你就玩起来了  发表于 2023-1-24 01:30
 楼主| 比神乐 发表于 2023-1-22 16:02 | 显示全部楼层
帖子发出之前,代码可以显示红色和蓝色,发出去之后,颜色就不对了。
RDS小定 发表于 2023-1-22 19:57 | 显示全部楼层
新年第一帖
forgot 发表于 2023-1-24 01:30 | 显示全部楼层
点赞点赞
cooldog123pp 发表于 2023-1-27 22:56 | 显示全部楼层
很给力的代码,注释也写的很详细,很有参考价值,多谢楼主分享
wilhelmina2 发表于 2023-2-2 11:35 | 显示全部楼层
这个网口怎么做的?              
 楼主| 比神乐 发表于 2023-2-2 14:36 | 显示全部楼层
wilhelmina2 发表于 2023-2-2 11:35
这个网口怎么做的?

淘宝上买的。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

470

主题

3535

帖子

7

粉丝
快速回复 在线客服 返回列表 返回顶部

470

主题

3535

帖子

7

粉丝
快速回复 在线客服 返回列表 返回顶部