1.lwip介绍 lwip是瑞典计算机科学院网络嵌入式系统小组(sics)的adam dunkels(亚当·邓克尔) 开发的一个小型开源的tcp/ip协议栈。实现的重点是在保持 tcp 协议主要功能的基础上减少对ram的占用。
lwip是light weight(轻型)ip 协议,有无操作系统的支持都可以运行。lwip 实现的重点是在保持tcp协议 主要功能的基础上减少对ram的占用,它只需十几kb的ram和 40k左右的rom就可以运行,这使lwip协议栈适合在低端的嵌入式系统中使用。lwip提供三种api:
raw api (netconn)lwip api bsd api 2.lwip源码下载 源码下载地址:lwip源码
3 lwip源码移植 这里以1.4.1为例。
1.解压文件
2.打开已完成dm9000驱动的工程,在工程中创建lwip文件夹,在lwip文件夹中创建src文件夹和lwip1.4_config文件夹:
3.将lwip-1.4.1源码中的src中所有文件复制到用户创建的src中:
4.复制contrib中文件
5.删除不必要文件
6.打开工程,添加.c文件到工程中
7.添加.h文件路径
8.编译工程
9.修改sys_arch.c文件,只保留下面函数,其它全部删除。
10.修改lwipopts.h文件
11.修改ethernetif.c文件
4.lwip协议栈使用示例之 — 获取动态ip 在lwip_confg目录下创建lwip_config.c和lwip_config.h文件
lwip_config.c文件:
#include lwip_config.h#include lwip/ip_addr.h#include lwip/init.h#include lwip/netif.h#include netif/etharp.h#include lwip/dhcp.h#include lwip/tcp_impl.hextern err_t ethernetif_init(struct netif *netif);//网卡初始化函数,原型在ethernetif.c中extern void ethernetif_input(struct netif *netif);/**************lwip协议栈初始化***********/struct netif lwip_netif; //结构体原型在lwip/netif.h中void lwip_config_init(void){ ip_addr_t ip_addr={0};//ip地址 ip_addr_t netmask={0};//子网掩码 ip_addr_t gw={0};//网关 /*静态分配ip*/// ip4_addr(&ip_addr,192,168,12,23);//设置静态ip// ip4_addr(&netmask,255,255,255,0);//子网掩码// ip4_addr(&netmask,192,168,12,1);//网关 /*1.lwip协议栈初始化*/ lwip_init(); /*2.添加新的网卡设备到lwip协议栈中*/ /*err_t ethernet_input(struct pbuf *p, struct netif *netif)处理已经读取从硬件接口发来的一个数据包*/ netif_add(&lwip_netif,&ip_addr,&netmask,&gw,null,ethernetif_init,ethernet_input); /*3.设置网卡为lwip协议栈默认设备*/ netif_set_default(&lwip_netif); /*4.注册网卡设备为默认接口*/ netif_set_up(&lwip_netif); /*5.动态分配ip*/ dhcp_start(&lwip_netif);}/*****dhcp定期数据处理函数(轮询方式实现数据更新)****/u32 lwip_tcp_time_cnt=0;u32 lwip_arp_time_cnt=0;u32 lwip_dhcp_time_cnt=0;u32 lwip_update_dhcp_time_cnt=0;u8 lwip_dhcp_stat=0;void lwip_dataupdata(void){ /*250ms 更新一次*/ if(lwip_tcp_time_cnt>=tcp_tmr_interval) { lwip_tcp_time_cnt=0; tcp_tmr(); //对 tcp 数据进行解析 } /*5000ms 更新一次*/ if(lwip_arp_time_cnt>=arp_tmr_interval) { lwip_arp_time_cnt=0; etharp_tmr();//清理 arp 缓存表 } //500ms获取一次 if(lwip_dhcp_time_cnt>=dhcp_fine_timer_msecs ) { lwip_dhcp_time_cnt=0; dhcp_fine_tmr(); //解析 dhcp 请求,判断 ip 地址是否获取成功 } /*60s 更新一次*/ if(lwip_update_dhcp_time_cnt>=dhcp_coarse_timer_msecs) { lwip_update_dhcp_time_cnt=0; dhcp_coarse_tmr(); //更新检查 dhcp 的租约时间 } ethernetif_input(&lwip_netif); //读取网卡的数据进行上报 if(lwip_dhcp_stat==0) { lwip_getdhcp_addr(); }}/******获取动态分配的ip地址*************/void lwip_getdhcp_addr(void){ char buff[200]; u32 ip_addr;//ip地址 u32 netmask;//子网掩码 u32 gw;//网关 ip_addr=lwip_netif.ip_addr.addr;//ip地址 netmask=lwip_netif.netmask.addr;//子网掩码 gw=lwip_netif.gw.addr; if(ip_addr!=0) { lwip_dhcp_stat=1;//成功获取到ip地址 printf(ip地址:%d.%d.%d.%drn,(ip_addr>>0)&0xff,(ip_addr>>8)&0xff,(ip_addr>>16)&0xff,(ip_addr>>24)&0xff); snprintf(buff,sizeof(buff),ip地址:%d.%d.%d.%d,(ip_addr>>0)&0xff,(ip_addr>>8)&0xff,(ip_addr>>16)&0xff,(ip_addr>>24)&0xff); lcd_showstr(30,30+20*4,16,(u8 *)buff);//ip地址 printf(子网掩码:%d.%d.%d.%drn,(netmask>>0)&0xff,(netmask>>8)&0xff,(netmask>>16)&0xff,(netmask>>24)&0xff); snprintf(buff,sizeof(buff),子网掩码:%d.%d.%d.%drn,(netmask>>0)&0xff,(netmask>>8)&0xff,(netmask>>16)&0xff,(netmask>>24)&0xff); lcd_showstr(30,30+20*5,16,(u8 *)buff);//子网掩码 printf(网关:%d.%d.%d.%drn,(gw>>0)&0xff,(gw>>8)&0xff,(gw>>16)&0xff,(gw>>24)&0xff); snprintf(buff,sizeof(buff),网关:%d.%d.%d.%drn,(gw>>0)&0xff,(gw>>8)&0xff,(gw>>16)&0xff,(gw>>24)&0xff); lcd_showstr(30,30+20*6,16,(u8 *)buff);//子网掩码 }} 5.主函数#include dm9000.h#include lwip_config.hu8 dm9000_tx_buff[64]={0x11,0x22,0x33,0x44,0x55};u8 dm9000_rx_buff[1024];int main(){ char buff[200]; u8 stat; beep_init(); led_init(); key_init(); w25q64_init(); usartx_init(usart1,115200,72); timx_init(tim2,72,20*1000); iic_init(); printf(初始化完成rn); nt35310_init(); /*dm9000初始化*/ lcd_showstr(30,30,16,dm9000初始化中。。。);//显示字符串 if(dm9000_init()==0) { printf(dm9000初始化成功rn); lcd_showstr(30,30+20,16,dm9000t ok!);//显示字符串 } else { printf(dm9000初始化失败rn); lcd_showstr(30,30+20,16,dm9000t err!);//显示字符串 } /*获取dm9000工作模式*/ lcd_showstr(128,30+20*2,16,网卡信息);//显示字符串 stat=dm9000_get_speedandduplex();//获取连接状态和工作方式 if(stat!=0xff) { printf(网卡速度:%d mbps 模式:%srn,(stat&0x02)?10:100,(stat&0x01)?全双工:半双工); snprintf(buff,sizeof(buff),网卡速度:%d mhzt %s,(stat&0x02)?10:100,(stat&0x01)?全双工:半双工); lcd_showstr(30,30+20*3,16,(u8 *)buff);//网卡速度 } else { printf(dm9000网卡状态信息获取失败!rn); lcd_showstr(30,30+20*3,16,(u8 *)获取网卡信息失败!);//网卡速度 } lwip_config_init();//lwip协议栈初始化 timx_init(tim6,72,1000); tim6->cr1|=1<<0; while(1) { lwip_dataupdata(); }} 6.运行效果
贸泽电子2022年新增超55家供应商 进一步扩大产品分销阵容
专业PCB软件中一致界面的优点
蓝牙耳机戴久了耳朵疼、推荐几款佩戴舒适的蓝牙耳机
印度批准塔塔建设ATMP工厂
从工业互联网平台标杆Predix的商业模式看我国工业互联网平台发展
STM32之LWIP网络协议栈移植步骤与方案
搭载MediaTek 天玑1000+的Redmi K30至尊纪念版
Flex电源模块宣布BMR466和BMR461 DC/DC电源模块具备BGA和LGA两种封装
上海推出的电子墨水屏站牌产品,被誉为“等车神器”
魅族16T或将下月发布,搭载高通骁龙855旗舰平台
通往真正合乎道德的AI之路是困难的
无线充电功能技术-LG_V30:IPhone做得到,我们也能做得到!将于8月正式上市
英特尔全面布局5G 产品,顺利提供客戶5G数据解決方案
小米前副总裁崔宝秋出任RISC-V厂商进迭时空首席技术顾问
FPGA开发板与25美分的硬币,你看出了什么?
科创板嘉元科技独立董事孙世民介绍、履历信息
波特率与比特率的区别在哪?二者又有何关系呢?
希氏异构展示了其最新的AI技术和医疗行业的应用解决方案
STM32 CAN总线筛选器的四种情况
基于西门子S7-200CPU224 PLC器件实现多段电阻炉炉温控制系统的设计