通过LWIP 的RAW API 进行与服务器的UDP通信(stm32 f103 -- enc28j60)

本文详细介绍了如何在STM32F103微控制器上利用LWIP库的RAW API实现与服务器的UDP通信。通过enc28j60网络模块,文章阐述了初始化过程、数据包结构、主要函数的功能,包括`lwip_comm_init()`、`udp_demo_recv()`和`udp_demo_senddata()`,以及数据的接收与发送处理。
摘要由CSDN通过智能技术生成

LWIP的RAW API UDP通信详解(stm32f103—enc28j60)
项目整体托管到github上

实现任务

通过接收到上位机端发送来的数据来实现控制开发板做相应的操作。

代码实现

首先看看几个主要的结构体

//发送数据包

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状态
}

数据包是根据我们和服务器端所定的协议来构建的。如下图
和上位机所定的协议
udp_pcb udp协议控制块(用来装一些双方连接信息)

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地址
/* 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控制结构体主要对上述结构体进行封装。
//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
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值