【1】w5500网卡 w5500是一种基于tcp/ip协议的网络通讯芯片,可以提供网络连接功能,相当于是一种嵌入式以太网控制器,具有低功耗、高速传输、易于集成等特点。w5500芯片能够支持tcp、udp、ipv4、arp、icmp、igmp等协议,使得它变得非常适合用于嵌入式设备与互联网之间的通信需求,例如智能家居、工业控制、远程监控等场景。w5500网卡还有一个特点是它支持硬件协议堆栈,这意味着它可以非常快地执行协议栈中的操作,从而大大提高了数据传输的效率。同时,w5500还具有较低的功耗,因此非常适合嵌入式设备这种资源受限的场景。
w5500芯片通过spi总线与mcu进行通信,mcu需要实现spi总线协议来控制w5500进行数据交互。
【2】spi协议 spi(serial peripheral interface)协议是一种串行外设接口协议,是一种全双工、同步的接口技术,通常用于连接微控制器和外设,例如传感器、存储器、显示器等。spi协议传输效率高,使用简单,开销较小,因此被广泛应用于嵌入式系统中。
spi协议使用主从模式,主设备可以控制多个从设备,从设备不能主动向主设备发送数据或信息。spi协议具有以下几个重要的信号线:
sclk:时钟线,由主设备提供,用于同步主从设备之间的数据传输。 mosi(master out slave in):主输出从输入线,由主设备提供,用于向从设备发送数据。 miso(master in slave out):主输入从输出线,由从设备提供,用于向主设备发送数据。 ss(slave select):从设备选择信号线,由主设备提供。当主设备需要与某个从设备通信时,将该线电平拉低,以选择需要通信的从设备。 spi协议的数据传输是基于数据字节的传输,主设备每次通过mosi线发送一个字节,从设备通过miso线接受该字节,并回传一个字节。数据的传输顺序可以根据时钟线(sclk)的极性和相位配置为四种不同的模式。spi协议支持的模式受闪存、ram、i/o和模拟/数字转换器等外设和类型的限制。
【3】w5500建立tcp协议通信 以下是stm32通过w5500建立tcp通信,并访问tcp服务器,完成数据收发的示例代码。
代码中使用了stm32 hal库,w5500的ip地址和端口号需要根据实际情况进行设置。
#include main.h #include stdio.h #include stm32f1xx_hal.h #include wizchip_conf.h #include socket.h #include dhcp.h /* private variables */ spi_handletypedef hspi1; /* private function prototypes */ void systemclock_config(void); static void mx_gpio_init(void); static void mx_spi1_init(void); void w5500_init(void); uint8_t socket; uint8_t buf[1024]; int main(void) { /* mcu configuration */ hal_init(); systemclock_config(); mx_gpio_init(); mx_spi1_init(); /* w5500 initialization */ w5500_init(); /* connect to tcp server */ uint8_t server_ip[4] = {192, 168, 1, 100}; uint16_t server_port = 5000; uint8_t connected = 0; while (!connected) { if (getsn_sr(socket) == sock_closed) { socket = socket(af_inet, sock_stream, ipproto_tcp); if (socket == 0xff) { /* error: failed to create socket */ } else { /* configure socket */ uint8_t dest_ip[4] = {192, 168, 1, 200}; uint16_t dest_port = 5000; uint8_t buf[4]; iinchip_write(sn_dipr(socket), dest_ip); iinchip_write(sn_dport(socket), dest_port); iinchip_socket_control(socket, sn_cr_open); hal_delay(10); /* try to connect to server */ iinchip_socket_control(socket, sn_cr_connect); hal_delay(1000); if (getsn_sr(socket) == sock_established) { connected = 1; } else { /* connection failed */ iinchip_socket_control(socket, sn_cr_close); hal_delay(10); } } } } /* send data to server */ uint8_t tx_data[4] = {0x01, 0x02, 0x03, 0x04}; write(socket, tx_data, sizeof(tx_data)); /* receive data from server */ int rx_len = 0; while (1) { rx_len = getsn_rx_rsr(socket); if (rx_len > 0) { read(socket, buf, rx_len); /* data received from server, do something */ } = spi_direction_2lines; hspi1.init.datasize = spi_datasize_8bit; hspi1.init.clkpolarity = spi_polarity_low; hspi1.init.clkphase = spi_phase_1edge; hspi1.init.nss = spi_nss_soft; hspi1.init.baudrateprescaler = spi_baudrateprescaler_128; hspi1.init.firstbit = spi_firstbit_msb; hspi1.init.timode = spi_timode_disable; hspi1.init.crccalculation = spi_crccalculation_disable; hspi1.init.crcpolynomial = 10; hal_spi_init(&hspi1); } /* gpio initialization */ static void mx_gpio_init(void) { gpio_inittypedef gpio_initstruct = {0}; __hal_rcc_gpioa_clk_enable(); /*configure gpio pin : pa4 */ gpio_initstruct.pin = gpio_pin_4; gpio_initstruct.mode = gpio_mode_output_pp; gpio_initstruct.speed = gpio_speed_freq_low; hal_gpio_init(gpioa, &gpio_initstruct); } /* system clock configuration */ void systemclock_config(void) { rcc_oscinittypedef rcc_oscinitstruct = {0}; rcc_clkinittypedef rcc_clkinitstruct = {0}; /** initializes the rcc oscillators according to the specified parameters in the rcc_oscinittypedef structure. */ rcc_oscinitstruct.oscillatortype = rcc_oscillatortype_hse; rcc_oscinitstruct.hsestate = rcc_hse_on; rcc_oscinitstruct.hsepredivvalue = rcc_hse_prediv_div1; rcc_oscinitstruct.pll.pllstate = rcc_pll_on; rcc_oscinitstruct.pll.pllsource = rcc_pllsource_hse; rcc_oscinitstruct.pll.pllmul = rcc_pll_mul9; if (hal_rcc_oscconfig(&rcc_oscinitstruct) != hal_ok) { error_handler(); } /** initializes the cpu, ahb and apb buses clocks */ rcc_clkinitstruct.clocktype = rcc_clocktype_hclk|rcc_clocktype_sysclk |rcc_clocktype_pclk1|rcc_clocktype_pclk2; rcc_clkinitstruct.sysclksource = rcc_sysclksource_pllclk; rcc_clkinitstruct.ahbclkdivider = rcc_sysclk_div1; rcc_clkinitstruct.apb1clkdivider = rcc_hclk_div2; rcc_clkinitstruct.apb2clkdivider = rcc_hclk_div1; if (hal_rcc_clockconfig(&rcc_clkinitstruct, flash_latency_2) != hal_ok) { error_handler(); } } 【4】封装mqtt协议报文 下面使用mqtt client library for contiki来连接mqtt服务器。这个库适用于不同的平台,包括stm32。在使用前,需要根据需求进行一些配置,例如: 指定mqtt服务器的地址和端口号,配置mqtt客户端id和主题等。
#include contiki.h #include contiki-net.h #include mqtt.h #include stm32f1xx_hal.h #include wizchip_conf.h #include w5500.h /* mqtt configuration */ #define server_ip_addr 192.168.1.100 #define server_port 1883 #define mqtt_client_id mqtt_stm32 #define mqtt_topic example_topic /* network configuration */ static wiz_netinfo gwiznetinfo = { .mac = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06}, .ip = {192, 168, 1, 200}, .sn = {255, 255, 255, 0}, .gw = {192, 168, 1, 1}, .dns = {8, 8, 8, 8}, .dhcp = netinfo_static }; /* w5500 buffer */ static uint8_t buf[2048]; /* prototypes */ static void mx_spi1_init(void); static void mx_gpio_init(void); void systemclock_config(void); void error_handler(void); void w5500_select(void); void w5500_unselect(void); uint8_t w5500_writebyte(uint8_t b); uint8_t w5500_readbyte(void); void mqtt_callback(struct mqtt_connection *m, void *userdata, mqtt_event_t event, mqtt_data_t *data); /* mqtt connection */ static struct mqtt_connection mqtt_conn; static struct mqtt_message *msg_ptr = null; static uint8_t mqtt_connected = 0; process(mqtt_process, mqtt process); autostart_processes(&mqtt_process); /* mqtt process */ process_thread(mqtt_process, ev, data) { process_begin(); /* initialize w5500 */ reg_wizchip_cs_cbfunc(w5500_select, w5500_unselect); reg_wizchip_spi_cbfunc(w5500_readbyte, w5500_writebyte); wizchip_init(buf, buf); /* configure network */ ctlnetwork(cn_set_netinfo, (void*)&(gwiznetinfo)); /* dhcp initialization */ uint8_t /* enable dhcp */ dhcp_client_start(); /* wait for dhcp to finish */ while (gwiznetinfo.dhcp == netinfo_dhcp) { hal_delay(1000); // wait for dhcp to finish } /* print ip address */ printf(ip address: %d.%d.%d.%dn, gwiznetinfo.ip[0], gwiznetinfo.ip[1], gwiznetinfo.ip[2], gwiznetinfo.ip[3]); /* configure mqtt connection */ memset(&mqtt_conn, 0, sizeof(mqtt_conn)); mqtt_conn.state = mqtt_init; mqtt_conn.host = server_ip_addr; mqtt_conn.port = server_port; mqtt_conn.client_id = mqtt_client_id; mqtt_conn.user_data = null; mqtt_conn.user_name = null; mqtt_conn.password = null; mqtt_conn.protocol_version = mqtt_version_3_1_1; mqtt_conn.keep_alive = 60; /* connect to mqtt server */ mqtt_connect(&mqtt_conn); /* wait for mqtt connection to finish */ while (!mqtt_connected) { process_pause(); } /* publish message to mqtt server */ static char msg[100] = hello from stm32 using mqtt protocol!; msg_ptr = mqtt_msg_publish_init(msg, strlen(msg), mqtt_topic, mqtt_qos_level_0, mqtt_retain_off); mqtt_publish(&mqtt_conn, msg_ptr); /* wait for message to be sent */ while (mqtt_conn.out_buffer_sent == 0) { process_pause(); } /* subscribe to mqtt topic */ mqtt_subscribe(&mqtt_conn, mqtt_topic, mqtt_qos_level_0); /* loop forever */ while (1) { process_pause(); } process_end(); } /* spi initialization / static void mx_spi1_init(void) { / spi1 parameter configuration*/ hspi1.instance = spi1; hspi1.init.mode = spi_mode_master; hspi1.init.direction = spi_direction_2lines; hspi1.init.datasize = spi_datasize_8bit; hspi1.init.clkpolarity = spi_polarity_low; hspi1.init.clkphase = spi_phase_1edge; hspi1.init.nss = spi_nss_soft; hspi1.init.baudrateprescaler = spi_baudrateprescaler_128; hspi1.init.firstbit = spi_firstbit_msb; hspi1.init.timode = spi_timode_disable; hspi1.init.crccalculation = spi_crccalculation_disable; hspi1.init.crcpolynomial = 10; hal_spi_init(&hspi1); } /* gpio initialization */ static void mx_gpio_init(void) { gpio_inittypedef gpio_initstruct = {0}; __hal_rcc_gpioa_clk_enable(); /*configure gpio pin : pa4 */ gpio_initstruct.pin = gpio_pin_4; gpio_initstruct.mode = gpio_mode_output_pp; gpio_initstruct.speed = gpio_speed_freq_low; hal_gpio_init(gpioa, &gpio_initstruct); } /* system clock configuration */ void systemclock_config(void) { rcc_oscinittypedef rcc_oscinitstruct = {0}; rcc_clkinittypedef rcc_clkinitstruct = {0}; /** initializes the rcc oscillators according to the specified parameters in the rcc_oscinittypedef structure. */ rcc_oscinitstruct.oscillatortype = rcc_oscillatortype_hse; rcc_oscinitstruct.hsestate = rcc_hse_on; rcc_oscinitstruct.hsepredivvalue = rcc_hse_prediv_div1; rcc_oscinitstruct.pll.pllstate = rcc_pll_on; rcc_oscinitstruct.pll.pllsource = rcc_pllsource_hse; rcc_oscinitstruct.pll.pllmul = rcc_pll_mul9; if (hal_rcc_oscconfig(&rcc_oscinitstruct) != hal_ok) { error_handler(); } /** initializes the cpu, ahb and apb buses clocks */ rcc_clkinitstruct.clocktype = rcc_clocktype_hclk|rcc_clocktype_sysclk |rcc_clocktype_pclk1|rcc_clocktype_pclk2; rcc_clkinitstruct.sysclksource = rcc_sysclksource_pllclk; rcc_clkinitstruct.ahbclkdivider = rcc_sysclk_div1; rcc_clkinitstruct.apb1clkdivider = rcc_hclk_div2; rcc_clkinitstruct.apb2clkdivider = rcc_hclk_div1; if (hal_rcc_clockconfig(&rcc_clkinitstruct, flash_latency_2) != hal_ok) { error_handler(); } } /* error handler */ void error_handler(void) { while (1) { // error } } /* w5500 select */ void w5500_select(void) { hal_gpio_writepin(gpioa, gpio_pin_4, gpio_pin_reset); } /* w5500 unselect */ void w5500_unselect(void) { hal_gpio_writepin(gpioa, gpio_pin_4, gpio_pin_set); } /* w5500 write byte */ uint8_t w5500_writebyte(uint8_t b) { uint8_t res; hal_spi_transmitreceive(&hspi1, &b, &res, 1, hal_max_delay); return res; } /* w5500 read byte */ uint8_t w5500_readbyte(void) { uint8_t b = 0xff; hal_spi_transmitreceive(&hspi1, &b, &b, 1, hal_max_delay); return b; } /* mqtt callback */ void mqtt_callback(struct mqtt_connection *m, void *userdata, mqtt_event_t event, mqtt_data_t *data) { switch (event) { case mqtt_event_connected: printf(mqtt connectedn); mqtt_connected = 1; break; case mqtt_event_disconnected: printf(mqtt disconnectedn); mqtt_connected = 0; break; case mqtt_event_published: printf(mqtt message publishedn); break; case mqtt_event_suback: printf(mqtt subscribed to topicn); break; case mqtt_event_unsuback: printf(mqtt unsubscribed from topicn); break; case mqtt_event_data: printf(mqtt received messagen); printf(topic: %.*sn, data->topic_name_size, data->topic_name); printf(message: %.*sn, data->data_size, (char *)data->data); break; default: break; } }
探究锂离子电池工作原理与制造工艺
泰尔认证中心向vivo颁发国内首批手机适老化认证证书
电路中为什么要使用光耦器件?
MOSFET作为开关案例及控制表
了解冷藏集装箱温度实时监测系统的应用
STM32配合W5500网卡连接华为云物联网平台通信
应用开发中结构体和链表的关系是怎样的
微处理器温度控制模拟输出阶段功能块
如何实现水电站智慧生态流量监测
冗余和热备有什么区别
无线充电在电动汽车应用及注意事项
雷达电磁环境的数字建模和仿真设计
展现科创新力量,开启全球合作新篇章:吹田电气产品发布会成功举办
影响PCB回流炉设备的因素及解决方法
圆周率智能X万链信息|战略合作,开创Web3.0新篇章
AX5043射频模组的50mW的窄带传输性能介绍
提升Linux技能的13个必杀技!
三星正式发布全新5G SoC Exynos 2100
为什么苹果HomePod销量惨淡 甚至不敌阿里巴巴的天猫精灵
中国电梯行业产量和存量双双稳定增长,采购规模处于平稳增长的态势