STM32配合W5500网卡连接华为云物联网平台通信

【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销量惨淡 甚至不敌阿里巴巴的天猫精灵
中国电梯行业产量和存量双双稳定增长,采购规模处于平稳增长的态势