stm32上基于LwIP移植LibArtnet

这个东西做了两天,第一天改底层接口,编译通过。

第二天调通整个程序。

这里难点在于对LwIP不熟悉,在STM32上开发,居然也没有ULINK,连烧程序都是要用串口的。

如果有朋友有需要,我可以给出几个比较关键的东西,不过也说明一下我的开发环境,我是基于神州4号开发板,用keil开发的。

1. UDP客户端/服务器端代码。

main函数:

int main(void)
{
        struct udp_pcb *Udppcb_svr = NULL;
	struct ip_addr dAddr;
	struct pbuf *p = NULL;
	int ret = 0;
	
	System_Setup();
             
 	/* Initilaize the LwIP satck */
 	LwIP_Init();
		
	p = pbuf_alloc(PBUF_TRANSPORT, sizeof(UDPArr), PBUF_RAM);
        if (p == NULL)
	{
		printf("no memory for p \r\n");
	}
	p->payload = (void *)(UDPArr); // 全局变量,只是一个hello字符串。

        while (1)
 	{    
		/* Periodic tasks */
		System_Periodic_Handle();
		//ARMJISHU_TouchScreen();

		if (init_artnet_flag < TEST_INTERVAL)
		{
			init_artnet_flag++;

			if (get_brdcast_addr() != 0)
			{
				Delay_ARMJISHU(4000);
				if (init_artnet_flag == 0x4000)
				{
					printf("brdcast addr: %x \r\n", get_brdcast_addr());

					Udppcb_svr = udp_new();
					if (NULL == Udppcb_svr)
					{
						printf("no memory for Udppcb_svr\r\n");
					}

					ret = udp_bind(Udppcb_svr, IP_ADDR_ANY, 161);
					if (ret != ERR_OK)
					{
						printf("bind error : %d\r\n", ret);
					}

					//IP4_ADDR(&dAddr , 192,168,1,107);
					dAddr.addr = get_brdcast_addr();
 														
					ret = udp_connect(Udppcb_svr, &dAddr, 61234);
					if (ret != ERR_OK)
					{
						printf("connect error : %d\r\n", ret);
					}					

					printf("ready send \r\n");
					udp_send(Udppcb_svr, p);
					printf("send ok \r\n");

					udp_disconnect(Udppcb_svr);
					pbuf_free(p);

					ret = udp_bind(Udppcb_svr, IP_ADDR_ANY, 161);
					if (ret != ERR_OK)
					{
						printf("bind error : %d\r\n", ret);
					}

					//Udppcb_svr->so_options |= SOF_BROADCAST;

					udp_recv(Udppcb_svr, UDP_Receive, NULL);

					init_artnet_flag = ARTNET_INIT_OK;
				}	
			}
			else
			{
				init_artnet_flag = 0;
			}
			
		}
	}
}

我这段代码的逻辑大概是开机初始化,然后等待DHCP分配到IP给板子,之后再去尝试连接到指定的UDP服务器,广播也可以,指定地址也可以,发送一个包,之后就断开连接,做成服务器的形式。

对上述代码有几个关键点想说明的,pbuf_alloc如果用我提供的PBUF_TRANSPORT类型去申请的话,一定要知道,开辟空间时,要预留IP层和UDP/TCP层的头部大小,并且用户数据要跳过这个头部再开始使用。否则很容易造成在调用socket的发送函数之后,整个程序死掉。


UDP_Receive函数:

void UDP_Receive(void *arg, struct udp_pcb *upcb, struct pbuf *p,
                       struct ip_addr *addr, u16_t port)
{
	struct ip_addr dAddr = *addr;
	
	if (p != NULL)
	{
		printf("addr: %x, port: %d\r\n", dAddr.addr, port);
		printf("total len: %d, len: %d\r\n", p->tot_len, p->len);//, (char *)(p->payload));

		// echo for debug
		dAddr.addr = get_brdcast_addr();
		udp_sendto(upcb, p, &dAddr, port);

		pbuf_free(p);
	}
}
这是做成一个简单的回显。

2. Artnet中我改过的代码。

就不在这里贴了,但是可以提供一个链接下载。

你可能感兴趣的:(系统移植,网络编程)