1844|3

283

帖子

2

TA的资源

纯净的硅(初级)

楼主
 

全能小网关|CH32V208--6、板载ETH功能初体验 [复制链接]

WCHNET协议库

随着物联网的普及,越来越多的单片机系统需要用到网络通讯。
WCHNET 芯片自带以太网 MAC,部分芯片有内置 10M PHY,支持 10M 以太网(部分芯片还支持 100M/1000M 速率),全双工,半双工,自动协商,线路自动转换等功能,可以直接和网络终端如 PC,嵌入式设备进行数据交互。WCHNET 协议栈库提供了 TCP/IP 子程序库,集成了 TCP、UDP、ARP、RARP、ICMP、IGMP等以太网协议栈,可以同时支持 TCP、UDP 和 IPRAW 三种模式。

库函数

WCHNET的库其实并没有多复杂,也只是提供一些简单的功能,实现一些TCP/IP的简单应用是不错的。例如socket,http服务,mqtt应用等等。
但是如果想实现更多的功能,例如sntp校时,websocket服务,grpc服务等等应用,还是需要考虑类似lwip这些使用更广泛的库。

运行DHCP例程

这段代码演示了如何使用WCH提供的以太网库进行DHCP操作,获取IP地址,并创建TCP连接。

  1. /********************************** (C) COPYRIGHT *******************************
  2. * File Name : main.c
  3. * Author : WCH
  4. * Version : V1.0.0
  5. * Date : 2022/05/20
  6. * Description : Main program body.
  7. *********************************************************************************
  8. * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
  9. * Attention: This software (modified or not) and binary are used for
  10. * microcontroller manufactured by Nanjing Qinheng Microelectronics.
  11. *******************************************************************************/
  12. /*
  13. *@Note
  14. DHCP example, demonstrating that DHCP automatically obtains an IP address.
  15. For details on the selection of engineering chips,
  16. please refer to the "CH32V20x Evaluation Board Manual" under the CH32V20xEVT\EVT\PUB folder.
  17. */
  18. #include "string.h"
  19. #include "eth_driver.h"
  20. u8 MACAddr[6]; //MAC address
  21. u8 IPAddr[4] = {0, 0, 0, 0}; //IP address
  22. u8 GWIPAddr[4] = {0, 0, 0, 0}; //Gateway IP address
  23. u8 IPMask[4] = {0, 0, 0, 0}; //subnet mask
  24. u8 DESIP[4] = {192, 168, 1, 100}; //destination IP address
  25. u16 desport = 1000; //destination port
  26. u16 srcport = 1000; //source port
  27. u8 SocketId;
  28. u8 SocketRecvBuf[WCHNET_MAX_SOCKET_NUM][RECE_BUF_LEN]; //socket receive buffer
  29. u8 MyBuf[RECE_BUF_LEN];
  30. /*********************************************************************
  31. * @fn mStopIfError
  32. *
  33. * <a href="https://bbs.eeworld.com.cn/home.php?mod=space&uid=159083" target="_blank">@brief</a> check if error.
  34. *
  35. * @param iError - error constants.
  36. *
  37. * <a href="https://bbs.eeworld.com.cn/home.php?mod=space&uid=784970" target="_blank">@return</a> none
  38. */
  39. void mStopIfError(u8 iError)
  40. {
  41. if (iError == WCHNET_ERR_SUCCESS)
  42. return;
  43. printf("Error: %02X\r\n", (u16) iError);
  44. }
  45. /*********************************************************************
  46. * @fn TIM2_Init
  47. *
  48. * @brief Initializes TIM2.
  49. *
  50. * @return none
  51. */
  52. void TIM2_Init(void)
  53. {
  54. TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure = {0};
  55. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
  56. TIM_TimeBaseStructure.TIM_Period = SystemCoreClock / 1000000;
  57. TIM_TimeBaseStructure.TIM_Prescaler = WCHNETTIMERPERIOD * 1000 - 1;
  58. TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  59. TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  60. TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
  61. TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
  62. TIM_Cmd(TIM2, ENABLE);
  63. TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
  64. NVIC_SetPriority(TIM2_IRQn, 0x80);
  65. NVIC_EnableIRQ(TIM2_IRQn);
  66. }
  67. /*********************************************************************
  68. * @fn WCHNET_CreateTcpSocket
  69. *
  70. * @brief Create TCP Socket
  71. *
  72. * @return none
  73. */
  74. void WCHNET_CreateTcpSocket(void)
  75. {
  76. u8 i;
  77. SOCK_INF TmpSocketInf;
  78. memset((void *) &TmpSocketInf, 0, sizeof(SOCK_INF));
  79. memcpy((void *) TmpSocketInf.IPAddr, DESIP, 4);
  80. TmpSocketInf.DesPort = desport;
  81. TmpSocketInf.SourPort = srcport++;
  82. TmpSocketInf.ProtoType = PROTO_TYPE_TCP;
  83. TmpSocketInf.RecvBufLen = RECE_BUF_LEN;
  84. i = WCHNET_SocketCreat(&SocketId, &TmpSocketInf);
  85. printf("WCHNET_SocketCreat %d\r\n", SocketId);
  86. mStopIfError(i);
  87. i = WCHNET_SocketConnect(SocketId); //make a TCP connection
  88. mStopIfError(i);
  89. }
  90. /*********************************************************************
  91. * @fn WCHNET_DataLoopback
  92. *
  93. * @brief Data loopback function.
  94. *
  95. * @param id - socket id.
  96. *
  97. * @return none
  98. */
  99. void WCHNET_DataLoopback(u8 id)
  100. {
  101. #if 1
  102. u8 i;
  103. u32 len;
  104. u32 endAddr = SocketInf[id].RecvStartPoint + SocketInf[id].RecvBufLen; //Receive buffer end address
  105. if ((SocketInf[id].RecvReadPoint + SocketInf[id].RecvRemLen) > endAddr) { //Calculate the length of the received data
  106. len = endAddr - SocketInf[id].RecvReadPoint;
  107. }
  108. else {
  109. len = SocketInf[id].RecvRemLen;
  110. }
  111. i = WCHNET_SocketSend(id, (u8 *) SocketInf[id].RecvReadPoint, &len); //send data
  112. if (i == WCHNET_ERR_SUCCESS) {
  113. WCHNET_SocketRecv(id, NULL, &len); //Clear sent data
  114. }
  115. #else
  116. u32 len, totallen;
  117. u8 *p = MyBuf, TransCnt = 255;
  118. len = WCHNET_SocketRecvLen(id, NULL); //query length
  119. printf("Receive Len = %d\r\n", len);
  120. totallen = len;
  121. WCHNET_SocketRecv(id, MyBuf, &len); //Read the data of the receive buffer into MyBuf
  122. while(1){
  123. len = totallen;
  124. WCHNET_SocketSend(id, p, &len); //Send the data
  125. totallen -= len; //Subtract the sent length from the total length
  126. p += len; //offset buffer pointer
  127. if( !--TransCnt ) break; //Timeout exit
  128. if(totallen) continue; //If the data is not sent, continue to send
  129. break; //After sending, exit
  130. }
  131. #endif
  132. }
  133. /*********************************************************************
  134. * @fn WCHNET_HandleSockInt
  135. *
  136. * @brief Socket Interrupt Handle
  137. *
  138. * @param socketid - socket id.
  139. * intstat - interrupt status
  140. *
  141. * @return none
  142. */
  143. void WCHNET_HandleSockInt(u8 socketid, u8 intstat)
  144. {
  145. if (intstat & SINT_STAT_RECV) //receive data
  146. {
  147. WCHNET_DataLoopback(socketid); //Data loopback
  148. }
  149. if (intstat & SINT_STAT_CONNECT) //connect successfully
  150. {
  151. WCHNET_ModifyRecvBuf(socketid, (u32) SocketRecvBuf[socketid], RECE_BUF_LEN);
  152. printf("TCP Connect Success\r\n");
  153. }
  154. if (intstat & SINT_STAT_DISCONNECT) //disconnect
  155. {
  156. printf("TCP Disconnect\r\n");
  157. }
  158. if (intstat & SINT_STAT_TIM_OUT) //timeout disconnect
  159. {
  160. printf("TCP Timeout\r\n");
  161. WCHNET_CreateTcpSocket();
  162. }
  163. }
  164. /*********************************************************************
  165. * @fn WCHNET_HandleGlobalInt
  166. *
  167. * @brief Global Interrupt Handle
  168. *
  169. * @return none
  170. */
  171. void WCHNET_HandleGlobalInt(void)
  172. {
  173. u8 intstat;
  174. u16 i;
  175. u8 socketint;
  176. intstat = WCHNET_GetGlobalInt(); //get global interrupt flag
  177. if (intstat & GINT_STAT_UNREACH) //Unreachable interrupt
  178. {
  179. printf("GINT_STAT_UNREACH\r\n");
  180. }
  181. if (intstat & GINT_STAT_IP_CONFLI) //IP conflict
  182. {
  183. printf("GINT_STAT_IP_CONFLI\r\n");
  184. }
  185. if (intstat & GINT_STAT_PHY_CHANGE) //PHY status change
  186. {
  187. i = WCHNET_GetPHYStatus();
  188. if (i & PHY_Linked_Status)
  189. printf("PHY Link Success\r\n");
  190. }
  191. if (intstat & GINT_STAT_SOCKET) { //socket related interrupt
  192. for (i = 0; i < WCHNET_MAX_SOCKET_NUM; i++) {
  193. socketint = WCHNET_GetSocketInt(i);
  194. if (socketint)
  195. WCHNET_HandleSockInt(i, socketint);
  196. }
  197. }
  198. }
  199. /*********************************************************************
  200. * @fn WCHNET_DHCPCallBack
  201. *
  202. * @brief DHCPCallBack
  203. *
  204. * @param status - status returned by DHCP
  205. * 0x00 - Success
  206. * 0x01 - Failure
  207. * arg - Data returned by DHCP
  208. *
  209. * @return DHCP status
  210. */
  211. u8 WCHNET_DHCPCallBack(u8 status, void *arg)
  212. {
  213. u8 *p;
  214. u8 tmp[4] = {0, 0, 0, 0};
  215. if(!status)
  216. {
  217. p = arg;
  218. printf("DHCP Success\r\n");
  219. /*If the obtained IP is the same as the last IP, exit this function.*/
  220. if(!memcmp(IPAddr, p ,sizeof(IPAddr)))
  221. return READY;
  222. /*Determine whether it is the first successful IP acquisition*/
  223. if(memcmp(IPAddr, tmp ,sizeof(IPAddr))){
  224. /*The obtained IP is different from the last value,
  225. * then disconnect the last connection.*/
  226. WCHNET_SocketClose(SocketId, TCP_CLOSE_NORMAL);
  227. }
  228. memcpy(IPAddr, p, 4);
  229. memcpy(GWIPAddr, &p[4], 4);
  230. memcpy(IPMask, &p[8], 4);
  231. printf("IPAddr = %d.%d.%d.%d \r\n", (u16)IPAddr[0], (u16)IPAddr[1],
  232. (u16)IPAddr[2], (u16)IPAddr[3]);
  233. printf("GWIPAddr = %d.%d.%d.%d \r\n", (u16)GWIPAddr[0], (u16)GWIPAddr[1],
  234. (u16)GWIPAddr[2], (u16)GWIPAddr[3]);
  235. printf("IPMask = %d.%d.%d.%d \r\n", (u16)IPMask[0], (u16)IPMask[1],
  236. (u16)IPMask[2], (u16)IPMask[3]);
  237. printf("DNS1: %d.%d.%d.%d \r\n", p[12], p[13], p[14], p[15]);
  238. printf("DNS2: %d.%d.%d.%d \r\n", p[16], p[17], p[18], p[19]);
  239. WCHNET_CreateTcpSocket(); //Create a TCP connection
  240. return READY;
  241. }
  242. else
  243. {
  244. printf("DHCP Fail %02x \r\n", status);
  245. /*Determine whether it is the first successful IP acquisition*/
  246. if(memcmp(IPAddr, tmp ,sizeof(IPAddr))){
  247. /*The obtained IP is different from the last value*/
  248. WCHNET_SocketClose(SocketId, TCP_CLOSE_NORMAL);
  249. }
  250. return NoREADY;
  251. }
  252. }
  253. /*********************************************************************
  254. * @fn main
  255. *
  256. * @brief Main program
  257. *
  258. * @return none
  259. */
  260. int main(void)
  261. {
  262. u8 i;
  263. Delay_Init();
  264. USART_Printf_Init(115200); //USART initialize
  265. printf("DHCP Test\r\n");
  266. if((SystemCoreClock == 60000000) || (SystemCoreClock == 120000000))
  267. printf("SystemClk:%d\r\n", SystemCoreClock);
  268. else
  269. printf("Error: Please choose 60MHz and 120MHz clock when using Ethernet!\r\n");
  270. printf("net version:%x\n", WCHNET_GetVer());
  271. if( WCHNET_LIB_VER != WCHNET_GetVer()){
  272. printf("version error.\n");
  273. }
  274. WCHNET_GetMacAddr(MACAddr); //get the chip MAC address
  275. printf("mac addr:");
  276. for(i = 0; i < 6; i++)
  277. printf("%x ", MACAddr<i>);
  278. printf("\n");
  279. TIM2_Init();
  280. WCHNET_DHCPSetHostname("WCHNET"); //Configure DHCP host name
  281. i = ETH_LibInit(IPAddr,GWIPAddr,IPMask,MACAddr); //Ethernet library initialize
  282. mStopIfError(i);
  283. if(i == WCHNET_ERR_SUCCESS)
  284. printf("WCHNET_LibInit Success\r\n");
  285. WCHNET_DHCPStart(WCHNET_DHCPCallBack); //Start DHCP
  286. while(1)
  287. {
  288. /*Ethernet library main task function,
  289. * which needs to be called cyclically*/
  290. WCHNET_MainTask();
  291. /*Query the Ethernet global interrupt,
  292. * if there is an interrupt, call the global interrupt handler*/
  293. if(WCHNET_QueryGlobalInt())
  294. {
  295. WCHNET_HandleGlobalInt();
  296. }
  297. }
  298. }

运行程序

运行程序后,插入网线,并重启设备,等待10秒左右,可以看到设备已获取到IP地址,如下图

在电脑上使用ps shell来ping板子,可以看到可以顺利连上板子

WCH官方库调用起来是挺简单的,官方给的demo也很好,可以快速帮开发者熟悉网络库的使用,整体体验下来还是挺舒服的。

此帖出自无线连接论坛

最新回复

我也有这个单片机, 能不能每次写完代码分享一下工程文件. 也好互相学习下   详情 回复 发表于 2024-8-6 03:18
点赞(1) 关注
 

回复
举报

7209

帖子

11

TA的资源

版主

沙发
 

WCH官方库调用起来是挺简单的,官方给的demo也很好,可以快速帮开发者熟悉网络库的使用,整体体验下来还是挺舒服的。

确实非常好的一家公司。

此帖出自无线连接论坛
 
 

回复

225

帖子

4

TA的资源

纯净的硅(初级)

板凳
 

我也有这个单片机, 能不能每次写完代码分享一下工程文件. 也好互相学习下

此帖出自无线连接论坛

点评

我这边运行的都是官方提供的SDK里面的demo呀,并不是自己写的代码  详情 回复 发表于 2024-8-6 10:43
 
 
 

回复

283

帖子

2

TA的资源

纯净的硅(初级)

4
 
御坂10032号 发表于 2024-8-6 03:18 我也有这个单片机, 能不能每次写完代码分享一下工程文件. 也好互相学习下

我这边运行的都是官方提供的SDK里面的demo呀,并不是自己写的代码

此帖出自无线连接论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
快速回复 返回顶部 返回列表