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);
}
- 本地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