这里会显示出您选择的修订版和当前版本之间的差别。
两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
lan_dhcp实验_动态分配ip地址 [2020/07/09 22:06] zgf |
lan_dhcp实验_动态分配ip地址 [2022/03/22 10:24] sean |
||
---|---|---|---|
行 2: | 行 2: | ||
|技术支持电话|**0379-69926675-801**||| | |技术支持电话|**0379-69926675-801**||| | ||
|技术支持邮件|Gingko@vip.163.com||| | |技术支持邮件|Gingko@vip.163.com||| | ||
- | |技术论坛|http://www.eeschool.org||| | ||
^ 版本 ^ 日期 ^ 作者 ^ 修改内容 ^ | ^ 版本 ^ 日期 ^ 作者 ^ 修改内容 ^ | ||
| V1.0 | 2020-07-09 | gingko | 初次建立 | | | V1.0 | 2020-07-09 | gingko | 初次建立 | | ||
行 17: | 行 16: | ||
==== 二、 实验设备及平台 ==== | ==== 二、 实验设备及平台 ==== | ||
- | - iCore4 双核心板。 | + | - iCore4 双核心板[[https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w4004-22598974120.15.5923532fsFrHiE&id=551864196684|点击购买]]。 |
- | - JLINK(或相同功能)仿真器。 | + | - JLINK(或相同功能)仿真器[[https://item.taobao.com/item.htm?id=554869837940|点击购买]]。 |
- Micro USB线缆。 | - Micro USB线缆。 | ||
- 网线。 | - 网线。 | ||
行 61: | 行 60: | ||
* LAN8720A功能框图如图所示: | * LAN8720A功能框图如图所示: | ||
+ | {{ :icore4:icore4_arm_hal_24_1.png?direct |}} | ||
* LAN8720A是低功耗的10/100M以太网PHY层芯片,I/O引脚电压符合IEEE802.3-2005标准,支持通过RMII接口与以太网MAC层通信,内置10-BASE-T/100BASE-TX全双工传输模块,支持10Mbps和100Mbps。 | * LAN8720A是低功耗的10/100M以太网PHY层芯片,I/O引脚电压符合IEEE802.3-2005标准,支持通过RMII接口与以太网MAC层通信,内置10-BASE-T/100BASE-TX全双工传输模块,支持10Mbps和100Mbps。 | ||
* LAN8720A可以通过自协商的方式与目的主机最佳的连接方式(速度和双工模式),支持HPAuto-MDIX自动翻转功能,无需更换网线即可将连接更改为直连或交叉连接。LAN8720A的主要特点如下: | * LAN8720A可以通过自协商的方式与目的主机最佳的连接方式(速度和双工模式),支持HPAuto-MDIX自动翻转功能,无需更换网线即可将连接更改为直连或交叉连接。LAN8720A的主要特点如下: | ||
行 76: | 行 75: | ||
* iCore4带有lan8720a嵌入式以太网控制器,本实验实现DHCP功能。当DHCP服务器接收到来自主机申请地址的信息时,DHCP服务器给主机指定一个具有时间限制的IP地址,时间到期或主机明确表示放弃该地址时,该地址可以被其他主机使用。实验原理图如下: | * iCore4带有lan8720a嵌入式以太网控制器,本实验实现DHCP功能。当DHCP服务器接收到来自主机申请地址的信息时,DHCP服务器给主机指定一个具有时间限制的IP地址,时间到期或主机明确表示放弃该地址时,该地址可以被其他主机使用。实验原理图如下: | ||
- | + | {{ :icore4:icore4_arm_hal_24_2.png?direct |}} | |
==== 四、 实验程序 ==== | ==== 四、 实验程序 ==== | ||
=== 1、主函数 === | === 1、主函数 === | ||
+ | <code c> | ||
+ | int main(void) | ||
+ | { | ||
+ | system_clock.initialize(); //系统时钟初始化 | ||
+ | led.initialize(); //LED初始化 | ||
+ | adc.initialize(); //ADC初始化 | ||
+ | delay.initialize(216); //延时初始化 | ||
+ | my_malloc.initialize(SRAMIN); //动态内存初始化 | ||
+ | usart6.initialize(115200); //串口波特设置 | ||
+ | usart6.printf("\033[1;32;40m"); //设置字体终端为绿色 | ||
+ | usart6.printf("\r\nHello, I am iCore4!\r\n\r\n"); //串口信息输出 | ||
+ | OSInit(); //UCOS初始化 | ||
+ | | ||
+ | while(lwip.initialize()) //lwip初始化 | ||
+ | { | ||
+ | LED_RED_ON; | ||
+ | usart6.printf("\r\nETH initialize error!\r\n\r\n");//ETH初始化失败 | ||
+ | } | ||
+ | tcp.initialize(); | ||
+ | OSTaskCreate(start_task,(void*)0,(OS_STK*)&START_TASK_STK[START_STK_SIZE-1],START_TASK_PRIO); | ||
+ | OSStart(); //开启UCOS | ||
+ | } | ||
+ | </code> | ||
=== 2、动态内存初始化 === | === 2、动态内存初始化 === | ||
+ | <code c> | ||
+ | void my_mem_init(u8 memx) | ||
+ | { | ||
+ | mymemset(mallco_dev.memmap[memx],0,memtblsize[memx]*4); | ||
+ | //内存状态表数据清零 | ||
+ | mallco_dev.memrdy[memx]=1; | ||
+ | //内存管理初始化OK | ||
+ | } | ||
+ | </code> | ||
=== 3、LWIP初始化 === | === 3、LWIP初始化 === | ||
+ | <code c> | ||
+ | u8 lwip_comm_init(void) | ||
+ | { | ||
+ | OS_CPU_SR cpu_sr; | ||
+ | struct netif *Netif_Init_Flag; //调用netif_add()函数时的返回值,用于判断网络初始化是否成功 | ||
+ | struct ip_addr ipaddr; //ip地址 | ||
+ | struct ip_addr netmask; //子网掩码 | ||
+ | struct ip_addr gw; //默认网关 | ||
+ | if(lan8720.memory_malloc())return 1; //内存申请失败 | ||
+ | if(lwip_comm_mem_malloc())return 1; //内存申请失败 | ||
+ | if(lan8720.initialize())return 2; //初始化LAN8720失败 | ||
+ | tcpip_init(NULL,NULL); //初始化tcp ip内核,该函数里面会创建tcpip_thread内核任务 | ||
+ | lwip_comm_default_ip_set(&lwipdev); //设置默认IP等信息 | ||
+ | #if LWIP_DHCP //使用动态IP | ||
+ | ipaddr.addr = 0; | ||
+ | netmask.addr = 0; | ||
+ | gw.addr = 0; | ||
+ | #else //使用静态IP | ||
+ | IP4_ADDR(&ipaddr,lwipdev.ip[0],lwipdev.ip[1],lwipdev.ip[2],lwipdev.ip[3]); | ||
+ | IP4_ADDR(&netmask,lwipdev.netmask[0],lwipdev.netmask[1] ,lwipdev.netmask[2],lwipdev.netmask[3]); | ||
+ | IP4_ADDR(&gw,lwipdev.gateway[0],lwipdev.gateway[1],lwipdev.gateway[2],lwipdev.gateway[3]); | ||
+ | usart6.printf("网卡en的MAC地址为:................%d.%d.%d.%d.%d.%d\r\n",lwipdev.mac[0],lwipdev.mac[1],lwipdev.mac[2],lwipdev.mac[3],lwipdev.mac[4],lwipdev.mac[5]); | ||
+ | usart6.printf("静态IP地址........................%d.%d.%d.%d\r\n",lwipdev.ip[0],lwipdev.ip[1],lwipdev.ip[2],lwipdev.ip[3]); | ||
+ | usart6.printf("子网掩码..........................%d.%d.%d.%d\r\n",lwipdev.netmask[0],lwipdev.netmask[1],lwipdev.netmask[2],lwipdev.netmask[3]); | ||
+ | usart6.printf("默认网关..........................%d.%d.%d.%d\r\n",lwipdev.gateway[0],lwipdev.gateway[1],lwipdev.gateway[2],lwipdev.gateway[3]); | ||
+ | #endif | ||
+ | Netif_Init_Flag=netif_add(&lwip_netif,&ipaddr,&netmask,&gw,NULL,ðernetif_init,&tcpip_input);//向网卡列表中添加一个网口 | ||
- | + | #if LWIP_DNS | |
- | + | dns_init(); | |
+ | #endif | ||
+ | if(Netif_Init_Flag==NULL)return 3;//网卡添加失败 | ||
+ | else//网口添加成功后,设置netif为默认值,并且打开netif网口 | ||
+ | { | ||
+ | netif_set_default(&lwip_netif); //设置netif为默认网口 | ||
+ | netif_set_up(&lwip_netif); //打开netif网口 | ||
+ | } | ||
+ | return 0;//操作OK. | ||
+ | } | ||
+ | |||
+ | </code> | ||
=== 4、TCP初始化 === | === 4、TCP初始化 === | ||
+ | <code c> | ||
+ | static INT8U tcp_server_init(void)//创建TCP服务器线程 | ||
+ | { | ||
+ | INT8U res; | ||
+ | OS_CPU_SR cpu_sr; | ||
+ | |||
+ | OS_ENTER_CRITICAL(); //关中断 | ||
+ | res = OSTaskCreate(tcp_server_thread,(void*)0,(OS_STK*)&TCPSERVER_TASK_STK[TCPSERVER_STK_SIZE-1],TCPSERVER_PRIO); //创建TCP服务器线程 | ||
+ | OS_EXIT_CRITICAL(); //开中断 | ||
+ | |||
+ | return res;//返回值:0 TCP服务器创建成功 | ||
+ | } | ||
+ | </code> | ||
=== 5、TCP服务器任务 === | === 5、TCP服务器任务 === | ||
+ | <code c> | ||
+ | static void tcp_server_thread(void *arg)//tcp服务器任务 | ||
+ | { | ||
+ | struct netconn *conn, *newconn; | ||
+ | err_t err,recv_err; | ||
+ | unsigned char remot_addr[4]; | ||
+ | ip_addr_t ipaddr; | ||
+ | unsigned short port; | ||
+ | struct netbuf *recvbuf; | ||
- | + | LWIP_UNUSED_ARG(arg); | |
- | + | ||
+ | conn = netconn_new(NETCONN_TCP); //创建一个TCP链接 | ||
+ | netconn_bind(conn,IP_ADDR_ANY,TCP_SERVER_PORT); //绑定端口 8088号端口 | ||
+ | netconn_listen(conn); //进入监听模式 | ||
+ | |||
+ | while(1){ | ||
+ | err = netconn_accept(conn,&newconn); //接收连接请求 | ||
+ | |||
+ | if (err == ERR_OK) //处理新连接的数据 | ||
+ | { | ||
+ | newconn->recv_timeout = 10; | ||
+ | netconn_getaddr(newconn,&ipaddr,&port,0); //获取远端IP地址和端口号 | ||
+ | remot_addr[3] = (uint8_t)(ipaddr.addr >> 24); | ||
+ | remot_addr[2] = (uint8_t)(ipaddr.addr >> 16); | ||
+ | remot_addr[1] = (uint8_t)(ipaddr.addr >> 8); | ||
+ | remot_addr[0] = (uint8_t)(ipaddr.addr); | ||
+ | usart6.printf("pc ip : %d.%d.%d.%dserver,lacol port:%d\r\n",remot_addr[0], remot_addr[1],remot_addr[2],remot_addr[3],port); | ||
+ | while(1) | ||
+ | { | ||
+ | recv_err = netconn_recv(newconn,&recvbuf); | ||
+ | if((recv_err == ERR_OK)||(recvbuf != NULL)) //接收到数据 | ||
+ | { | ||
+ | recv_err = netconn_write(newconn ,recvbuf->p->payload,recvbuf->p->len,NETCONN_NOCOPY); //将接受到的数据原封不动的再发出去 | ||
+ | |||
+ | netbuf_delete(recvbuf); | ||
+ | }else if(recv_err == ERR_CLSD){ //关闭连接 | ||
+ | netconn_close(newconn); | ||
+ | netconn_delete(newconn); | ||
+ | usart6.printf("lacol ip :%d.%d.%d.%d close connect\r\n",remot_addr[0], remot_addr[1],remot_addr[2],remot_addr[3]); | ||
+ | break; | ||
+ | }else if(recv_err == ERR_MEM) //内存错误,请稍后再试 | ||
+ | { | ||
+ | OSTimeDlyHMSM(0,0,0,5); //延时5ms | ||
+ | }else OSTimeDlyHMSM(0,0,0,5); //延时5ms | ||
+ | } | ||
+ | }else OSTimeDlyHMSM(0,0,0,5); //延时5ms | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </code> | ||
==== 五、 实验步骤 ==== | ==== 五、 实验步骤 ==== | ||
行 109: | 行 237: | ||
* 实通过串口终端显示出信息。 | * 实通过串口终端显示出信息。 | ||
- | + | {{ :icore4:icore4_arm_hal_24_3.png?direct |}} | |