• 快乐的响板
    了解作者
  • C/C++
    开发工具
  • 9.2MB
    文件大小
  • zip
    文件格式
  • 0
    收藏次数
  • 1 积分
    下载积分
  • 0
    下载次数
  • 2021-04-27 16:43
    上传日期
使用lwip和stm32F102,实现与服务器端通信,实现服务器控制开发板。
a.zip
内容介绍
[LWIP的RAW API UDP通信详解(stm32f103---enc28j60)](https://blog.csdn.net/weixin_42149196/article/details/90246815) [项目整体托管到github上](https://github.com/WyxLOVES/LWIP-RAW-API-UDP-stm32-f103----enc28j60-) # 实现任务 通过接收到上位机端发送来的数据来实现控制开发板做相应的操作。 # 代码实现 ### 首先看看几个主要的结构体 //发送数据包 ~~~c struct sardata { u8 head[4]; //标志头 u16 length; //长度 u8 humi[2]; //温湿度传感器状态 u8 data[4]; //温度湿度数据 u8 elengine[2];//电机及状态 u8 led[3]; //led灯 }; //初始化上述结构体函数,用来发送数据包到上位机 void initsardata(void) { u8 i; sendrecv.head[0]=0x5A;//Z sendrecv.head[1]=0x4E;//N sendrecv.head[2]=0x4A;//J sendrecv.head[3]=0x4A;//J 相当于前缀 sendrecv.length=15; for(i=0;i<8;i++) { sendrecv.data[i]=0x00; } sendrecv.humi[0]=0x00;//传感器0状态 sendrecv.humi[1]=0x00;//传感器1状态 sendrecv.elengine[0]=0x00;//电机0状态 sendrecv.elengine[1]=0x00;//电机1状态 sendrecv.led[0]=0x00;//led0状态 sendrecv.led[1]=0x00;//led1状态 sendrecv.led[2]=0x00;//led2状态 } ~~~ 数据包是根据我们和服务器端所定的协议来构建的。如下图 ![和上位机所定的协议](https://img-blog.csdnimg.cn/20190516183614441.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjE0OTE5Ng==,size_16,color_FFFFFF,t_70) udp_pcb udp协议控制块(用来装一些双方连接信息) ~~~ c struct udp_pcb { /* Common members of all PCB types */ IP_PCB; /* 指向下一个PCB */ struct udp_pcb *next; u8_t flags; /** 端口 本地和远端定义的端口号*/ u16_t local_port, remote_port; #if LWIP_IGMP /** outgoing network interface for multicast packets */ ip_addr_t multicast_ip; #endif /* LWIP_IGMP */ #if LWIP_UDPLITE /** used for UDP_LITE only */ u16_t chksum_len_rx, chksum_len_tx; #endif /* LWIP_UDPLITE */ /** 接受回调函数*/ udp_recv_fn recv; /** user-supplied argument for the recv callback 用户提供的回调函数 */ void *recv_arg; }; ~~~ - ip_addr 32位的IP地址 - 设置远端IP地址 ~~~c /* This is the aligned version of ip_addr_t, used as local variable, on the stack, etc. */ struct ip_addr { u32_t addr; }; /*此函数用来设置远端IP地址 */ void udp_demo_set_remoteip(void) { u8 *tbuf; u16 xoff; u8 key; POINT_COLOR=RED; tbuf=mymalloc(SRAMIN,100); //申请内存 if(tbuf==NULL)return; //前三个IP保持和DHCP得到的IP一致 同一网段 lwipdev.remoteip[0]=lwipdev.ip[0];//192 lwipdev.remoteip[1]=lwipdev.ip[1];//168 lwipdev.remoteip[2]=lwipdev.ip[2];//1 lwipdev.remoteip[3]=(uint8_t)(0x01);//自己定义服务器端IP sprintf((char*)tbuf,"Remote IP:%d.%d.%d.",lwipdev.remoteip[0],lwipdev.remoteip[1],lwipdev.remoteip[2]);//远端IP POINT_COLOR=BLUE; xoff=strlen((char*)tbuf)*8+30; printf("KEY1:+ KEY0:-\r\n"); printf("KEY_UP:OK\r\n"); //此处使用可调节式的远端IP设置 while(1) { key=KEY_Scan(0); if(key==WKUP_PRES)break; else if(key) { if(key==KEY1_PRES)lwipdev.remoteip[3]++;//IP增加 if(key==KEY0_PRES)lwipdev.remoteip[3]--;//IP减少 printf("%d.%d.%d.%d\r\n",lwipdev.remoteip[0],lwipdev.remoteip[1],lwipdev.remoteip[2],lwipdev.remoteip[3]);//显示新IP } } myfree(SRAMIN,tbuf); } ~~~ 1. 本地IP可从上述代码看出,本地IP采用DHCP动态分配的IP地址,如果分配不成功则使用默认设置IP,如下代码所示,还初始化了MAC、默认远端IP、默认子网掩码、默认网关。lwip控制结构体主要对上述结构体进行封装。 ```c //lwip控制结构体 typedef struct { u8 mac[6]; //MAC地址 u8 remoteip[4]; //远端主机IP地址 u8 ip[4]; //本机IP地址 u8 netmask[4]; //子网掩码 u8 gateway[4]; //默认网关的IP地址 vu8 dhcpstatus; //dhcp状态 //0,未获取DHCP地址; //1,进入DHCP获取状态 //2,成功获取DHCP地址 //0XFF,获取失败. }__lwip_dev; //lwip 默认IP设置 //lwipx:lwip控制结构体指针 void lwip_comm_default_ip_set(__lwip_dev *lwipx) { //默认远端IP为:192.168.1.100 lwipx->remoteip[0]=192; lwipx->remoteip[1]=168; lwipx->remoteip[2]=1; lwipx->remoteip[3]=100; //MAC地址设置(高三字节固定为:2.0.0,低三字节用STM32唯一ID) lwipx->mac[0]=enc28j60_dev.macaddr[0]; lwipx->mac[1]=enc28j60_dev.macaddr[1]; lwipx->mac[2]=enc28j60_dev.macaddr[2]; lwipx->mac[3]=enc28j60_dev.macaddr[3]; lwipx->mac[4]=enc28j60_dev.macaddr[4]; lwipx->mac[5]=enc28j60_dev.macaddr[5]; //默认本地IP为:192.168.1.30 lwipx->ip[0]=192; lwipx->ip[1]=168; lwipx->ip[2]=1; lwipx->ip[3]=30; //默认子网掩码:255.255.255.0 lwipx->netmask[0]=255; lwipx->netmask[1]=255; lwipx->netmask[2]=255; lwipx->netmask[3]=0; //默认网关:192.168.1.1 lwipx->gateway[0]=192; lwipx->gateway[1]=168; lwipx->gateway[2]=1; lwipx->gateway[3]=1; lwipx->dhcpstatus=0;//没有DHCP } ``` ## int main(void) 主函数我们主要看下lwip_comm_init();与udp_demo_test();这两个函数。 ```c extern u8 udp_demo_flag; //UDP 测试全局状态标记变量 int main(void) { u8 key; delay_init(); //延时函数初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级 uart_init(115200); //串口初始化为115200 KEY_Init(); //初始化按键 LED_Init(); //LED端口初始化 TIM3_Int_Init(1000,719); //定时器3频率为100hz //系统时钟 用来保持LWIP精准计时 MOTOR_PWM_Init(7199,0); //=====初始化PWM 10KHZ,用于驱动电机 如需初始化电调接口 改为MiniBalance_PWM_Init(9999,35) 200HZ FSMC_SRAM_Init(); //初始化外部SRAM my_mem_init(SRAMIN); //初始化内部内存池 my_mem_init(SRAMEX); //初始化外部内存池 while(lwip_comm_init()) //lwip初始化 TCP/IP协议栈 { delay_ms(1200); } printf("LWIP Init Success!\r\n"); #if LWIP_DHCP //使用DHCP while((lwipdev.dhcpstatus!=2)&&(lwipdev.dhcpstatus!=0XFF))//等待DHCP获取成功/超时溢出 { lwip_periodic_handle(); //LWIP内核需要定时处理的函数 } #endif delay_ms(500); //延时1s delay_ms(500); udp_demo_test(); //UDP 模式 连接 连接成功就在此函数 //连接失败才会执行 下面while(1)用来再次连接上位机 while(1) { key = KEY_Scan(0); if(key == KEY1_PRES) //按KEY1键建立连接 { if((udp_demo_flag & 1<<5)) printf("UDP连接已经建立,不能重复连接\r\n"); //如果连接成功,不做任何处理 else udp_demo_test(); //当断开连接后,调用udp_demo_test()函数 } delay_ms(10); } } ``` ### u8 lwip_comm_init(void) *此函数的执行流程* 1. 初始化enc28j60模块 2. 初始化lwip内核 3. 设置默认IP等信息 4. 如果使用DHCP,则开启DHCP服务并分配IP等信息 5. 添加网口 6. 设置网口为默认网口 7. 打开网口 ```c //LWIP初始化(LWIP启动的时候使用) //返回值:0,成功 // 1,内存错误 // 2,DM9000初始化失败 // 3,网卡添加失败. u8 lwip_comm_init(void) { struct netif *Netif_Init_Flag; //调用netif_add()函数时的返回值,用于判断网络初始化是否成功 struct ip_addr ipaddr; //ip地址 struct ip_addr netmask; //子网掩码 struct ip_addr gw; //默认网关 if(lwip_comm_mem_malloc())return 1; //内存申请失败 if(ENC28J60_Init())return 2; //初始化ENC28J60 lwip_init(); //初始化LWIP内核 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.g
评论
    相关推荐
    • STM32F103+UCOS II+LWIP.zip
      一个非常好的STM32F103+UCOS II+LWIP的移植例程
    • LWIP and ucOS 在STM32F103上的应用
      使用说明 (1)工程文件路径:例程目录\USART+RTC\MDK-ARM\Project.uvproj ... (3)请使用MDK 4.0以上版本打开,MDK版本过低会导致无法识别工程。 (4)使用调试工具为ULINK (5)HEX文件下载到板子里后,串口将打印一些...
    • STM32+FreeRtos+Lwip+ENC28J60
      STM32+FreeRtos+Lwip程序基于ENC28J60,程序测试通过,添加UDP测试。
    • STM32F103ZET6 移植的UCOSIII+LWIP(DM9000) 使用HAL库
      STM32F103ZET6 移植的UCOSIII+LWIP,使用HAL库,方便代码复用及移植,网卡芯片使用DM9000,经过长时间PING测试无问题
    • STM32F103学习资料和开发手册
      STM32F103学习资料和开发手册,包括但不限于: 1、STM32F1开发指南-库函数版本_V3.1 .pdf; 2、STM32F1开发指南-寄存器版本_V3.1 .pdf; 3、STM32F1 EMWIN开发手册_V2.0.pdf; 4、STM32F1 FreeRTOS开发手册_V1.0.pdf...
    • stm32f103+dm9051 LwIP網路平台源代碼
      stm32f103採用SPI接口的乙太控制器DM9051, 在uCOS-ii+LwIP平台和Keil工具上開發Web, 手機控制LED, 內含simple iPerf.
    • FreeModeBus + LWIP + STM32F103
      FreeModeBus + LWIP + STM32F103
    • 基于lwip+freertos+stm32+enc28j60项目版本
      本工程是基于lwip+freertos+stm32f103+enc28j60代码,可以ping通,其中enc28j60是中断方式,下载后修改自己的spi,中断接口就可以使用。
    • STM32F103 uCOSII2.91+lwip-1.3.2 (DM9000)
      CortexM3 STM32F103 DM9000 网路稳定,红牛3代开发板例程,绝对原版代码。 uCOS LWIP DM9000 FTP lwip DM9000 TCP UDP DHCP IPV6 IPV4 uCOSII2.91 lwip-1.3.2 DM9000
    • stm32f103 freertos + lwip
      使用野火开发板,芯片采用stm32f103,实现了freertos代码的移植,以及lwip的移植,使用socket网络编程,编译环境为MDK5