CH32V307教程[第九集][以太网]

您所在的位置:网站首页 苹果千兆以太网端口 CH32V307教程[第九集][以太网]

CH32V307教程[第九集][以太网]

2024-07-15 16:11| 来源: 网络整理| 查看: 265

赤兔开发板以太网模块使用教程 一、基本介绍

大家好,这里是Verimake,今天给大家介绍下赤兔以太网配件的使用方法。 开始之前我们先来看下赤兔开发板上这款主控CH32V307VCT6芯片手册, 从手册上我们可以看到,307内部有1G和10M的以太网,这里要注意下,1G是不含有物理层PHY的,如果需要使用是需要外部PHY芯片的,通过相应的接口来控制的,而10M是307内部就有PHY,我们将10M的接口引出连接网口就是我们的以太网模块。 通过数据手册我们可以看到如果需要使用1G则需要通过RGMII接口连接一款千兆的芯片,由于赤兔的开发板设计我们没有将RGMII接口引出,所以没有做这样的以太网设计。 接下来我们看下设备的连接: 模块通过FFC的软排线引出和赤兔开发板的摄像头接口相连接,这里只要注意排线的安装不要装反即可,正确方向如图所示。连接后模块不需要单独供电。通过RJ-45接头的网线可以将赤兔连接到电脑、交换机或者路由器上,在局域网中就可以访问到赤兔,可以接收赤兔发送的数据,也可以给赤兔下发数据或者控制,也可以通过网线进行赤兔和赤兔之间通信。下面我们先介绍PC和赤兔之间的通信。

二、样例演示

首先我们打开沁恒提供的EVT样例里面的ETH目录下有网口的相关例程,我们先打开TCPClient的例程,该例程是赤兔开发板作为客户端,登录网络中的TCPServer端,和服务端建立TCP连接后就可以将服务端发送的信息接收下来,然后再通过TCP发送给服务端。这个例程开始使用前需要将一些地方进行修改,主要是网口上的两个灯控制口需要更改为PB8和PB9。 修改如下:

void Ethernet_LED_Configuration(void) { GPIO_InitTypeDef GPIO={0}; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //修改为B口 GPIO.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9; //修改为8和9口 GPIO.GPIO_Mode = GPIO_Mode_Out_PP; GPIO.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB,&GPIO); Ethernet_LED_LINKSET(1); Ethernet_LED_DATASET(1); } void Ethernet_LED_LINKSET(u8 setbit) { if(setbit){ GPIO_SetBits(GPIOB, GPIO_Pin_8); //设置PB8为1 } else { GPIO_ResetBits(GPIOB, GPIO_Pin_8); //设置PB8为0 } } void Ethernet_LED_DATASET(u8 setbit) { if(setbit){ GPIO_SetBits(GPIOB, GPIO_Pin_9); //设置PB9为1 } else { GPIO_ResetBits(GPIOB, GPIO_Pin_9); //设置PB9为0 } }

修改好之后我们编译先看看实验现象然后我们再详细学习下代码。编译好后下载代码到赤兔,通过网线连接好赤兔和PC(如果有的笔记本没有网口可以通过usb转网口的hub实现),设置PC的网口的IP地址为192.168.1.100,掩码255.255.255.0,网关192.168.1.1.连接完成后。我们在PC机上调试时候可以借助网络调试助手来测试网络通信,打开网络调试助手,设置协议类型为TCP Server,本地主机地址为192.168.1.100,如果地址下拉里面没有这个地址需要检查连接赤兔开发板的网口ip4地址设置是否是上面的要求,是否是先连接赤兔开发板再打开了软件。如果是第一种只需要按要求修改即可,如果是第二种只需要把软件关闭重新开就可以了。本地端口设置为1000.打开通信,此时网络调试助手就会收到一个连接。如图会有显示。并且可以看到连接的地址是192.168.1.10。此时点击发送,就会看见接收部分就会显示刚刚发送的信息。此外通过串口连接赤兔,还可以看到相关的连接信息。如下。 那么它是怎么工作的呢,我们接下来详细的看下它的运作过程。

三、样例解析

打开工程,我们先来看下本工程和其他工程的区别,在这个工程里多了一个NetLib的目录,里面存放了两个文件一个WCHNET.h和libwchnet.a。这是沁恒制作的网络库,WCHNET.h里面我们可以看到相关的宏定义的量以及网络控制函数。我们在使用时候就是利用这些函数即可。.a文件就是这些函数的静态库,源码这里是没有的。那么我们只需要知道如何使用就可以了。接下来我们看下main.c里面程序运行过程吧。 首先在main函数中:

int main(void) { u8 i; Delay_Init(); USART_Printf_Init(115200); /*串口打印初始化*/ printf("TcpClient Test\r\n"); SET_MCO(); //设置时钟 TIM2_Init(); //初始化定时器2 WCH_GetMac(MACAddr); /*获取芯片Mac地址*/ i=WCHNET_LibInit(IPAddr,GWIPAddr,IPMask,MACAddr); /*以太网库初始化*/ mStopIfError(i); if(i==WCHNET_ERR_SUCCESS) printf("WCHNET_LibInit Success\r\n"); while(!(WCHNET_GetPHYStatus()&PHY_LINK_SUCCESS)) /*等待PHY连接成功*/ { Delay_Ms(100); } WCHNET_CreatTcpSocket(); /*创建Tcp socket*/ while(1) { WCHNET_MainTask(); /*以太网库主任务函数,需要循环调用*/ if(WCHNET_QueryGlobalInt()) /*查询以太网全局中断,如果有中断,调用全局中断处理函数*/ { WCHNET_HandleGlobalInt(); } } }

从代码中我们可以看到,首先初始化赤兔的网络,如果网络有接入,则开始TCP连接。在while循环中以太网主任务必须要循环调用,通过查询以太网的全局中断可以判断是否有接收数据,是否还在连接中等状态,从而进行相关工作。例如例程中通过查询中断,如果有接收到数据,就会将数据发回。接下来我们看下接收到以太网全局中断函数WCHNET_HandleGlobalInt();

void WCHNET_HandleGlobalInt(void) { u8 initstat; u16 i; u8 socketinit; initstat = WCHNET_GetGlobalInt(); /* 获取全局中断标志*/ if(initstat & GINT_STAT_UNREACH) /* 不可达中断 */ { printf("GINT_STAT_UNREACH\r\n"); } if(initstat & GINT_STAT_IP_CONFLI) /* IP冲突中断 */ { printf("GINT_STAT_IP_CONFLI\r\n"); } if(initstat & GINT_STAT_PHY_CHANGE) /* PHY状态变化中断 */ { i = WCHNET_GetPHYStatus(); /* 获取PHY连接状态*/ if(i&PHY_Linked_Status) printf("PHY Link Success\r\n"); } if(initstat & GINT_STAT_SOCKET) /* scoket 产生中断 */ { for(i = 0; i < WCHNET_MAX_SOCKET_NUM; i ++) { socketinit = WCHNET_GetSocketInt(i); /* 获取socket中断并清零 */ if(socketinit)WCHNET_HandleSockInt(i,socketinit); /* socket中断查询 */ } } }

在以太网全局中断中可以查询如连接状态,不可达,socket中断等。在接收到服务器的数据后就会产生socket中断,使用WCHNET_HandleSockInt函数就可以根据socket的不同中断进行不同的操作了。

void WCHNET_HandleSockInt(u8 sockeid,u8 initstat) { u32 len; if(initstat & SINT_STAT_RECV) /* socket接收中断*/ { len = WCHNET_SocketRecvLen(sockeid,NULL); /* 获取socket缓冲区数据长度 */ printf("WCHNET_SocketRecvLen %d \r\n",len); WCHNET_SocketRecv(sockeid,MyBuf,&len); /* 获取socket缓冲区数据 */ WCHNET_SocketSend(sockeid,MyBuf,&len); /* 演示回传数据 */ } if(initstat & SINT_STAT_CONNECT) /* socket连接成功中断*/ { printf("TCP Connect Success\r\n"); } if(initstat & SINT_STAT_DISCONNECT) /* socket连接断开中断*/ { printf("TCP Disconnect\r\n"); } if(initstat & SINT_STAT_TIM_OUT) /* socket连接超时中断*/ { printf("TCP Timout\r\n"); /* 延时200ms,重连*/ Delay_Ms(200); WCHNET_CreatTcpSocket(); } }

这里我们就可以看到如果是接收中断,就会把接收的数据通过WCHNET_SocketSend(sockeid,MyBuf,&len); 再发出去。如果连接成功会打印信息,连接断开也会打印相应信息,连接超时除了会打印信息外还会重新连接。相应的全局中断和socket中断在WCHNET.h中都可以找到。如图: 那么在创建连接时候我们之前设置ip、端口等信息是在main.c开头设置的,

u8 IPAddr[4] = {192,168,1,10}; /*IP地址*/ u8 GWIPAddr[4] = {192,168,1,1}; /*网关*/ u8 IPMask[4] = {255,255,255,0}; /*子网掩码*/ u8 DESIP[4] = {192,168,1,100}; /*目的IP地址*/ u8 SocketId; /*socket id号*/ u8 SocketRecvBuf[WCHNET_MAX_SOCKET_NUM][RECE_BUF_LEN]; /*socket缓冲区*/ u8 MyBuf[RECE_BUF_LEN]; u16 desport=1000; /*目的端口号*/ u16 srcport=1000; /*源端口号*/

如果需要在局域网中有多个赤兔连接,那么各自的ip最后的值需要加以区分。

四、样例拓展

接下来我们做一点修改,尝试着不同的功能。例如将接收的内容在LCD上显示,如果接收到led on我们就将LED1打开,接收到led off我们就把LED1熄灭。 第一步:添加LCD的相关库到工程。拷贝lcd.c lcd.h font.h到User目录下。在main.c里面的main函数添加lcd初始化函数:

Delay_Init(); USART_Printf_Init(115200); /*串口打印初始化*/ printf("TcpClient Test\r\n"); lcd_init(); LCD_SetBrightness(60); lcd_set_color(WHITE, BLUE); lcd_fill(0, 0, 239, 239, WHITE); SET_MCO();

这里需要注意LCD_SetBrightness(60);里面的值越大屏幕越暗,最大100。然后我们设置背景为白色,打印字符为蓝色。 接下来在接收数据那里添加把接收的数据在lcd上显示。

if(initstat & SINT_STAT_RECV) /* socket接收中断*/ { len = WCHNET_SocketRecvLen(sockeid,NULL); /* 获取socket缓冲区数据长度 */ printf("WCHNET_SocketRecvLen %d \r\n",len); WCHNET_SocketRecv(sockeid,MyBuf,&len); /* 获取socket缓冲区数据 */ lcd_show_string(3, 10, 16," "); lcd_show_string(3, 10, 16, MyBuf); WCHNET_SocketSend(sockeid,MyBuf,&len); /* 演示回传数据 */ }

编译后,下载,我们重新发送数据,观察屏幕可以看到相应的信息。 第二步: 添加LED控制,需要首先初始化led_gpio,编写函数led_gpio();

void led_gpio(){ GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE); //设置PE11为输出管脚控制额LED1 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOE, &GPIO_InitStructure); }

然后将这个函数在main函数中进行初始化。只需要添加led_gpio();在lcd初始化下面。 然后修改接收部分,添加led控制。

if(initstat & SINT_STAT_RECV) /* socket接收中断*/ { len = WCHNET_SocketRecvLen(sockeid,NULL); /* 获取socket缓冲区数据长度 */ printf("WCHNET_SocketRecvLen %d \r\n",len); WCHNET_SocketRecv(sockeid,MyBuf,&len); /* 获取socket缓冲区数据 */ if(strncmp(MyBuf,"led on",6)==0|strncmp(MyBuf,"led off",7)==0 ) { if (strncmp(MyBuf,"led on",6)==0) { GPIO_ResetBits(GPIOE, GPIO_Pin_11); } else { GPIO_SetBits(GPIOE, GPIO_Pin_11); } } else { lcd_show_string(3, 10, 32," "); lcd_show_string(3, 10, 32, MyBuf); } WCHNET_SocketSend(sockeid,MyBuf,&len); /* 演示回传数据 */ }

这里需要注意,MyBuf每次接收完数据后是不会清空的,所以接收数据是有叠加的,所以字符比较函数要使用指定长度的strncmp(); 编译下载后,我们可以测试下,观看下效果。 自此本次的例程演示就结束了。

拓展介绍

如果需要将多个赤兔组成局域网,需要使用下面的网络结构; 图里的pc机也可以使用赤兔来作为server的角色。

目前例程里使用的是网络调试助手的工具,如果需要自己设计上位机程序,这里推荐使用python进行开发,python socket开发非常简单,简单几句就可以建设TCP Server。加上Qt的界面开发做一个有界面的网络上位机就很简单了。 此外按照EVT里面以太网的例程,我们还可以将赤兔配置为TCP Server或者使用UDP通信,这些内容和本例程非常相似,有兴趣的可以按本例程进行测试。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3