UDP通信具有速度快的优点,TCP通信有例程可以参考,但是UDP通信却没有。
目标
新建一个PicoW模块基于UDP协议、STA模式的“echo”例程工程,可以通过手机与PicoW进行通信,并通过串口打印出相关信息。
新建工程
参考前面帖子的工程创建方法,使用“pico project generato”工具,工程名为“Test_IwIP_UDP”,勾选“Console over UART”和“Background IwIP”。
代码编写
前面的工作已经将工程框架搭建完成,下面贴出主要的代码。
添加头文件
#include "lwip/udp.h"
添加定义与全局变量
主要是WIFI用户名和密码,这里XX需要替换为自己的,通信端口号和pcb。
#define WIFI_SSID "XXXXXXXXXXX"
#define WIFI_PASSWORD "XXXXXXXXX"
#define RCV_FROM_PORT 1234
struct udp_pcb * rcv_udp_pcb;
main函数编写
主要是芯片的初始化,连接WiFi路由器,绑定UDP,注册接收回调函数,进行LED灯闪烁。UDP没有TCP那么多的功能,例如连接成功,发送成功等,都是没有回调函数的。
int main()
{
static bool LED_State=0;
stdio_init_all();
puts("Test IwIP UDP");
if (cyw43_arch_init()) {
printf("Wi-Fi init failed");
return -1;
}
cyw43_arch_enable_sta_mode();
printf("Connecting to Wi-Fi...\n");
if (cyw43_arch_wifi_connect_timeout_ms(WIFI_SSID, WIFI_PASSWORD, CYW43_AUTH_WPA2_AES_PSK, 30000)) {
printf("failed to connect.\n");
return 1;
} else {
printf("Connected.\n");
}
rcv_udp_pcb = udp_new();
err_t err = udp_bind(rcv_udp_pcb,IP_ADDR_ANY,RCV_FROM_PORT);
udp_recv(rcv_udp_pcb, RcvFromUDP,NULL);
while (true) {
sleep_ms(100);
if(LED_State){
LED_State=false;
}else{
LED_State=true;
}
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, LED_State);
}
return 0;
}
接收回调函数和发送函数的编写
在接收函数中将发送者的相关信息打印出来,并将收到的信息发送。UDP理论上是没法确实两者是否连接成功的,也不能像TCP一样,连接成功后可以发送一个“连接成功”的信息给Client。只有当收到信息后,才能通过收到信息,知道是谁发送了信息,进而发送回去。
void SendUDP(const ip_addr_t *dst_ip , int port, void * data, int data_size)
{
struct pbuf * p = pbuf_alloc(PBUF_TRANSPORT,data_size+1,PBUF_RAM);
char *pt = (char *) p->payload;
memcpy(pt,data,data_size);
pt[data_size]='\0';
cyw43_arch_lwip_begin();
udp_sendto(rcv_udp_pcb,p,dst_ip,port);
printf("send -> %s\n", pt);
cyw43_arch_lwip_end();
pbuf_free(p);
}
void RcvFromUDP(void * arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t*addr,u16_t port)
{
char *buffer=calloc(p->len+1,sizeof(char)); // use calloc to >
strncpy(buffer,(char *)p->payload,p->len);
printf("received from %d.%d.%d.%d port=%d\n",addr->addr&0xff,
(addr->addr>>8)&0xff,
(addr->addr>>16)&0xff,
addr->addr>>24,port);
printf("Length = %d , Total Length = %d\n",p->len,p->tot_len);
printf("payload -> %s\n", buffer);
free(buffer);
pbuf_free(p);
SendUDP(addr,port,buffer,p->len);
}
运行效果
在手机上运行“lb_socket_Android”APP,这是我自己编写的UDP通信软件,在前面有介绍,最后有下载。通过上一帖的方法知道PicoW的IP地址,然后输入端口号,点击连接。编辑发送数据,点击发送,就会看到接收到相同的数据。
连接串口调试助手,在串口调试助手上,会有WiFi连接整个过程的信息,例如,接收回调函数打印的相关信息。
APP源码与编写:socket学习(Android收发)